mapeamento para incluir o símbolo no cursor com uma expressão que contém o símbolo


7

Estou lendo as postagens de script do vim há uma hora, mas tenho medo de não ter as habilidades necessárias para aplicá-las ao meu problema. Ao editar matemática em documentos em látex, frequentemente desejo substituir símbolos matemáticos como +, -, = por \ Pad {+}, \ Pad {-}, \ Pad {=}, em que \ Pad é uma macro de látex I ' definido para colocar espaço ao redor do símbolo. Gostaria de colocar meu cursor em um símbolo assim, digitar algumas letras, dizer ;Pe fazer com que essa ação substitua o símbolo por

\Pad{whatever the symbol under the cursor is}

Qualquer ajuda seria muito apreciada!

`

Respostas:


5
function! s:PadMacro(type) abort
    if a:type ==# 'char'
        normal! `[v`]d
    elseif a:type ==# 'line'
        normal! '[V']d
    elseif a:type ==# 'v'
        normal! `<v`>d
    else
        return
    endif
    let string = '\Pad{' . @" . '}'
    silent execute "normal! i\<c-r>=string\r"
endfunction
nnoremap <silent> ;P :set operatorfunc=<sid>PadMacro<cr>g@
vnoremap <silent> ;P :<c-u>call <sid>PadMacro(visualmode())<cr>

Se você colocar o código anterior no seu vimrc, ele deve fazer o que você deseja.

Para usá-lo, bateu ;P{motion}ea PadMacro()função deve incluir os caracteres cobertos por {motion}com \Pad{e }.

Exemplos de uso:

  • ;Plcolocar o caractere embaixo do cursor (porque lé um movimento que cobre o caractere embaixo do cursor)
  • ;Piwcolocar a palavra sob o cursor (porque iwé um objeto de texto que cobre todos os caracteres dentro da palavra sob o cursor)
  • ;Piscolocar a frase na qual o cursor está (porque isé um objeto de texto que cobre todos os caracteres dentro de uma frase)
  • ;P$ para colocar os caracteres entre o cursor e o final da linha
  • ;P para incluir os caracteres visualmente selecionados

Tudo o que é feito pela PadMacro()função é considerado uma edição única, o que significa que é repetível em pontos.
Em outras palavras, se você tiver várias partes semelhantes de texto para anexar, \Pad{}não há necessidade de clicar no mapeamento todas as vezes, apenas na primeira vez (depois disso, você pode pressionar .para repetir sua última edição).

Para obter uma lista completa de texto-objetos sobre os quais você pode aplicar seu gabinete, consulte:
:help text-objects.


Fabuloso, muito obrigado @saginaw. Na verdade, tenho alguns comandos de espaçamento diferentes que uso, como \ pad, \ ppad, além do Pad. Obviamente, eu poderia duplicar a macro para cada uma delas, mas, para fins instrucionais, presumo que há uma maneira de passar um argumento para a macro, modificar a linha "let string" para inserir o argumento em vez de Pad e definir um noremap diferente para cada opção, por exemplo,; p iria inserir \ pad,; pp iria inserir \ ppad? Obrigado novamente!
Leo Simon

@LeoSimon Você pode definir um grupo inteiro de mapeamentos com um único forloop e o :executecomando. Veja aqui um exemplo: github.com/romainl/dotvim/blob/master/vimrc#L307-L312 Não deve ser difícil fazer a mesma coisa para seus mapeamentos. No entanto, não sei como passar "pad", "ppad", ... como argumento para a função. Eu tenho uma ideia (depois de ler :h g@, parece que você pode adicionar um grupo opcional de argumentos ...e acessar o primeiro argumento deste grupo a:1), mas não consegui escrever uma função de trabalho. Se eu puder, eu aviso você.
Saginaw

Obrigado @saginaw, comecei no loop for, mas, infelizmente, não consegui passar da primeira base. Tentei o seguinte como um passo inicial: dentro de sua macro,
Leo Simon

@LeoSimon Espero que o nome PadMacronão seja muito enganador, porque é apenas uma função vimscript. Eu chamei assim porque você disse que \Pad{}era interpretado como uma macro de látex. Mas se você preferir, pode chamá-lo de qualquer outra coisa ( PadEnclosurepor exemplo). Para os mapeamentos, digamos que você tem 3 funções MyFunctionA, MyFunctionBe MyFunctionC, cada um aplicando uma certa transformação no seu texto. E você quiser mapeá-los para ;Pa, ;Pbe ;Pc. Em seguida, o código a seguir deve poder fazer isso por você: paste.debian.net/plain/356949 Não testado, portanto, não tenho certeza de que funcione.
Saginaw

Obrigado! @saginaw. PadMacro está perfeitamente bem. Seu loop funcionou lindamente. Tudo ficaria um pouco mais elegante se eu pudesse incluir a função de script real no loop. É fácil modificar a linha \let string = para aceitar um item da lista em vez de um bloco; a parte do problema é definir o nome da macro como um item da lista em vez de uma string literal, ou seja, o seguinte não funciona (não surpreendentemente) function! s: . func_name . (type) abort. Talvez exista alguma maneira de criar a função com um nome genérico e, em seguida, copiar a função genérica para func_name no loop?
Leo Simon

5

A ideia é simples:

  1. você recorta o texto que deseja colocar ao redor e entra no modo de inserção,
  2. você insere a primeira parte,
  3. você insere o conteúdo do registro sem nome,
  4. você insere a última parte,
  5. você sai do modo de inserção.

Para o seu exemplo, você faria:

s\Pad{<C-r>"}<Esc>

Que pode ser mapeado para sua conveniência:

" normal mode, for single characters
nnoremap ;P s\Pad{<C-r>"}<Esc>

" visual mode, for multiple characters
xnoremap ;P s\Pad{<C-r>"}<Esc>

Observe que é possível usar um registro diferente se você não quiser desordenar o registro sem nome. Aqui eu uso o zregistro:

"zs\Pad{<C-r>z}<Esc>

3

Apenas mais uma solução para o caso em que surround não apenas um símbolo (exemplo da minha configuração para surround com "[" & "]"

vmap Q[ O<Esc>i[<Esc>gvo<Esc>la]<Esc>
nnoremap Q[ veO<Esc>i[<Esc>gvo<Esc>la]<Esc>

A chave é usar "o" e "O" para ir para o início / fim da seleção

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.