Mover formulário para cima e para baixo no modo paredit

13

Eu tenho usado a Edição Estrutural do cursive (um modo pareditado para Intellij e Cursive) e encontrei um bom comando lá chamado move form-up (e para baixo).

Mover formulário para cima faz isso (este |é o ponto):

(+ 1 |(+ 2 3) 4) => (+ (+ 2 3) 1 4)

e Mover formulário para baixo é análogo:

(+ 1 |(+ 2 3) 4) => (+ 1 4 (+ 2 3))

É possível fazer isso no modo paredit do Emacs? Eu acho que não está no conjunto de parênteses básico (pelo menos não está descrito nesta folha de dicas)

Rodrigo Flores
fonte
Agradável. Agora é uma operação que eu poderia me ver fazendo.
PythonNut
2
FWIW, pelo menos para os dois exemplos que você mostra, plain C-M-tfaz a mesma coisa. Mas acho que o que você quer dizer é que a mesma forma continua sendo movida, em vez de trocar o progresso pelo próximo par de sexps.
Desenhou

Respostas:

13

Como o @Drew sugeriu, C-M-tfaz o que você quer. A regra é assim:

  • Coloque o ponto no meio de dois sexps.
  • Pressione C-M-t(que é executado transpose-sexp).
  • O sexp esquerdo é sempre movido para a direita junto com point. Isso é muito importante , caso contrário você ficará confuso sem fim.

Ou, você pode simplesmente pensar que isso não é transposição, mas simplesmente para avançar, você precisa colocar um ponto após o sexp que deseja mover.

No entanto, existe um conveniente: quando você deseja transpor o sexp esquerdo para trás, você usa o mesmo, C-M-tmas é fornecido com um argumento de prefixo negativo e isso é inconveniente. Outra questão é que esse ponto não segue o sexp esquerdo transposto para trás . Para resolver esse problema, criamos uma versão reversa de transpose-sexps:

(defun reverse-transpose-sexps (arg)
  (interactive "*p")
  (transpose-sexps (- arg))
  ;; when transpose-sexps can no longer transpose, it throws an error and code
  ;; below this line won't be executed. So, we don't have to worry about side
  ;; effects of backward-sexp and forward-sexp.
  (backward-sexp (1+ arg))
  (forward-sexp 1))

Em seguida, vincule-o ao C-M-yque está ao lado C-M-te é livre no Emacs padrão.

(global-set-key (kbd "C-M-y") 'reverse-tranpose-sexps)

Aqui está uma demonstração; você notará que (MY-SEXP1)está à esquerda o tempo todo para avançar / retroceder:

insira a descrição da imagem aqui

Tu Do
fonte
5

É possível fazer isso com lispy , que é uma forma avançada de paredit-mode.

Para o seu caso de uso:

  • w se move para cima
  • s desce

A única coisa é que o cursor precisa estar em paren, como está no seu exemplo:

(+ 1 |(+ 2 3) 4)

Você também pode mover vários sexps de uma só vez com we s, se os marcar com uma região. Veja a documentação para mais informações.

abo-abo
fonte
;; Existe uma maneira de usar apenas esses dois comandos? ;; Eu pareço perder "M-left" e "M-right" ao fazê-lo: `(add-hook 'clojure-mode-hook (lambda () (modo lispy 1)) (local-set-key (kbd" M - <up> ") 'lispy-move-up) (chave de configuração local (kbd" M- <down> ")' lispy-move-down))` `
nha
1

Aqui está outro comando (da biblioteca misc-cmds.el) que faz praticamente o que você solicita. Basta vinculá-lo a uma única chave ( C-M-tou qualquer outra coisa). Use-o para mover um sexp para frente e para trás repetidamente.

Um prefixo negativo arg transpõe para trás, como transpose-sexp, mas também deixa point pronto para fazer outra transposição para trás. E ao repetir, um prefixo negativo arg apenas inverte a direção.

Então, se você ligar o comando para, digamos, C-oe, em seguida move o sexp que está à esquerda do ponto à direita três vezes, em seguida, para a esquerda duas vezes, depois para a direita uma vez.C-o C-o C-o C-- C-o C-o C-- C-o

Um prefixo numérico arg tem efeito apenas no primeiro uso, ou seja, não ao repetir - ao repetir, o movimento é sempre um sexp por vez.

(defun reversible-transpose-sexps (arg)
  "Reversible and repeatable `transpose-sexp'.
Like `transpose-sexps', but:
 1. Leaves point after the moved sexp.
 2. When repeated, a negative prefix arg flips the direction."
  (interactive "p")
  (when (eq last-command 'rev-transp-sexps-back) (setq arg  (- arg)))
  (transpose-sexps arg)
  (unless (natnump arg)
    (when (or (> emacs-major-version 24)
              (and (= emacs-major-version 24)  (> emacs-minor-version 3)))
      (backward-sexp (abs arg)) (skip-syntax-backward " ."))
    (setq this-command  'rev-transp-sexps-back)))

(Nota: O comportamento de transpose-sexpsmudou em 24.4, daí o teste de versão aqui. Antes de 24.4, o ponto acabou no lugar certo para continuar (por exemplo, repita). Começando com 24.4, o ponto está no lugar errado para isso. uma regressão ou adiciona um recurso útil ou corrige algum outro bug provavelmente está nos olhos de quem vê. ;-) Arquivei o bug # 20698 do Emacs para isso, agora.)

Desenhou
fonte