vim: Continuar macro após erro no submacro?


14

Estou no processo de embelezar algum código-fonte usando o vim. {1}

Criei algumas macros do vim que executam as etapas individuais: remoção do espaço em branco à direita, remoção de linhas vazias depois {, remoção de linhas vazias antes {, esse tipo de coisa.

Agora, quero criar uma macro que execute todas as macros individuais em sequência. No entanto, quando a primeira macro recursiva termina (porque não consegue mais encontrar correspondências -> erro de correspondência), minha macro "wrapper" também termina.

Existe uma maneira de fazer uma macro vim continuar depois que um submacro gerou um erro?

{1} Eu sei sobre reformatters automáticas. Eu posso até usá-los no meu problema atual. Eu apenas mencionei a reformatação de fonte pelo bem do exemplo. Não poste nenhuma resposta sobre esse embelezador de origem ou sobre isso. A questão não é sobre reformatação de código em si , mas sobre macros do vim.

Exemplo:

  • Macro 1 - aparar espaços em branco à direita - qw/\s\+$d$@wq
  • Macro 2 - excluir linhas vazias antes} - qe/\n\n *}dd@eq
  • Macro do invólucro - retabitação, Macro 1, Macro 2 - qr:retab@w@eq

Quando executo o invólucro - @r- ele irá retabular e, em seguida, execute a Macro 1 até que não seja encontrado mais espaço em branco à direita, e finalize ( sem executar a Macro 2).

Esclarecimento:

O que estou procurando é como chamar um submacro para que, quando esse submacro termine, a macro de chamada continue?

Respostas:


12

Eu sugiro que você use :trypara "absorver" o erro do submacro.

Aqui está um exemplo bobo:

:let @a='f|dt|@a'
:let @q=':try|exe "norm! @a"|endtry^Mj0@q'
@q

Sua macro de wrapper ficaria assim:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'

Embora garyjohn tenha fornecido uma solução alternativa por não ter um erro em um submacro, esta é a única resposta que realmente lida com esse erro. Eu tenho que me desculpar; Eu não verificar a sua resposta em tempo útil para que você obtenha o (agora expirado) de recompensas ... :-(
DevSolar

25

Se o comando com falha for uma substituição que não está encontrando seu padrão, por exemplo,

:%s/foo/bar/

quando foonão existe no buffer, você pode adicionar o esinalizador para ignorar esse erro, por exemplo,

:%s/foo/bar/e

Vejo

:help :s_flags

Você pode dizer ao Vim para ignorar os erros de alguns comandos: ex, precedendo-os com :silent!. Vejo

:help :silent


Editar após a adição de exemplo à pergunta

Macro 1 e Macro 2 são recursivas e nenhum mecanismo explícito para terminar a recursão. Meu palpite é que um dos testes internos do Vim para recursão ilimitada está sendo acionado, o que gera um erro. Se a Macro 1 estiver gerando esse erro, esse erro encerrará a execução da Macro Wrapper logo após @w.

Minha sugestão seria limitar o número de vezes que suas macros estão sendo executadas reescrevendo-as como: ex comandos e limitando o intervalo de linhas nas quais elas são executadas. Por exemplo:

qw:%s/\s\+$//^Mq
qe:%s/\n\n *}/\r}/^Mq

onde ^Msignifica digitar sua tecla Enter ou Return. Não testei esses itens juntos na macro Wrapper, mas acho que você poderá corrigir os erros que cometi.


Não é uma substituição no meu caso, mas uma simples descoberta (ou seja, /foo). Embora de :silent!fato o truque do submacro recursivo não tenha abortado a macro do wrapper, agora o submacro não termina de jeito nenhum ... e suspeito que fazê-lo de alguma forma terminar novamente também encerraria a macro do wrapper. Parece que estou preso. : - \
DevSolar 5/05

É difícil dizer o que pode estar errado sem ver as macros que você está usando ou um exemplo simples que apresenta o mesmo problema.
precisa saber é o seguinte

Adicionado um exemplo.
DevSolar

2

O que funcionou para mim foi uma combinação das respostas de Peter Rincker e @garyjohn. Separadamente, eu continuava recebendo problemas estranhos.

nnoremap <leader>rt :silent! %s/\s\+$//e<CR>
let @r='\rt'
let @t=':try|silent! exe "norm! @r"|endtry|w^M'

Eu acho que a silent!no <leader>rt, e os personagens da tubulação entre o endtryeo wforam as chaves - simplesmente ter a quebra de linha após a endtryfalha. Eles tryfuncionaram quando eu os inseri, mas quando executados como uma macro, o erro sobre o texto da pesquisa não foi encontrado continuaria sendo gerado.


1

Rotineiramente, crio macros dinamicamente quando preciso realizar uma tarefa repetitiva entre muitos arquivos. No meu caso, tenho o NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ) instalado no VIM, que cria uma vsplitjanela e, à esquerda, tenho uma lista de todos os arquivos em o diretório atual. Em um exemplo, preciso encontrar a primeira instância da string MY_TESTno arquivo e excluir, se houver, um prefixo rotulado como CUSTOM_PREFIX-dessa linha, salvar o arquivo e passar para a próxima.

Aqui está como eu tenho essa macro trabalhar em cerca de 2000 arquivos no diretório atual. Eu poderia escrever um script bash para fazer isso, mas é mais rápido no VIM, no meu caso. As +teclas denotam ser pressionadas sim

# Start recording a macro sequence to register 'A'

q,a

# Search silently for the string "MY_TEST"; DO NOT report an error
# if the string could not be found.
:silent! /MY_TEST


# Replace, on just the current line, the string "CUSTOM_PREFIX-", with
# nothing (ie: delete it), and suppress any warning messages if the
# string could not be found on the current line.
:s/CUSTOM_PREFIX-//e


# Now issue some UI commands. CTRL-W then and arrow key lets you hope
# between tabs/splits/windows within vim.

CTRL+ W,

# Scroll down to the next file in the list in NERDtree



# Open the next file

ENTER

# End the macro

q

# Run the macro a thousand times in VIM

1000, @,a

Espero que isto ajude!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.