Come rimuovere semplicemente le parentesi graffe


8

Uno dei miei amici mi ha detto che posso usare il trucco qui sotto per rimuovere un paio di parentesi graffe.

Posiziona il cursore all'interno della coppia di parentesi graffe che desideri rimuovere.

y i {per strappare il testo tra parentesi graffe, v a {quindi incollarlo p.

Funziona bene come:

for(int i = 0; i < s.length(); i++) {
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Dopo aver eseguito il comando:

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];

fino a quando ho incontrato questa situazione (manca lo spazio prima della prima parentesi graffa).

for(int i = 0; i < s.length(); i++){
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Dopo aver eseguito questi comandi, il blocco di testo diventa

for(int i = 0; i < s.length(); i++
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
)

L'area che seleziono in modalità visiva sembra buona, ma perché le parentesi si abbassano?


Sei sicuro dell'esempio di codice che hai pubblicato? Non capisco da dove return -1;viene. Potresti anche specificare dove posizionare il cursore prima di eseguire ogni sequenza di tasti?
statox

@statox Mi dispiace per quello ... Ho corretto l'ultimo blocco e ho aggiunto una descrizione su dove ho posizionato il cursore. Grazie per la tua raccomandazione :-)
MrDwZ,

Non posso replicare questo. yi{fa uno strattone tra le parentesi graffe e vapseleziona visivamente il paragrafo (l'intero testo in questo caso) ma non vedo come questo cambi il testo. Sei sicuro di non fare yi{+ va{+ p?
Jjaderberg,

2
Ho appena provato yi{+ va{+ psul tuo testo in una sessione pulita (no vimrc, -u NONE) e questo riproduce il tuo risultato. Io non sono sicuro perché, per esempio, pe Psia per dare a questo risultato, nonostante i{e a{a caratteri in movimento. Sarebbe utile se potessi a) fornire un testo di esempio su cui la tua tecnica funziona e b) confermare dove si verifica il "cambiamento" nella tua tecnica. @Ben indica una buona soluzione nella sua risposta (io uso quel plugin) ma non mi dispiacerebbe imparare perché questo accade in primo luogo.
Jjaderberg,

Sono proprio come @jjaderberg che non riesco a riprodurre il comportamento che descrivi. Dare i dettagli richiesti nei suoi commenti sarebbe davvero una buona idea.
statox

Risposte:


6

Installa il plugin "surround" . Quindi puoi semplicemente farlo d s B .

Dalla pagina del progetto:

Surround.vim è tutto su "dintorni": parentesi, parentesi, virgolette, tag XML e altro. Il plugin fornisce mappature per eliminare, modificare e aggiungere facilmente un ambiente simile in coppia.

Il comando dsseguito da qualsiasi oggetto di testo ( Bin questo caso, per "Blocco", come nell'oggetto di testo aBo iB) eliminerà i caratteri circostanti che definiscono l'oggetto di testo. Pertanto, d s B nel tuo caso realizza ciò che volevi.

Altri comandi includono c s B b, se si voleva cambiare il circostante {...}in (...), o y s {qualsiasi oggetto di spostamento del cursore o il testo} B da aggiungere che circonda {...}il testo selezionato dal cursore.

Vedi la pagina del plugin e la documentazione per maggiori dettagli.


Questa è una buona soluzione. Considereresti di aggiungere una o due frasi che spiegano come funziona questo plugin e perché la particolare mappatura compie il compito?
Jjaderberg,

Esiste un modo elegante per rimuovere quelle parentesi graffe senza un plug-in? : (
MrDwZ,

Può essere. Ma il surround è davvero leggero e uno dei plugin "essenziali". Quindi può anche installarlo ...
Ben

6

Sommario

È un bug e c'è una patch (743). Il bug ha effetto su entrambi i tuoi esempi, ma non lo vedi in un caso perché il personaggio che viene spostato verso il basso è un (spazio bianco). La soluzione è installare la patch, ma ci sono anche molte soluzioni alternative o metodi alternativi, non interessati dal bug.

NB : {, }e Btutto si riferiscono allo stesso oggetto di testo: Block ( :help aB, :help iB). Se questa o altre risposte usano un segno diverso da quello usato nella domanda, questo potrebbe essere il motivo.

Il bug

Non lo capisco del tutto, ma ecco una spiegazione, se qualcuno è interessato.

Il comportamento che vedi è dovuto a un bug menzionato da Yukihiro Nakadaira su vim_dev e la sua patch è rilasciata come 7.4.743: "p" in modalità Visual causa una divisione inaspettata della linea .

La modalità visiva put ( :help v_p) dovrebbe sostituire il testo selezionato visivamente con il testo di un registro. Il problema si verifica quando a) il registro è di tipo formato da linee ( :help linewise-register), ma la selezione visiva è di tipo a caratteri e b) le estremità di selezione visiva all'ultimo colonna di una riga. Nel tuo caso, se strattoni il blocco interno e poi selezioni visivamente un blocco e incolla, il registro yanked sarà lineare e la selezione visiva sarà caratteriale. Possiamo tirare sia il blocco interno che un blocco su registri nominati e ispezionare:

Su

for(int i = 0; i < s.length(); i++){  
    int index = s[i] - c;  
    if(root->next[index] == NULL)  
        root->next[index] = new TrieNode;  
    root = root->next[index];  
}

noi facciamo

"ayi{
"bya{
:registers ab

che mostra

--- Registers ---
"a       int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J
"b   {^J    int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J}

e

:echo getregtype('a') " displays 'V' for linewise
:echo getregtype('b') " displays 'v' for characterwise

Per sostituire una selezione visuale per carattere con un registro lineare, le linee che contengono l'inizio e la fine della selezione visiva devono essere divise in due, in modo che il testo possa essere inserito tra. Questo di solito funziona bene:

Esecuzione di vim as vim -u NONE -U NONEe digitazione
( a )

iaaa
bbb
ccc
ddd<Esc>ggYjlvp

risultati in

aaa
b
aaa
b
ccc

e ( b )

iaaa
bbb
ccc
ddd<Esc>ggYjvjp

in

aaa

aaa
cc
ddd

Ma quando la selezione visuale per carattere termina all'ultima colonna di una linea (e non include la nuova riga /n/ ^J) qualcosa va storto. Ha a che fare con la posizione del cursore, che è improvvisamente disattivata di -1 e deve essere appositamente incrementata, che è ciò che fa la patch. Confronta ( a ) con il comando <Esc>ggYjllvp, cioè lo stesso comando tranne che sposta un'altra colonna a destra in modo che il cursore si trovi sull'ultima "b" sulla linea. Il risultato è lo stesso di prima!

Ora prendi il seguente testo:

if (TIRED){
    goto bed;
} else {
    goto work;
}

Con il cursore sulla seconda riga, il tuo yi{va{plavoro va bene e dà

if (TIRED)
    goto bed;
 else {
    goto work;
}

Il registro yank è ancora lineare e la selezione visuale in modo caratteristico, ma la selezione visiva non termina più nell'ultima colonna e tutto va bene.

Testi di esempio dalla domanda

Per i due testi di esempio, in cui l'unica differenza è uno spazio vuoto tra la parentesi chiusa e l'apertura della parentesi graffa nella prima riga, può sembrare che il tuo comando si comporti diversamente, ma in realtà non lo è. Nel primo caso, quello che sembra avere successo, dovrebbe esserci uno spazio bianco finale sulla prima riga una volta rimosse le parentesi. Quello spazio bianco finale è invece sull'ultima riga. Conyi{va{p

for(int i = 0; i < s.length(); i++) {
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

diventa

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
␣

proprio come

for(int i = 0; i < s.length(); i++){
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

diventa

for(int i = 0; i < s.length(); i++
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
)

soluzioni

La soluzione sarebbe installare la patch, ma ci sono molti altri modi per rimuovere le parentesi circostanti che non soffrono del bug. La soluzione migliore è la risposta di @Gilles, ma la più semplice potrebbe essere quella di selezionare visivamente prima di strappare, per mantenere il registro in modo caratteristico.

Il plugin surround di Tim Pope è eccellente, ma (almeno per me) non si limita a rimuovere le parentesi: unisce la seconda riga alla prima, rimuove il rientro e sposta il cursore all'inizio della prima riga. Questo lascia un po 'di pulizia non banale da fare. Ingo Karkat e Luc Hermitte hanno plugin che si occupano di registri e incolla (sono sicuro che ce ne sono molti altri) e che dovrebbero essere in grado di farlo. Non ho molta familiarità con loro, ma credo che con le parentesi graffe che potresti fare <M-b>xper eliminare le parentesi circostanti e per un put più potente (specialmente in modalità visiva) potresti guardare ReplaceWithRegister e UnconditionalPaste .

Il modo migliore è quello dato in @Gilles risposta, [{x]}x. È veloce, gestisce bene i blocchi nidificati e non unisce le linee in modo inappropriato o fa casini con il rientro. Se c'è uno spazio bianco prima della parentesi quadra aperta puoi aggiungere facilmente xa al comando per rimuoverlo:[{xx]}x

Altri comandi alla vaniglia

Ancora una volta, il comando più appropriato che mi viene in mente è quello nella risposta di @Gilles, [{x]}xo [{xx]}x, ma qui ci sono due alternative specificamente alla luce di questo errore.

Yank in modo caratteristico

Dal momento che il bug si verifica solo per il registro visivo put put su selezione carattere, e poiché è solo accidentale al tuo blocco interno che è lineare, puoi invece scegliere di strattonarlo in modo caratteristico. Un modo semplice è quello di selezionare visivamente l'interno del blocco prima tirando esso, e fare in modo che la selezione visiva è a caratteri (cioè, l'uso vnon V): vi{yva{p. Questo può essere il modo più semplice perché è molto simile a come si esegue attualmente l'operazione.

Non usare il put visivo

Altri comandi, come modifica ed elimina, non sono interessati da questo errore. Puoi tirare come prima, ma poi eliminare un blocco nel registro del buco nero ( :help quote_) e inserire, oppure eliminare un blocco e inserire dal registro 0 ( :help quote0): yi{"_da{poppureyi{da{"0p

Generalità

Infine, ci sono modi simili alla risposta di @Gilles: vai all'inizio di un blocco, elimina il carattere, vai alla fine di un blocco, elimina il carattere, ma sono più generici. L'unico motivo per usarli sarebbe se il "blocco" che stai eliminando è eccentrico e non ha movimenti associati che funzionano così come [{per un blocco delimitato da parentesi graffe. È possibile che il plugin vim-surround sia in grado di gestire bene questi blocchi eccentrici, ma sarebbero due modi vanilla

  1. Selezionare visivamente il blocco eccentrico e uscire dalla modalità visiva. Il cursore si trova sull'ultimo carattere della selezione. Eliminalo, quindi vai all'inizio dell'ultima selezione ( :help `<) ed elimina il carattere.va{<Esc>x`<x
  2. Cerca all'indietro l'inizio del blocco eccentrico ed elimina il carattere, quindi cerca in avanti la fine del blocco eccentrico ed elimina il carattere. ?{<CR>x/}<CR>xQuesto potrebbe non funzionare bene con i blocchi nidificati.

Conteggio dei caratteri

+----+------------------------+----------------------------+------------+
|    | method                 |          command           | characters |
+----+------------------------+----------------------------+------------+
| 1. | vim-surround           | ds{                        |          3 |
| 2. | @Gilles answer         | [{x]}x                     |          6 |
| 3. | Characterwise yank     | vi{yva{p                   |          8 |
| 4. | Delete, not visual put | yi{"_da{p or yi{da{"0p     |          9 |
| 5. | Visual mark            | va{<Esc>x`<x               |          8 |
| 6. | Search                 | ?{<CR>x/}<CR>x             |          8 |
+----+------------------------+----------------------------+------------+

5

Dal momento che non stai chiedendo di riportare il cursore nella sua posizione originale, [{x]}xfa il lavoro. È lungo 6 caratteri con due pressioni di Shiftma il principio è semplice, quindi è facile da ricordare.

Se vuoi tornare alla posizione originale, puoi usare [{x``]}x``

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.