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
:g/^Level \d:/{COMMANDS}
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
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
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 decimal d
, ocupando pelo menos 2 espaços 2
e preenchendo com 0 0
. 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 contagem i
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
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
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 digitado I
(ou qualquer outra operação) você mesmo no modo normal. usamos o !
after normal
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 palavras 2w
, puxar até o i-ésimo caractere 'h' y" . i . "th
, mover para o final da linha $
e colar p
.
É 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.
:unlet! i
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.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
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ívelsubstitute(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:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Via comando normal:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Exemplo de entrada:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Exemplo de saída:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More