Como obtenho o preenchimento automático para várias entradas em um modelo de captura no modo de organização?

0

Estou usando o modo de org do Emacs com modelos de captura extensivamente, mas uma coisa ainda está me irritando: não consigo obter o preenchimento automático para várias entradas em prompts, exceto tags. Considerando o seguinte modelo de captura:

("m" "meeting" entry
   (file+datetree "~/Dropbox/org/meetings.org")
   "* %^{Description} %^G
   Time: %T
   %?
   ** Meeting info
   Place: %^{Place|Headquarters|Customer}
   Participants: %^{Participants|me|Tony|bossman}
   "
   :clock-in t)

Para as tags (% ^ G), o preenchimento automático para várias entradas funciona como um encanto, mas, para os Participantes, o preenchimento automático funciona apenas para uma única entrada, independentemente de eu as separar por: ou

Eu gostaria de preencher automaticamente o participante para cada entrada que eu separar, ou:

Melhor ainda seria se ela criasse uma lista dinâmica de preenchimento automático para os participantes, como, por exemplo, para que eu não precisasse especificar todos os participantes possíveis no modelo de captura.

    
por Fredrik Forséll 09.10.2015 / 08:50

1 resposta

0

Os modelos de captura do modo Org incluem um % -escape para executar Elisp arbitrário, que podemos usar para fazer praticamente qualquer coisa. Aqui como usá-lo para conseguir o que você quer:

Primeiro, aqui estão duas funções que criam uma tabela de conclusão dinâmica. O primeiro apenas encontra todas as correspondências para um regexp especificado. o segundo usa o primeiro para obter especificamente o tipo de itens que você procurando por.

(defun my/dynamic-completion-table-regexp (regexp &optional group buffer)
  "Return alist containing all matches for REGEXP in BUFFER.

The returned alist contains the matches as keys, and each key is
associated with a nil value.

If the optional parameter GROUP (an integer) is supplied, only
that part matching the corresponding parenthetical subexpression
is taken as the key.

If BUFFER is omitted, it defaults to the current buffer.  Note
that the entire buffer is scanned, regardless of narrowing."
  (let ((buffer (or buffer (current-buffer)))
        (group  (or group 0))
        table match)
    (with-current-buffer buffer
      (save-excursion
        (save-restriction
          (widen)
          (goto-char (point-min))
          (while (re-search-forward regexp nil :noerror)
            (setq match (substring-no-properties (match-string group)))
            (add-to-list 'table (list match))))))
    table))

(defun my/dynamic-completion-table-by-field (field &optional delims buffer)
  "Return alist containing all entries for FIELD in BUFFER.

Look in BUFFER for all lines of the form \"FIELD: TEXT\",
possibly with leading or trailing whitespace.  If DELIMS is
omitted, consider TEXT as a single item; otherwise, it should be
a regexp matching the delimiters between the items inside TEXT.
Empty items are discarded, and whitespace surrounding the
delimiters is removed.

The returned alist contains one key for each item found; all keys
are associated with the value nil.

If BUFFER is omitted, it defaults to the current buffer.  Note
that the entire buffer is scanned, regardless of narrowing."
  (require 'cl-lib)                     ; For 'cl-mapcan'
  (let ((table (my/dynamic-completion-table-regexp
                (concat "^\s-*"
                        (regexp-quote field)
                        ": \(.+\)\s-*$")
                1 buffer)))
    (cl-mapcan (lambda (x)
                 (mapcar #'list
                         (split-string (car x) delims :omit-nulls "\s-+")))
               table)))

Agora precisamos de uma função que leia do minibuffer, saiba como usar essas funções e usar o preenchimento de marca do modo Org para obter tipo de conclusão por item que você está procurando. Também precisa ser ciente do processo de captura, para que ele possa verificar o buffer de destino do buffer de captura.

(defun my/org-capture-read-multiple (field completion &optional delims)
  "Read one or more items for FIELD in capture template.

The COMPLETION parameter can be any sort of completion
table or function valid for the second parameter of
'completing-read'.  It may also be the keyword :dynamic, which
indicates that 'my/dynamic-completion-table-by-field' should be
used to generate a completion table dynamically.

The optional parameter DELIMS is ignored except with the :dynamic
option, in which case it is passed to
'my/dynamic-completion-table-by-field' as the parameter of the
same name.

If this function is invoked from within an Org-mode capture
process, the current buffer will be the target buffer for the
capture attempt, not the buffer used to fill the capture
template."
  (let* ((buffer (if (equal (buffer-name) "*Capture*")
                     (org-capture-get :buffer)
                   (current-buffer)))
         (completion (if (eq completion :dynamic)
                         (my/dynamic-completion-table-by-field
                          field delims buffer)
                       completion)))
    (with-current-buffer buffer
      (let ((org-last-tags-completion-table completion)
            org-completion-use-ido)
        (org-completing-read-no-i (format "%s: " field)
                                  #'org-tags-completion-function)))))

Para usá-los, você precisará modificar seu modelo. Por exemplo, você poderia substituir a linha "Participantes" no seu modelo acima por

Participants: %(my/org-capture-read-multiple \"Participants\" :dynamic \"[,:]\")
    
por 05.11.2015 / 01:33