Como criar um comando em um plug-in que pode ser chamado a partir do vimrc

8

Estou trabalhando em um plug-in que permite aos usuários criar operadores personalizados. Os operadores aplicariam uma expressão VimL ao objeto de movimento ou texto sobre o qual o operador se move.

Mantendo uma interface de usuário limpa

Eu acho que a interface mais limpa para definir os operadores personalizados seria usar um comando. Eu defini um comando :MapExpressque seria chamado assim:

:MapExpress cd '/* ' . v:val . ' */'

Isso criaria um operador no modo Normal e um mapeamento no modo Visual para cdenvolver o movimento ou a seleção nos delimitadores de comentários no estilo C.

Claro, aqui está um problema. Você não pode chamar um comando definido em um plug-in do seu .vimrcarquivo.

Soluções alternativas pouco satisfatórias

Eu vim com algumas soluções alternativas com as quais não estou totalmente feliz.

O usuário usa autocmd VimEnter *para chamar o comando

Embora isso funcione, ele adiciona muita "sobrecarga mental". Eu acho que muitos usuários do Vim não têm uma sólida compreensão de como autocmdfunciona.

Usuário cria um arquivo no ~/.vim/after/plugin/qual chama o comando

Novamente, isso funcionaria, mas tem a desvantagem de que essa parte da configuração está em seu próprio arquivo, facilmente perdida e esquecida.

Movo as definições de comando para o autoload/diretório do meu plug-in e o usuário chama algum método que aciona o carregamento do arquivo e, portanto, os comandos a serem definidos

Isso ficaria assim:

call express#init()
MapExpress cd '/* ' . v:val . ' */'

Um pouco melhor, mas isso causaria confusão sobre se o express#init()método é necessário para o plugin funcionar.

Alternativas ao uso de um comando

Também considerei algumas alternativas ao uso de um comando para definir o operador, mas cada uma tem suas ressalvas.

O usuário chama uma função para definir os operadores

Isso seria algo como isto:

call express#operator('cd', '"/* ".v:val." */"')

Isso não é terrível, mas tem a desvantagem de exigir uma expressão citada. Isso pode ser irritante quando você deseja usar aspas em sua expressão.

Usuário usa um <expr>mapeamento

Como isso:

nmap <expr> cd express#nmap('"/* ".v:val." */"')
xmap <expr> cd express#xmap('"/* ".v:val." */"')

Ele tem o mesmo requisito de expressão tediosa e também viola o DRY, a menos que você introduza uma variável (não ideal).

Ok, e daí?

Aqui estão todas as minhas idéias e por que não gosto de nenhuma delas. Estou sendo muito exigente? Existe alguma solução melhor que eu não tenha pensado?

tommcdo
fonte
2
A solução de carregamento automático não me parece muito ruim, especialmente se você usar um nome de função ligeiramente mais específico do que está fazendo. É difícil criar um bom exemplo sem saber para que outra funcionalidade seu plug-in tinha que o init de carregamento automático não é necessário, mas talvez algo assim call express#initMapCommands()? Qualquer coisa que exija citações extras, no entanto, é uma péssima idéia.
Rich
É para isso que estou me inclinando, eu acho.
21415 Tommycdo em
@ tommcdo e hoje eu aprendi como <q-args>realmente funciona. Obrigado
D. Ben Knoble

Respostas:

5

Parece-me que você está procurando :runtime. Você pode executar perfeitamente os comandos definidos nos plugins do seu .vimrc, mas precisa saber o nome do plug-in (que o define) antes disso.

" 1- Prepare the plugin-suite if it's managed through VAM/Vundle/NeoBundle/...
ActivateAddons FooBar

" 2- Be sure the plugin is loaded
runtime plugin/foobar.vim

" 3- And finally run (defensively) the command
if !exists(':FooBar')
   echo "Sorry some initializations will be ignored as foobar is nowhere to be found"
else
   FooBar abc
   FooBar 135468
endif

Nota: ao contrário da solução de carregamento automático, essa abordagem não trava a fonte .vimrc. Se um plug-in de carregamento automático não puder ser encontrado (através da execução de uma função), o vim lançará um erro. :runtimepermanece silencioso se nenhum plug-in puder ser carregado.

Luc Hermitte
fonte
11
Isso é muito trabalho para o usuário final. Como desenvolvedor de plug-ins, estou tentando minimizar o esforço necessário para usar meu plug-in.
31515 Tommcdo
Esta solução é para um .vimrc que você pode implantar onde seu plug-in não está instalado. Para um guia de instalação simplificado, é apenas :runtime. Caso contrário, use uma opção, como sugerido pelo romainl.
Luc Hermitte
Mesmo assim, isso exige que o usuário saiba onde está o arquivo. Se eles usam um gerenciador de plugins, pode ser um lugar menos óbvio que plugin/.
31515 Tommcdo
Se eles usam um gerenciador de plugins, ele sempre estará presente plugin/- se você organizar seu "projeto" / repositório dessa maneira. Os gerenciadores de plugins atualizam automaticamente a 'runtimepath'opção.
Luc Hermitte
Oh, bom argumento.
tommcdo
2

Uma lista seria a IMO a solução mais fácil:

let g:pluginname_my_operators = [
    ['cd', '/* ' . v:val . ' */'],
    ['cm', '<em>' . v:val . '</em>']
]

Verifique g:pluginname_my_operatorsquando você inicializa seu plug-in e executa :MapExpressem cada item, se aplicável, enquanto ainda permite que seus usuários usem o comando para definição on-the-fly.

romainl
fonte
2
Isso realmente precisaria de mais citações ... v:valdeve fazer parte da sequência, porque é avaliada quando os internos do mapa são chamados. Penso que qualquer solução que envolva citações seja inferior ao ideal.
22415 Tommcdo