EMACS: Como avaliar a menor expressão S em que o cursor está ou a seguinte expressão S
-
24-09-2019 - |
Pergunta
Qual é uma boa maneira de avaliar o (+ 100 (+ 100 100))
parte em
(+ (+ 1 2) (+ 100 (+ 100 100)))
?
Por enquanto, faço isso por CX CE, o que significa que preciso localizar os parênteses finais, o que é difícil na maioria dos casos. Options > Paren Matching Highlighting
Ajuda, mas ainda preciso mover o cursor em direção aos parênteses finais até que a correspondência destacada seja o parêntese inicial.
Uma maneira seria ter a versão reversa do CX CE, para que eu possa colocar o cursor nos parênteses iniciais como este:
(+ (+ 1 2) |(+ 100 (+ 100 100)))
e depois pressione a ordem de chave apropriada.
Ou eu poderia colocar o cursor dentro da expressão, mas não dentro de expressões menores::
(+ (+ 1 2) (+ | 100 (+ 100 100)))
e pressione uma chave de chave. Porque o objetivo de um alvo é mais fácil se o alvo for grande.
Como posso fazer esse comando? Ou já existe um fornecido?
Sidenote: Cursor do bar e cursor de caixa
Emacsers que usam o Cursor da caixa (padrão) podem se perguntar onde estou colocando o cursor com a notação de barra acima. No Emacs, você pode escolher o cursor da caixa ou o cursor de barra, (bar-cursor-mode t)
. Quando o cursor da barra está entre as letras A e B, o cursor da caixa está em B. Portanto, a barra é a parede esquerda da caixa.
Aliás, o conceito de cursor de bar é útil de alguma maneira incomum: a prática de itentar do index1 para o índice2-1 na programação surpreende iniciantes. Ajuda a imaginar index1 e index2 como barras indicadoras (paredes esquerdas) em vez de caixas.
Solução
Vincule uma chave para um ou ambos:
(defun eval-next-sexp ()
(interactive)
(save-excursion
(forward-sexp)
(eval-last-sexp nil)))
(defun eval-surrounding-sexp (levels)
(interactive "p")
(save-excursion
(up-list (abs levels))
(eval-last-sexp nil)))
Relacionado tangencialmente, eu recomendo paredit Para trabalhar com expressões S. Os comandos e encadernações de edição da estrutura tornam a edição S-Expressões uma brisa. Liga c-down a up-list
, para que eval-surrounding-sexp
Acima é quase exatamente o mesmo que C-down CX CE (a única diferença é que a função usa save-excursion
para impedir o movimento).
Outras dicas
Você pode escrever um comando assim:
(require 'thingatpt)
(defun eval-sexp-at-or-surrounding-pt ()
"evaluate the sexp following the point, or surrounding the point"
(interactive)
(save-excursion
(forward-char 1)
(if (search-backward "(" nil t)
(message "%s" (eval (read-from-whole-string (thing-at-point 'sexp)))))))
Dentro Pingentes de gelo Existe uma maneira geral de fazer o que você deseja.
Por padrão, no minibuffer M-. está ligado a um comando que insere texto (ou próximo) ponto no minibuffer (não entra ou faz mais com ele; apenas insere).
Você pode, por exemplo, usar M-: Para avaliar um Lisp Sexp, e então você usa M-. Para pegar um sexo em/próximo ponto.
Se você repetir M-. Em seguida, ele cai o que apenas agarrou e pega algum outro tipo de coisa (texto) em/próximo ponto e insere isso. Por padrão, ele percorre esse tipo de coisa, em ordem:
uma. Um símbolo Lisp ou nome do arquivo.
b. A região ativa (texto selecionado) ou uma palavra.
c. A lista mais imediata.
d. A próxima maior lista.
e. A próxima maior lista.
f. Qualquer arquivo ou url da função ffap-guesser
suposições.
g. Qualquer que seja a função thing-at-point-url-at-point
suposições.
O que isso significa para o seu exemplo de (+ (+ 1 2) (+ 100 (+ 100 100)))
?
Se o ponto é antes do 1
do segundo a pouca 100
, por exemplo, esses são os sexps que são inseridos consecutivamente no minibuffer quando você bate M-. repetidamente, em ordem:
uma. +
b. 100
c. (+ 100 100)
d. (+ 100 (+ 100 100))
e. (+ (+ 1 2) (+ 100 (+ 100 100)))
?
Então, para inserir as maiores listas de anexo que você faria MILÍMETROS-. M-. M-. M-. M-., isto é, atingido M-. cinco vezes.
Para esse comportamento, em particular para a captura precisa das listas, você também precisa da biblioteca Coisa no ponto+.
Há um embutido eval-defun
. Está vinculado por padrão para C-M-x. É semelhante ao que você deseja, mas Evalals o Defun de nível superior. Talvez você possa adaptar isso.