2016-08-05 4 views
4

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

(defmacro align-by (name doc regex) 
    "Alignment function factory." 
    (declare (indent 1)) 
    (let ((fn (intern name))) 
    `(defun ,fn (start end) 
     ,doc 
     (interactive "r") 
     (align-regexp start end ,regex)))) 

(align-by "align-backslash" 
    "Align backslashes at end of line in region." 
    "\\(\\s-*\\)\\\\$") 

Я знаю, что могу это написать, но могу ли я избежать необходимости писать это для каждой функции?

;;;###autoload (autoload 'align-backslash "this-file") 
+1

Какой сценарий вам понадобится? Я с трудом думаю о чем-то, что не будет разрешено просто автозагрузкой самого макроса, но я предполагаю, что это просто над моей головой, поэтому я искренне любопытен. – Jack

ответ

1

Это не ясно, где макрос будет подобрать имя файла, который будет Автозагружаемый - не передать имя файла макроса, в настоящее время.

Предполагая, что имя файла происходит из файла, который посещается, когда макрос расширяется, это будет сделать это:

(defmacro align-by (name doc regex) 
    "Alignment function factory." 
    (declare (indent 1)) 
    (let ((fn (intern name))) 
    `(progn 
     ,(and (buffer-file-name) 
      `(autoload ',name ,(buffer-file-name))) 
     (defun ,fn (start end) 
     ,doc 
     (interactive "r") 
     (align-regexp start end ,regex))))) 

Тестирование:

(macroexpand '(align-by "align-backslash" 
      "Align backslashes at end of line in region." 
      "\\(\\s-*\\)\\\\$")) 

C-u C-x C-e показывает, что это дает это когда текущий буфер не посещает файл:

(progn 
    (autoload '"align-backslash" nil) 
    (defun align-backslash 
     (start end) 
    "Align backslashes at end of line in region." 
    (interactive "r") 
    (align-regexp start end "\\(\\s-*\\)\\\\$"))) 

И это gi VES это, когда буфер посещает файл foo.el, где ".../foo.el" действительно абсолютное имя файла, для foo.el:

(progn 
    (autoload '"align-backslash" ".../foo.el") 
    (defun align-backslash 
     (start end) 
    "Align backslashes at end of line in region." 
    (interactive "r") 
    (align-regexp start end "\\(\\s-*\\)\\\\$"))) 
+0

Вам не нужно развернуть макросы: 'autoload' вызывается вместе с определением' defun' при вызове '(align-by" align-backslash "...)'. – artscan

1

Код, который поднимает ;;;###autoload печенье действительно расширить макросы перед тем, глядя на код, так что вы должны сможете просто разместить cookie ;;;###autoload прямо перед выражением (align-by ...) и получить правильную автозагрузку, размещенную в файле <foo>-autoloads.el.

Проблема заключается в том, что ваш макрос, вероятно, не будет определен в момент создания автозагрузок, поэтому на самом деле макрообмена не произойдет. Может быть, M-x report-emacs-bug в порядке.

1

В EMACS руководства mentioned

Если вы пишете определение функции с необычным макросом, который не является одним из известных и признанных методов определения функций, использование обычного волшебной автозагрузки комментария будет копировать все определения в loaddefs.el. Это нежелательно. Вы можете поставить нужную автозагрузку вызова в loaddefs.el вместо написав это:

;;;###autoload (autoload 'foo "myfile") 
(mydefunmacro foo 
    ...) 

Вашего align-by подобен mydefunmacro в ручном примере. Это неизвестный метод определения функции, и он не поддерживается механизмом autoload.

Итак, есть три варианта:

  1. Продлить список поддерживаемых типов (defun, defmacro, cl-defun, defclass ...) ваши специальные макросы. Затем вы можете использовать простой ;;;###autoload «декоратор».
  2. Придумайте свой собственный механизм анализа «myfile» (без выполнения) и «loaddefs», заполняемый необходимыми определениями автозагрузки.
  3. Используйте более сложную конструкцию (с (autoload 'align-backslash "myfile")) как функция defintion способ.

Если переписать align-by так (без intern):

(defmacro align-by-defun (name doc regex) 
    "Alignment function factory." 
    (declare (indent 1)) 
    `(defun ,name (start end) 
    ,doc 
    (interactive "r") 
    (align-regexp start end ,regex))) 

;;;###autoload (autoload 'align-backslash "myfile") 
(align-by-defun align-backslash 
    "Align backslashes at end of line in region." 
    "\\(\\s-*\\)\\\\$") 

вы можете увидеть, что align-by только метод определения функции (например, cl-defun).

+0

Нет, вы можете использовать 'align-by-defun' как фабрику функций. Это не имеет значения. Но у вас есть полный список ваших функций (выравнивание-обратная косая черта, ...) заблаговременно? Или он будет создан динамически? – artscan

+0

Вы хотите, чтобы у всех из них была ссылка 'this-file' (для определения' align-by') в буфере справки или что-то еще? – artscan