Tenho um problema que consigo pensar em duas abordagens gerais para resolver, mas não conheço detalhes específicos para nenhuma delas.
...
Level 1: cũng also
Level 1: và and
Level 1: như like; such as
Level 2: các plural marker
Level 2: của belonging to
...
Para cada linha que começa com "Nível n", quero inserir um número, começando com "01". Para simplificar, vamos acrescentar o número.
Abordagem 1: Selecione manualmente todas as linhas com o mesmo nível. Invoque a magia que estou prestes a aprender.
Abordagem 2: escreva uma pesquisa e substitua o que corresponde a todas as linhas com o nível especificado, que em cada correspondência inclui um número no texto de substituição, que é incrementado em um a cada correspondência.
Encontrei perguntas semelhantes no StackOverflow ou em outros sites do Vim, mas cada um parece ter um ou mais dos seguintes problemas:
- Trata-se de inserir o número da linha atual em vez de um número arbitrário, mas incrementador.
- Não zera o número.
- Na verdade, não funciona para seleções no meu Vim 7.4 em execução no Windows 7. (Essas resultam no erro
E481: No range allowed
.)
Estou executando o gVim no Windows com o mswin.vim, mas uma solução que funcione em todas as instalações do vanilla Vim sem precisar personalizar a configuração pode ser a melhor.
Respostas:
Semelhante à resposta em https://vi.stackexchange.com/a/818/227 , você pode usar o comando global.
Com ele, você pode instruir o vim a procurar linhas correspondentes a um padrão e executar comandos nele.
No seu caso, você deseja anexar texto às linhas que começam com "Nível N:", para que nosso comando global possa ser
Usando o comando substitute (substituição de expressão regular) para o comando
Os comandos são mais divertidos. Eu normalmente gosto de fazer uma substituição de expressão regular para coisas como essa, pois é fácil usar variáveis.
Exemplo para sua pergunta
Como funciona
Na seção de substituição de um comando de substituição pode ser uma expressão.
A primeira coisa que faremos é definir uma variável
i
para ser o número inicial. Eu escolhi 1, mas qualquer número serve.let i = 1
Em seguida, executamos nosso comando global, que nos prepara para executar uma ação nas linhas correspondentes.
g/^Level \d:/
Teremos nosso comando global inserido o valor e incrementado nosso contador usando o comando de substituição e o comando let.
s/^/\=printf("%02d ", i)/ | let i = i+1
A expressão regular do comando de substituição encontra o início da linha
^
e a substitui por uma expressão, e nossa expressão será o resultado de uma impressão formatada. Como na linguagem C, o printf do vim usa parâmetros de formatação.%02d
significa converter um argumento como se fosse um número decimald
, ocupando pelo menos 2 espaços2
e preenchendo com 00
. Para detalhes e outras opções de conversão (incluindo formatação de ponto flutuante), consulte:help printf
. Damos a printf nossa variável de contagemi
e ela nos dá01
a primeira vez,02
a segunda vez, etc. Isso é usado pelo comando de substituição para substituir o início da linha, inserindo efetivamente o resultado da impressãof no início.Note que eu coloquei um espaço após o d:
"%02d "
. Você não pediu na pergunta (e não vi exemplo de saída), mas suspeitei que você desejasse separar o número da palavra "Nível". Remova o espaço da sequência fornecida para printf para ter o número inserido ao lado de L no nível.Finalmente, isso
let i = i + 1
incrementa nosso contador após cada substituição.Isso pode ser aplicado geralmente para substituir partes de linhas correspondentes a outros critérios por dados funcionais arbitrários.
Usando comandos normais combinados
Isso é bom para inserções simples ou edição complexa. Assim como no substituto, usaremos global para corresponder, mas, em vez da substituição da expressão regular, executaremos uma série de operações como se digitadas pelo usuário.
Exemplo para sua pergunta
Como funciona
Os valores usados são muito semelhantes ao substituto (ainda estamos usando printf para formatar nosso número para torná-lo 0 preenchido com 2 dígitos), mas a operação é diferente.
Aqui usamos o comando execute, que pega uma string e executa a string como um comando ex (
:help :exe
). Construímos uma string que combina "normal! I" com nossos dados, que serão "normais! I01" na primeira vez e "normal! I02" na segunda vez, etc.O
normal
comando executa operações como se estivesse no modo normal. Neste exemplo, nosso comando normal éI
, que insere no início da linha. Se tivéssemos usado,dd
ele excluiria a linha,o
abriria uma nova linha após a linha correspondente. É como se você tivesse digitadoI
(ou qualquer outra operação) você mesmo no modo normal. usamos o!
afternormal
para garantir que nenhum mapeamento fique no nosso caminho. Veja:help :normal
.O que é inserido então é o valor da nossa printf, como no primeiro exemplo de uso de substituto.
Esse método pode ser mais sofisticado que o regex, porque você pode fazer coisas como
execute "normal! ^2wy" . i . "th$p"
: o que vai para o início do texto^
, avançar duas palavras2w
, puxar até o i-ésimo caractere 'h'y" . i . "th
, mover para o final da linha$
e colarp
.É quase como executar uma macro, mas na verdade não usa um registro e pode combinar seqüências de caracteres de qualquer expressão. Eu acho isso muito poderoso.
Abordagem em que cada nível tem seu próprio contador
Você pode querer que cada nível obtenha seu próprio contador. Se você souber o número máximo de níveis antes do tempo, faça o seguinte (adicionar código extra para encontrar o nível mais alto pode não ser muito difícil, mas tornaria essa resposta muito longa. Isso está demorando muito).
Primeiro, liberte i, caso já o tenhamos usado como um número inteiro. Não podemos converter i em uma lista, temos que criá-lo dessa maneira.
Em seguida, vamos definir i para ser uma lista contendo o número de níveis. Você mostrou 2 na sua pergunta, mas vamos assumir 10 para se divertir. Como a indexação de lista é baseada em 0, e não quero me preocupar em corrigir uma baseada em 1, como a sua lista, apenas criaremos elementos suficientes (11) e nunca usaremos o índice 0.
Em seguida, precisamos de uma maneira de obter o número do nível. Felizmente, o substituto também está disponível como uma função, portanto, forneceremos nossa linha e extrairemos o número do nível
substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Como agora eu sou uma lista de 11
1
s (cada índice é o contador do nosso nível), agora podemos ajustar qualquer um dos exemplos acima para usar o resultado dessa substituição:Via comando substituto:
Via comando normal:
Exemplo de entrada:
Exemplo de saída:
fonte
Você pode criar a partir de https://stackoverflow.com/a/4224454/15934 para zerar seus números.
Mas, para simplificar a ação dos números de preenchimento, eu usaria um par de funções e um comando:
Depois, selecione suas linhas e digite
:PrependNumber
(você verá:'<,'>PrependNumber
. [Nota: o comando aceita um parâmetro opcional: o padrão antes do qual o número será inserido]fonte
line(".")
significa "usar o número da linha atual"? Esse foi o meu problema 1. Com respostas anteriores que pude encontrar.$HOME/vimfiles/plugin/whatevernameyouwish.vim
. Ou mesmo o seu$HOME/_vimrc
(nome do arquivo do Windows), se preferir (pela primeira vez). Se você não tem certeza do que $ HOME é em sua máquina, pedir vim o que ele pensa que é ->:echo $HOME
:source
se o script vim está instalado corretamente no diretório certo ({rtp} / plugin ou {rtp} / ftplugin / {filetype} / ftplugin para plugins específicos do tipo de arquivo).:source
é o que tivemos que jogar há mais de uma década e meia atrás.Você pode abordá-lo gravando uma macro. Começando com seu arquivo original, anteceda a primeira instância com o número.
Mova o cursor para
01
, selecione e puxe-o comyiw
. Agora você deseja registrar suas ações a partir deste ponto.qq/^Level 1<CR>P<C-A>A<space><esc>0yiwq
qq
Iniciar uma macro no registro q/^Level 1<CR>
Procure uma linha começando com "Nível 1"P
cole antes do cursor (contém seu número)<C-A>
incrementa o númeroA<space><esc>
Inserir um espaço após o número0
Mover para o inícioyiw
puxar o número atualq
Terminar a macroRepita essa macro usando
@q
.fonte
<C-A>
controle + um? Isso seleciona tudo no Vim no Windows.