Tornar zG e zW persistentes

7

Edit : Eu transformei isso em um pequeno plugin. Esta é a minha primeira tentativa de escrever uma e não tenho idéia do que estou fazendo, portanto qualquer ajuda é muito apreciada. :)

Aqui está: https://github.com/danielbmarques/vim-dialect

----------

Quero continuar usando zge zwadicionando palavras aos vim globais spellfile, mas quero usar zGe zWadicionar palavras a um spellfile específico do arquivo que estou editando . Em outras palavras, eu quero zGe zWseja persistente para cada arquivo.

Definir as spellfilemudanças nos comandos zge zw, enquanto o que eu quero é mudar apenas os comandos zGe zW.

Então, eu fiz isso:

:au BufNewFile,BufRead * let &l:spellfile = expand('%:p:h') . '/.' .
    \ substitute(expand('%:t'), '\(.*\)\..*', '\1', '') . '.utf-8.add'
nnoremap zG :call LocalSpell("zG")<cr>
nnoremap zW :call LocalSpell("zW")<cr>
nnoremap zuG :call LocalSpell("zuG")<cr>
nnoremap zuW :call LocalSpell("zuW")<cr>
nnoremap zg :call GlobalSpell("zg")<cr>
nnoremap zw :call GlobalSpell("zw")<cr>
nnoremap zug :call GlobalSpell("zug")<cr>
nnoremap zuw :call GlobalSpell("zuw")<cr>
vnoremap zG :call LocalSpell("gvzG")<cr>
vnoremap zW :call LocalSpell("gvzW")<cr>
vnoremap zuG :call LocalSpell("gvzuG")<cr>
vnoremap zuW :call LocalSpell("gvzuW")<cr>
vnoremap zg :call GlobalSpell("gvzg")<cr>
vnoremap zw :call GlobalSpell("gvzw")<cr>
vnoremap zug :call GlobalSpell("gvzug")<cr>
vnoremap zuw :call GlobalSpell("gvzuw")<cr>

function! LocalSpell(cmd)
    if &l:spellfile == ""
        execute "normal! " . a:cmd
    else
        execute "normal! " . tolower(a:cmd)
    endif
endfunction

function! GlobalSpell(cmd)
    let b:spellfile = &l:spellfile
    setlocal spellfile=
    execute "normal! " . a:cmd
    let &l:spellfile = b:spellfile
endfunction

E funciona ... mas não parece uma boa solução para mim (editar: já está ficando melhor :)). Por isso, pensei em publicá-lo aqui, caso alguém tenha idéias ou melhorias melhores para sugerir. O que você acha?

dbmrq
fonte
Onde você incluiu o código acima? Um plugin de tipo de arquivo? Como é acionado / lido?
MMontu
@ mMontu Bem, por enquanto acabei de adicioná-lo ao meu vimrc. Eu estava pensando em escrever um pequeno plugin apenas para tirá-lo de lá. Não vejo por que tornar esse tipo de arquivo específico, nunca quero que as palavras adicionadas sejam descartadas e spellfilesó é criada quando a primeira zGé executada.
dbmrq
Como você mencionou a spellfile specific to the file I'm editing, pensei que estava usando vários arquivos de ortografia para zG; como o nome do arquivo ortográfico é derivado do nome do arquivo ( let &l:spellfile = expand('%:p:h')...), você pode conseguir isso para um tipo de arquivo específico, definindo o nome do arquivo e os mapeamentos ao abrir esse arquivo (você precisará incluir <buffer>nos mapeamentos). Também assumi que você desejava essa alteração zGapenas para alguns arquivos específicos.
MMontu
@ mMontu Oh, não, eu não quis dizer um spellfilepara tipos de arquivos específicos , mas um spellfilepara cada arquivo . Para adicionar palavras, e quando eu abrir esse arquivo novamente, elas ainda serão adicionadas, mas apenas para esse arquivo específico e não para outros. Também é uma ideia interessante. Infelizmente, parece que não é uma maneira de obter mais de um arquivo ortográfico; caso contrário, eu poderia fazer os dois e ter um comando para adicionar palavras ao arquivo atual e outro para adicionar palavras ao tipo de arquivo atual.
dbmrq
Eu estava falando exatamente sobre isso one spellfile for each file. Talvez eu tenha esquecido alguma coisa, mas se você adicionou o código ao seu, .vimrcnão poderia ter mais de um arquivo ortográfico, a menos que explicitamente :sourcenovamente para reavaliar o arquivo %.
MMontu

Respostas:

2

Idéia legal!

Você não menciona o que acha que está errado com o seu código. Parece muito bom para mim!

Eu provavelmente faria o contrário: é apenas o comportamento local que você deseja alterar; portanto, idealmente, removeríamos a GlobalSpellfunção e todos os mapeamentos globais e apenas alteraríamos a funcionalidade de ortografia local.

Infelizmente, essa abordagem só funciona se 'spellfile'não estiver vazia antes da execução do comando automático. (Como com um vazio 'spellfile', o Vim descobre um local no 'runtimepath'momento em que você adiciona uma ortografia, mas você não tem como acessar esse caminho.) Também não funcionará se 'spellfile'já houver uma lista: para ser mais robusto, deve realmente conte as entradas e altere a zgcontagem de acordo.

Portanto, a abordagem a seguir é adequada para uso pessoal em um .vimrc, mas você realmente não pode usá-lo em seu plugin.

set spell
set spellfile=~/global.utf-8.add

augroup persistent_spelling
  autocmd!
  autocmd BufNewFile,BufRead * let &l:spellfile .= ',' . expand('%:p:h') . '/.' .
    \ substitute(expand('%:t'), '\(.*\)\..*', '\1', '') . '.utf-8.add'
augroup END

function! LocalSpell(cmd)
  if &l:spellfile !~ ","
    execute "normal! " . a:cmd
  else
    execute "normal! 2" . tolower(a:cmd)
  endif
endfunction

nnoremap zG :call LocalSpell("zG")<cr>
nnoremap zW :call LocalSpell("zW")<cr>
nnoremap zuG :call LocalSpell("zuG")<cr>
nnoremap zuW :call LocalSpell("zuW")<cr>
vnoremap zG :call LocalSpell("gvzG")<cr>
vnoremap zW :call LocalSpell("gvzW")<cr>
vnoremap zuG :call LocalSpell("gvzuG")<cr>
vnoremap zuW :call LocalSpell("gvzuW")<cr>

No exemplo acima Eu também rodeado seu autocommandem um augroup, que é sempre uma boa idéia.

Você também pode considerar o uso de mapeamentos de expressão. Você removeria o ifbloco da função e escreveria mapeamentos como:

nnoremap <expr> zG if &l:spellfile !~ ',' ? 'zG' : ':call LocalSpell("zG")<CR>'

Porém, não tenho certeza se vale a pena: neste caso, você está apenas movendo a complexidade da função para o mapeamento.

A única outra coisa que se destaca é a longa série de comandos de mapa muito semelhantes. Você pode reduzir isso um pouco com um loop (e ao contrário do acima, você pode usar esta abordagem no seu plugin):

for lhs in ['zG', 'zW', 'zuG', 'zuW']
  execute 'nnoremap' lhs ':call LocalSpell("'.lhs.'")<cr>'
  execute 'vnoremap' lhs ':call LocalSpell("gv'.lhs.'")<cr>'
  let lhs = tolower(lhs)
  execute 'nnoremap' lhs ':call GlobalSpell("'.lhs.'")<cr>'
  execute 'vnoremap' lhs ':call GlobalSpell("gv'.lhs.'")<cr>'
endfor

Se você estiver se sentindo super seco , poderá criar todos os mapeamentos com uma única :executelinha, mas acho que é uma péssima idéia: você acabaria com um código muito mais complicado, quase tão longo quanto o original! Tentei de qualquer maneira, por diversão:

for [map_type, gv_type] in items({'n': '', 'v': 'gv'})
  for scope_type in ['Local', 'Global']
    for undo_type in ['', 'u']
      for spell_type in ['G', 'W']
        if scope_type == 'Global'
          let spell_type = tolower(spell_type)
        endif
        let lhs = 'z'.undo_type.spell_type
        execute map_type.'noremap' lhs
          \ ':call' scope_type.'Spell("'.gv_type.lhs.'")<cr>'
      endfor
    endfor
  endfor
endfor

Finalmente, notei que nenhuma das opções acima funciona se o arquivo que você está editando tiver um sublinhado no nome, porque você não pode usar sublinhados nos nomes dos arquivos de ortografia! Você precisará alterar seu comando automático para removê-los / transformá-los.

Rico
fonte