Substitua o texto dentro de vários delimitadores (por exemplo: colchetes, aspas)

9

Costumo fazer alguma implementação de teste com valores codificados, que mais tarde quero alterar. Gostar

ref = open('specific-file-name')

Que eu gostaria de mudar

ref = open(fname)

Estou acostumado a vim e lá posso digitar ci(fnameassumindo que o ponto está dentro dos colchetes. ( ci(significa substituir os suportes internos).

Como posso obter algo como 'substituir interior' no emacs?

kain88
fonte

Respostas:

9

Usando expand-region

Eu recomendaria instalar o expand-regionpacote (disponível também no Melpa). Seria útil para editar situações mencionadas no seu exemplo e muito mais.

expand-regioné inteligente. Com base no modo principal, ele tentará descobrir o que você está tentando selecionar. Não sei de qual idioma você tem o snippet de exemplo, então usarei o seu snippet de código de exemplo e o modificarei levemente para Python (remove;). Portanto, minha explicação abaixo é com o trecho de código abaixo em um python-modebuffer.

ref = open('specific-file-name') 

Se o ponto estiver próximo a uma aspas simples

Os retângulos verticais pretos abaixo indicam a aparência do cursor.

# point on left of left quote, the cursor is hiding the quote under it
ref = open(▮specific-file-name') 

# point on left of right parenthesis, the cursor is hiding the parenthesis under it       
ref = open('specific-file-name'▮

Em qualquer um dos casos, quando o fizer M-x er/expand-region, 'specific-file-name'será selecionado e você poderá pressionar DEL(ou retroceder) para excluir a seleção.

Se você delete-selection-modeativou (eu gosto de ativá-lo pessoalmente), você pode começar a digitar depois de fazer a seleção e isso substituirá a seleção.

Obviamente, se você usa er/expand-regionmuito, vincula-o a uma ligação de chave curta. Eu gosto de ligá-lo C-\. Então, com o ponto ao lado de uma única citação: C-\fnamevai me darref = open(fname);

insira a descrição da imagem aqui

Se point estiver em algum lugar dentro das aspas

Usando expand-region, o ponto não precisa estar próximo das aspas. Mas, neste caso, você precisará de apenas mais alguns (geralmente um ou dois mais) pressionamentos de tecla.

Digamos que a posição do cursor esteja como abaixo agora:

# cursor shown below is hiding the i character under it
ref = open('specif▮c-file-name')

Usando a mesma ligação que usei acima:

  • A primeira vez que eu clicar C-\selecionará specific.
  • Agora só preciso clicar \para expandir a seleção ( expand-regionrecurso). Isso irá selecionar specific-file-name.

    Se você tinha ligado er/expand-regionpara C-=, bater =novamente fará a expansão incremental. Leia sua documentação sobre como vincular chaves para expansão / contração incremental da seleção.

  • Bater \mais uma vez irá selecionar 'specific-file-name'.
  • Agora você continua pressionando DELpara excluir a seleção e digitar fname. Se delete-selection-modeestiver ativado, você pode pular o DELtraço.

Em resumo, com delete-selection-modehabilitado, os cursos chaves parecer: C-\\\fname.

insira a descrição da imagem aqui


Usando change-inner

Eu também me deparei com o change-innerpacote dos magnars do expand-regionautor (que usa como back-end) para fazer exatamente o que o Vim faz (e também alterar o exterior ).expand-regionci

Do pacote README:

change-innerdá a você o cicomando do vim , construindo expand-region. É mais facilmente explicado pelo exemplo:

function test() {
  return "semantic kill";
}

Com ponto após a palavra semântica

change-inner "mataria o conteúdo da string
change-outer "mataria a string inteira
change-inner {mataria a declaração de retorno
change-outer {mataria o bloco inteiro

Kaushal Modi
fonte
3

Com uma região

Para fazer isso com uma região, começando em:

ref = open(|'specific-file-name');

pressione C-SPC C-b C-M-n C-b C-w.

Maneira mais rápida

A partir do ponto anterior a parênteses, assim como no Vim:

ref = open|('specific-file-name');

C-M-k( kill-sexp) resultará em:

ref = open|;

Se você tiver electric-pair-modeativado, poderá reinserir ()apenas (. Portanto, a sequência de teclas completa é C-M-k (- não muito mais que ci(.

abo-abo
fonte
1
Além disso, se o ponto é antes da citação esquerda, ref = open(|'specific-file-name');, C-M-kvai dar ref = open(|);. As citações também são sexps equilibrados .
Kaushal Modi
Eu estava pensando delete-everything-inside-parensem algo, não delete-first-sexp-inside-parens.
abo-abo
Solução agradável, mas exige que eu mude de ponto antes da expressão que quero substituir. O pacote 'change inner' funciona quando point está em qualquer lugar dentro da expressão (o mesmo que vi).
kain88
1

evil emula a maior parte do Vim e faz objetos de texto fora da caixa.

Em outras palavras, com evilativado e usando as teclas de atalho padrão, ci(fará exatamente o que você está perguntando: altere o que está dentro dos parênteses.

Mais precisamente, ci(acorrentará evil-changea evil-inner-paren. Você também pode criar seus próprios objetos de texto arbitrários, como desejar.

Dan
fonte
Eu sei sobre o mal (eu o uso há um tempo agora). Gostaria de saber como isso pode ser feito no emacs 'puro'.
kain88
@ kain88: justo: acho que haverá várias respostas para esta pergunta. Por curiosidade, porém, se você já usa evil, por que deseja a não evilalternativa?
Dan
(comentário não sério) @ Dan Ele provavelmente está se preparando para ir para o lado sombrio.
precisa
Notei que o mal às vezes não se encaixa bem com outros modos. Além disso, eu estou curioso para ver como editando estaria usando apenas emacs
kain88
1

Usando smartparens

Mate

1) Use C-M-u( sp-backward-up-sexp) para sair dos 'delimitadores.

2) Use C-0 C-M-k( 0prefixo + sp-kill-sexp) para matar coisas dentro do sexp atual ou C-k( sp-kill-hybrid-sexp). O último só funciona quando smartparens-strict-modeestá ativado e o sexp atual se encaixa em uma linha.

ref = open('specific|-file-name')
// C-M-u
ref = open(|'specific-file-name')
// C-k
ref = open(|)

Marcar e excluir / matar / copiar

1) Encontre o caminho para o início do sexp (neste exemplo C-M-u sp-backward-up-sexpé suficiente), marque C-SPCe vá para o final do sexp com sp-end-of-sexp.

2) Em seguida, você pode fazer o que quiser: C-wmatar região, matar região M-wde salvar anel (copiar), backspaceexcluí-la sem bagunçar o anel de morte (somente com delete-selection-mode)

ref = open('specific|-file-name')
// C-M-u
ref = open(|'specific-file-name')
// C-SPC - mark is now active
ref = open(|'specific-file-name')
// sp-end-of-sexp (my binding: M-e)
ref = open(<'specific-file-name'|)
// backspace
ref = open(|)

Função Mark-inside-sexp

smartparensO pacote tem uma sp-mark-sexpfunção que marca todo o próximo sexp, ou seja, delimitadores e outras coisas entre eles.

Você pode usar uma função como esta para tirar delimitadores da seleção:

(defun mark-inside-sexp-using-sp ()
  (interactive)
  (sp-mark-sexp)
  (exchange-point-and-mark) (backward-char)
  (exchange-point-and-mark) (forward-char)
  (message "MARK INSIDE SEXP (using sp)"))

(global-set-key (kbd "s-SPC") 'mark-inside-sexp-using-sp)
;; this is "super" modifier (win key) with space

Saia do seu sexp usando C-M-urepetidamente e ative a marca-dentro-sexp-usando-sp e decida o que fazer com a região ativa.

mmajcher
fonte