Получить ссылку org для автоматической вставки описания ссылки?

11

Q: Как я могу получить пользовательскую orgфункцию ссылки для автоматической вставки описания?

Я хотел бы хранить orgссылки на файлы в diredбуфере, но предпочел бы, чтобы описание ссылки было именем файла без пути, а не сообщало полный путь, то есть:

file:~/the/full/path/myfile.ext     ; default, but no thanks
myfile.ext                          ; what I want

Теперь: org-store-linkжесткие ссылки diredдля обеспечения по умолчанию. Вместо этого я написал пользовательскую функцию (извлечение из жестко закодированной функции) и добавил ее в org-store-link-functions:

(defun dired-store-link ()
  (when (derived-mode-p 'dired-mode)
    (let ((file (dired-get-filename nil t)))
      (setf file (if file
                     (abbreviate-file-name (expand-file-name file))
                   default-directory))
      (org-store-link-props :type        "dired"
                            :link        file
                            :description (file-name-nondirectory file))
      file)))

(add-to-list 'org-store-link-functions #'dired-store-link)

Пока все хорошо, и работает как положено, но с одной стороны:

  • При вызове org-insert-linkсо встроенным поведением по умолчанию он просто вставляет ссылку, не спрашивая у меня описания.
  • При вызове org-insert-linkс моей пользовательской функцией мне предлагается ввести описание (которое корректно заполняется именем файла, хранящимся в :descriptionсвойстве).

Мне бы не хотелось каждый раз запрашивать описание, и я хочу org-insert-linkиспользовать значение, :descriptionкоторое устанавливает пользовательская функция.

Как я могу убедить org-insert-linkиспользовать :descriptionавтоматически, не спрашивая меня об этом?

Дэн
источник
Помогают ли необязательные аргументы link-locationили default-descriptionфункция org-insert-link? Если параметр LINK-LOCATION не равен nil, это значение будет использоваться в качестве местоположения ссылки вместо интерактивного чтения. Если параметр DEFAULT-DESCRIPTION не равен nil, это значение будет использоваться в качестве описания по умолчанию.
юрист
@lawlist: спасибо за предложение, хотя я не уверен, как настроить его в интерактивном режиме, не добавляя его в другую функцию. Тем не менее, это заставило меня прочитать документацию более внимательно, что заставило меня ответить на вопрос.
Дан

Ответы:

4

Внизу строки документации org-insert-linkнаходится примечание, которое:

Если org-make-link-description-functionне ноль, эта функция будет вызываться с целью ссылки, и результатом будет описание ссылки по умолчанию.

По всей видимости, orgв процессе хранения ссылки выбрасывается много информации, поэтому все, что осталось org-stored-links- это список записей формы (link description). Поскольку более ранняя функция имеет имя файла для ссылки, это выглядит следующим образом:

(defun org-link-describe (link desc)
  (if (file-exists-p link)
      desc
    (read-string "Description: " desc)))

(setf org-make-link-description-function #'org-link-describe)

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

Дэн
источник
2
Теперь, когда вы знаете эту функцию, вы не можете отказаться dired-store-linkи просто использовать это, чтобы создать описание, которое вы хотите? Я думаю, что это будет намного короче.
Малабарба
1
@Malabarba: вы, вероятно, правы - эту функцию можно переписать, чтобы проверить ссылку на файл и действовать соответствующим образом. Попробую, когда у меня будет свободное время.
Дан
3

Я использую org 9.1.6, и, к моему ужасу, кажется, что org-store-link-functionsтеперь это встроенная функция org (а не ловушка), поэтому оригинальное решение больше не работает. Можно использовать обходной путь org-link-parameters, но вместо этого я использую следующий небольшой взлом, который, кажется, делает свое дело:

(defun my//dired-store-link (orig-fun &rest args)
  (if (derived-mode-p 'dired-mode)
      (let ((file (dired-get-filename nil t)))
        (setf file (if file
                       (abbreviate-file-name (expand-file-name file))
                     default-directory))
        (let ((link (concat "file:" file))
              (desc (file-name-nondirectory file)))
          (push (list link desc) org-stored-links)
          (car org-stored-links)))
    (apply orig-fun args)))
(advice-add 'org-store-link :around #'my//dired-store-link)

В качестве бонуса, это не запрашивает описание, так как добавляемое описание не org-stored-linksравно нулю.

Мэтт Крамер
источник