emacs: помогите мне решить проблему порядка автозагрузки с помощью flymake и csharp

Как я могу доставить модуль, требующий исправления flymake, с минимальным временем запуска (=автозагрузка) и минимальным воздействием на emacs.el пользователя?

Я работаю над модулем flymake-for-csharp. Он работает с flymake, учит тому, как быть более гибким с файлами кода C#. Например, вместо простого make-файла flymake-for-csharp также может использовать файл .csproj или напрямую вызывать csc.exe.

Модуль работает нормально. Теперь я пытаюсь сделать его автозагрузку должным образом.

вот вызов.

Чтобы определить, какие языки будут обрабатываться flymake, flymake.el включает в себя список расширений файлов (.java, .cs, .c и т. д.), а также процедуры инициализации и очистки для каждого из этих языков. В файле flymake.el по умолчанию есть запись для C#, но, как я уже сказал, поведение C# по умолчанию недостаточно гибко. Чтобы сделать его более гибким, мне нужно заменить запись C# в списке flymake, чтобы она указывала на новую логику инициализации/очистки в модуле flymake-for-csharp. Я со мной?

Нет проблем с исправлением списка во время выполнения. Это выглядит так:

  (let (elt
        (csharp-entry nil)
        (masks flymake-allowed-file-name-masks))

    ;; Find the existing C# entry
    (while (consp masks)
      (setq elt (car masks))
      (if (string= "\\.cs\\'" (car elt))
          (setq csharp-entry elt))
      (setq masks (cdr masks)))

    ;;  remove the original entry for C# ...
    (if csharp-entry
        (setq flymake-allowed-file-name-masks
              (delete csharp-entry flymake-allowed-file-name-masks)))

    ;; Now add a new entry for C#, with the custom init and cleanup methods.
    (setq flymake-allowed-file-name-masks
          (cons
           '("\\.cs\\'" flymake-for-csharp-init flymake-for-csharp-cleanup)
           flymake-allowed-file-name-masks)))

Долгосрочное решение состоит в том, чтобы убедить авторов flymake и emacs принять логику, которая в настоящее время содержится в flymake-for-csharp. Тогда список получит более гибкие процедуры инициализации/очистки и ваш дядя Боб.

Но пока я хочу, чтобы flymake-for-csharp работал с существующим (встроенным) flymake.el. Вот в этом и проблема: как сделать автозагрузку flymake-for-csharp, при этом пропатчивая алист?

В идеале я бы хотел, чтобы emacs.el пользователя выглядел так:

(autoload 'flymake-for-csharp-init "flymake-for-csharp" nil nil)

...возможно, с небольшой секцией (eval-after-load ...

Но видите ли, функция flymake-for-csharp-init будет вызываться только после того, как список flymake будет исправлен, чтобы включить новую запись для C#.

Есть ли выход из этой ситуации с курицей и яйцом?


один подход, который я придумал, заключался в использовании (require 'flymake-for-csharp) вместо autoload. В этом модуле flymake-for-csharp запустите только логику исправления, а затем каким-то образом используйте автозагрузку для остальных функций. Будет ли это хорошей идеей? Потребует ли это, чтобы я доставлял flymake-for-csharp в 2 разных файлах?

Другой подход, о котором я подумал, заключался в использовании eval-after-load на flymake.el. В этом я мог бы обеспечить функцию исправления. Пара вопросов с этим:

  • Будет ли это работать, только если flymake загружается автоматически? Что происходит с логикой внутри eval-after-load для модуля, который уже загружен, когда eval'd (внешний) eval-after-load?

  • как мне это сделать, не затрагивая emacs.el пользователя?


Подводя итог, как я могу доставить модуль, требующий исправления flymake, с минимальным временем запуска (=автозагрузка) и минимальным воздействием на emacs.el пользователя?


person Cheeso    schedule 16.11.2010    source источник
comment
Понятия не имею, но то, что ты делаешь, кажется потрясающим, и я смело аплодирую.   -  person George Mauer    schedule 17.11.2010


Ответы (1)


Если я правильно понимаю, если пользователь добавит это к своему .emacs, это решит проблему:

;;;###autoload
(eval-after-load "flymake" '(code-that-patches-flymake-allowed-file-name-masks))
(autoload 'flymake-for-csharp-init "flymake-for-csharp" nil nil)

Теперь, если вы работаете с людьми, использующими ваш пакет, вы можете использовать трюк loaddefs.el, чтобы этот код автоматически загружался пользователем, поместив комментарий ;;;###autoload прямо перед строкой eval-after-load в вашем пакете, а затем пересобрав файл loaddefs.el.

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


Комментарий к вашему коду очистки, я считаю, что его можно упростить до:

(let ((csharpentry (assoc "\\.cs\\'" flymake-allowed-file-name-masks)))
  (when csharpentry
    (setcdr csharpentry '(flymake-for-csharp-init flymake-for-csharp-cleanup))))
person Trey Jackson    schedule 16.11.2010
comment
эй, продолжение... давайте позвоним в fn, который исправляет алист flymake-for-csharp-monkeypatch-flymake. предположим, я предоставляю эту fn в flymake-for-csharp.el и помечаю ее ;;;###autoload. Тогда пользователям нужно будет просто включить одну строку (eval-after-load "flymake" '(flymake-for-csharp-monkeypatch-flymake)) в свой .emacs? Это сведет к минимуму влияние на .emacs. Я думаю, это также подразумевает загрузку всего модуля flymake-for-csharp при загрузке flymake, в то время как ваше предложение откладывает загрузку модуля csharp, но, возможно, это нормально. Как вы думаете? - person Cheeso; 05.01.2011
comment
@Cheeso ;;;###autoload работает только в том случае, если у вас есть что-то для сборки файла loaddefs.el (см. ссылку в моем ответе для loaddefs.el trick. Итак, если у вас работает автозагрузка, я считаю, что вы правы. - person Trey Jackson; 05.01.2011