Como simplesmente remover chaves

8

Um amigo meu me disse que eu posso usar o truque abaixo para remover um par de colchetes.

Coloque o cursor dentro do par de colchetes que você deseja remover.

y i {para puxar o texto entre chaves v a {e colar p.

Funciona bem como:

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];
}

Depois de executar o 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];

até conhecer essa situação (falta o espaço antes do primeiro colchete).

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];
}

Depois de executar esses comandos, o bloco de texto se torna

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];
)

A área que seleciono no modo visual parece boa, mas por que os parênteses diminuem?

MrDwZ
fonte
Você tem certeza do exemplo de código publicado? Eu não entendo como isso return -1;vem. Além disso, você pode precisar onde coloca o cursor antes de executar cada sequência de teclas?
statox
@statox Desculpe por isso ... Corrigi o último bloco e adicionei uma descrição sobre onde coloquei o cursor. Obrigado pela sua recomendação :-)
MrDwZ
Não consigo replicar isso. yi{puxa entre os colchetes e vapseleciona visualmente o parágrafo (o texto inteiro neste caso), mas não vejo como isso altera o texto. Tem certeza de que não está fazendo yi{+ va{+ p?
Jjaderberg
2
Eu apenas tentei yi{+ va{+ pno seu texto em uma sessão limpa (sem vimrc -u NONE) e isso reproduz o resultado. Não sei ao certo por que, por exemplo, pe Pambos dão esse resultado, apesar i{e se a{movendo no sentido característico. Ajudaria se você pudesse: a) fornecer um texto de exemplo no qual sua técnica funcione eb) confirmar onde a técnica 'muda' na sua técnica. @ Ben indica uma boa solução alternativa em sua resposta (eu uso esse plug-in), mas eu não me importaria de aprender por que isso acontece em primeiro lugar.
Jjaderberg
Eu sou como @jjaderberg, não consigo reproduzir o comportamento que você descreve. Dar os detalhes solicitados em seus comentários seria uma boa ideia.
Statox

Respostas:

6

Instale o plugin "surround" . Então você pode apenas fazer d s B .

Na página do projeto:

O Surround.vim tem tudo a ver com "ambiente": parênteses, colchetes, aspas, tags XML e muito mais. O plug-in fornece mapeamentos para excluir, alterar e adicionar ambientes em pares facilmente.

O comando dsseguido por qualquer objeto de texto ( Bnesse caso, para "Bloquear", como no objeto aBou iBtexto) excluirá os caracteres ao redor que definem o objeto de texto. Assim, d s B no seu caso, realiza o que você queria.

Outros comandos incluem c s B b, se você deseja alterar o ambiente {...}para (...), ou y s {qualquer movimento do cursor ou objeto de texto} B para adicionar ambiente {...}ao texto selecionado pelo cursor.

Veja a página do plugin e a documentação para mais detalhes.

Ben
fonte
Esta é uma boa solução alternativa. Você consideraria adicionar uma ou duas frases explicando como esse plug-in funciona e por que o mapeamento específico realiza a tarefa?
jjaderberg
Existe alguma maneira elegante de remover esses aparelhos sem um plug-in? : (
MrDwZ 25/06
Talvez. Mas o surround é realmente leve e um dos plugins "essenciais". Portanto, pode também instalá-lo ...
Ben
6

Sumário

É um bug e existe um patch (743). O bug afeta os dois exemplos, mas você não o vê em um caso, porque o caractere que é movido para baixo é um (espaço em branco). A solução é instalar o patch, mas também existem muitas soluções alternativas ou métodos alternativos, não afetados pelo bug.

NB : {, }e Btodos se referem ao mesmo objeto texto: Block ( :help aB, :help iB). Se essa ou outras respostas usarem um sinal diferente do usado na pergunta, talvez seja por isso.

O inseto

Eu não entendo completamente, mas aqui está uma explicação, se alguém estiver interessado.

O comportamento que você vê é devido a um bug mencionado por Yukihiro Nakadaira no vim_dev e seu patch foi lançado como 7.4.743: "p" no modo Visual causa uma divisão inesperada de linhas .

O modo visual put ( :help v_p) deve substituir o texto selecionado visualmente pelo texto de um registro. O erro acontece quando a) O registo é do tipo linewise ( :help linewise-register), mas a seleção visual é do tipo characterwise e b) as extremidades seleção visual na última coluna de uma linha. No seu caso, se você puxar o bloco interno e selecionar visualmente um bloco e colar, o registro arrancado será no sentido da linha e a seleção visual será no caráter. Podemos puxar o bloco interno e um bloco para registros nomeados e inspecionar:

Em

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];  
}

nós fazemos

"ayi{
"bya{
:registers ab

que 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

Para substituir uma seleção visual caracterizada por um registro linear, as linhas que contêm o início e o final da seleção visual devem ser divididas em duas, para que o texto possa ser inserido no meio. Isso geralmente funciona muito bem:

Executando o vim as vim -u NONE -U NONEe digitando
( a )

iaaa
bbb
ccc
ddd<Esc>ggYjlvp

resulta em

aaa
b
aaa
b
ccc

e ( b )

iaaa
bbb
ccc
ddd<Esc>ggYjvjp

no

aaa

aaa
cc
ddd

Mas quando a seleção visual caractere termina na última coluna de uma linha (e não inclui a nova linha /n/ ^J), algo dá errado. Tem a ver com a posição do cursor, que é subitamente desligada por -1 e deve ser especialmente incrementada, que é o que o patch faz. Compare ( a ) com o comando <Esc>ggYjllvp, ou seja, o mesmo comando, exceto mova mais uma coluna para a direita para que o cursor fique no último "b" da linha. O resultado é o mesmo de antes!

Agora pegue o seguinte texto:

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

Com o cursor na segunda linha, você yi{va{ptrabalha muito bem e dá

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

O registro do arranco ainda está no sentido da linha e a seleção visual no sentido dos caracteres, mas a seleção visual não termina mais na última coluna e está tudo bem.

Exemplos de textos da pergunta

Para os dois exemplos de texto, onde a única diferença é um espaço em branco entre o fechamento de parênteses e a abertura de colchetes na primeira linha, pode parecer que seu comando se comporta de maneira diferente, mas realmente não. No primeiro caso, aquele que parece bem-sucedido, deve haver um espaço em branco à direita na primeira linha depois que os colchetes forem removidos. Esse espaço em branco à direita fica na última linha. Comyi{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];
}

torna-se

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];
␣

Assim como

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];
}

torna-se

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];
)

Soluções

A solução seria instalar o patch, mas existem muitas outras maneiras de remover os colchetes ao redor que não sofrem com o bug. A melhor solução alternativa é a resposta do @Gilles, mas o mais fácil pode ser selecionar visualmente antes de puxar, para manter o registro caractere.

O plugin surround de Tim Pope é excelente, mas (pelo menos para mim) faz mais do que remover os colchetes: une a segunda linha à primeira, remove o recuo e move o cursor para o início da primeira linha. Isso deixa uma limpeza não trivial para fazer. Ingo Karkat e Luc Hermitte têm plugins que lidam com registros e colagens (tenho certeza que existem muitos outros) e que devem ser capazes de fazer isso. Eu não estou muito familiarizado com eles, mas acredito que, com lh-colchetes, você pode <M-b>xexcluir os colchetes circundantes e, para uma colocação mais poderosa (especialmente no modo visual), você pode ver ReplaceWithRegister e UnconditionalPaste .

A melhor maneira é a dada na resposta do @Gilles [{x]}x,. É rápido, lida bem com blocos aninhados e não junta linhas de maneira inadequada ou mexe com o recuo. Se houver um espaço em branco antes do suporte de abertura, você poderá adicionar facilmente um xao comando para removê-lo:[{xx]}x

Outros comandos vanilla

Novamente, o comando mais apropriado que consigo pensar é o da resposta do @Gilles, [{x]}xou [{xx]}x, mas aqui estão duas alternativas especificamente à luz desse bug.

Yank characterwise

Como o erro ocorre apenas para o registro visual colocado em linha a linha sobre a seleção entre caracteres, e como é acidental ao seu puxão interno do bloco ser lateral, você pode optar por puxá-lo no sentido contrário. Uma maneira fácil é selecionar visualmente o bloco interno antes de arrancá-lo, e para certificar-se de que a seleção visual é characterwise (ou seja, o uso vnão V): vi{yva{p. Essa pode ser a maneira mais fácil, pois é muito semelhante à maneira como você faz a operação no momento.

Não use visual put

Outros comandos, como alterar e excluir, não são afetados por esse bug. Você pode puxar como antes, mas excluir um bloco no registro do buraco negro ( :help quote_) e colocar ou excluir um bloco e colocar no registro 0 ( :help quote0): yi{"_da{pouyi{da{"0p

Generalidade

Finalmente, existem maneiras semelhantes à resposta do @Gilles - mover para o início de um bloco, excluir caractere, mover para o final de um bloco, excluir caractere - mas que são mais genéricas. A única razão para usá-las seria se o "bloco" que você está excluindo for excêntrico e não tiver movimentos associados que funcionem tão bem quanto [{para um bloco delimitado por colchetes. Há uma chance de que o plug-in vim-surround possa lidar bem com esses blocos excêntricos, mas duas maneiras básicas seriam

  1. Selecione visualmente o bloco excêntrico e saia do modo visual. O cursor está no último caractere da seleção. Exclua-o e vá para o início da última seleção ( :help `<) e exclua o caractere.va{<Esc>x`<x
  2. Pesquise para trás o início do bloco excêntrico e exclua o caractere; em seguida, pesquise o final do bloco excêntrico e exclua o caractere. ?{<CR>x/}<CR>xIsso pode não funcionar bem com blocos aninhados.

Contador de caracteres

+----+------------------------+----------------------------+------------+
|    | 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 |
+----+------------------------+----------------------------+------------+
jjaderberg
fonte
5

Como você não está solicitando que o cursor retorne à sua posição original, [{x]}xfaz o trabalho. Tem 6 caracteres com duas impressões, Shiftmas o princípio é direto, por isso é fácil de lembrar.

Se você quiser voltar à posição original, pode usar [{x``]}x``

Gilles 'SO- parar de ser mau'
fonte