Rientro automatico del codice elisp quando si aggiunge o si rimuove il codice prima di un blocco rientrato


18

Di 'che ho un codice elisp come:

(+ 2 3▮(+ 3
          4))

C'è un modo per rientrare automaticamente nel rientro dopo il cursore, quando aggiungo o rimuovo i simboli?

Quindi dopo aver premuto SPC 4 SPC, otterrei automaticamente:

(+ 2 3 4 ▮(+ 3
             4))

Posso fare questo manuale chiamando mark-sexpseguito da indent-region. Ci sono modi migliori per farlo?


Non penso che ci siano combinazioni di tasti predefinite convenienti, ma potresti crearne alcune tu stesso.
shosti,

Lo so, ma mi chiedo in particolare che ci siano modi migliori per farlo. Ad esempio, electric-indent-modeè molto meglio che mappare <return>sunewline-and-indent
Maciej Goszczycki il

Risposte:


14

Invece di mark-sexp+ indent-region, puoi premere C-M-q. Questo chiamerà indent-pp-sexp. Non automatico, ma un po 'meglio che dover invocare due comandi.

Oppure, se si utilizza paredit-mode, premere M-q. Ciò riproporrà l'intera definizione della funzione in cui ti trovi.


1
(add-hook 'post-self-insert-hook 'indent-pp-sexp)funziona sorprendentemente bene.
Maciej Goszczycki,

Sembra buono. Potrebbe essere costoso in alcune modalità, ma è comunque un approccio gradevole.
Dmitry,

Per gli utenti di Smartparens, puoi reindirizzare l'attuale defun con M-x sp-indent-defun. Lo vincolo a C-M-q.
Radon Rosborough,

15

Modalità rientro aggressiva

Poiché alcune persone lo hanno chiesto, ho trasformato questa risposta in un pacchetto .

Se hai configurato Melpa, puoi installarlo con

M-x package-install RET aggressive-indent

Consulta il file Leggimi per tutte le opzioni, ma il modo più semplice per attivarlo è:

(add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode)

La vecchia risposta

Quanto segue esegue il rientro automatico solo sui buffer elisp. Ha il vantaggio di lavorare anche quando cancelli o strappi cose (invece di scrivere semplicemente). È facile da aggiungere anche ad altre modalità.

Questa funzione indenterà qualunque espressione s sia attualmente presente nel punto. Se lo desideri, puoi associarlo a una chiave, ma prima vedi sotto.

(require 'cl-lib)

(defun endless/indent-defun ()
  "Indent current defun.
Do nothing if mark is active (to avoid deactivating it), or if
buffer is not modified (to avoid creating accidental
modifications)."
  (interactive)
  (ignore-errors
    (unless (or (region-active-p)
                buffer-read-only
                (null (buffer-modified-p)))
      (let ((l (save-excursion (beginning-of-defun 1) (point)))
            (r (save-excursion (end-of-defun 1) (point))))
        (cl-letf (((symbol-function 'message) #'ignore))
          (indent-region l r))))))

Questo hook lo farà in modo che questa funzione verrà eseguita dopo aver digitato qualsiasi cosa, ma solo nei buffer elisp. Questo dovrebbe mantenere tutto sempre rientrato.

(add-hook
 'emacs-lisp-mode-hook
 (lambda ()
   (add-hook 'post-command-hook
             #'endless/indent-defun nil 'local)))

Provalo! Funziona straordinariamente bene.

Inoltre, seguendo il suggerimento di @ holocronweaver nei commenti, puoi usare qualcosa di simile al seguente per i linguaggi di tipo c:

(define-key c++-mode-map ";"
  (lambda () (interactive)
    (insert ";")
    (endless/indent-defun)))

Sarebbe eccellente se questo rientra automaticamente nei messaggi di rientro automatico e nelle lingue meglio gestite che terminano con punti e virgola.
holocronweaver,

@holocronweaver certo, posso provarlo. Quale modalità principale ha messaggi di rientro? E qual è il problema con i punti e virgola?
Malabarba,

Tutte le modalità che ho provato sul trunk Emacs hanno prodotto messaggi di rientro, incluso elisp. Poiché i punti e virgola terminano una riga in molte lingue, fino a quando non si digita il punto e virgola la riga seguente salta come se facesse parte della riga corrente.
holocronweaver,

@holocronweaver Silenzia i messaggi. Grazie per segnalarlo.
Malabarba,

Grazie per la correzione! Una soluzione al problema del punto e virgola è di rientrare nei linguaggi c-mode solo quando si digita un punto e virgola.
holocronweaver,

3

Non conosco una soluzione preesistente, ma è possibile utilizzare post-self-insert-hookper realizzare questo da soli:

(defun my-indent-next-sexp ()
  (interactive)
  (mark-sexp)
  (indent-region))

(add-hook 'post-self-insert-hook 'my-indent-next-sexp)

Tuttavia, mi preoccuperei di potenziali problemi di prestazioni.


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.