Чи є пакет або режим автоматичного вирівнювання для Emacs?


15

Бувають випадки, коли я редагую файли (наприклад, Маріонеткові маніфести), коли я хочу вирівняти вміст буфера на ходу. Наприклад, я знаю, що я можу використовувати align-regexpабо alignвирівняти такий код, якщо я вибрав:

# M-x align-regexp "=>" will line everything up nicely 
file { "/etc/foo":
  ensure => present,
  mode => "0666",
  source => "puppet:///modules/example/foo",
}

Але мені дуже хочеться, щоб це відбувалося на ходу, не вибираючи регіону чи цілого буфера. Чи є пакет або режим, який це зробить, чи це щось, що потрібно було б вбудувати в режим, який мене цікавить?

Редагувати: Я запитав про Puppet та CFEngine, оскільки саме це я кодую в більшість цих днів, і я сильно віддаю перевагу вирівняному тексту. Однак мені також було цікаво (і це не висловлювалось добре), щоб знати, чи вирівнювання під час руху є функцією, яка є загальною в режимах Emacs (переважно в режимах для мов програмування), або якщо більшість людей вирівнюють під час збереження або в деяких інший пункт.


Існує розширений регіон , який корисний для вибору послідовно більших областей.
bastibe

1
Чи можете ви описати більше того, що ви зазвичай вирівнюєте? Це просто знаки рівності та в ляльковому режимі? Ви можете змінити код у цій відповіді Emacs SE для автоматичного відступу від @Malabarba, щоб отримати те, що потрібно. Просто замініть indent-regionз align-to-equalsі визначити цю функцію , як (defun align-to-equals (begin end) (interactive "r") (align-regexp begin end "\\(\\s-*\\)=" 1 1 nil)); і emacs-lisp-mode-hookс puppet-mode-hook.
Каушал Моді

Відповіді:


5

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

(require 'cl-lib)

(defvar my--auto-align-overlays nil)
(make-variable-buffer-local 'my--auto-align-overlays)

(defun my-auto-align (beg end regexp)
  (interactive "r\nsRegexp: ")
  (let ((ol (make-overlay beg end)))
    (overlay-put ol 'evaporate t)
    (overlay-put ol 'my--auto-align-regexp regexp)
    (overlay-put ol 'modification-hooks '(my--auto-align-function))
    (push ol my--auto-align-overlays)
    (add-hook 'post-command-hook 'my--auto-align-pch nil t)))

(defun my--auto-align-function (ol &rest _args)
  (cl-pushnew ol my--auto-align-overlays)
  (add-hook 'post-command-hook 'my--auto-align-pch nil t))

(defun my--auto-align-pch ()
  (dolist (ol my--auto-align-overlays)
    (align-regexp (overlay-start ol) (overlay-end ol)
                  (concat "\\(\\s-*\\)" (overlay-get ol 'my--auto-align-regexp))
                  1 align-default-spacing))
  (setq my--auto-align-overlays nil)
  (remove-hook 'post-command-hook 'my--auto-align-pch))

Але якщо ви хочете, щоб він був повністю автоматичним, вам знадобиться знайти спосіб визначити, які регіони ви хочете автоматично вирівняти (а з якими повторно виражати), що складніше. Я здогадуюсь, ви можете надати кілька повторних виразів, а потім просканувати буфер на наявність послідовних рядків, які відповідають одному з цих регулярних виразів.


Раніше я не використовував накладки, але в керівництві Elisp, здається, йдеться про те, що вони змінюють зовнішній вигляд - я зрозумів це правильно? Якщо так, чи означає це, що ця відповідь змінює лише те, як виглядає буфер, а не власне вміст файлу після його збереження? (Це останнє, що я шукав, але змінити зовнішній вигляд було б цікавим варіантом.)
Святий Аардварк Ковролін

2
@SaintAardvarktheCarpeted Накладки зазвичай використовуються для зміни зовнішнього вигляду, але їх застосовність виходить за рамки цього. У цій відповіді (IIUC) накладки використовуються для позначення областей, які слід вирівняти (тому буфер дійсно змінюється, а не лише зовнішній вигляд). Функція my-auto-alignвикористовується для визначення цих накладок (позначте регіони, які потрібно вирівняти). Причина (я думаю), що Стефан переживає всю цю проблему, полягає в тому, що (на відміну від відступу), якщо ви просто спробуєте вирівняти весь буфер, ви отримаєте небажані результати, тому вам потрібно вирівняти шматки за раз.
Малабарба

3

Ляльковий режим передбачає puppet-align-block. Ви можете домовитись, щоб ця функція була викликана автоматично, наприклад, додавши її post-command-hookлокально (не перевірено):

(defun puppet-auto-align ()
  (unless (puppet-in-string-or-comment-p)
    (puppet-align-block)))

(define-minor-mode puppet-auto-align-mode
  :init-value nil
  :keymap nil
  :lighter "PAl"
  :group 'puppet-lint
  (if puppet-auto-align-mode
      (add-hook 'post-command-hook #'puppet-auto-align nil 'local)
    (remove-hook 'post-command-hook #'puppet-auto-align 'local)))

(add-hook 'puppet-mode-hook #'puppet-auto-align-mode)

Зауважте, що є вагомі причини цього не робити. Це не особливо розумно, і замінить будь-яке ручне вирівнювання, яке ви можете зробити де завгодно, що зламається особливо погано, якщо автоматичне вирівнювання не працюватиме для якогось більш складного коду лялечки.

Отже, виступаючи як підтримувач режиму ляльок - я рекомендую проти цього, і ми не допоможемо вам або приймемо звіти про помилки, якщо ви використовуєте цей код.

Крім того, для великих блоків ресурсів це може бути повільним, тому, ймовірно, ви хочете використовувати таймер простою замість post-command-hookбезпосередньо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.