Я широко использую Emacs org-mode с шаблонами захвата, но меня все еще раздражает одна вещь: я не могу получить автозаполнение для нескольких записей в приглашениях, кроме тегов. Учитывая следующий шаблон захвата:

("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)

Для тегов (% ^ G) автозаполнение для нескольких записей работает как талисман, но для участников автозаполнение работает только для одной записи, независимо от того, разделяю ли я их: или,

Я хотел бы автозаполнения участника для каждой записи, которую я разделяю, или:

Еще лучше было бы, если бы он построил динамический список автозаполнения для участников, например, для этого, чтобы мне не нужно было указывать всех возможных участников в шаблоне захвата.

1 ответ1

0

Шаблоны захвата в режиме Org включают % -escape для выполнения произвольного elisp, который мы можем использовать практически для чего угодно. Вот как использовать его, чтобы получить то, что вы хотите:

Во-первых, вот две функции, которые создают динамическую таблицу завершения. Первый просто находит все совпадения для заданного регулярного выражения. Второй использует первый, чтобы получить именно тот тип предметов, который вы ищете.

(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)))

Теперь нам нужна функция, которая читает из минибуфера, знает, как использовать эти функции, и использует завершение тега в режиме Org, чтобы получить вид завершения каждого элемента, который вы ищете. Он также должен знать о процессе захвата, поэтому он может сканировать целевой буфер вместо буфера захвата.

(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)))))

Чтобы использовать их, вам нужно изменить свой шаблон. Например, вы можете заменить строку "Участники" в шаблоне выше на

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .