Recurso de pesquisa / substituição para troca de texto

12

Eu frequentemente me pego tentando substituir, por exemplo, foopor bare barcom fooem um buffer.

A maneira como costumo fazer é:

  • 3 query-substitui: aaa -> @@@, bbb -> aaa,@@@ -> bbb
  • desista da automação e faça a substituição manualmente

Suponho que seja possível fazer algo funcionar usando a ,sintaxe query-replace-regexppara testar se a sequência correspondente é aaaou bbb. Mas a sintaxe resultante seria muito complicada, por isso nunca tentei realmente.

A questão é que, dada a complexidade de uma tarefa, acho que deve haver uma maneira melhor de fazer uma única etapa, integrada ou em um pacote existente. Existe?

T. Verron
fonte
Pode haver uma maneira de etapa única, mas sua primeira maneira não é ruim, IMO. E se você escolher a sequência de substituição correta, poderá fazer uma substituição sem consulta para a segunda passagem.
Desenhou
@ Drew Para regular query-replace, eu sei que geralmente é mais rápido do M-% str1 str2que mover o ponto e fazer a alteração manualmente. É legal, porque não preciso perder tempo pensando no que será mais rápido, mesmo que haja apenas uma ocorrência de str1. Idealmente, gostaria que a inversão de texto fosse tão rápida quanto possível, para que eu possa usá-la sem pensar também.
T. Verron
Alguém fornecerá uma resposta simples. Você pode, sem dúvida, fazer o que pede, por exemplo, usando uma expressão Lisp para a substituição, referenciando o texto a ser substituído. Por exemplo, use algo semelhante ao idioma de troca (setq a (prog1 b (setq b a))). E pode até haver uma maneira mais simples.
Desenhou
2
Não acho \,(if \1 "b" "a")especialmente feio (contra uma regexp de \(a\)\|b), mas ainda assim as palavras precisam ser digitadas duas vezes, se isso a incomoda.
politza 19/09/16
2
Por que não \(aaa\)\|bbb?
politza 21/09/16

Respostas:

7

Aqui está um pequeno comando que fará isso:

(defun query-swap-strings (from-string to-string &optional delimited start end)
  "Swap occurrences of FROM-STRING and TO-STRING."
  (interactive
   (let ((common
          (query-replace-read-args
           (concat "Query swap"
                   (if current-prefix-arg
                       (if (eq current-prefix-arg '-) " backward" " word")
                     "")
                   (if (use-region-p) " in region" ""))
           nil)))
     (list (nth 0 common) (nth 1 common) (nth 2 common)
           (if (use-region-p) (region-beginning))
           (if (use-region-p) (region-end)))))
  (perform-replace
   (concat "\\(" (regexp-quote from-string) "\\)\\|" (regexp-quote to-string))
   `(replace-eval-replacement replace-quote (if (match-string 1) ,to-string ,from-string))
   t t delimited nil nil start end))
link0ff
fonte
Obrigado, isso é muito mais elaborado do que algo que eu mesmo teria escrito! Talvez você possa elaborar sobre os recursos implementados? Vejo que, com o argumento prefix, você retrocede, que executa a substituição apenas na região, se necessário ... Ou é apenas uma reescrita da query-replaceinversão, para que ele retenha todos os seus recursos? Não corresponde a 100% da definição nos meus emacs, mas eu ainda estou com 24,5 ...
T. Verron
@ T.Verron Este é apenas um corpo padrão da query-replacefamília de funções da versão mais recente, portanto mantém todos os recursos. Ao final da função, adicionei minha maneira recomendada de trocar as strings mencionadas no manual do Emacs.
link0ff
Eu provavelmente aceitei muito rápido. A função só funciona aqui (emacs 24.3) se eu comentar backwarde region-noncontiguous-pda chamada paraperform-replace . É um problema geral ou significa que a interface perform-replacemudou entre as versões?
T. Verron 14/10
Sim, a interface mudou com estes 2 argumentos adicionadas na versão mais recente, para que eles não existem em mais adiantados,
link0ff
2
Esta solução também parece estar bem agora.
Name
9

Instalar plur

e execute o comando plur-query-replace

e entrada {foo,bar}e sua substituição{bar,foo}

Pressione ypara substituir as ocorrências conforme desejado.

Existem também variantes não interativas e semelhantes a pesquisas deste comando.

InHarmsWay
fonte
Obrigado! O objetivo do plur também é algo que eu tenho procurado algumas vezes, definitivamente vou dar uma olhada nele. Minha única hesitação decorre do comentário do autor do pacote acima ...;)
T. Verron 20/09/16
1
plurrequer emacs 24.4.
T. Verron