Vários cursores no local desejado

13

Estou usando o plugin vim-multiple-cursors .

Eu gostaria de colocar os cursores exatamente onde eu quero. Por exemplo ( [x]são as posições do cursor):

Lorem ipsum dolor sit amet[1], consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna[2]
aliqua.

Em Texto sublime, eu normalmente colocava o primeiro cursor, depois passava para a próxima posição com as teclas de setas e colocava o segundo.

Existe algo semelhante no VIM? Com este plugin ou outro.

EDITAR

Após um comentário, meu interesse em fazê-lo apareceu ao tentar escrever
\section[My first section in this book]{My first section in this book}
em um .texarquivo. Minha primeira reação foi escrever \section[]{}e depois colocar dois cursores para escrever a mesma coisa dentro do []e {}.

Outro exemplo seria adicionar _someStuffapós vários nomes de variáveis ​​diferentes. Por exemplo, gire isso:

variable1 = 2
my_variable2 = 12
var3 = 14

nisso:

variable1_someStuff = 2
my_variable2_someStuff = 12
var3_someStuff = 14

Com vários cursores, eu posso fazer selecionando um cursor de coluna e depois indo para o final da palavra, inserindo etc. etc. Mas acho que seria fácil escolher exatamente onde quero que os cursores estejam.

tomasyany
fonte
1
Eu acho que uma pergunta importante a fazer é por que você quer fazer isso? O que você está tentando fazer? O uso de vários cursores não está realmente "seguindo o caminho do Vim", provavelmente existe uma maneira diferente de fazer o que você deseja, pelo menos com a mesma eficiência, usando os recursos internos.
Statox
@statox. Veja editar. Dei dois exemplos que me vieram à mente. O segundo que posso realizar com o plug-in vim-multiple-cursors, mas o primeiro não posso, pelo menos de uma maneira fácil.
tomasyany
@ Nobe4. Obrigado, o segundo script fez isso.
tomasyany

Respostas:

29

Usar o cursor múltiplo não é uma coisa do Vimmer

Como eu disse nos comentários, o uso de cursores múltiplos (mesmo com um plug-in) não é realmente "seguir o caminho do Vim", eu entendo perfeitamente que é atraente para alguém que vem do Sublime-Text, mas muitas vezes você pode encontrar alternativas que são pelo menos tão eficiente com os recursos internos do Vim.

Obviamente, encontrar essas soluções alternativas nem sempre é fácil e às vezes leva tempo, mas fica mais fácil com sua experiência com o Vim e você verá que, com o tempo, vários cursores parecerão totalmente inúteis para você.

Isso é legal, mas como posso encontrar uma maneira alternativa?

Não existe uma resposta universal, pois depende muito do que você está tentando fazer, apenas tentarei dar algumas dicas sobre as primeiras coisas a tentar:


O comando dot .

O comando Dot é provavelmente uma das ferramentas mais poderosas do Vim, ele simplesmente nos permite repetir a última alteração. Eu não poderia explicar melhor do que Drew Neil em seu Practical Vim . Eu acho que todo Vimmer deve considerar a leitura deste livro.

A força desse comando é que a última alteração pode ser uma ação trabalhando em um personagem, uma linha ou um arquivo inteiro. Por exemplo, uma alteração pode ser delimitada no momento em que você entra no modo de inserção e no momento em que volta ao modo normal.

Com isso em mente, é fácil fazer o que você queria fazer com o multicursor:

  • Primeiro vamos configurar nosso ambiente: vamos escrever como você sugeriu

    \section[]{}

  • Em seguida, faça uma alteração repetida. O cursor está ativado }, pressione F[para voltar ao [personagem. Em seguida, entre no modo de inserção com ie digite My first section in this booke volte ao modo normal com ESC:

    \section[My first section in this book]{}

  • E aqui vem a parte mágica: Vamos digitar f{para colocar o cursor no {personagem e pressionar .para repetir a última alteração:

    \section[My first section in this book]{My first section in this book}

Todo o desafio do comando dot é aprender a fazer alterações repetíveis: ele virá com o Grokking Vim, mas o básico é entender como fazer suas alterações de maneira repetível.

Por exemplo, para inserir um ponto e vírgula no final de uma linha, você prefere usar em A;vez de $a;. Por quê?

Como A;cria uma ação atômica, quando você usar .em outra linha, não importa onde esteja na linha, você inserirá o ponto e vírgula no final. Enquanto que, ao usar, $a;você divide sua alteração em duas partes $ae ;, se você .a inserir, inserirá o ponto e vírgula na posição atual do cursor.

NOTA A fórmula mágica no Vim é n.. Um fluxo de trabalho muito legal é:

  • procure o local com o qual deseja editar /pattern
  • faça sua edição repetível
  • use npara ir para o próximo local para editar
  • use .para repetir a edição
  • repita os dois últimos passos: Você é o rei do mundo (ou pelo menos das edições)

macros

As macros são outra ferramenta extremamente importante no Vim, pois permitem gravar uma sequência de pressionamentos de teclas e repeti-la como se você tivesse digitado novamente.

Vou usar, como exemplo, seu segundo caso de uso:

variable1 = 2
my_variable2 = 12
var3 = 14

Mais uma vez, o importante é aprender como tornar suas macros eficientes (darei um exemplo de contador logo depois):

  • Coloque o cursor na palavra variable1e comece a gravar sua macro qq. Isso significa "começar a gravar todas as minhas futuras teclas pressionadas no registro chamado q".

  • Comece a fazer sua edição digitando:

    • 0 para ir no começo da linha
    • e para ir no final da primeira palavra
    • a acrescentar depois do cursor
    • .someStuff para anexar o texto desejado
    • <Esc> parar a inserção
    • j para ir na próxima linha
    • q parar de gravar a macro
  • Você terá:

variable1.someStuff = 2
my_variable2 = 12
var3 = 14
  • Agora você pode usar a macro para repetir sua edição. Como você está na linha certa para editar, você pode simplesmente executar a macro com @q. Como queremos executá-lo duas vezes, você pode usar 2@qe obterá o seguinte resultado:
variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14

NOTA 1 Como você deve ter notado, o uso 0eano início da macro foi realmente importante. De fato, se você tivesse colocado o cursor no final da primeira palavra antes de gravar a macro e executá-la novamente, seu resultado teria sido:

variable1.someStuff = 2
my_variable2 = 12.someStuff
var3 = 14.someStuff

Como seu cursor, o texto seria inserido na posição do cursor após a alteração da linha (ou seja, no final da linha, neste caso)

NOTA 2 As macros são extremamente poderosas e você pode até criar macros recursivas quando se sentir confortável com elas. Aqui sua macro poderia ter sido:

`0ea.someStuff<Esc>j@q`

A final @qteria chamado a macro por si só em vez de usar 2@q; você teria usado @qe todo o trabalho teria sido feito.


bloqueio visual

Aí vem outro truque que não se aplica diretamente ao seu caso de uso, mas pode ser realmente útil para editar um grande número de linhas ao mesmo tempo. Vamos pegar esse extrato de código CSS:

li.one   a{ background-image: url('/images/sprite.png'); }
li.two   a{ background-image: url('/images/sprite.png'); }
li.three a{ background-image: url('/images/sprite.png'); }

E se você movesse os sprites de imagespara components?

Bem, você pode colocar o cursor sobre o idos imagese pressione <C-v>. Isso iniciará o modo de bloco visual, que permite selecionar os blocos. Agora você pode digitar t/ para selecionar a palavra que deseja alterar e 2jselecionar todas as ocorrências da palavra.

Depois disso, basta digitar cpara alterar a palavra e depois components. Quando você sair do modo de inserção, verá:

li.one   a{ background-image: url('/components/sprite.png'); }
li.two   a{ background-image: url('/components/sprite.png'); }
li.three a{ background-image: url('/components/sprite.png'); }

O comando global

O comando global é uma ferramenta que permite aplicar um comando ex mode em linhas que correspondem a um padrão, mais uma vez, é uma boa maneira de aplicar a mesma alteração em locais diferentes sem a necessidade de vários cursores.

A sintaxe é a seguinte:

:[range] g / pattern / command

Para mais detalhes sobre o [range]parâmetro, consulte :h :range. Não detalharei aqui, simplesmente lembrarei que %representa o arquivo inteiro, '<,'> representa a última seleção e 1,5representa as linhas 1 a 5 do arquivo.

Este parâmetro define as linhas que serão tratadas pelo comando global. Se nenhum intervalo for especificado, o comando global será usado %por padrão.

O argumento [padrão] é um padrão de pesquisa, como você costuma usar com o mecanismo de pesquisa. Como ele integra o histórico de pesquisa, você pode deixar esse campo em branco e o comando global usará o último padrão de pesquisa no histórico de pesquisa.

Finalmente, o parâmetro [command] é um comando ex, como você provavelmente está acostumado.

Agora, o comportamento do comando global é bastante simples:

  • Repita todas as linhas definidas no parâmetro [range]
  • Se a linha atual corresponder ao padrão definido, aplique o comando

Como o parâmetro [command] é um comando ex, você pode fazer muitas coisas. Vamos pegar o pseudo-código a seguir, que não é muito interessante e tem muitas mensagens de depuração:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"

echo "end of for loop"

Agora, digamos que você tenha certeza de que esse código funcione e que deseja excluir essas echoinstruções inúteis :

  • Você pode aplicar seu comando global em todo o arquivo para ter que acrescentar o comando com %(ou sem nada, pois %é o intervalo padrão).

  • Você sabe que as linhas que você deseja excluir correspondem ao padrão echo

  • Você deseja excluir essas linhas para usar o comando :delete que também pode ser abreviado comod

Então você simplesmente terá que usar a seguinte função:

:%global/echo/delete

Que também pode ser abreviado como

:g/echo/d

Observe que %desapareceu, globalé abreviado como ge deletecomo d. Como você pode imaginar, o resultado é:

var myList  = null
var i       = 0

myList = new List()

for (i=0; i<10; i++)
    myList.Add(i)

NOTA 1 Um ponto importante que demorei algum tempo a perceber é que o normalcomando é um comando ex, o que significa que você pode usá-lo com o comando global. Isso pode ser realmente poderoso: digamos que eu queira duplicar todas as linhas que contêm eco, não preciso de uma macro ou mesmo da fórmula mágica n.. Eu posso simplesmente usar

:g/echo/normal YP

E pronto:

var myList  = null
var i       = 0

myList = new List()
echo "List instantiated"
echo "List instantiated"

for (i=0; i<10; i++)
    myList.Add(i)
    echo i . " added to the list"
    echo i . " added to the list"

echo "end of for loop"
echo "end of for loop"

NOTA 2 "Ei, e se eu quiser usar meu comando em linhas que não correspondam a um padrão específico?"

globaltem um comando oposto vglobalabreviado vque funciona exatamente como globalexceto, exceto que o comando será aplicado em linhas que não correspondem ao parâmetro [pattern]. Dessa forma, se aplicarmos

:v/echo/d

No nosso exemplo anterior, obtemos:

echo "List instantiated"
    echo i . " added to the list"
echo "end of for loop"

O deletecomando foi aplicado em linhas que não continham echo.


Aqui espero que essas poucas dicas lhe dêem idéias sobre como se livrar do seu plug-in de múltiplos cursores e usar o Vim da maneira Vim ;-)

Como você pode imaginar, esses exemplos são bem simples e são feitos apenas para demonstrar que, quando você segue o caminho do Vim, raramente precisa de vários cursores. Meu conselho seria quando você encontrar uma situação em que você acha que seria útil, anotá-la e levar algum tempo depois para encontrar uma solução melhor. Em 99% das vezes, você encontrará uma maneira mais rápida / eficiente de fazer isso.

Também vou me repetir mais uma vez, mas realmente o incentivo a ler o Practical Vim de Drew Neil, porque este livro não é sobre "Como fazer isso ou isso no Vim", é sobre "Como aprender a pensar da maneira Vim" o que permitirá que você construa sua própria solução para seus problemas futuros em um bom caminho.


PS Agradecimentos especiais a @Alex Stragies por seu trabalho de edição e pelas correções que ele fez neste longo post.

statox
fonte
Resposta muito completa. Na verdade, eu conhecia todos esses comandos, mas nunca pensei em usá-los assim ... acho que preciso de mais prática. No entanto, devo dizer que às vezes o 'vim-way' leva mais tempo do que apenas usar algum plug-in (por exemplo, seu exemplo de CSS pode ser feito muito mais rápido com o plug-in que mencionei), e às vezes leva muito mais curto (na verdade, o vasto na maioria das vezes o vim é mais rápido que qualquer editor de texto, se usado corretamente).
tomasyany
Aliás, acho que sua resposta já está completa. Aceito, mas se você quiser adicionar mais detalhes, faça-o e ficarei feliz em lê-los.
tomasyany
1
@tomasyany: De fato, às vezes, o uso do "modo vim" pode parecer mais longo (não consigo contar quantas vezes passo mais tempo criando uma macro funcional do que se tivesse feito as alterações manualmente), mas com a prática, eventualmente, fica mais rápido. Uso o Vim há apenas um ano e estou (muito) longe de ser um especialista, mas sinto que minha edição melhora continuamente à medida que pratico.
statox
1
Provavelmente também deve mencionar o gnobjeto de texto. Ele aborda alguns casos de uso de vários cursores. Pesquise com /, então dgnou cgn, depois repita com ..
Justin M. Keyes
@ Justin, eu não estou realmente familiarizado gn, vou tentar e adicioná-lo depois. Valeu pelo aviso!
Statox
5

Seus casos de uso para mim parecem querer saber o .comando key (repita o último comando de edição)

  • Vá para o primeiro lugar, pressione i, insira seu texto,<ESC>
  • vá para o local 2, pressione .(Ponto) ==> Texto idêntico é inserido
  • Para descer uma linha aqui e inserir novamente (ao inserir em linhas consecutivas), pressione <ALT>-j.

Seu exemplo tex para mim é resolvido por:

I\section[]{}<ESC>hhiMy first Sec...<ESC>lll.

Alex Stragies
fonte
É uma solução bastante agradável. Eu conhecia perfeitamente o .comando principal, mas nunca pensei em usá-lo dessa maneira. Eu concordo que é uma boa maneira. Mas sua resposta não se refere à questão real, portanto não seria apropriado aceitá-la, eu acho.
precisa saber é o seguinte
1
Bem, sua pergunta (depois de adicionar os casos de uso desejados) me lembrou "Eu realmente gosto das minhas tesouras e quero apertar um parafuso com elas. Diga-me como". E me apontando-lo para um uso bacana para uma chave de fenda;) (I adicionado como uma resposta, porque eu não sei, como fazer a formatação nos comentários)
Alex Stragies
4

Mais maneiras do Vim.

Primeira tarefa:

\section[foobar baz]{foobar baz}

Fluxo de trabalho:

\section[]{}
hh
ifoobar baz<Esc>
$.

Segunda tarefa:

variable1 = 2
my_variable2 = 12
var3 = 14

Comando:

3:norm ea_somestuff

Resultado:

variable1_somestuff = 2
my_variable2_somestuff = 12
var3_somestuff = 14
romainl
fonte