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.