Sostituisci il testo all'interno di vari delimitatori (ad es. Parentesi quadre, virgolette)


9

Faccio spesso alcune implementazioni di test con valori hardcoded che successivamente voglio cambiare. Piace

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

In cui vorrei cambiare

ref = open(fname)

Sono abituato a vim e lì posso digitare ci(fnamesupponendo che il punto sia all'interno delle parentesi. ( ci(sta per sostituire le staffe interne).

Come posso ottenere qualcosa come "sostituire l'interno" in emacs?

Risposte:


9

utilizzando expand-region

Consiglio di installare il expand-regionpacchetto (disponibile anche su Melpa). Sarebbe utile per modificare le situazioni menzionate nel tuo esempio e molto altro.

expand-regionè intelligente. Basato sulla modalità principale, proverà a capire cosa stai cercando di selezionare. Non so da quale lingua hai lo snippet di esempio, quindi userò lo snippet di codice di esempio e lo modificherò leggermente per Python (remove;). Quindi la mia spiegazione di seguito è con lo snippet di codice in basso in un python-modebuffer.

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

Se il punto è accanto a una singola citazione

I rettangoli verticali neri sottostanti indicano l'aspetto del cursore.

# 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'▮

In entrambi i casi, quando lo fai M-x er/expand-region, 'specific-file-name'verrà selezionato e puoi quindi premere DEL(o backspace) per eliminare la selezione.

Se hai delete-selection-modeabilitato (mi piace averlo abilitato personalmente), puoi iniziare a digitare via dopo aver fatto la selezione e questo sovrascriverà la selezione.

Ovviamente, se usi er/expand-regionmolto, lo legheresti a una scorciatoia da tastiera breve. Mi piace legarlo a C-\. Quindi, con il punto accanto a una singola citazione: C-\fnamemi daràref = open(fname);

inserisci qui la descrizione dell'immagine

Se il punto è da qualche parte all'interno delle virgolette

Utilizzando expand-region, il punto non deve essere vicino alle virgolette. Ma in questo caso, avrai bisogno di pochi altri tasti (di solito uno o due più).

Supponiamo che ora la posizione del cursore sia la seguente:

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

Usando la stessa associazione che ho usato sopra:

  • La prima volta che premo C-\selezionerò specific.
  • Ora ho solo bisogno di premere \per espandere la selezione ( expand-regionfunzione). Quello selezionerà specific-file-name.

    Se tu avessi legata er/expand-regiona C-=, colpendo =ancora una volta farà l'espansione incrementale. Leggi la sua documentazione su come associare i tasti per l'espansione / contrazione incrementale della selezione.

  • Colpire \ancora una volta si selezionerà 'specific-file-name'.
  • Ora si procede con il colpo DELper eliminare la selezione e quindi digitare fname. Se delete-selection-modeabilitato, puoi saltare il DELtratto.

In sintesi, con delete-selection-modeabilitata, i tasti che assomigliano: C-\\\fname.

inserisci qui la descrizione dell'immagine


utilizzando change-inner

Mi sono anche imbattuto nel change-innerpacchetto degli expand-regionautori magnars (che usa expand-regioncome back-end) per fare esattamente quello che fa il Vim ci(e anche cambiare l'esterno ).

Dal pacchetto README:

change-innerti dà il cicomando di Vim, basandoci su expand-region. È più facilmente spiegato dall'esempio:

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

Con punto dopo la parola semantica

change-inner "ucciderebbe il contenuto della stringa
change-outer "ucciderebbe l'intera stringa
change-inner {ucciderebbe la dichiarazione di ritorno
change-outer {ucciderebbe l'intero blocco


3

Con una regione

Per fare ciò con una regione, a partire da:

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

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

Modo più veloce

A partire dal punto precedente a paren, proprio come in Vim:

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

C-M-k( kill-sexp) comporterà:

ref = open|;

Se hai attivato electric-pair-mode, puoi reinserirlo ()solo con (. Quindi l'intera sequenza di tasti è C-M-k (- non molto più lunga di ci(.


1
Inoltre, se il punto si trova prima della virgoletta sinistra ref = open(|'specific-file-name');, C-M-kdarà ref = open(|);. Le citazioni sono anche sexps equilibrati .
Kaushal Modi,

Stavo pensando a delete-everything-inside-parenscose del genere, no delete-first-sexp-inside-parens.
abo-ABO

Bella soluzione ma mi richiede di spostare il punto prima dell'espressione che voglio sostituire. Il pacchetto 'change inner' funziona quando point è ovunque all'interno dell'espressione (uguale a vi).
kain88,

1

evil emula la maggior parte di Vim e fa oggetti di testo fuori dalla scatola.

In altre parole, con evilattivato e utilizzando le associazioni di tasti predefinite, ci(farà esattamente quello che stai chiedendo: cambia ciò che è racchiuso tra parentesi.

Più precisamente, ci(volontà catena evil-changea evil-inner-paren. Puoi anche creare i tuoi oggetti di testo arbitrari come preferisci.


Conosco il male (l'ho usato per un po 'di tempo). Vorrei sapere come farlo in emac "puri".
kain88,

@ kain88: abbastanza giusto: immagino che ci saranno più risposte a questa domanda. Per curiosità, però, se usi già evil, perché dovresti desiderare la non evilalternativa?
Dan

(commento non serio) @Dan Probabilmente si sta preparando a venire sul lato oscuro.
Kaushal Modi,

Ho notato che il male a volte non gioca bene con altre modalità. Inoltre sono curioso di vedere come il montaggio sarebbe usare solo emacs
kain88,

1

Utilizzando smartparens

Uccidere

1) Usa C-M-u( sp-backward-up-sexp) per uscire dai 'delimitatori.

2) Usa C-0 C-M-k( 0prefisso + sp-kill-sexp) per uccidere cose all'interno del sexp corrente o C-k( sp-kill-hybrid-sexp). Quest'ultimo funziona solo quando smartparens-strict-modeè abilitato e il sexp corrente si inserisce in una riga.

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

Contrassegna ed elimina / uccidi / copia

1) Trova l'inizio di sexp (in questo esempio C-M-u sp-backward-up-sexpè sufficiente), imposta mark C-SPCe vai alla fine di sexp con sp-end-of-sexp.

2) Quindi puoi fare quello che vuoi: C-wuccidere la regione, M-wuccidere-ring-save (copiare) la regione, backspaceeliminarla senza ingombrare l'anello di uccisione (solo con 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(|)

Funzione mark-inside-sexp

smartparensIl pacchetto ha una sp-mark-sexpfunzione che segna l'intero prossimo sexp, cioè delimitatori e cose tra loro.

È possibile utilizzare una funzione come questa per eliminare i delimitatori dalla selezione:

(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

Esci dal tuo sexp usando C-M-uripetutamente e spara mark-inside-sexp-using-sp e poi decidi cosa fare con la regione attiva.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.