Como depurar um mapeamento?

66

Vejo muitas perguntas aqui em que um usuário tem um mapeamento que não funciona e, na maioria das vezes, os motivos são bastante semelhantes.

Sugiro fazer desta pergunta uma referência para esse tipo de pergunta, para fornecer um procedimento completo para depurar um mapeamento. Se um usuário como um problema com um mapeamento, ele pode ser redirecionado aqui para eliminar os problemas mais comuns.

É claro que ainda haverá casos particulares que exigirão uma pergunta dedicada e não serão abordados aqui.

statox
fonte

Respostas:

89

Seu mapeamento não faz o que deve fazer ou se comporta de maneira diferente do esperado, várias etapas a seguir para solucionar isso:

Verifique se a chave está efetivamente mapeada para o que deve fazer

O Vim fornece um comando :map. Por padrão (quando nenhum argumento é fornecido), o comando mostrará todos os mapeamentos criados atualmente. Aqui está um exemplo do resultado do comando:

resultado de <code>: map </code>

Como sempre, o documento é seu amigo: :h map-listing

Você pode ver na primeira coluna o modo do mapeamento ( npara o modo normal, vpara o visual, etc.), a segunda coluna mostra as chaves mapeadas e a última coluna para a qual as chaves estão mapeadas. Observe que, antes das ações mapeadas, alguns caracteres adicionais podem aparecer, é importante entendê-los:

  • * indica que não é remapeável (ou seja, não é um mapeamento recursivo, veja know when to use noremais adiante nesta resposta)
  • & indica que somente os mapeamentos locais de script são remapeáveis
  • @ indica um mapeamento local de buffer

Ao pedir ajuda sobre um mapeamento, é bom adicionar essas informações, pois pode ajudar outras pessoas a entender o comportamento do seu mapeamento.

É possível restringir o prompt a um modo particular com a irmã-comandos de :map, como :vmap, :nmap, :omap, etc.

Agora, para restringir sua pesquisa ao mapeamento problemático, você pode passar a sequência de teclas que você está depurando como o parâmetro dos comandos, assim:

:map j
:map <Leader>m
:map <F5>

Observe que a <Leader>chave será substituída pelo seu valor real na lista.

Se o resultado do comando mostrar que suas chaves estão mapeadas corretamente, provavelmente significa que o problema não vem do Vim, mas do seu terminal ou do ambiente da área de trabalho. Veja a parte Verifique se seu mapeamento é realmente interceptado pelo Vim

Se o resultado do comando mostrar que suas chaves não estão mapeadas corretamente, consulte a parte a seguir.

Verifique o que substituiu seu mapeamento

Outro uso conveniente do :mapcomando é combiná-lo com verbose: Isso solicitará o último arquivo que modificou seu mapeamento.

Por exemplo, veja estas duas capturas de tela que são os resultados de :verbose map: a primeira é um mapeamento modificado por my .vimrce a segunda é um mapeamento criado por um plugin:

Conjunto de mapeamento do vimrc

Conjunto de mapeamento de um plug-in

Agora, se você vir que outro script modificou seu mapeamento, precisará ver se é possível removê-lo ou modificar seu comportamento. (Observe que alguns plugins fornecem variáveis ​​para ativar / desativar seus mapeamentos, infelizmente nem todos os plugins fazem isso)

Se o último arquivo que mudou seu mapeamento for seu .vimrc, verifique se não há outra linha que também defina um mapeamento para a mesma chave. O .vimrcarquivo substituirá felizmente quaisquer mapeamentos pelo último de seu tipo no arquivo.

Verifique se o seu mapeamento é realmente interceptado pelo Vim

Várias situações podem indicar que o Vim não intercepta sua chave:

  • O comando :mapmostra que sua tecla está mapeada corretamente, mas pressioná-la não faz nada.
  • Seu mapeamento funciona no gVim (GUI), mas não faz nada no terminal Vim
  • Seu mapeamento funciona em um emulador de terminal definido, mas não em outro
  • Seu mapeamento funciona em um sistema operacional definido, mas não em outro.

Provavelmente, é causada por uma das duas seguintes coisas:

  • Algo intercepta a chave antes do Vim : podem ser diferentes aplicativos: seu SO, seu ambiente de trabalho, seu emulador de terminal, Tmux (se você o usar) ...

    Para solucionar isso, você deve:

    • Tente remover temporariamente o seu .tmux.confse você usar o tmux
    • Consulte o documento do seu terminal ou do seu ambiente de trabalho.

    Você também pode se referir a sites irmãos como superusuário , Unix e Linux , askUbuntu , etc ...

    Se esse for o problema, você terá duas soluções: você gasta (muito) tempo para alterar o comportamento do aplicativo que causa o problema ou encontra outra combinação de teclas para mapear que não é interceptada por outro aplicativo.

  • Seu emulador de terminal não pode lidar com a combinação de teclas que você está tentando mapear : os emuladores de terminal são implementados de maneira diferente e alguns deles não conseguem lidar com uma combinação de teclas específica. (A razão pela qual eles não podem estar fora do escopo desta pergunta, consulte o documento ou os sites irmã mencionados anteriormente para obter mais detalhes).

    Nesse caso, você não tem muitas soluções: ou você muda sua chave por outra que é tratada adequadamente pelo seu terminal ou o seu emulador de terminal.

Verifique as armadilhas comuns

Alguns problemas nos mapeamentos são bastante recorrentes e, principalmente, relacionados à sintaxe do vimscript. Se o seu mapeamento tiver um comportamento inesperado, lembre-se de verificar os seguintes pontos:

  • Não coloque um comentário na mesma linha do seu mapeamento ; em vez disso, coloque o comentário na linha acima. Exemplo:

    Não faça isso:

    inoremap ii <esc>    " ii to go back into normal mode
    

    O Vim considerará os espaços em branco, o "e o comentário como parte do mapeamento, o que resultará em um comportamento inesperado.

    Em vez disso, faça isso:

    " ii to go back into normal mode
    inoremap ii <esc>
    

    Isso é mais fácil de ler e não atrapalha o seu mapeamento.

  • Não canalize seus comandos com| . Exemplo:

    Não faça isso:

    nnoremap <Leader>x :w | !% python -m json.tools
    

    O Vim considerará o canal |como uma terminação de comando: quando você fornecer seu .vimrcmapeamento nnoremap <Leader>x :wserá criado, o comando externo !% python -m json.toolsserá executado.

    Em vez disso, faça isso:

    nnoremap <Leader>x :w <bar> !% python -m json.tools
    

    Veja uma explicação sobre<bar> .

  • Saiba quando usar nore: sempre .

    LearnVimscriptTheHardWay explicar isso muito claramente: Nunca use map, nmap, vmap, etc ... Sempre prefiro a versão nore: noremap, nnoremap, vnoremap, etc ... Por quê? noresignifica non-recursivemapeamento, significa que o lado direito do mapeamento será considerado o recurso interno, mesmo que você o tenha remodelado. Exemplo:

    Digamos que você queira mapear >para excluir uma linha e -aumentar o recuo de uma linha. Se você não usar mapeamentos não recursivos, faça isso:

    ( Não faça isso, é por exemplo )

    nmap > dd
    nmap - >
    

    Quando você acertar >sua linha será excluída, isso é bom. Mas quando você atingir -sua linha, também será excluído em vez de recuado. Por quê? Porque o Vim entendeu "Eu recebi um hit no -qual eu deveria traduzir para o >qual eu deveria, por sua vez, traduzir para dd".

    Em vez disso, faça isso

    nnoremap > dd
    nnoremap - >
    

    Dessa forma, o Vim será traduzido -como >e não tentará fazer nenhuma outra tradução por causa do nore.

    Nota de edição "Sempre" pode ser uma resposta exagerada em alguns casos, você precisará usar o formulário de mapeamento recursivo, mas isso não é muito comum. Para esclarecer, citarei @romainl nesta resposta :

    Use um mapeamento recursivo apenas se você pretende usar qualquer outro mapeamento em seu mapeamento. Use mapeamentos não recursivos, se não o fizer.

  • Lembre-se de que algumas combinações de teclas são equivalentes : Devido aos códigos hexadecimais produzidos, algumas combinações de teclas serão interpretadas pelo Vim como outra chave. Por exemplo

    • <C-h> é equivalente a <backspace>
    • <C-j> Como <enter>
    • Nos teclados franceses, <M-a>é o mesmo áe o mesmo ocorre com todos os <m-mapeamentos. Como o @LucHermitte apontou no comentário, há um problema com plugins usando esse tipo de mapeamento como o vim-latex.
    • <C-S-a>é equivalente a <C-a> . Mapear Ctrl + letra maiúscula separadamente de Ctrl + letra minúscula não é possível, devido à maneira como os terminais enviam códigos ASCII.

    Quando seu mapeamento parece afetar outra tecla, tente usar outra combinação lhs, se isso resolver o problema, inspecione quais códigos hexadecimais são enviados ao Vim.

  • Verifique se seu líder está definido corretamente : Se seus mapeamentos envolventes<leader>não funcionarem e você mudou seu líder com o comandomapleader, verifique se a definição de seu líder é feita antes da definição dos mapeamentos. Caso contrário, o Vim tentará criar mapeamentos com uma chave que não é a que você pensa. Além disso, se você quiser usar a barra de espaço como líder (o que é bastante atual), certifique-se de usar a notação correta:let mapleader = "\<Space>"

Seu mapeamento ainda não funciona?

Se você seguiu todas as etapas desta resposta e seu mapeamento ainda não funciona como você deseja, provavelmente solicita ajuda neste site.

Para ajudar as pessoas a ajudá-lo, lembre-se de fornecer algumas informações cruciais como:

  • O comando que você usou para definir seu mapeamento.
  • O que você espera que seu mapeamento faça.
  • Uma descrição precisa do problema:

    "Não funciona" não será realmente útil para pessoas que tentarão ajudá-lo. Você deve especificar se o mapeamento não faz nada ou como se comporta de maneira diferente do que você esperava.

  • Indique também que você realmente seguiu as etapas descritas aqui e os resultados obtidos :mape:verbose map

Tudo isso economizará a você e aos usuários do site muito tempo.


Um comando útil: :unmap

Às vezes, pode ser útil redefinir um mapeamento sem sair do Vim para ajudar a depurar seu comportamento.

Para fazer isso, você pode usar o comando :unmap <key>que removerá o mapeamento atribuído aos <key>modos Normal, Visual e Operacional pendente. :iunmapremoverá os mapeamentos para o modo Inserir. Para outros modos, consulte :help :unmap.


Referências

Uma excelente introdução ao mapeamento: learnvimscriptthehardway (E muitos outros aspectos do Vim)

O doc: :h mapping, :h :map

A seção 20 das Perguntas frequentes do Vim trata de mapeamento e contém perguntas interessantes:

E um bônus: uma pergunta sobre práticas recomendadas para descobrir quais chaves usar em seu mapeamento

statox
fonte
2
Compartilhar minha experiência com outros usuários, conforme sugerido por nosso moderador . E I see a lot of questions on here where a user has a mapping which doesn't work and most of the time the reasons are pretty similarcomo eu disse na primeira linha da minha pergunta, a reunião desses motivos deve permitir reduzir o número de perguntas duplicadas sobre o mapeamento.
Statox
11
Um problema recorrente com os teclados franceses e vim-latex: <m-i>e ésão iguais para o vim, e o mesmo para todas as teclas meta +: eles estão associados a um diacrítico diferente.
Luc Hermitte
11
Também é importante saber ler os mapeamentos de buffer-local quando pedimos sua definição com :map {sequence}-> há um *destaque inverso no que o vim imprime antes da ação associada.
Luc Hermitte
2
Às vezes, queremos realmente depurar o que acontece. Normalmente, quando o mapeamento chama um mapeamento de plug, ou uma função com um nome impossível de lembrar ou com parâmetros complexos. Nesse caso, podemos executar: :debug normal {keysequence}(sem qualquer bang), ou :debug i{keysequence}para mapeamentos modo de inserção, etc. Se a sequência de teclas contém coisas como chaves especiais ( <cr>, <left>, <c-x>, <m-i>, <leader>...). Então precisamos jogar com execute + aspas duplas + barra invertida -> :debug execute "normal \<leader>\<cr>Z".
Luc Hermitte
2
Em relação às meta-seqüências, esse é um ponto antigo do FAQ, já que o vim-latex optou por usar coisas como <m-i>. A maioria dos usuários não usa a meta-chave, pois é fortemente orientada para executar o Vim no terminal - onde a meta-chave não pode ser usada simplesmente. Precisamos usar gvim ou macvim para perceber o problema.
precisa