Esiste un pacchetto o una modalità di allineamento automatico per Emacs?


15

Ci sono momenti in cui sto modificando i file (ad esempio i manifest di Puppet) in cui voglio allineare al volo i contenuti del buffer. Ad esempio, so che posso usare align-regexpo alignallineare il codice in questo modo, purché sia ​​selezionato:

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

Ma quello che voglio davvero è che questo accada al volo , senza dover selezionare una regione o l'intero buffer. C'è un pacchetto o una modalità che lo farà, o è qualcosa che dovrebbe essere integrato nella modalità che mi interessa?

Modifica: ho chiesto informazioni su Puppet e CFEngine, poiché è quello che codifico in questi giorni e ho una forte preferenza per il testo allineato. Tuttavia, ero anche curioso (e non ho espresso così bene) di sapere se l'allineamento al volo è una caratteristica comune nelle modalità Emacs (principalmente nelle modalità per i linguaggi di programmazione) o se la maggior parte delle persone si allinea durante il salvataggio o in alcuni altro punto.


Esiste una regione di espansione , utile per selezionare ambiti successivamente più grandi.
bastibe,

1
Puoi descriverci di più su ciò che di solito allineare? Sono solo segni uguali e in modalità fantoccio? Puoi modificare il codice in questa risposta Emacs SE per il rientro automatico di @Malabarba per ottenere ciò che desideri. Sostituisci semplicemente indent-regioncon align-to-equalse definisci questa funzione come (defun align-to-equals (begin end) (interactive "r") (align-regexp begin end "\\(\\s-*\\)=" 1 1 nil)); e emacs-lisp-mode-hookcon puppet-mode-hook.
Kaushal Modi,

Risposte:


5

Se desideri contrassegnare una regione per l'allineamento automatico, probabilmente non è troppo difficile fare qualcosa come:

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

Ma se vuoi che sia completamente automatico, dovresti trovare un modo per caratterizzare quali regioni vuoi allineare automaticamente (e con quale regexp), che è più difficile. Immagino che potresti fornire alcune regexps e quindi scansionare il buffer per le righe consecutive che corrispondono a una di quelle regexps.


Non ho mai usato sovrapposizioni prima, ma il manuale Elisp sembra dire che sono per alterare l'aspetto - ho capito bene? In tal caso, ciò significa che questa risposta modifica solo l'aspetto del buffer, anziché il contenuto effettivo del file una volta salvato? (È l'ultimo che stavo cercando, ma cambiare aspetto sarebbe un'opzione interessante.)
Saint Aardvark the Carpeted

2
Le sovrapposizioni @SaintAardvarktheCarpeted sono comunemente usate per alterare l'aspetto, ma la loro applicabilità va oltre. In questa risposta (IIUC), le sovrapposizioni vengono utilizzate per contrassegnare le regioni che devono essere allineate (quindi il buffer viene realmente modificato, non solo l'aspetto). La funzione my-auto-alignviene utilizzata per definire questi overlay (contrassegnare le regioni che si desidera allineare). Il motivo (penso) Stefan sta attraversando tutti questi problemi è che (a differenza del rientro) se provi ad allineare l'intero buffer, otterrai risultati indesiderati, quindi devi allineare i pezzi alla volta.
Malabarba,

3

Modalità Puppet fornisce puppet-align-block. È possibile disporre che questa funzione venga chiamata automaticamente, ad esempio aggiungendola a post-command-hooklivello locale (non testato):

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

Nota però che c'è una buona ragione per non farlo. Non è particolarmente intelligente e sovrascriverà qualsiasi allineamento manuale che potresti fare ovunque, il che si interromperà particolarmente male, se l'allineamento automatico non funziona per un codice Puppet più contorto.

Quindi, parlando come manutentore della modalità fantoccio, ti sconsiglio e non ti aiuteremo né accetteremo segnalazioni di bug, se stai usando questo codice.

Inoltre, per blocchi di risorse di grandi dimensioni, potrebbe essere lento, quindi probabilmente si desidera utilizzare un timer di inattività anziché post-command-hookdirettamente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.