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 NONE
e 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{p
lavoro 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>x
per 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 x
a 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]}x
o [{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 v
non 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{p
oppureyi{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
- 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
- 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>x
Questo 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 |
+----+------------------------+----------------------------+------------+
return -1;
viene. Potresti anche specificare dove posizionare il cursore prima di eseguire ogni sequenza di tasti?