Как превратить (неинтерактивную) функцию в команду (интерактивную функцию) в Emacs-LISP? - PullRequest
2 голосов
/ 01 ноября 2019

Я хочу вызвать функцию markdown-back-to-heading, которая является родной в режиме уценки в Emacs. Я понимаю, что interactive превращает неинтерактивные функции интерактивными или формально функции в команды :

Специальная форма: интерактивный arg-дескриптор

Эта специальная форма объявляет, что функция является командой, и поэтому ее можно вызывать в интерактивном режиме (через Mx или путем ввода связанной с ней последовательности клавиш).

Я пытался:

(define-key markdown-mode-map (kbd "C-c C-h") 'markdown-back-to-heading)

Это выдает ошибку: Wrong type argument: commandp, markdown-back-to-heading.

Итак, я обернул его интерактивной функцией, и она работает:

(defun my-markdown-back-to-heading ()
  "Wrap function to be called interactively."
  (interactive)
  (markdown-back-to-heading))

(define-key markdown-mode-map (kbd "C-c C-h") 'my-markdown-back-to-heading)

Есть ли лучший способ превратить встроенную функцию в интерактивную команду?

Ответы [ 3 ]

2 голосов
/ 02 ноября 2019

В качестве альтернативы вы можете использовать символьное свойство interactive-form.

Подробнее см. Ch i g (elisp)Using Interactive

Вот простой пример:

;; Enable M-x kill-process (to kill the current buffer's process).
;; (This is not normally a command, but it is useful as one.)
(put 'kill-process 'interactive-form '(interactive))

Более сложная версия, которую я на самом деле использую:

(put 'kill-process 'interactive-form
     '(interactive
       (let ((proc (get-buffer-process (current-buffer))))
         (if (process-live-p proc)
             (unless (yes-or-no-p (format "Kill %S? " proc))
               (error "Process not killed"))
           (error (format "Buffer %s has no process" (buffer-name))))
         (list proc))))
2 голосов
/ 01 ноября 2019

Если вы хотите сделать markdown-back-to-heading интерактивным, у вас есть несколько хороших вариантов:

  • подайте отчет об ошибке, чтобы сделать его апстримом. Включение патча вместе с отчетом об ошибке может помочь ускорить процесс.
  • используйте совет, такой как:

    (advice-add 'markdown-back-to-heading :before
                (lambda () (interactive "^") nil))
    

Если вместо этого вы хотитечтобы улучшить интерактивность функции, например, если вы хотите поддерживать shift-selection , вы можете добавить интерактивный код ^ с (interactive "^") вместо (interactive), чтобы Emacs знал, что это навигациякоманда (и, следовательно, если вы используете его со сдвигом-привязкой, он выберет соответствующий текст). Вот страница руководства со списком интерактивных кодов и другими вариантами интерактивности на странице руководства, которую вы упомянули .

0 голосов
/ 02 ноября 2019

Следуя предложению @ Stefan, я подал заявку на выпуск Github , а представил патч , который добавляет строку (interactive "P") в исходный код:

(defun markdown-back-to-heading (&optional invisible-ok)
  "Move to previous heading line, or beg of this line if it's a heading.
Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
  (interactive "P")
  (markdown-move-heading-common #'outline-back-to-heading invisible-ok))

и теперь я могу связать его с помощью

(define-key markdown-mode-map (kbd "C-c C-h") 'markdown-back-to-heading)

Я установил markdown-mode из MELPA, поэтому для этого изменения потребовалось удаление пакета , затем эти шаги из репозитория README. Я разветвил репо и локально клонировал репо:

git clone git@github.com:miguelmorin/markdown-mode

и добавил эти строки для инициализации Emacs:

(add-to-list 'load-path (expand-file-name "~/code/markdown-mode"))

(autoload 'markdown-mode "markdown-mode"
   "Major mode for editing Markdown files" t)
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))

(autoload 'gfm-mode "markdown-mode"
   "Major mode for editing GitHub Flavored Markdown files" t)
(add-to-list 'auto-mode-alist '("README\\.md\\'" . gfm-mode))

(require 'markdown-mode)
...