Automatyczne ponowne wcięcie kodu elisp podczas dodawania lub usuwania kodu przed wciętym blokiem


18

Powiedz, że mam kod elisp, taki jak:

(+ 2 3▮(+ 3
          4))

Czy istnieje sposób automatycznego ponownego wcięcia seksu za kursorem, gdy dodam lub usunę symbole?

Po naciśnięciu SPC 4 SPCautomatycznie uzyskałbym:

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

Mogę wykonać tę instrukcję, dzwoniąc, mark-sexpa następnie indent-region. Czy są na to lepsze sposoby?


Nie sądzę, że istnieją jakieś wygodne domyślne skróty klawiszowe, ale możesz je łatwo stworzyć samodzielnie.
shosti

Wiem, ale zastanawiam się, czy są na to lepsze sposoby. Na przykład, o electric-indent-modeile lepiej niż mapowanie <return>donewline-and-indent
Maciej Goszczycki

Odpowiedzi:


14

Zamiast mark-sexp+ indent-regionmożesz nacisnąć C-M-q. To zadzwoni indent-pp-sexp. Nie automatyczny, ale nieco lepszy niż konieczność wywoływania dwóch poleceń.

Lub jeśli używasz paredit-mode, naciśnij M-q. To ponownie oprze się na całej definicji funkcji, w której się znajdujesz.


1
(add-hook 'post-self-insert-hook 'indent-pp-sexp)działa zaskakująco dobrze.
Maciej Goszczycki

Wygląda dobrze. W niektórych trybach może to być kosztowne, ale mimo to jest to przyjemne podejście.
Dmitry

W przypadku użytkowników Smartparens możesz ponownie włączyć bieżący defun M-x sp-indent-defun. Wiążę to z C-M-q.
Radon Rosborough

15

Tryb agresywnego wcięcia

Ponieważ niektórzy o to prosili, zamieniłem tę odpowiedź w pakiet .

Jeśli masz skonfigurowaną Melpę, możesz ją zainstalować za pomocą

M-x package-install RET aggressive-indent

Zobacz plik Readme dla wszystkich opcji, ale najprostszym sposobem na jego włączenie jest:

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

Stara odpowiedź

Następujące automatyczne wcięcie dotyczy tylko buforów elisp. Ma tę zaletę, że działa również podczas wymazywania lub szarpania (zamiast pisania). Łatwo jest również dodać do innych trybów.

Ta funkcja wcina dowolne wyrażenie s, w którym znajduje się obecnie punkt. Możesz powiązać go z kluczem, jeśli chcesz, ale najpierw zobacz poniżej.

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

Ten haczyk sprawi, że ta funkcja będzie uruchamiana po wpisaniu czegokolwiek, ale tylko w buforach elisp. To powinno sprawić, że wszystko będzie zawsze wcięte.

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

Spróbuj! Działa wyjątkowo dobrze.

Ponadto, postępując zgodnie z sugestią @ holocronweaver w komentarzach, możesz użyć czegoś takiego jak dla języków podobnych do c:

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

Byłoby doskonale, gdyby to uciszyło automatyczne wcięcia i lepiej obsługiwało języki kończące się średnikami.
holocronweaver

@holocronweaver na pewno mogę tego spróbować. Który tryb główny ma wiadomości z wcięciami? Na czym polega problem ze średnikami?
Malabarba

Wszystkie tryby, które wypróbowałem na pniu Emacsa, generowały wcięcia, w tym elisp. Ponieważ średniki kończą wiersz w wielu językach, dopóki nie wpiszesz średnika, następna linia przeskakuje tak, jakby była częścią bieżącego wiersza.
holocronweaver

@holocronweaver Wyciszono wiadomości. Dzięki za zwrócenie na to uwagi.
Malabarba

Dzięki za poprawkę! Jednym z rozwiązań problemu średnika jest wcięcie tylko w językach trybu c, gdy jest wpisany średnik.
holocronweaver

3

Nie znam wcześniejszego rozwiązania, ale możesz post-self-insert-hookto zrobić samodzielnie:

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

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

Martwiłbym się jednak potencjalnymi problemami z wydajnością.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.