Czy jest dostępny pakiet lub tryb automatycznego wyrównywania dla Emacsa?

15

Są chwile, kiedy edytuję pliki (na przykład manifesty marionetkowe), w których chcę wyrównać zawartość bufora w locie. Na przykład wiem, że mogę używać align-regexplub alignwyrównywać kod w ten sposób, o ile go wybrałem:

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

Ale tak naprawdę chcę, aby stało się to w locie - bez konieczności wybierania regionu lub całego bufora. Czy istnieje pakiet lub tryb, który to zrobi, czy jest to coś, co musiałoby być wbudowane w tryb, który mnie interesuje?

Edycja: Pytałem o Puppet i CFEngine, ponieważ w większości przypadków to właśnie koduję i zdecydowanie preferuję wyrównany tekst. Byłem jednak ciekawy (i nie wyraziłem tego dobrze), czy wyrównanie w locie jest cechą powszechną w trybach Emacsa (głównie w trybach języków programowania), czy też większość ludzi dostosowuje się podczas zapisywania lub w niektórych inny punkt.

Święty Aardvark Wykładzina
źródło
Istnieje region rozwinięcia , który jest przydatny do wybierania kolejno większych zakresów.
bastibe
1
Czy możesz opisać więcej na temat tego, co zwykle wyrównywałbyś? Czy to tylko znaki równości w trybie marionetkowym? Możesz zmodyfikować kod w tej odpowiedzi Emacsa SE na automatyczne wcięcie przez @Malabarba, aby uzyskać to, czego chcesz. Wystarczy wymienić indent-regionsię align-to-equalsi określają tę funkcję jak (defun align-to-equals (begin end) (interactive "r") (align-regexp begin end "\\(\\s-*\\)=" 1 1 nil)); i emacs-lisp-mode-hookz puppet-mode-hook.
Kaushal Modi

Odpowiedzi:

5

Jeśli chcesz oznaczyć region do automatycznego wyrównania, prawdopodobnie nie jest to zbyt trudne z czymś takim:

(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))

Ale jeśli chcesz, aby była w pełni automatyczna, musisz znaleźć sposób, aby scharakteryzować, które regiony chcesz automatycznie wyrównać (i z jakim wyrażeniem regularnym), co jest trudniejsze. Myślę, że możesz podać kilka wyrażeń regularnych, a następnie zeskanować bufor w poszukiwaniu kolejnych wierszy pasujących do jednego z tych wyrażeń regularnych.

Stefan
źródło
Nie korzystałem wcześniej z nakładek, ale instrukcja Elisp wydaje się mówić, że zmieniają wygląd - czy zrozumiałem to, prawda? Jeśli tak, czy to oznacza, że ​​ta odpowiedź zmienia jedynie wygląd bufora, a nie faktyczną zawartość pliku po jego zapisaniu? (To był ten ostatni, którego szukałem, ale zmiana wyglądu byłaby interesującą opcją.)
Saint Aardvark the
2
@SaintAardvarktheCarpeted Overlays są powszechnie używane do zmiany wyglądu, ale ich zastosowanie wykracza poza to. W tej odpowiedzi (IIUC) nakładki służą do oznaczania obszarów, które mają zostać wyrównane (tak więc bufor jest naprawdę zmieniany, a nie tylko wygląd). Funkcja my-auto-alignsłuży do definiowania tych nakładek (zaznacz regiony, które chcesz wyrównać). Powodem (chyba) Stefana jest ten cały problem, ponieważ (w przeciwieństwie do wcięć), jeśli po prostu spróbujesz wyrównać cały bufor, uzyskasz niepożądane wyniki, więc musisz wyrównać kawałki na raz.
Malabarba
3

Tryb lalek zapewnia puppet-align-block. Możesz ustawić automatyczne wywoływanie tej funkcji, np. Dodając ją post-command-hooklokalnie (nieprzetestowane):

(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)

Pamiętaj jednak, że istnieje dobry powód, aby tego nie robić. Nie jest to szczególnie sprytne i zastąpi ręczne wyrównanie, które możesz zrobić w dowolnym miejscu, co zepsuje się szczególnie źle, jeśli automatyczne wyrównanie nie zadziała w przypadku bardziej skomplikowanego kodu Puppet.

Dlatego - mówiąc jako opiekun trybu lalek - odradzam, a jeśli nie używasz tego kodu, nie pomożemy ci ani nie przyjmiemy zgłoszeń błędów.

Ponadto w przypadku dużych bloków zasobów może być powolny, więc prawdopodobnie chcesz użyć bezczynnego timera zamiast post-command-hookbezpośrednio.

księżycowy
źródło