Полиморфные обратные вызовы в Emacs / Elisp - PullRequest
8 голосов
/ 25 ноября 2011

Какой идиоматический способ реализации полиморфных обратных вызовов в elisp?

В частности, предположим, что у меня есть второстепенный режим с функцией, которая выполняет определенную операцию, а затем вызывает другую функцию. Эта вторая функция должна иметь различную реализацию в зависимости от того, содержит ли текущий буфер файл C ++ или файл Java.

В качестве альтернативы, предположим, я хочу перегрузить переменные, а не функции. Например, я хочу вызвать некоторый внешний исполняемый файл, и один из переданных ему аргументов отличается в зависимости от того, имеет ли текущий буфер файл C ++ или файл Java. Я хочу иметь возможность построить командную строку в обобщенной функции и заменить один аргумент в зависимости от содержимого буфера. make-variable-buffer-local правильный подход? В какой момент (и по какому механизму) эти локальные переменные изначально должны быть установлены?

Ответы [ 3 ]

5 голосов
/ 25 ноября 2011

Я думаю, у вас есть множество подходов.Некоторые опции, которые приходят на ум для вашей функции обратного вызова:

  1. Локальные переменные буфера, как вы упомянули.

    Как вы их установите, будет зависеть от вашего варианта использования, но вы могли бы реализовать определенные ловушки основного режима или after-change-major-mode-hook для общего случая.

    make-variable-buffer-local, безусловно, правильный подход, если вы хотите, чтобы переменная всегда была локальной для буфера.

  2. Alist отображает основные режимы на связанные с ними функции.

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

  3. Просто сгенерируйте имя функции на основе имени основного режима, вызывая его, если такая функция существует.

Во всех случаях есть вероятность, что вы будете использовать funcall или apply для запуска выбранной функции.

Номера 1 и 2 также будут относиться ко второй части вашего вопроса.

1 голос
/ 25 ноября 2011

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

http://lists.gnu.org/archive/html/gnu-emacs-sources/2011-03/msg00001.html

1 голос
/ 25 ноября 2011

Если вы редактируете файл C ++ или Java, этот буфер должен быть в c++-mode или java-mode соответственно. Таким образом, вы можете сделать что-то вроде следующего:

(defun function1 ()
  (interactive)
  ;; put your generic code here
  (cond ((string= major-mode "c++-mode")
     (function2-cpp))
    ((string= major-mode "java-mode")
     (function2-java))
    (t (message "I don't know what mode this is"))))

(defun function2-cpp ()
  (message "this is cpp mode"))

(defun function2-java ()
  (message "this is java mode"))
...