Modificando o recuo de algumas formas do Emacs Lisp

8

Gostaria que alguns formulários do Emacs Lisp fossem recuados como o Common Lisp. Por exemplo, no Emacs Lisp, ifé recuado assim:

(if COND
    THEN
  ELSE)

enquanto eu preferiria assim:

(if COND
    THEN
    ELSE)

Eu poderia fazer isso:

(setq lisp-indent-function #'common-lisp-indent-function)

Mas isso afeta todas as formas, quebrando assim o recuo das macros do Emacs Lisp, como cl-letfe qualquer macro definida pelo usuário.

Elena
fonte

Respostas:

17

Responda:

Os símbolos para funções e macros têm uma lisp-indent-functionpropriedade que você pode definir com declareou no seu caso, uma vez que ifjá está definido, você pode apenas usar put.

Você pode ler sobre os possíveis valores de propriedade aqui:

M-: (info "(elisp) Indenting Macros") return

ifA configuração padrão é o 2que significa que o tratamento especial do segundo formulário é compensado.

Você pode alterar o valor da propriedade para 'defune todos os formulários do corpo serão alinhados.

(put 'if 'lisp-indent-function 'defun)

Melhor prática:

É importante observar que há uma razão para o estilo de indentação. ifno Elisp NÃO é como ifno Common Lisp.

Observe as diferentes assinaturas:

Lisp comum: (if TEST THEN &OPTIONAL ELSE)

Emacs Lisp: (if COND THEN ELSE...)

No Emacs lisp, você pode ter quantas formas após a condição desejar, mas apenas a primeira forma é a cláusula THEN, todas as outras formas fazem parte da cláusula ELSE.

Este é um ifformulário Elisp válido que não é válido no CL:

(if something
    (message "THEN")
  (message "all")
  (message "these")
  (message "run")
  (message "on")
  (message "ELSE"))

Isso mostra por que é importante que a cláusula THEN seja mais recuada, para que ela se destaque contra todas as formas ELSE.

Além de o recuo ser importante para a capacidade do usuário de analisar o código, ele também contraria os padrões de estilo aceitos do elisp. 99.99999% (calculado com cuidado) do código elisp que você encontrar usará exatamente o mesmo esquema de indentação padrão. Alterar o recuo ifpara seu próprio uso dificultará o trabalho em outras pessoas, e dificultará que outros trabalhem no seu.

Jordon Biondo
fonte
2

Na verdade, eu uso o recuo Common Lisp, com o recuo Elisp para if. Você pode personalizar algum código semelhante ao meu:

(setq lisp-indent-function 'common-lisp-indent-function)
(eval-after-load 'cl-indent
  `(progn
     (put 'cl-flet 'common-lisp-indent-function
          (get 'flet 'common-lisp-indent-function))
     (put 'cl-labels 'common-lisp-indent-function
          (get 'labels 'common-lisp-indent-function))
     (put 'if 'common-lisp-indent-function 2)))
abo-abo
fonte
Obrigado, mas isso exigiria que eu também corrigisse o recuo de todas as macros definidas pelo usuário. Prefiro seguir a rota oposta e corrigir apenas o recuo ifconforme executado por lisp-indent-function.
Elena
Eu tenho essa configuração há anos. Não existem outras macros necessárias para "corrigir". Lembre-se de colocar uma declaredeclaração em cada nova macro, o que é bom de qualquer forma.
abo-abo