terça-feira, 30 de junho de 2009

Trocando as funções entre <Esc> e <Capslock>

A tecla <Esc> é muito usada no Vim, mas muitos consideram-na um entrave na
produtividade pela sua posição, longe da home row do teclado.
Uma solução é usar uma outra tecla próxima e de pouco uso no lugar do <Esc> . A
tecla preferida é o <Capslock> .

No Ubuntu use:
Sistemas - Preferências - Teclado - Disposições - Opções da disposição -
Comportamento da tecla CapsLock.
Escolha:
Trocar Esc e Caps Lock

quarta-feira, 10 de junho de 2009

Listando todas definições de macro C no modo comando

Para listar todas definições de uma macro use:
:dlist EOF
É semelhante a
[D e ]D
mas permite também selecionar um intervalo de linhas a serem pesquisadas.
O comando:
:dsearch EOF
pesquisa definições também, mas só lista a primeira.

Saltando para definições de macro C em modo comando

O comando:
:djump /padrão/
salta para a primeira definição de macro que encontrar no arquivo corrente e nos
includes. É semelhante ao comando de modo normal:
[<Ctrl-D>
porém permite selecionar um intervalo para restringir a procura.
O comando:
:dsplit
faz um ':split' seguido de um ':djump'

Listando as ocorrências de um palavra em modo comando

O comando:
:{intervalo}ilist /padrão/
mostra todas linhas que tem uma ocorrência do padrão.
A busca vai no arquivo corrente e nos includes.

É semelhante a:
[I e ]I
mas permite restringir a um intervalo de linhas
Por exemplo, listar todas linhas que tenham 'EOF':
:ilist EOF
O comando:
:isearch EOF
é semelhante a ':ilist' mas lista somente a primeira ocorrência.

terça-feira, 9 de junho de 2009

Pesquisando e saltando para uma palavra em modo comando

O comando:
{intervalo}:ijump {contagem} {/padrão/}
procura a primeira ocorrência da palavra dentro do intervalo.
A procura ocorre no arquivo corrente e nos arquivos apontados pela diretiva
'#include'. A 'contagem' diz para saltar para a uma ocorrência específica.

Exemplo:
:ijump /define\s*EOF/
procura a primeira linha que contenha 'define EOF'. Neste caso, ela está dentro do arquivo de include 'stdio.h'.
Faz o mesmo que
[<Ctrl-I> e ]<Ctrl-I>
porém pode restringir a um intervalo de linhas.
O comando:
:isplit /padrão/
funciona como um ':split' seguido de um ':ijump'.

segunda-feira, 8 de junho de 2009

Opção para tornar default a flag 'g' do substitute

O comando ':substitute' por default só altera a 1ª ocorrência de uma linha.
Para alterar todas use a flag 'g'.

Para torna-la o default use:
:set gdefault
Agora o ':substitute' altera todas ocorrências sempre.

No entanto, isso poderá quebrar scripts que você possa usar.

Repetindo a última substituição

O comando:
{intervalo}:& {flags} {contagem}
repete o último comando ':substitute' com o mesmo padrão e o mesmo string de substituição, mas sem as mesmas flags.

Exemplo, o comando seguinte substitui somente a 1ª ocorrência:
1 substitute /a\+/b/p
Test b* aa* a*
Agora para repetir, mas de com flag global:
:&g
O comando ':&' sem argumentos repete o último ':substitute'.

O comando de modo normal '&' repete também o último ':substitute'. Pode usar uma
contagem para repetir '&'.
O comando:
:{intervalo}~ {flags} {contagem}
repete o último 'substitute' com o mesmo string de substituição mas com último string usado em um padrão de pesquisa (comandos '/' ou '?').

Substituindo texto forçando a opção 'magic'

A opção 'magic' controla se certos caracteres tem valor especial. Para serem
usados literalmente tem que ser escapados.
Exemplo, '*', significa ('magic') nenhum ou 1 ou mais ocorrências.
Se desligar a opção ('nomagic') ela será usada literalmente.

Se quiser fazer um ':substitute' forçando a opção 'magic' ligada use:
:smagic /a*/b/g
Para forçar 'nomagic':
:snomagic /a*/b/g

terça-feira, 2 de junho de 2009

Imprimindo linhas na tela mostrando os caracteres invisíveis

Para imprimir linhas na tela mas mostrando os caracteres invisíveis (fim de
linha, tab, etc) use:
:1,5list
Um '$' é colocado após o fim-de-linha e os caracteres invisíveis são mostrados
no formato '^letra'.

Imprimindo linhas na tela

Se quiser imprimir linhas na tela use:
:1,5print
Se a opção 'number' não estiver ligada, use:
:1,5#
para imprimir linhas pré-fixadas com o número.

Inserindo texto pela linha de comando

Suponha que você que inserir texto pela linha de comando.
Use:
:1 append
para inserir texto após a linha 1.
Use:
:1 insert
para inserir texto antes da linha 1.
Digite o texto.
Para encerrar faça uma linha com somente um ponto (.).

domingo, 31 de maio de 2009

Opção para desligar o mapeamento recursivo

Por default, o Vim faz mapeamentos recursivos.
Para desligar isso use a opção:
:set noremap
Mas isto pode quebrar alguns scripts.
Use, ao invés, o comando:
:noremap ...

Forçando a expansão e a não-expansão de uma abreviação

O comando:
<Ctrl-]>
força a expansão da abreviação no modo inserção.
O comando:
<Ctrl-C>
faz com se sai do modo inserçao. A diferença com <Esc> é que ele não expande a
abreviação antes de entrar no modo normal.

sexta-feira, 29 de maio de 2009

Opção para definir o tamanho máximo de uma tag

Alguns sistemas limitam o tamanho máximo de um nome de função. Se você quiser
limitar isto quando pesquisando tags use:
:set taglength=número

quarta-feira, 27 de maio de 2009

Testando se o Vim pode localizar o arquivo de uma diretiva #include

Para listar todos arquivos '#include' não puderam ser localizados, use:
:checkpath
Ele verifica não somente as diretivas '#include' do arquivo sendo editado como
quaisquer arquivos que as diretivas incluem e assim por diante.
Para os includes que falharam inclua os paths necessários na opção 'path'.
Para listar todos arquivos '#include' use:
:checkpath!

Opção para definir que caracteres são usados como par de delimitadores

Para definir que caracteres serão identificados pelo comando '%' use a opção:
:set matchpairs = (:),{:},[:]
Para identificar o par '<>' (tag HTML) use:
:set matchpairs+=<:>

segunda-feira, 25 de maio de 2009

Comparando visualmente dois arquivos

Suponha que você quer comparar dois arquivos que diferem em poucas edições.
Abra duas janelas com os dois arquivos.
Agora execute o comando em cada janela:
:set scrollbind
Agora quando uma janela rola a outra rola também.
Se quiser parar a sincronização em um janela:
:set noscrollbind
E localizado o ponto desejado no arquivo, recomeça a rolar ao mesmo tempo a
partir desses locais:
:set scrollbind
Para voltar a sincronizar as janelas (isto é, linha 1 com linha 1), ligue
'scrollbind' em ambas janelas e use:
:syncbind
A opção:
set scrollopt=
controla como o scrollbind trabalha.

Opção para definir que palavra causa indentação na próxima instrução C

Para que uma palavra dispare uma indentação na próxima instrução C use a opção:
:set cinwords=string
O valor default é:
:set cinwords=if,else,while,do,for,switch

Opção para definir quanto espaço uma indentação C terá

Para controlar quanto irá ter um indentação C use a opção:
:set cinoptions=string
Aonde o 'string' consiste de uma lista pares chave-indentação separados por
vírgulas.
A 'chave' é uma única letra que diz que parte do programa será afetada.
A 'indentação' diz quantos espaços será usado na indentação. Pode ser um número
negativo. Também pode ser em múltiplos de 'shiftwidth'.

Opção para definir que tecla dispara uma indentação C

Uma lista de teclas que quando usadas no modo inserção causam re-indentação da
linha corrente. Somente usada se 'cident' ou 'indentexpr'.
Use:
:set cinkeys=string
O string é uma lista de pares 'caractere de tipo caractere da tecla'.
Os tipos podem ser:
! a tecla seguinte não é inserida. Isto é útil se você quiser definir uma tecla
  que só dispara a re-indentação da linha. <Ctrl-F> é a tecla default nesse
  caso.
* a linha será re-indentada antes que a tecla seja inserida.
0 a tecla causa indentação somente se ela é o primeiro caractere digitado na
  linha.
As teclas-caractere podem ser:
<nome>    O nome da tecla.
^nome O nome de uma tecla de controle.
o Diz ao Vim para indentar quando for usado o comando 'o'.
O Diz ao Vim para indentar quando for usado o comando 'O'.
e Re-indenta a linha quando for digitado o último 'e' de else.
: Re-indenta quando for digitado um ':' após um label ou 'case'.
O valor default é:
0{,0},0),:,0#,!^F,o,O,e
que especifica que uma indentação ocorre se:
0{  se foi digitado '{' como primeiro caractere em uma linha.
0} se foi digitado '}' como primeiro caractere em uma linha.
0) se foi digitado ')' como primeiro caractere em uma linha.
: se foi digitado ')' depois de um label ou instrução 'case'.
0# se foi digitado '#' como primeiro caractere em uma linha.
!^F se foi digitado <Ctrl-F> (o qual não é inserido).
o se foi digitado um <CR> em qualquer lugar ou usou o comando 'o' (não no modo
    inserção).
O se foi usado o comando 'O' (não no modo inserção).
e se foi digitado o segundo 'e' para um 'else' no início de uma linha.

domingo, 24 de maio de 2009

Opção para definir um programa externo de formatação

Você pode definir que programa de formatação que o Vim usa quando o comando '='
é usado.
Se não for definido o Vim usa a rotina interna de indentação que indenta
programas C ou C++.
Por exemplo, para usar o programa GNU de indentação 'indent':
:set equalprg=/usr/local/bin/indent

Opção para indentar em múltiplos de shiftwidth

Por default, um comando de indentação (>, <) insere 'shiftwidth' espaços mesmo
que a linha já tenha espaços na frente da linha. Isso pode distorcer o layout
desejado.

Para evitar isso ligue a opção:
:set shiftround
para que o Vim sempre insira espaços em múltiplos de 'shiftwidth'.

Os comandos de modo inserção:
<Ctrl-T>
<Ctrl-D>
sempre arredondam as indentações para múltiplos de 'shiftwidth'.

Usando um modeline para configurar as opções de tabs

O Vim dá várias opções para tratar o uso de tabs dentro dos arquivos.
No entanto, isso significa que cada pessoa pode tratar o mesmo arquivo de
maneira diferente.

Uma solução é colocar um comentário especial no início ou fim do arquivo
informando que tab stops usar.

Por exemplo:
/* vim:tabstop=8:expandtabs:shiftwidth=8 */
O Vim ao ler esse comentário irá configurar as opções para você.

sábado, 23 de maio de 2009

Colando texto do registrador com indentação no modo normal

Se você tem algum texto em um registrador, você usaria no modo normal:
"registradorp
"registradorP
para colar. Mas se o registrador já estiver indentado e a auto-indentação estiver ligada o resultado poderá ser confuso (dupla-indentação).
O comando:
"registrador]p
"registrador]P
faz a mesma coisa, mas também ajusta a indentação conforme o local.

Colando texto do registrador com indentação no modo inserção

Normalmente, no modo inserção, para inserir o conteúdo de registradores se usa:
<Ctrl-R>registrador
Mas isso, especialmente em código de programas, pode causar problemas.

Se o conteúdo do registrador é uma cópia de um código já indentado, ao inserir, o
Vim usa essa indentação e mais a indentação automática, causando uma dupla
indentação. Isso produz um layout errado.

Uma alternativa é usar:
<Ctrl-R><Ctrl-O>registrador
isso insere o conteúdo do registrador mas sem fazer a auto-indentação. O problema é que o conteúdo já tem a indentação original e pode não ser coerente com o local
aonde está sendo inserindo.

Para inserir com o Vim recalculando a indentação correta use:
<Ctrl-R><Ctrl-P>registrador

Removendo a indentação automática temporariamente

Suponha que você está editando um programa com 'autoindent' gerando indentações automáticas.
Num certo ponto você deseja colocar um bloco de comentários sem ser afetado pela
indentação automática.

Um modo é usar
<Ctrl-D>
repetidamente.
Outra é digitar:
 0<Ctrl-D> 
Isso faz com que o editor remova toda indentação automática e coloque o cursor
na coluna 1, enquanto estiver no modo inserção.

Agora, você quer digitar um label ou uma diretiva '#ifdef' na coluna 1, mas
somente em uma linha e depois volta para a autoindentação.
Use:
 ^<Ctrl-D> 
quando você entrar na linha seguinte volta a autoindentação.

Evitando a repetição de uma seleção no modo seleção

Após a execução de um mapeamento e menu a seleção do modo seleção é restaurada (a não ser que a área tenha sido deletada).

Para evitar, especialmente em macros que selecionam, fazem algum coisa e depois
se quer que a seleção desapareça, use o comando:
gV

Mudando do modo seleção para o modo visual

Se você estiver no modo seleção, use o comando:
<Ctrl-O>
para executar um único comando no modo visual. Após isso, volta ao modo seleção.
Para mudar para o modo visual sem retornar para o modo seleção use:
<Ctrl-G>

Alterando e deletando texto com o modo seleção

O modo seleção é semelhante ao modo visual, porém mais limitado.
No modo seleção você só pode usar <Backspace> para deletar e caracteres visíveis
para substituir.
Isso é mais rápido que a seleção visual porque você não precisar entrar um
comando no final para fazer a mudança. Mas o repertório é bem menor.

Para selecionar use:
gh    inicie uma seleção caractere por caractere.
gH inicie uma seleção linha a linha.
gCtrl-H inicie uma seleção de bloco.
Mova o cursor com teclas de direção (flechas) para completar a seleção.

Para deletar use:
<BS> ou <Ctrl-H>

Para substituir:
Digite o primeiro caractere visível, o editor entra em modo
inserção.
Continue a entrar o texto.
<Esc>

sexta-feira, 22 de maio de 2009

Codificando um bloco de texto

Com um texto selecionado, use o comando:
g?
para codificar (tornar incompreensível) ou para retirar a codificação.
É usado o esquema de codificação Rot13.
Para descodificar, chame de novo o comando.

Abrindo uma janela com o primeiro arquivo que contenha uma palavra

Se você posicionar o cursor sob uma palavra e pressionar:
<Ctrl-W><Ctrl-I>
o vim pesquisará no arquivo corrente e nos includes, retornando a primeira
ocorrência na nova janela.

Abrindo uma janela com o arquivo alternado

Para dividir a janela e editar o arquivo alternado use:
<Ctrl-W><Ctrl-^>

quarta-feira, 20 de maio de 2009

Movendo o cursor no modo inserção

No modo inserção não se pode usar as teclas tradicionais de movimento (hjkl).
Use ao invés:
<Left>
<Right>
<Up>
<Down>
Pressionando ao mesmo tempo a tecla
<Ctrl>
o movimento é por palavra.
<Home>
move para o início e <End> para o fim da linha.
Para mover para o início:
<C-Home>
para o fim da linha:
 <C-End>
Para mover uma tela para frente e para trás:
<PageUp> e <PageDown>

terça-feira, 19 de maio de 2009

Abrindo um arquivo com a execução de um comando

Você pode iniciar o Vim executando um comando logo no início.
Para posicionar o cursor numa linha use:
gvim +87 file.c
Para pesquisar um string e posicionar o cursor :
gvim +/include file.c
Para executar um comando logo após abrir um arquivo:
gvim +/set\ dir=/tmp file.c
Se houver espaços na expressão regular e no comando eles deve ser escapados (\).

sábado, 16 de maio de 2009

Usando o registrador-expressão (=) para entrar resultados de uma expressão no texto

O registrador-expressão permite que você avalie uma expressão e coloque o
resultado em alguma parte do texto.

Em modo normal, use a sequencia:
"=
o Vim salta para a linha de comando, aonde você pode digitar uma expressão, por exemplo:
38*56
em seguida, mova o cursor e cole resultado:
p
Em modo inserção pode-se usar a sequencia:
<Ctrl-R>"= (o Vim salta para linha de comando)
38*56
<Enter>
A expressão pode conter os operadores aritméticos comuns (*,+,-,/, etc) assim como as várias funções e operadores especializados do Vim.

Pode usar variáveis ambientais usando $NOME (por exemplo, $HOME), assim como variáveis Vim, simplesmente usando o nome dela como 'LineSize', por exemplo.

A linha de comando também dispõe de um histórico de expressões que pode ser recuperadas com as teclas de direção.

Usando o registrador buraco negro para evitar de salvar o texto deletado

Ao colocar texto no registrador 'buraco negro' (_), faz com que ele desapareça.

O registrador 'buraco negro' é útil se você quiser deletar um texto (com d ou c, por exemplo), mas não quer que ele vá para os registradores 1 a 9, como de costume.

Por exemplo, para deletar uma linha e coloca-la no registrador 1 use:
dd
Mas para deletar e não mexer no registrador 1 use
"_dd

Usando registradores especiais

O Vim possui uma série de registradores especiais. Aqui tem o seu conteúdo e se pode ser gravado pelo usuário:
0     O último texto copiado                      gravável
- O último texto deletado menor que uma linha read-only
. O último texto inserido read-only
% O nome do arquivo corrente read-only
# O nome do arquivo alternado read-only
/ O último string pesquisado read-only
: O último comando ':' read-only
_ O registrador 'buraco negro' gravável
= Uma expressão read-only
* O texto selecionado com o mouse gravável

sexta-feira, 15 de maio de 2009

Mostrando o conteúdo dos registradores

Use o comando:
:registers
Para mostrar registradores específicos:
:registers ax
mostra o conteúdo dos registradores 'a' e 'x'.

Colando texto

Após comandos de deleção ou cópia, você pode colar o texto em outro lugar.
Cola após o cursor:
{"registrador}p
Cola antes do cursor:
{"registrador}P
Cola após o cursor e deixa o cursor depois do novo texto:
{"registrador}gp
Cola antes do cursor e deixa o cursor depois do novo texto:
{"registrador}gP

quinta-feira, 14 de maio de 2009

Opção para definir que caracteres tem significado especial na expressão regular

A opção 'magic' quando ligada define que caracteres tem valor especial em uma
expressão regular.
Por exemplo '*' significa zero ou mais ocorrências.
Recomenda-se sempre deixa-la ligada (o default) para portabilidade.

Expressão regular: agrupamento

Você pode especificar um grupo na expressão regular através de:
\(...\)
Por exemplo:
a\(XY\)*b
obtém 'ab', 'aXYb', 'aXYXYb', etc.
Quando você define o grupo, o primeiro é assinalado ao item \1.
Por exemplo, para achar palavras repetidas:
\(\<\a\+\>\) \1
Descrevendo a expressão:
Inicia um grupo \(
início de palavra \<
uma ou mais letras, o máximo possível \a\+
fim de palavra \)
Fim do grupo \)
Um espaço
A ocorrência obtida dentro do grupo anterior
O primeiro grupo é assinalado a \1, o segundo a \2, e assim por diante.

Expressão regular: Classe de caracteres pré-definida

O Vim tem algumas classes de caracteres pré-definidas para coleções comuns de
caracteres.
Por exemplo, todas as letras maiúsculas, você pode usar a expressão [A-Z] ou
a classe:
[:upper]
obtém um caractere de letras maiúsculas.
Para obter um caractere dentro alfabeto inteiro use:
[[:upper][:lower]]

quarta-feira, 13 de maio de 2009

Opção para definir o número mudanças salvas pelo Vim para fazer undo

Use a opção:
:set undolevels=5000
para limitar a 5000 mudanças que salvas para poderem ser desfeitas pelo Vim.

terça-feira, 12 de maio de 2009

Opção para usar '~' com comando de movimento

Quando a opção essa opção está ligada:
:set tildeop
o comando '~' troca o case do caractere.
Quando desligada:
:set notildeop
a sintaxe do comando muda para '~movimento'.
Por exemplo:
~fq
muda o case de todos caracteres até e inclusive o primeiro 'q'.

Opção para habilitar a entrada de dígrafos usando Backspace

Se você pretende entrar muitos dígrafos ligue a opção:
:set digraph
Agora você pode entrar dígrafos com a sequencia:
caractere <BS> caractere
Por exemplo:
c<BS>o
é o caractere ©.
Naturalmente, essa convenção dificulta a correção usando backspace, pois agora
ele cria um dígrafo, não deleta o caractere.
Para desligar a opção:
:set nodigraph

domingo, 10 de maio de 2009

Posicionando a linha do cursor no meio da tela

Para posicionar a linha do cursor no meio da tela use:
zz
que deixa o cursor na sua coluna atual ou
z.
que deixa o cursor na primeiro caractere não-branco.

Posicionando a linha do cursor no rodapé da janela

Use:
z-
88z-
para posicionar na linha final da tela, com o cursor no primeiro caractere
não-branco.
zb
15zb
para posicionar na linha final da tela, com o cursor na coluna original.
A linha final é alterada pelo valor da opção 'scrolloff'.

Posicionando a linha do cursor no topo da janela

Se você quiser posicionar a linha do cursor no topo da janela use:
z<Enter>
(no entanto, a opção 'scrolloff' pode deixar uma margem de linhas acima dela).
Para posicionar uma linha qualquer:
88z<Enter>
Posiciona a linha 88 no topo.
O comando 'z' além de mover para o topo, deixa o cursor no 1º caractere
não-branco da linha.
Se quiser que o cursor continue na coluna original use:
zt
88zt

Opção para definir quantas linhas avançar/retroceder quando o cursor atinge início/fim da tela

Quando o cursor atinge o início ou fim da tela, com comandos com o 'j' ou 'k',
essa opção define quantas linhas o Vim avança ou retorna (se houver):
:set scrolljump=5
O default é 1.
Não é usado para comandos de rolagem de tela (<Ctrl-E>, <Ctrl-D>, etc).
Útil para terminais lentos.

quinta-feira, 7 de maio de 2009

Opção para definir quais teclas podem passar o início ou fim de linha

Use:
:set whichwrap={string}
Define que teclas move o cursor para esquerda/direita em direção à linha
anterior/seguinte.

Repetindo o comandos de salto para caractere

Para repetir esses comandos (f,F,t,T), use:
;
Para repetir na direção oposta use:
,
Pode-se usar contagem de comando:
3;
3,

Opção para definir que caracteres podem ser exibidos literalmente na tela

Use:
:set isprint={especificação}
Cuidado com a especificação, pois pode bagunçar a tela.

Usa a mesma {especificação} de 'iskeyword'.

terça-feira, 5 de maio de 2009

Expressão regular: Definindo o fim da ocorrência (match)

O item '\ze' em uma expressão regular define o local aonde termina uma ocorrência. O texto seguinte é só testado para validar o regex mas não é retornado.

Esse comando é útil quando você quer um texto que deve ser seguido por outro, mas não deseja que ele faça parte da ocorrência.

Exemplo:
end\ze\(if\|for\)
'end', define o fim da ocorrência, seguido de 'if' ou 'for'. Retorna 'end' quando ocorrer 'endif' e 'endfor'.

Pode ser usado múltiplas vezes, o último '\ze' é o que é usado.

Expressão regular: Definindo o início da ocorrência (match)

O item '\zs' em uma expressão regular define o local aonde começa uma ocorrência. O texto anterior é só testado para validar o regex mas não é retornado.

Esse comando é útil quando você quer um texto que deve ser precedido por outro, mas não deseja que ele faça parte da ocorrência.

Exemplo:
/^\s*\zsif
localiza o início da linha, seguido de zero ou mais espaços, define o início da
ocorrência, seguido de 'if'. A expressão localiza 'if's no início da linha
ignorando os espaços precedentes.
Pode ser usado múltiplas vezes, o último '\zs' é o que é usado:
/\(.\{-}\zsFab\)\{3}
Localiza a terceira ocorrência de 'Fab'.

domingo, 26 de abril de 2009

Saltando para um byte específico do buffer

Use o comando:
{contagem}go
para saltar para um byte específico do arquivo.
O comando:
:goto {número}
faz o mesmo.
Use o comando
g<Ctrl-G>
para ajudar a ver a posição do cursor.

Arquivo read-only e o gerenciador de versão de fontes

A opção 'readonly' é ligada automaticamente quando é lido é read-only.

Em uma ocasião você deveria desliga-la: quando você está usando um sistema de
controle de fontes que deixa os arquivo em modo read-only.
Quando você edita-lo no Vim, ele avisa que o arquivo é só para leitura e liga a
opção 'readonly'.

Neste ponto você lembra que esqueceu de dizer ao gerenciador de fontes que você
quer editar o arquivo.

Assim você usa o comando ':shell' para ir ao command prompt e executa comandos
que diz ao gerenciador que você quer editar o arquivo.
Depois de obter a permissão do gerenciador, você volta ao Vim ao entrar 'exit' e
executa o seguinte comando para dizer que o arquivo é editável:
:set noreadonly

Opção que informa se o buffer corrente foi alterado

A opção 'modified' é ligada automaticamente pelo Vim quando o buffer é
modificado.
Não é necessário ligar essa opção, pois ela é gerencia pelo editor.
No entanto você pode testa-la em vim scripts.

Salvando a edição do arquivo para o swap file

Se você fez bastante alterações em um arquivo e deseja preserva-las em caso de
crash você usa:
:w
No entanto isso sobrepõe o arquivo original com as alterações.
Uma alterativa é usar o comando:
:preserve
Ele irá gravar todas alterações no swap file somente. O arquivo original
permanece intacto e só será mudado quando você fizer um ':w' ou um 'ZZ'.
Se o sistema cai você pode recuperar os dados mesmo que o arquivo original tenha
sido perdido.
Sem esse comando você precisaria tanto do swap file como do arquivo original
para recuperar os dados.

sábado, 25 de abril de 2009

Opção para forçar o Unix/Linux gravar o swap file

No Unix/Linux quando você grava um arquivo, os dados normalmente vão para um
buffer de memória e são gravados de fato quando o sistema achar que é o momento.
Isto pode levar alguns segundos.
Se você quiser ter certeza que os dados vão para o disco use:
:set swapsync
Este comando executa uma operação 'sync' depois de cada gravação do swap file
para forçar a gravação em disco.

Desativando o swap file

Você pode querer desativar o uso de um swap file quando editando um arquivo
muito grande e não se importa com recuperação.
Use:
:set noswapfile
Essa opção é específica para cada buffer.

Escolhendo entre várias versões do swap file

O Vim busca sempre evitar de gravar sobre um swap file existente. A primeira vez
que edita o swap file chama '.arquivo.txt.swp', na vez seguinte
'.arquivo.txt.swo' e assim por diante.
Você pode dizer ao Vim qual swap file utilizar:
vim -r .arquivo.txt.swo
Para ver qual o nome do swap file que está sendo usado use:
:swapname

A sequência de eventos quando gravando um arquivo

Sequência de passos quando o Vim grava um arquivo.

1. O Vim verifica se o arquivo foi alterado externamente. Caso tenha
acontecido o editor envia uma aviso e pergunta se quer continuar.
2. Se 'writebackup' ou 'backup' estão ligados, qualquer backup antigo é
removido. O arquivo corrente então é copiado para o backup.
3. O buffer é gravado no arquivo.
4. Se o 'patchmode' está ligado e não existe nenhum arquivo de patch, o arquivo
de backup é renomeado e se torna o arquivo de patch.
5. Se a opção 'backup' não está ligada, e 'writebackup' está ligada, remove o
arquivo de backup.

Entrando no modo restrito pela linha de comando

Use:
vim -Z
No modo restrito, todos comandos que fazem uso do shell externo são proibidos.
Isso inclui ':shell', , filtragem, etc.

Mostrando a versão e opções de compilação pela linha de comando

Use a opção:
vim --version
Mostrará a versão do Vim e as opções que foram usadas na compilação do programa.

Mostrando o help da linha de comando

Use:
vim --help
Será mostrado todos argumentos de linha de comando.

Saindo do modo inserção automaticamente depois de um intervalo de tempo

Se você entra em modo inserção deve ser pressionado o para voltar para o modo normal para executar alguns comandos.

Elimine essa ação repetitiva definindo o código abaixo em seu .vimrc:
" automaticamente deixe o modo inserção depois de 'updatetime' milisegundos 
" de inatividade.
au CursorHoldI * stopinsert
" defina o 'updatetime' de até 2 segundos quando no modo inserção
au InsertEnter * let updaterestore=&updatetime | set updatetime=2000
au InsertLeave * let &updatetime=updaterestore
O primeiro autocomando tem o evento 'CursorHoldI' que ocorre quando o usuário
não digita nada durante o tempo especificado na opção 'updatetime' e está no
modo inserção. O comando executado será 'stopinsert', o qual equivale a
pressionar no modo inserção.

O autocomando seguinte, ativado no 'InsertEnter' que ocorre antes de entrar no
modo inserção, salva o a opção 'updatetime' e define num valor conveniente, aqui
2 segundos.

O autocomando final, ativado no 'InsertLeave' que ocorre ao deixar o modo
inserção, retorna o valor original da opção 'updatetime'.

Isso permite usar um valor específico de 'updatetime' para sair do modo inserção
sem afetar outras funções, por exemplo mapeamento com várias teclas.

sexta-feira, 24 de abril de 2009

Opção para definir como a última linha do arquivo termina

O Vim supõe que a última linha termina com um carácter .
Algumas vezes você encontra um arquivo estranho que contém uma linha incompleta.
Quando o Vim encontra este tipo de arquivo, ele liga a opção 'noendofline'.
Se o seu arquivo termina com uma linha completa, a opção 'endofline' é ligada.

Se quiser mudar se o arquivo termina com use:
:set endofline
caso contrário:
:set noendofline
Esta opção só funciona com
:set binary

Definindo uma lista de arquivos com palavras para autocompletar

Use a seguinte opção:
:set dictionary=arquivo,arquivo,...
Isso define arquivos que serão procurados quando pressionando <Ctrl-N> e
<Ctrl-P> para completar palavras.
Exemplo:
:set dictionary=/home/joao/palavras
Você pode também especificar um dicionário na opção 'complete' com a flag 'k':
:set complete+=/home/joao/palavras

quinta-feira, 23 de abril de 2009

Gravando um arquivo

Para gravar o buffer (arquivo) use:
:write teste.txt 
:w teste.txt
O comando ':write' não regrava um arquivo existente com o mesmo nome. Use:
:w! teste.txt
para forçar isso.
Para gravar e sair do Vim use:
:wq
para gravar e sair, sem gravar os buffers ocultos use:
read-only se:
:wq!
Para gravar com um novo nome:
:wq b.txt
Para forçar a gravação, caso o nome já exista use:
:wq! b.txt
Para gravar, somente se o buffer foi mudado , e sair use:
:xit

Salvando configurações definidas na linha de comando em um arquivo

Depois de experimentar com os comandos ':map', ':abbreviate' e ':set', seria legal se
pudesse salva-los e usa-los de novo.
O comando ':mkvimrc' grava todas suas definições em um arquivo:
:mkvimrc {arquivo}
Você pode ler esse arquivo usando o comando:
:source {arquivo}
Somente mapeamentos globais são gravado.

quarta-feira, 22 de abril de 2009

Opção para definir o arquivo com a lista de erros de compilação

A opção:
:set errorfile=
define o arquivo default que o comando ':clist' e opção de linha de comando '-q'
usarão para percorrer os erros de compilação.
Este arquivo não é usado como saída do comando ':make'.

Usando um arquivo de erros gerado externamente

Caso você tenha rodado 'make' externo e gerado seu próprio arquivo de erro, você pode dizer ao Vim sobre ele com:
:cfile 'arquivo-de-erro'
'arquivo-de-erro' é a saída do comando 'make' ou do compilador.
Se 'arquivo-de-erro' não foi especificado a opção 'errofile' é usada.

terça-feira, 21 de abril de 2009

Classificando um bloco de linhas no modo visual

Ponha o cursor na 1ª linha do bloco.
Inicie o modo visual-linha:
V
Mova para o final do bloco
Execute o comando de filtro:
!sort
O Vim preenche a linha de comando com:
'<,'>!sort

Classificando linhas usando marca

Classificando uma série de linhas (de um Makefile):
SOURCES = \
            time.cpp \
            set_ix.cpp \
            rio_io.cpp \
            arm.cpp \
            app.cpp \
            amem.cpp \
            als.cpp \
            aformat.cpp \
            adump.cpp \
            rio.cpp \
            progress.cpp \
            add.cpp \
            acp.cpp \
            rio_glob.cpp
Posicione o cursor no início da lista (a 2ª linha).
Crie uma marca ali:
ma
Posicione o cursor no final da lista.
Entre o filtro:
!'a
O vim traduz na linha de comando para:
:.,$!
Entre o filtro:
sort
As linhas são classificadas.

Percorrendo uma lista de tags selecionadas

Caso os comandos ':tag {palavra}' ou ':tselect {palavra}' retornem mais uma
ocorrência, use os comandos abaixo:
:tnext
próxima tag
:tprevious
tag anterior
:tNext
tag anterior
:tfirst
primeira tag
:tlast
última tag
Todos suportam o argumento 'contagem' para saltar 'n' ocorrências.

Procurando tag usando expressão regular

Se você só conhece parte do nome de uma procedure você pode usar o comando
:tag
para procura-la usando uma regexp.
Procure uma procedure que tem 'write' no nome:
:tag /write
Procure uma procedure que comece com 'read':
:tag /^read
Procure uma procedure cuja grafia você tem dúvidas:
:tag /DoFile\|do_file\|Do_File
:tag /[Dd]o_\=[Ff]ile
Esses comandos podem retornar múltiplos resultados.

Mapeamento para percorrer os buffers

Use:
map <C-right> <ESC>:bn<CR>
map <C-left> <ESC>:bp<CR>
Mapeamentos para retornar o buffer anterior e seguinte respectivamente.

Opção para definir que programa chamar para o comando 'K'

O comando 'K' chamará um programa externo que receberá a palavra sob o cursor.
O programa a ser chamado está declarado na opção:
:set keywordprg=man
No Unix, o default é 'man'. Pode-se definir ':help' para chamar o help do Vim
passando a palavra.

Indentando um bloco no modo visual

1. Posicione o cursor no delimitador.
2. Inicie o modo visual:
v
3. Selecione o bloco {} internamente com:
i}
4. Indente o texto com:
>

segunda-feira, 20 de abril de 2009

Indentando um bloco de texto entre delimitadores

Se quiser indentar um nível um texto entre '{}' faça:
Posicione o cursor no delimitador e use o comando-movimento seguinte:
>%
Infelizmente isso indenta o delimitador também. Se você quiser só deslocar o conteúdo do bloco :
Posicione o cursor no delimitador e use comando-objeto_texto:
>i{
'i{' é o objeto texto 'bloco {} interno'.

Mostrando as definições de macro de um programa C

Mostrando as definições de macro de um programa C.
Mostra a partir do início:
[d

Mostra depois do cursor:
]d

Mostrando uma lista com todas definições de macro de um program C.
Mostra a partir do início:
[D

Mostra depois do cursor:
]D

Saltando para definição da macro C cujo nome está sob o cursor

Salta para uma definição da macro cujo nome está sob o cursor use.
A pesquisa começa no início do arquivo:
[<Ctrl-D>
A pesquisa começa a partir do cursor:
]<Ctrl-D>
Esses comandos procuram também nos arquivos que estão em '#include'.

Saltando para a linha que tem a palavra sob o cursor

Para saltar para a primeira ocorrência da palavra sob o cursor:
[<Ctrl-I>
Começa a partir do início do arquivo. Linhas que parecem comentários são
ignoradas

Para saltar para ocorrências a partir do cursor para frente:
]<Ctrl-I>

Mudando de modo visual carácter/linha para bloco

Se você está usando o modo visual carácter ou linha mas descobre que você deveria estar
usando o modo visual bloco use o comando:
<Ctrl-V>
para mudar rapidamente.

Copiando texto no modo visual

O comando 'y' irá copiar o texto selecionado em um registrador. Enquanto que o comando 'Y' copiará linhas inteiras no registrador.

Opção para controlar o uso de janelas quando se muda de buffer

A ação default do vim para os comandos 'split/buffer' (p.e :sbnext, :sbuffer
arquivo ,etc) é dividir a janela corrente e carregar o arquivo.
Usando a opção:
:set switchbuf=useopen
faz com que o Vim só salte para a primeira janela que contiver o buffer, se
existir.
Nota: você ainda pode dividir a janela para ver 2 visões do mesmo arquivo com
comandos ':split'.
Quando você roda o ':make' e ocorre erro, o Vim mostrará o arquivo com o
problema na janela corrente.
Se usar:
:set switchbuf=split
o editor dividirá a janela corrente mostrando o arquivo errado na nova janela.

sábado, 18 de abril de 2009

Expressão regular: usando escape para caracteres especiais

Se for pesquisar usando caracteres que são caracteres especiais de expressão
regular, eles devem ser precedidos pr backslash ('\').
Por exemplo,^, $,. portanto deve ser escapados com o backslash (\):
/lei\.

Expressão regular: Um carácter qualquer

'.' corresponde a um carácter qualquer.
Pesquise por uma palavra que tenha um carácter qualquer (.):
/la.a
'la' seguido de um carácter qualquer seguido de 'a'

sexta-feira, 17 de abril de 2009

Mostrando qual idioma o Vim está usando

Use:
:language

Layout portável de um arquivo de sintaxe

Siga essas orientações para fazer arquivos de sintaxe acessíveis para todos.
Comece com um header que explique para que é o arquivo de sintaxe, quem o mantém
e quando foi sua última atualização. Não inclua muita informação sobre o
histórico de mudanças, poucas pessoas irão le-la.
Exemplo:
" Vim syntax file
" Language: C
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2001 Jun 18
" Remark: Included by the C++ syntax.
Use o mesmo layout que os outros arquivos de sintaxe. Usar um arquivo de sintaxe
existente irá lhe economizar um monte de tempo.

Escolha um bom e descritivo nome para seu arquivo de sintaxe. Use letras
minusculas e dígitos. Não faça-o muito longo, ele é usado em muitos lugares: O
nome do arquivo de sintaxe 'nome.vim', 'filetype', use 'b:current_syntax' no início
de cada grupo de sintaxe (nameType, nameStatement, nameString, etc).

Comece com um teste do 'b:current_syntax'. Se estiver definido, algum outro
arquivo de sintaxe, mais no início do 'runtimepath' já foi carregado:
if exists("b:current_syntax")
    finish
endif
Para ser compatível com o Vim 5.8 use:
if version < 600
  syntax clear
elseif exists("b:current_syntax")
  finish
endif
Defina 'b:current_syntax' para o nome da sintaxe no final. Não esqueça que
arquivos incluídos fazem isto também, você pode ter que redefinir
'b:current_syntax' se você incluir dois arquivos.

Se você quiser que seu arquivo de sintaxe funcione com Vim 5.x, adicione um
teste do v:version. Veja 'yacc.vim' por um exemplo.

Não inclua qualquer coisa que é uma preferencia do usuário. Não, define
'tabstop', 'expandtab', etc. Estes pertencem ao filetype plugin.

Não inclua mapeamentos ou abreviaçoes. Somente inclua a definição de 'iskeyword'
se for realmente necessária para reconhecimento de palavras-chave.

Para permitir que os próprios usuários selecionem sua cores preferidas, faça um
nome de grupo diferente para cada tipo de item colorizado. Então associe cada um
deles para um dos grupos de colorização padrão. Isto fará com que trabalhe com
qualquer esquema de cores.
Se você selecionar cores específicas ele irá parecer ruim com alguns esquemas de
cores. E não esqueça que algumas pessoas usam uma cor de fundo diferente, ou só
tem oito cores disponíveis.

Para a associação use 'hi def link', para que o usuário possa selecionar
colorização diferente antes que seu arquivo de sintaxe seja carregado. Exemplo:
hi def link nameString  String
hi def link nameNumber Number
hi def link nameCommand Statement
          ... etc ...
Adicione o argumento 'display' para itens que não serão usados quando
sincronizando, para acelerar a rolagem para trás e o Ctrl-L.

Adicionando novos itens a um arquivo de sintaxe existente

Quando um arquivo de sintaxe já existe, mas está faltando alguns itens, você
pode adiciona-los em um arquivo separado.

Isto evita mudar o arquivo de sintaxe distribuído, o qual seria perdido quando
instalando uma nova versão do Vim.

Grave os comandos de sintaxe em seu arquivo, possivelmente usando nomes de
grupos da sintaxe existente. Por exemplo, para adicionar novos tipos de
variáveis para o arquivo de sintaxe C:
:syntax keyword cType off_t uint
Grave o arquivo com o mesmo nome que o arquivo de sintaxe original. Neste caso
'c.vim'.
Coloque-o em um diretório próximo ao final do 'runtimepath'. Isto faz que seja
carregado depois do arquivo de sintaxe original. No Unix seria:
~/.vim/after/syntax/c.vim 

Instalando um novo arquivo de sintaxe

Quando seu arquivo de sintaxe estiver pronto, jogue-o em um diretório 'syntax'
no 'runtimepath'. No Unix, isso seria '~/.vim/syntax'.
O nome do arquivo de sintaxe deveria ser igual ao tipo do arquivo, com '.vim'
adicionado. Assim para a linguagem 'x', o path completo do arquivo seria:
~/.vim/syntax/x.vim
Você também deve fazer o tipo do arquivo ser conhecido.

Se o seu arquivo funciona bem, você poderia querer que ele estivesse disponível
para outros usuários Vim.
Após testar bem o arquivo, passe-o por e-mail ao manutendor do Vim:
<maintainer@vim.org>. Também explique como o tipo do arquivo pode ser detectado.
Com um pouco de sorte seu arquivo pode ser incluído na próxima versão do Vim.

Definindo como será sincronizada a tela no arquivo de sintaxe

Os compiladores analisam um arquivo a partir do início. Para o Vim é mais complicado pois deve começar no meio aonde a edição está sendo feita. Então, como ele sabe aonde ele está?

O segredo é o comando ':syntax sync'. Ele diz ao Vim como descobrir aonde está.
Por exemplo, o comando seguinte diz ao Vim para procurar atrás pelo início
ou fim de um comentário no estilo C e começar a colorização de sintaxe a partir
de lá:
:syntax sync ccomment
Você pode ajustar este processamento com alguns argumentos. O argumento
'minlines' diz ao Vim o número mínimo de linhas para procurar atrás, e
'maxlines' diz ao editor o número máximo de linhas para pesquisar.

Por exemplo, o seguinte comando diz ao Vim para olhar 10 linhas antes do topo da
tela:
:syntax sync ccomment minlines=10 maxlines=500
Se ele não consegue descobrir aonde ele está naquele espaço, ele começa olhar
mais e mais para atrás até que ele descubra o que fazer. Mas ele não olha atrás não mais que 500 linhas. (Um 'maxlines' grande torna lento o processamento. Um
valor pequeno pode causar a sincronização falhar.)

Para fazer a sincronização um pouco mais rápida, diga ao Vim quais itens de
sintaxe que podem ser pulados. Todo 'match' e 'region' que somente precisa ser usado
quando estiver realmente mostrando o texto pode ser dado o argumento 'display'.

Por default, o comentário a ser encontrado será colorizado como parte do grupo
de sintaxe 'Comment'. Se você colorizar as coisas de outro modo, você pode
especificar um outro grupo de sintaxe:
:syntax sync ccomment xAltComment
Se sua linguagem de programação não tem comentários estilo C dentro dele, você
pode tentar outro modo de sincronização. O modo mais simples é dizer ao Vim para
retornar um número de linhas e tentar descobrir as coisas a partir de lá.
O seguinte comando diz ao Vim para voltar atraś 150 linhas e começar a analisar a
partir de lá:
:syntax sync minlines=150
O valor grande de 'minlines' pode fazer o Vim ficar lento, especialmente quando percorrendo o arquivo para trás.
Finalmente, você pode especificar um grupo de sintaxe a ser procurado usando
este comando:
:syntax sync match {sync−group−name}
        \ grouphere {group−name} {pattern}
Isto diz ao Vim que quando ele ver o {pattern} o grupo de sintaxe chamado de {group-name} começa exatamente depois do padrão dado.

O {sync−group−name} é usado para dar um nome para essa especificação de
sincronização. Por exemplo, a linguagem de script 'sh' começa com um comando
if [ −−f file.txt ] ; then ~
        echo "File exists" ~
fi
Para definir um diretiva 'grouphere' para esta sintaxe, você usa o seguinte
comando:
:syntax sync match shIfSync grouphere shIf "\<if\>"
O argumento 'grouphere' diz ao Vim que o padrão termina o grupo. Por exemplo, o
fim do grupo 'if/fi' é o seguinte:
:syntax sync match shIfSync groupthere NONE "\<fi\>"
Neste exemplo, o 'NONE' diz ao Vim que você não está em nenhum região especial
de sintaxe. Em particular, você não está num bloco 'if'.

Você pode também definir matches e regions sem nenhum argumento 'grouphere' ou
'groupthere'.

Estes grupos são para grupos de sintaxe pulados durante a sincronização. Por
exemplo, o seguinte comando pula pula sobre qualquer coisa dentro de '{}', mesmo se ele normalmente correspondesse com outro método de sincronização:
:syntax sync match xSpecial /{.*}/

quinta-feira, 16 de abril de 2009

Incluindo um arquivo de sintaxe dentro de outro

A linguagem C++ é um superconjunto da linguagem C. Como você não vai querer criar dois arquivos de sintaxe, você pode colocar o arquivo de sintaxe do C++ dentro do C com o seguinte comando:
:runtime! syntax/c.vim
O comando ':runtime!' procura no 'runtimepath' por todos arquivos 'syntax/c.vim'.
Isto faz a sintaxe C++ ser definida parecida com os arquivos C.

Se você mudou o arquivo de sintaxe 'c.vim', ou adicionou itens com um arquivo
extra, estes serão carregados também.

Depois de carregados os itens de sintaxe C os itens específicos de C++ podem ser
definidos. Por exemplo, adicionar palavras-chave que não são usadas no C:
:syntax keyword cppStatement new delete this friend using
Isto funciona exatamente como qualquer outro arquivo de sintaxe.

Agora considere a linguagem Perl. Ela consiste de duas partes distintas: um
parte de documentação no formato POD, e um programa escrito no próprio Perl.

A seção POD começa com '=head' e termina com '=cut'.
Você quer definir a sintaxe POD em um arquivo, e usa-lo a partir do arquivo
de sintaxe do Perl.

Para o Perl, os comandos são :
:syntax include @Pod <sfile>:p:h/pod.vim
:syntax region perlPOD start=/^=head/ end=/^=cut/ contains=@Pod
Quando '=head' é encontrado em um arquivo Perl, a região 'PerlPOD' começa.
Nesta região o cluster @POD está contido. Todos os itens definidos como itens
nível do topo nos arquivos de sintaxe 'pod.vim' serão localizados aqui. Quando
'=cut' é encontrado, a região termina e nos voltamos para os itens definidos
para o arquivo Perl.

O comando ':syntax include' é esperto o suficiente para ignorar um comando
':syntax clear' no arquivo incluído. E um argumento tal como 'contains=all'
somente conterão itens definidos no arquivo incluído, não no arquivo que o
inclui.

A parte ':p:h/' usa o nome do arquivo corrente (<sfile>), o expande
o path completo (:p), e então tira a parte da frente (:head).

Isto resulta no nome do diretório do arquivo. Isto faz com que o arquivo 'pod.vim'
no mesmo diretório seja incluído.

Simplificando definições de item com clusters no arquivo de sintaxe

Uma das coisas que você notará quando começar a escrever um arquivo de sintaxe
você acabará gerando um monte de grupos de sintaxe. O Vim permite que você
defina uma coleção de grupos de sintaxe chamada de 'cluster'.

Suponha que você tem uma linguagem que contém loops 'for', comandos 'if', loops
'while', e funções. Cada uma delas contém os mesmos elementos de sintaxe:
números e identificadores. Você define-os assim:
:syntax match xFor /^for.*/ contains=xNumber,xIdent
:syntax match xIf /^if.*/ contains=xNumber,xIdent
:syntax match xWhile /^while.*/ contains=xNumber,xIdent
Você tem que repetir a mesma clausula 'contains=' a cada vez. Se você quiser
adicionar outro item contido, você tem que adiciona-lo três vezes. Os clusters
de sintaxe simplificam esta definições ao permitir que você tenha um cluster
pronto para diversos grupos de sintaxe.

Para definir um cluster para os dois itens que os três grupos contém, use o
seguinte comando:
:syntax cluster xState contains=xNumber,xIdent
Os clusters são usados dentro de outros itens de sintaxe exatamente como
qualquer outro grupo de sintaxe.
Seus nomes começam com '@'. Assim, você pode definir os três grupos assim:
:syntax match xFor /^for.*/ contains=@xState
:syntax match xIf /^if.*/ contains=@xState
:syntax match xWhile /^while.*/ contains=@xState
Você pode adicionar novos nomes de grupo para este cluster com o argumento
'add':
:syntax cluster xState add=xString
Você pode remover grupos de sintaxe desta lista também:
:syntax cluster xState remove=xNumber

Definindo item com ou sem linha de continuação no arquivo de sintaxe

Vamos definir uma linha de um preprocessador.
Isto começa com um '#' na primeira coluna e segue até o final da linha. Uma
linha que termina com '\' faz a próxima linha ser uma linha de continuação.

O modo que você trata isso é permitindo o item de sintaxe conter um padrão de
continuação:
:syntax region xPreProc start=/^#/ end=/$/ contains=xLineContinue
:syntax match xLineContinue "\\$" contained
Neste caso, embora 'xPreProc' normalmente normalmente obtém um única linha, o
grupo contido nele (chamado de 'xLineContinue') permite-o ir para mais de uma
linha.
Por exemplo, ele irá localizar ambas dessas linhas:
#define SPAM spam spam spam \ ~
               bacon and spam ~
Neste caso, isto é o que você quer. Se não é isso que você quer, você pode pedir
para que a região esteja em uma única linha adicionando 'excludenl' para o
padrão contido.
Por exemplo, você quer colorir 'end' em 'xPreProc', mas somente no final da
linha.
Para evitar que 'xPreProc' continue na próxima linha, como 'xLineContinue' faz,
use 'excludenl' assim:
:syntax region xPreProc start=/^#/ end=/$/
        \ contains=xLineContinue,xPreProcEnd
:syntax match xPreProcEnd excludenl /end$/ contained
:syntax match xLineContinue "\\$" contained
'excludenl' deve ser posto antes do padrão. Desde que 'xLineContinue' não tem
'excludenl', um ocorrência dele estende 'xPreProc' para a próxima linha como
antes.

Definindo uma região que não ultrapasse uma linha no arquivo de sintaxe.

O argumento 'oneline' indica que a região não cruza um limite de linha.
Por exemplo:
:syntax region xIfThen start=/if/ end=/then/ oneline
Isto define uma região que começa em um 'if' e termina em um 'then'. Mas se não
existe nenhum 'then' após o 'if', a região não obtém uma ocorrência.

Nota:
Quando usando 'oneline' a região não começa se o padrão 'end' não obtém
ocorrência na mesma linha. Sem 'oneline' o Vim não verifica se existe uma
ocorrência para o padrão 'end'. A região começa mesmo que o padrão 'end' não
obtém ocorrência no resto do arquivo.

Definindo colorização de item por deslocamentos na região no arquivo de sintaxe

Suponha que você quer definir um região para o texto entre '(' e ')' depois de
um 'if'.
Mas você não quer incluir o 'if' ou o '(' e ')'. Você pode fazer isso
especificando 'offsets' (deslocamentos) para os padrões:
:syntax region xCond start=/if\s*(/ms=e+1 end=/)/me=s−1
O deslocamento para o padrão 'start' é 'ms=e+1'. 'ms' significa 'Match Start'. Isto
define um deslocamento para o início da ocorrência do texto. Normalmente a
ocorrência começa aonde o padrão localiza. 'e+1' significa que a ocorrência
agora começa no final que o padrão localizou, e então um carácter a mais.
O deslocamento para o final do padrão é 'me=s-1'. 'me' significa 'Match End'.
's-1' significa o início que o padrão localizou e então um carácter a menos.
O resultado neste texto :
if (foo == bar)
Somente 'foo == bar' será colorizado como 'xCond'.

Definindo um item com a colorização do item que o contém no arquivo de sintaxe

Em um arquivo na linguagem C você gostaria de colorir o texto '()' depois de um
'while' diferente do texto '()' depois de 'for'.

Em ambos casos, podem existir itens '()' aninhados, os quais deveriam ser
coloridos do mesmo modo.

Você deve ter certeza que a colorização pare no ')' correspondente.
Este é um modo de fazer isso:
:syntax region cWhile matchgroup=cWhile start=/while\s*(/ end=/)/
        \ contains=cCondNest
:syntax region cFor matchgroup=cFor start=/for\s*(/ end=/)/
        \ contains=cCondNest
:syntax region cCondNest start=/(/ end=/)/ contained transparent
Agora você pode dar 'cWhile' e 'cFor' uma colorização diferente. 'cCondNest'
pode aparecer em qualquer um deles, mas ele leva a colorização do item em que
está contido.
O argumento 'transparent' faz isso.

Note que o argumento 'matchgroup' tem o mesmo grupo que o próprio item. Porque
defini-lo então? O efeito secundário de usar um 'matchgroup' é que os itens
contidos não são encontrados encontrados no padrão com o item 'start'.

Isto evita que o grupo 'cCondNest' encontre o '(' bem após o 'while' ou o 'for'.
Se isto tivesse acontecido, ele iria se expandir o texto todo até encontrar ')'
e a região continuaria após ele.

Agora 'cCondNest' somente irá localizar após o padrão start, assim depois do primeiro '('.

quarta-feira, 15 de abril de 2009

Definindo a colorização de itens diferente da região que os contém em um arquivo de sintaxe

Quando você define uma região, a região inteira é colorida de acordo com o nome
do grupo especificado.
Para colorir o texto entre parenteses com o grupo 'xInside', por exemplo, use o
seguinte comando:
:syntax region xInside start=/(/ end=/)/
Suponha que você quer colorir os parenteses de modo diferente. Você pode fazer isso
com um monte de comandos 'region' misturados, ou pode usar o argumento
'matchgroup'.

O código a seguir, diz ao Vim para colorir o início e fim de uma região com um grupo de
colorização diferente (neste caso, o grupo 'xParen'):
:syntax region xInside matchgroup=xParen start=/(/ end=/)/
O argumento 'matchgroup' aplica aos padrões 'start' ou 'end' que vem depois dele.
No exemplo anterior, tanto 'start' ou 'end' são coloridos com 'xParen'. Para
colorir o final com 'xParenEnd':
:syntax region xInside matchgroup=xParen start=/(/
        \ matchgroup=xParenEnd end=/)/
Um efeito secundário de usar 'matchgroup' é que os itens contidos não serão
localizados no início ou fim da região.

Definindo os itens seguintes de um item no arquivo de sintaxe

A linguagem 'x' tem instruções na forma:
if (condition) then
Você quer colorir os três itens de forma diferente. Mas {condition} e 'then'
poderiam aparecer em outros lugares, aonde ele tem colorização diferente.
Isto é o que você pode fazer:
:syntax match xIf /if/ nextgroup=xIfCondition skipwhite
:syntax match xIfCondition /([^)]*)/ contained nextgroup=xThen skipwhite
:syntax match xThen /then/ contained
O argumento 'nextgroup' especifica qual item vem a seguir. Isto não é
necessário. Se nenhum dos itens que estão especificados são encontrados, nada
acontece.
Por exemplo, neste texto:
if not (condition) then 
O 'if' corresponde a 'xIf'. 'not' não corresponde com o nextgroup 'XIfCondition'
especificado, assim somente 'if' é colorido.

O argumento 'skipwhite' diz ao Vim que espaço em branco (espaços e tabs) podem
aparecer entre os itens. Argumentos similares são 'skipnl', o qual permite
quebra de linha entre os itens, e 'skipempty', o qual permite linhas vazias.
Note que 'skipnl' não pula uma linha vazia, alguma coisa deve ter
correspondência depois da quebra de linha.

Definindo um item que pode conter vários itens, com ou sem exceções, no arquivo de sintaxe

Você pode usar o argumento para especificar que qualquer coisa pode ser contida.
Por exemplo:
:syntax region xList start=/\[/ end=/\]/ contains=ALL
Todos os itens de sintaxe serão contidos dentro deste. Ele também contém a si
próprio, mas não na mesma posição (o que causaria um loop infinito).
Você pode especificar que alguns grupos não serão contidos. Assim ele contém
todos os grupos exceto aqueles que estão listados:
:syntax region xList start=/\[/ end=/\]/ contains=ALLBUT,xString 
Com o item 'TOP' você pode incluir todos os itens que não tem o argumento 'contained'.
'CONTAINED' é usado para incluir somente itens com um argumento 'contained'.

Definindo o uso múltiplo do fim de linha no arquivo de sintaxe

Considere os dois itens de sintaxe seguintes:
:syntax region xComment start=/%/ end=/$/ contained
:syntax region xPreProc start=/#/ end=/$/ contains=xComment
Você define um comentário como qualquer coisa a partir de '%' até o final da linha.
Uma definição de preprocessador é qualquer coisa a partir de '#' até o final da linha.

Como você pode ter um comentário sobre linha do preprocessador, a definição do
preprocessador inclui um argumento 'contains=xComment'.

Agora olhe o que acontece com este texto:
#define X = Y % Comment text ~
int foo = 1;
O que você vê é que a segunda linha é que ela também é colorida como 'xPreProc'.
A diretiva do preprocessador deveria terminar no final da linha.
Isto é porque você usou 'end=/$/'. Então o que está errado?

O problema é o comentário contido. O comentário começa '%' e termina no final da
linha. Depois que o comentário termina, a sintaxe do preprocessador continua.
Isto é depois do final da linha ter sido visto, assim a próxima linha é incluída
também.

Para evitar este problema e evitar um item de sintaxe contido comendo o fim de
linha necessário, use o argumento 'keepend'.
Isto cuida do localização dupla do fim de linha:
:syntax region xComment start=/%/ end=/$/ contained
:syntax region xPreProc start=/#/ end=/$/ contains=xComment keepend

Definindo itens aninhados recursivamente no arquivo de sintaxe

A linguagem 'x' define blocos de código entre chaves.
E um bloco de código pode conter outros blocos de código. Isto pode ser definido
deste modo:
:syntax region xBlock start=/{/ end=/}/ contains=xBlock
Suponha que você tenha este texto:
while i < b { ~
if a { ~
b = c; ~
} ~
} ~
Primeiro um 'xBlock' começa em '{' na primeira linha. Na segunda linha outro '}'
é encontrado. Desde que nos estamos dentro de um item 'xBlock', e ele contém a
si próprio, um item 'xBlock' aninhado irá começar aqui.

Assim a linha 'b = c' está dentro da região 'xBlock' de segundo nível.

Isto termina o 'xBlock' aninhado. Porque o '}' está incluído dentro da região
aninhada, ele está escondido da primeira região 'xBlock'.
Então, no último '}', a primeira região 'xBlock' termina.

Definindo itens aninhados no arquivo de sintaxe

Observe esse comentário:
%Get input TODO: Skip white space
Você quer colorizar 'TODO' com letras amarelas grandes, mesmo que ele esteja
dentro de um comentário que está colorizado em azul.

Para dizer para o Vim sobre isto, você define os seguintes grupos de sintaxe:
:syntax keyword xTodo TODO contained
:syntax match xComment /%.*/ contains=xTodo
A primeira linha, o argumento 'contido' diz ao Vim que essa palavra-chave pode
existir somente dentro de outro item de sintaxe.
A próxima linha tem 'contains=xTodo'. Isto indica que o elemento de sintaxe
'xTodo' está dentro dela. O resultado é que a linha de comentário como um todo
corresponde com 'xComment' e fica azul.
A palavra 'TODO' dentro dela corresponde com 'xTodo' e é colorida em amarelo.

terça-feira, 14 de abril de 2009

Usando regiões para identificar itens no arquivo de sintaxe

Na linguagem 'x', os strings são delimitados entre aspas duplas (").

Para colorir os strings você usa uma 'região'.
Você precisa de um início de região (aspas duplas) e um final de região (aspas
duplas).

Eis a definição:
:syntax region xString start=/"/ end=/"/
As diretivas 'start' e 'end' definem os padrões usados para localizar o início e
o fim de uma região.

Mas e para strings como este:
"A string with a double quote (\") in it"
Isto cria um problema: um string no meio do string encerra uma região. Você
precisa dizer ao Vim para pular qualquer aspas duplas com escape no string.

Faça com a palavra-chave 'skip':
:syntax region xString start=/"/ skip=/\\"/ end=/"/
Quando você usa uma região ao inves de um match ? A diferença principal é que
um item match é um único padrão, o qual deve corresponder como um todo.

A região começa tão logo o padrão 'start' tem correspondencia. Se o padrão 'end'
é encontrado ou não, não importa.

Assim se um item depende do padrão 'end' para ser localizado, você não pode usar uma região. Por outro lado, regiões são muitas vezes mais simples de definir. E é mais fácil de usar itens aninhados.

Usando uma expressão regular para identificar itens no arquivo de sintaxe

Considere estar definindo uma coisa um pouco mais complexa.
Você quer localizar identificadores comuns.
Para fazer isto você define um item de sintaxe 'match'.

Este item aqui corresponde com qualquer palavra consistindo somente de letras
minúsculas:
:syntax match xIdentifier /\<\l\+\>/
Nota: Palavras-chave sobrepõe qualquer outro item de sintaxe.
Assim as palavras-chave 'if', 'then', etc serão palavras-chave, como definido
com comandos ':syntax keyword', mesmo que elas correspondam com o padrão de
'xIdentifier'.

A parte final é um padrão, parecido com que é usado em pesquisa. Assim '/.../' é
usado para delimitar o padrão (como é feito no comando ':substitute').
Você pode usar outro carácter, como mais ou aspas duplas.

Agora defina um match para um comentário. Na linguagem 'x' é qualquer coisa a
partir de '#' até o final da linha:
:syntax match xComment /#.*/
Desde que você pode usar qualquer padrão de pesquisa, você pode colorir coisas
muito complexas com um item match.

segunda-feira, 13 de abril de 2009

Definindo uma palavra-chave incomum no arquivo de sintaxe

Os caracteres usados em uma palavra-chave devem estar na opção 'iskeyword'.
Se você usar outro caracter, a palavra nunca terá correspondência.
O Vim não dá uma mensagem de aviso disso.

A linguagem 'x' usa o caracter 'x' nas palavras-chave. Isto é como é feito:
:setlocal iskeyword+=−
:syntax keyword xStatement when−not
O comando 'setlocal' é usado para mudar 'iskeyword' somente no buffer corrente.
Todavia, ele muda o comportamento de comandos como 'w' e '*'. Se isso não é
desejado, não defina uma palavra-chave mas use um 'match'.

A linguagem 'x' permite abreviações. Por exemplo, 'next' pode ser abreviado para
'n', 'ne' ou 'nex'. Você pode defini-los usando este comando:
:syntax keyword xStatement n[ext]
Isto não faz correspondência com 'nextone', palavras-chave sempre fazem
correspondência com palavras-inteiras.

Definindo a palavra-chave no arquivo de sintaxe

O elemento mais básico da sintaxe é a palavra-chave. Para definir uma palavra-chave, use a
seguinte forma:
:syntax keyword {grupo} {palavra-chave} ...
O {grupo} é nome do grupo de sintaxe. Com o comando ':highlight' você pode
assinalar cores para um {grupo}. O argumento {palavra-chave} é a palavra-chave
de fato.
Eis alguns exemplos:
:syntax keyword xType int long char
:syntax keyword xStatement if then else endif
Este exemplo usa os nomes de grupo 'xType' e 'xStatement'. Por conveniência,
cada nome de grupo é prefixado pelo tipo do arquivo para a linguagem sendo
definida.
Este exemplo define a sintaxe para a linguagem 'x'.
Em arquivo de sintaxe para os scripts 'csh' o nome 'cshType' seria usado. Assim
o prefixo é igual ao valor do 'filetype'.

Esses comandos fazem com que as palavras 'int', 'long' e 'char' sejam coloridos
de um modo 'if', 'then', 'else' e 'endif' sejam coloridos de outro jeito.
Agora você precisa conectar os nomes de grupo 'x' com os nomes padrão do Vim.
Você faz isso com os seguintes comandos:
:highlight link xType Type
:highlight link xStatement Statement
Isto diz ao Vim para colorir 'xType' como 'Type' e 'xStatement' como
'Statement'.

Definindo se a linguagem é sensível ao case no arquivo de sintaxe

Algumas linguagens são sensíveis ao case (maiúsculo/minúsculo) como o C. Outras
não como o Pascal.
Você precisa dizer que tipo você tem com os comandos:
:syntax case match
:syntax case ignore
O argumento 'match' significa que o Vim irá corresponder com o case do elementos
de sintaxe. Portanto, 'int' difere de 'Int' e 'INT'.
Se o argumento 'ignore' é usado, os seguintes são equivalentes: 'Procedure',
'PROCEDURE' e 'procedure'.

Os comandos 'syntax case' podem aparecer em qualquer lugar e afetar as
definições de sintaxe que seguem. Na maioria dos casos, você tem somente um
comando ':syntax case' no seu arquivo de sintaxe; se você trabalha com uma
linguagem incomum que tem tanto elementos sensíveis ao case como insensíveis ao
case, você pode espalhar o comando ':syntax case' através do arquivo.

Listando os itens definidos no arquivo de sintaxe corrente

Use:
syntax
Isso é muito útil para verificar quais itens estão definidos. Muito útil quando
testando um novo arquivo de sintaxe.
Ele também mostra as cores usadas em cada item, o que ajuda a descobrir o que é
o que.

Para listar os itens em um grupo de sintaxe específico use:
:syntax list {nome-do-grupo}
Isto também pode ser usado para listar clusters. Simplesmente inclua '@' no
nome.

Apagando definições anteriores de um arquivo de sintaxe

Use:
:syntax clear
Não é necessário no arquivo de sintaxe final, mas muito útil quando
experimentando.

Ponto de partida para criar um arquivo de colorização de sintaxe

Se a colorização que vem com o Vim, para duas centenas de arquivos de diferentes
tipos, não inclui o seu, crie um arquivo de sintaxe.

Use um arquivo de sintaxe existente como ponto de partida para economizar tempo.
Busque um arquivo de sintaxe em '$VIMRUNTIME/syntax' para uma linguagem que é
parecida.

Fazendo o vim reconhecer um novo tipo de arquivo pelo conteúdo

Se o seu arquivo não pode ser reconhecido pelo nome do arquivo, você pode
faze-lo conhecido pelo seu conteúdo.

Por exemplo, muitos arquivos de script começam assim:
#!/bin/xyz
Para reconhecer esse script crie um arquivo 'scripts.vim' em seu diretório
runtime (no mesmo local aonde o 'filetype.vim' vai).
Ele fica assim:
if did_filetype()
  finish
endif
if getline(1) =~ '^#!.*[/\\]xyz\>'
    setf xyz
endif
O que primeiro teste com 'did_filetype()' é para evitar que você verifique o
conteúdo dos arquivos para os quais o tipo do arquivo foi detectado pelo nome do
arquivo. Isto evita perda de tempo em verificar um arquivo quando o comando 'setf' não
fará nada.
O arquivo 'scripts.vim' é sourced por um autocomando no arquivo 'filetype.vim'
default. Portanto, a ordem das verificações é:
1. arquivos 'filetype.vim' antes do '$VIMRUNTIME' no 'runtimepath'
2. primeira parte de '$VIMRUNTIME/filetype.vim'
3. todos os arquivos scripts.vim no 'runtimepath'
4. resto do '$VIMRUNTIME/filetype.vim'
5. os arquivos 'filetype.vim' depois do '$VIMRUNTIME' no 'runtimepath'

Se isso não é suficiente, adicione um autocomando que corresponde a todos
arquivos e faça source de um script ou execute uma função que verifique o
conteúdo do arquivo.

domingo, 12 de abril de 2009

Fazendo o vim reconhecer um novo tipo de arquivo pela extensão

Se você está usando um tipo de arquivo que não é reconhecido pelo Vim, isto é
como você faz ele ser reconhecido. Você precisa de um diretório runtime seu
próprio (~/.vim).

Crie um arquivo 'filetype.vim' que contém um autocomando para seu tipo de
arquivo:
augroup filetypedetect
au BufNewFile,BufRead *.xyz setf xyz
augroup END
Isto reconhecerá todos arquivos que terminem com '.xyz' como do tipo de arquivo
'xyz'.

Os comandos ':augroup' colocam este comando no grupo 'filetypedetect'. Isto
permite remover todos autocomandos para detecção de tipo de arquivo quando
fazendo ':filetype off'.

O comando 'setf' irá carregar a opção 'filetype' a menos que ela já carregada.
Isto assegura que 'filetype' não foi definida duas vezes.

Você pode usar muitos padrões diferentes para corresponder com o nome do seu
arquivo. Nomes de diretório podem ser incluídos.
Por exemplo, os arquivos debaixo de '/usr/share/scripts/' são todos arquivos
'ruby' mas não tem a extensão de nome de arquivo esperada. Adicione isto ao
exemplo:
augroup filetypedetect
au BufNewFile,BufRead *.xyz setf xyz
au BufNewFile,BufRead /usr/share/scripts/* setf ruby
augroup END
Todavia, se você editar agora um arquivo '/usr/share/scripts/README.txt', isto
não é um arquivo ruby.
O perigo de um padrão terminando em '*' é que ele rapidamente corresponde a
muitos arquivos.
Para evitar problemas como este, coloque o 'filetype.vim' em outro diretório, um
que está no final de 'runtimepath'. No Unix, po exemplo, você poderia usar
'~/.vim/after/filetype.vim'.
Você agora coloca a detecção de arquivos texto em '~/.vim/filetype.vim':
augroup filetypedetect
au BufNewFile,BufRead *.txt setf text
augroup END
Este arquivo é encontrado primeiro no 'runtimepath'. Então use isto no
'~/.vim/after/filetype.vim', o qual é encontra por último:
augroup filetypedetect
au BufNewFile,BufRead /usr/share/scripts/* setf ruby
augroup END
O que acontece agora é que o Vim procura pelo 'filetype.vim' em cada diretório
do 'runtimepath'.
Primeiro '~/.vim/filetype.vim' é localizado. o autocomando para pegar arquivos
'*.txt' está definido lá.
Então o Vim acha o 'filetype.vim' no '$VIMRUNTIME', o qual está no meio do
caminho no 'runtimepath'.
Finalmente, o '~/.vim/after/filetype.vim' é achado e o autocomando para detectar
arquivos ruby em '/usr/share/scripts' é adicionado.

Quando você editar agora '/usr/share/scripts/README.txt', os autocomandos são
verificados na ordem em que foram definidos. O padrão '*.txt' corresponde, então
'setf text' é executado para definir o tipo do arquivo como 'text'.
O padrão para o ruby corresponde também, e o 'setf ruby' é executado. Mas como o
'filetype' já foi definido como 'text', nada acontece aqui.

Quando você edita o arquivo '/usr/share/scripts/foobar' os mesmos autocomandos
são verificados. Somente aquele do 'ruby' corresponde e 'setf ruby' define
'filetype' para 'ruby'.

Alterando os defaults de um filetype plugin

Quando você começa a editar um arquivo de um certo tipo, por exemplo C ou um
shell script, você usa as mesmas opções e mapeamentos.
Pode ser que você esteja satisfeito com esses defaults, pois eles são mantidos
no mínimo.

Suponha que você quer que, para arquivos C, a opção 'softtabstop' seja e que
tenha um mapeamento para inserir comentários de três linhas.
Você faz isso somente com dois passos:

1. Crie seu próprio diretório runtime (se não já existir). No Unix isto é
'~/.vim'. Neste diretório crie o diretório 'ftplugin':
mkdir ~/.vim
mkdir ~/.vim/ftplugin
Se não estiver no Unix, verifique o valor da opção 'runtimepath' para ver aonde
o Vim buscara pelo diretório 'ftplugin':
:set runtimepath
Você normalmente usuaria o primeiro nome de diretório (antes da primeira
vírgula). Você poderia inserir no início um nome de diretório para a opção
'runtimepath' no seu arquivo 'vimrc' caso não goste do valor default.

2. Crie o arquivo '~/.vim/ftplugin/c.vim', com os conteúdos:
setlocal softtabstop=4
noremap <buffer> <LocalLeader>co/**************<CR><CR>/<Esc>
Agora tente editar um arquivo C. Você notará que a opção 'softtabstop' está com
o valor 4. Mas quando você editar outro arquivo ela volta para zero.

Isto é porque o comando ':setlocal' foi usado. Isto define o valor de
'softtabstop' somente localmente no buffer.

Tão logo você edite outro buffer, ele será definido com o valor definido para
aquele buffer. Para um novo buffer ele terá o valor default ou o valor do último
comando ':set'.

Por outro, o mapeamento para '\c' desaparecerá quando editando outro buffer.
O comando ':map <buffer>' cria um mapeamento que é local ao buffer corrente.

Isto funciona com qualquer comando de mapeamento: :'map'!, :'vmap', etc.
O <LocalLeader> no mapeamento é substituído com o valor de 'maplocalleader'.

Você pode achar exemplos de filetype plugins neste diretório:
$VIMRUNTIME/ftplugin/

sábado, 11 de abril de 2009

Distribuindo um script

Os usuários do Vim procuram scripts no site do Vim, http://www.vim.org.
Os scripts Vim podem ser usados em qualquer sistema. Pode não existir nenhum comando tar ou
gzip. Se quiser compactar seus arquivos o utilitário 'zip' é recomendado.

Para a maior portabilidade use o próprio Vim para compactar os scripts.
Isto pode ser feito com o utilitário Vimball.
Será bom se você adicionar uma linha para permitir atualização automática.

Criando uma script library

Certas funcionalidades serão necessárias em vários lugares.
Podemos coloca-las em um script e usa-las a partir de muitos outros scripts.
Esse script será chamado de script library (biblioteca).

Carregar manualmente uma script library é possível, desde que você evite de
carrega-la quando já estiver carregada. Você pode fazer isso com a função 'exists()':
if !exists('*MyLibFunction')
   runtime library/mylibscript.vim
endif
call MyLibFunction(arg)
Aqui você precisa saber que 'MyLibFunction()' está definido em um script
'library/mylibscript.vim' em um dos diretórios de 'runtimepath'.

Para fazer isso mais simples Vim oferece o mecanismo de autoload. Então o
exemplo se parecerá com isso:
call mylib#myfunction(arg)
Isto é muito mais simples. O Vim reconhecerá o nome da função e quando não
estiver definida procura pelo script 'autoload/mylib.vim' no 'runtimepath'.
Este script deve definir a função 'mylib#myfunction()'.

Você pode por muitas outras funções no script 'mylib.vim'. Mas você deve usar
nomes de função aonde a parte antes de '#' corresponde com o nome do script.
Caso contrário o Vim não saberá qual script carregar.

Se tiver muitas script libraries, você poderia querer usar subdiretórios:
call netlib#ftp#read('somefile')
No Unix, o script library usado para isto poderia ser:
~/.vim/autoload/netlib/ftp.vim
Aonde a função é definida assim:
function netlib#ftp#read(fname)
      " Read the file fname through ftp
endfunction

Note que o nome da função usado é o mesmo nome usada na chamada da função. E a
parte antes do último '#' corresponde exatamente ao subdiretório e ao nome do
script.

Você pode usar o mesmo mecanismo para variáveis:
let weekdays = dutch#weekdays
Isto carregará o script 'autoload/dutch.vim', o qual deveria conter algo como:
let dutch#weekdays = ['zondag', 'maandag', 'dinsdag', 'woensdag',
        \ 'donderdag', 'vrijdag',
'zaterdag']

Criando um plugin que carrega rapidamente

Um plugin pode crescer e se tornar muito grande.
O tempo de inicialização pode se tornar perceptível, mesmo que você raramente use o
plugin.

É o momento para um plugin de carga rápida.

A ideia básica é que o plugin seja carregado duas vezes.

A primeira vez os comandos do usuário e mapeamentos são definidos para que
ofereçam a funcionalidade.
A segunda vez as funções que implementam a funcionalidade são definidas.

Pode parecer surpreendente que para carregar rápido um plugin signifique
carregar o script duas vezes.
O que se busca é que ele carregue rapidamente a primeira vez, postergando o
grosso do script para a segunda vez, o que acontece quando você realmente o
utiliza.
Sempre que você utilizar a funcionalidade ele fica na realidade mais lento!

Note que desde do Vim 7 existe uma alternativa para o explicado aqui: use a funcionalidade 'autoload'.

O exemplo mostra como é feito:
" Vim global plugin for demonstrating quick loading
" Last Change: 2005 Feb 25
" Maintainer: Bram Moolenaar <Bram@vim.org>
" License: This file is placed in the public domain.
if !exists("s:did_load")
      command −nargs=* BNRead call BufNetRead(<f−args>)
      map <F19> :call BufNetWrite('something')<CR>
      let s:did_load = 1
      exe 'au FuncUndefined BufNet* source ' . expand('<sfile>')
      finish
endif
function BufNetRead(...)
      echo 'BufNetRead(' .
      string(a:000) . ')'
      " read functionality here
endfunction
function BufNetWrite(...)
      echo 'BufNetWrite(' . string(a:000) . ')'
      " write functionality here
endfunction
Quando o script é carregado pela primeira vez 's:did_load' não está definido. Os
comandos entre 'if' e 'endif' serão executados. Isto acaba em um comando
':finish', assim o resto do script não é executado.

A segunda vez que o script é carregado 's:did_load' existe e os comandos depois
de 'endif' são executados. Estes definem (possivelmente longas) funções
'BufNetRead()' e 'BufNetWrite()'.

Se você jogar esse script no seu diretório plugin Vim o executará na
inicialização. Esta é a sequencia de eventos que acontecem:

1. O comando 'BNread' é definido e a tecla <F19> é mapeada quando o script é
sourced na inicialização. Um autocomando 'FuncUndefined' é definido. O comando
':finish' faz com que o script termine antes.

2. O usuário digita o comando 'BNRead' ou pressiona a tecla <F19>. A função
'BufNetRead()' ou 'BufNetWrite()' será chamada.

3. O Vim não acha a função e dispara o evento do autocomando 'FuncUndefined'.
Desde que o padrão 'BufNet*' corresponde à função invocada, o comando 'source
fname' será executado. 'fname' será o nome do script, não importando ao está
localizado, pois ele vem da expansão de '<sfile>.

4. O script é novamente sourced, a variável 's:did_load' existe e as funções
estão definidas.

Note que funções que são carregadas depois correspondem ao padrão no autocomando
'FuncUndefined'. Você deve estar certo que nenhum outro plugin define funções
que correspondem a esse padrão.

Criando um plugin compilador

Um plugin compilador define as opções para o uso com um compilador específico.
O usuário pode carrega-lo com o comando ':compiler'.

Seu uso principal é definir as opções 'errorformat' e 'makeprg'.

Olhe nos exemplos instalados pela distribuição. O comando seguinte editará todos
plugins compiladores default:
:next $VIMRUNTIME/compiler/*.vim
Use o comando ':next' para ir para o próximo arquivo de plugin.

Existe dois itens especiais sobre estes arquivos.
Primeiro é um mecanismo para permitir que um usuário regrave ou adicione ao
arquivo default. Os arquivos default começam com:
:if exists("current_compiler")
: finish
:endif
:let current_compiler = "mine"
Quando você grava um arquivo compilador e coloca-o em seu diretório runtime
pessoal (no Unix, ~/.vim/compiler), você define a variável 'current_compiler'
para fazer que o arquivo default pule as definições.

O segundo mecanismo é usar ':set!' para ':compiler!' e ':setlocal' para
':compiler'.
O vim define o comando do usuário ':CompilerSet' para isto. Todavia, versões
mais antigas do Vim não fazem, assim seu plugin deveria defini-lo.
Eis um exemplo:
if exists(":CompilerSet") != 2
    command −nargs=* CompilerSet setlocal <args>
endif
CompilerSet errorformat& " use the default 'errorformat'
CompilerSet makeprg=nmake
Quando você escreve um compilador plugin para a distribuição Vim ou para o
diretório runtime a nível de sistema, use o mecanismo mencionado acima.
Quando 'current_compiler' já foi definido pelo plugin do usuário nada será
feito.

Quando você escreve um compilador plugin para sobrepor as definições de um
plugin default, não verifique o 'current_compiler'. Este plugin se supõe que
seja carregado por último, assim ele deveria estar em um diretório no final de
'runtimepath'.
No Unix, isto poderia ser '~/.vim/after/compiler'.

Definindo o nome do arquivo do filetype plugin

O filetype (tipo do arquivo) deveria estar incluído no nome do arquivo do
filetype plugin.
Use uma dessas três formas:
.../ftplugin/stuff.vim
.../ftplugin/stuff_foo.vim
.../ftplugin/stuff/bar.vim

Desfazendo mudanças feitas nas opções pelo filetype plugin

Quando o usuário faz ':set filetype xyz' o efeito do tipo do arquivo anterior
deveria ser desfeito.

Defina o valor da variável 'b:undo_ftplugin' com os comandos que irão desfazer as
definições em seu filetype plugin:
let b:undo_ftplugin = "setlocal fo< com< tw< commentstring<"
        \ . "| unlet b:match_ignorecase
b:match_words b:match_skip"
Ao usar 'setlocal' com '<' depois do nome da opção define a opção com seu valor
global. Este é na maioria das vezes a melhor maneira de voltar o valor de uma
opção.
Isto requer remover a flag 'C' de 'cpoptions' para permitir a continuação de
linha como mencionado em salvando 'cpoptions'.

Funções nos filetype plugin

A função só precisa ser definida uma vez.
Mas o filetype plugin será sourced a cada vez que um arquivo deste tipo for aberto.

Esta construção certifica que a função é definida somente uma vez:
:if !exists("*s:Func")
: function s:Func(arg)
: ...
: endfunction
:endif

As variáveis de um filetype plugin

Um filetype plugin será sourced para cada buffer do tipo dele.

As variáveis de script locais, 's:var', serão compartilhadas entre todas
invocações.
Use variáveis locais de buffer, 'b:var' se você quiser uma variável
específica para um buffer.

Comandos de usuários para um filetype plugin

Para adicionar um comando de usuário para um tipo específico de arquivo, para
que ele possa somente ser usado em um buffer, use o argumento '-buffer' do
comando ':command':
:command −buffer Make make %:r.s

sexta-feira, 10 de abril de 2009

Mapeamentos no filetype plugin

Certifique que os mapeamentos somente funcionarão no buffer corrente. Para isto use:
:map <buffer>
Isso tem que ser combinado com o mapeamento em dois passos explicado abaixo:
if !hasmapto('<Plug>JavaImport')
    map <buffer> <unique> <LocalLeader>i <Plug>JavaImport
endif
noremap <buffer> <unique> <Plug>JavaImport oimport ""<Left><Esc>
A função interna 'hasmapto()' é usada para verificar se o usuário já definiu o
mapeamento para '<Plug>JavaImport'. Se não definiu, o filetype plugin define o
mapeamento default.

Isso começa com um <LocalLeader>. Ele será substituído pelo valor que o usuário puser na variável 'maplocalleader'. Isso permitirá que o usuário selecione as teclas que ele quer que comece o mapeamento do filetype plugin. O default é o backslash
('\').

'<unique>' é usado para dar uma mensagem de erro se o mapeamento já existe ou
sobrepõe um mapeamento existente.

':noremap' é usado para evitar que outros mapeamentos que o usuário definiu
interfiram. Poderia também usar ':noremap <script>' para permitir somente
remapeamentos de mapeamentos definidos dentro do script e que comecem com '<SID>'.

O usuário deveria ter a chance de desabilitar os mapeamentos dentro do filetype
plugin sem desabilitar tudo. Eis um exemplo de um filetype plugin para email:
" Add mappings, unless the user didn't want this.
if !exists("no_plugin_maps") && !exists("no_mail_maps")
" Quote text by inserting "> "
if !hasmapto('<Plug>MailQuote')
    vmap <buffer> <LocalLeader>q <Plug>MailQuote
    nmap <buffer> <LocalLeader>q <Plug>MailQuote
endif
vnoremap <buffer> <Plug>MailQuote :s/^/> /<CR>
nnoremap <buffer> <Plug>MailQuote :.,$s/^/> /<CR>
endif
Duas variáveis globais são usadas:
'no_plugin_maps' que desabilita mapeamentos para todos filetype plugins.
'no_mail_maps' que desabilita mapeamentos para um tipo de arquivo específico.

Alterando opções no filetype plugin

Para ter certeza que o filetype plugin afeta somente o buffer corrente use o
comando:
:setlocal
para definir opções.

E somente defina opções que são locais para o buffer (veja o help da opção para
verificar isto). Quando se usa 'setlocal' em opções globais ou em opções locais
para janela, o valor mudará em muitos buffers, e isto não é o que o filetype plugin
deveria fazer.

Quando uma opção é uma lista de flags ou itens, considere usar '+=' ou '-=' para
manter o valor existente.
Fique atento que o usuário já poderia ter mudado o valor de uma opção.
Voltar o valor default de uma opção e então muda-la é uma boa idéia:
:setlocal formatoptions& formatoptions+=ro

Permitindo desabilitar o filetype plugin

Você deveria permitir que as pessoas possam desabilitar o seu plugin.
Coloque isto no topo do plugin:
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
    finish
endif
let b:did_ftplugin = 1
Isto também é necessário para evitar que o mesmo plugin seja executado duas
vezes para o mesmo buffer (acontece quando usando um comando ':edit' sem
argumentos).

Agora os usuários podem desabilitar a carga do filetype plugin default somente
com esta linha:
let b:did_ftplugin = 1
Isto requer que o diretório do filetype plugin venha antes do $VIMRUNTIME no
'runtimepath'.

Se você quiser usar o plugin default, mas regravar um das opções, você definir
uma opção diferente em um script:
setlocal textwidth=70
Agora grave isto no diretório 'after', para que ele seja sourced depois do
ftplugin 'vim.vim' distribuído.

No Unix isso seria '~/.vim/after/ftplugin/vim.vim'.
Note que o plugin default teria definido 'b:did_ftplugin', mas isto é ignorado
aqui.

O filetype plugin

Um filetype plugin é como um plugin global exceto que ele define as opções e
mapeamentos para o buffer corrente somente.

Detectando o tipo do arquivo através do nome do arquivo

Se o seu tipo de arquivo não é detectado automaticamente pelo Vim, você deveria escrever um
snippet de detecção em um arquivo separado.
É normalmente na forma de um autocomando que define o tipo do arquivo quando o
nome do arquivo corresponde a um padrão.
Exemplo:
au BufNewFile,BufRead *.foo set filetype=foofoo
Grave esse arquivo de uma linha como 'ftdetect/foofoo.vim' no primeiro diretório
que aparece em 'runtimepath'.
No Unix seria '~/.vim/ftdetect/foofoo.vim'.
A convenção é usar o nome do tipo do arquivo como o nome do script.

Você pode fazer verificações mais complicadas como inspecionar o conteúdo do
arquivo para reconhecer a linguagem.

Escrevendo a documentação de um plugin

É uma boa idéia escrever documentação para o plugin.
Especialmente quando seu comportamento pode ser mudado pelo usuário.

Eis um exemplo de um arquivo de help de plugin 'typecorr.txt':
1     *typecorr.txt*  Plugin for correcting typing mistakes
2
3 If you make typing mistakes, this plugin will have them corrected
4 automatically.
5
6 There are currently only a few corrections. Add your own if you like.
7
8 Mappings:
9 <Leader>a or <Plug>TypecorrAdd
10 Add a correction for the word under the cursor.
11
12 Commands:
13 :Correct {word}
14 Add a correction for {word}.
15
16 *typecorr−settings*
17 This plugin doesn't have any settings.
A primeira linha é a única em que o formato importa. Ela será extraída do
arquivo de help para ser colocada na seção 'LOCAL ADDITIONS:" do help.txt'.
O primeiro '*' deve estar na primeira coluna da primeira linha.
Depois de adicionar seu arquivo de help faça ':help' e verifique que as entradas
alinham adequadamente.

Você pode adicionar mais tags '*...*' dentro de seu arquivo help. Mas seja
cuidadoso de não de usar tags de help existentes. Você irá provavelmente usar
nome do plugin na maioria deles, como 'typecorr-settings' no exemplo.

Usar referencias para outras partes do help em '|...|' é recomendado. Isto torna
fácil para o usuário achar ajuda associada.

Use o formato 'unix' para gravar o script

Use a opção 'fileformat' com o valor 'unix', mesmo no Windows, para gravar o script. Desse modo ele poderá ser lido em qualquer lugar.

Usando variáveis de script em um plugin

Quando uma variável começa com 's:' ela é uma variável de script. Ela só pode
ser usada dentro de um script. Do lado de fora do script ela não é visível.

Isto evita problemas quando usando um mesmo nome de variável em scripts
diferentes.

As variáveis serão mantidas enquanto o vim estiver rodando.

E as mesmas variáveis serão usadas quando fazendo um sourcing do mesmo script
novamente.

O legal é que essas variáveis podem ser usadas também em funções, autocomandos e
comandos de usuário que estão definidos dentro do script.

Vamos usa-las no plugin para contar o número de correções:
19 let s:count = 4
..
30 function s:Add(from, correct)
..
34 let s:count = s:count + 1
35 echo s:count . " corrections now"
36 endfunction
Primeiro 's:count' é inicializada com '4' no próprio script. Quando mais tarde a
função 's:Add' é chamada, ela incrementa 's:count'. Não importa aonde a função
foi chamada, desde que ela foi definida no script, ela usará as variáveis locais
deste script.

Definindo um comando do usuário no plugin

Defina um comando do usuário para adicionar um correção dessa maneira:
38 if !exists(":Correct")
39 command −nargs=1 Correct :call s:Add(<q−args>, 0)
40 endif
O comando do usuário é definido somente se um outro comando com o mesmo nome
existe. Caso contrário teríamos um erro aqui.
Sobrepondo um comando de usuário existente com ':command!' não é um boa
ideia pois faria o usuário questionar porque o comando que ele criou não
funciona mais.

Os usos e diferenças de <SID> e <Plug> no plugin

Os strings <SID> e <Plug> são usados para evitar que mapeamento das teclas pressionadas interfiram com mapeamentos que são somente para serem usados a partir de outros mapeamentos.

As diferenças entre os dois:
<Plug>

Visível do lado de fora do script. Ele é usado para mapeamentos que o usuário
poderia querer mapear para um sequencia de teclas.

<Plug> é um código especial que uma tecla pressionada nunca produzirá.

Para tornar muito improvável que outros plugins usem a mesma sequencia de
caracteres, use esta estrutura: <Plug> nome-do-script nome-do-mapa

No nosso exemplo o nome do script é 'Typecorr' e o nome do mapa é 'Add'.
Isto resulta em '<Plug>TypecorrAdd'. Somente o primeiro carácter do nome do
plugin e do nome do mapa é maiúsculo, para que possamos ver aonde o nome do mapa
começa.

<SID>
É o script ID, um identificador único para o script.

Internamente o vim traduz <sid> para '<SNR>123_', aonde '123' pode ser qualquer
número. Assim uma função '<SID>Add()' terá o nome de fato '<SNR>11_Add()' em um script e, em um outro script, '<SNR>22_Add()'.
Você pode ver isso se você usa o comando ':function' para obter uma lista de funções.

A tradução de <SID> em mapeamentos é exatamente a mesma, isto é como você pode chamar uma função local
de script a partir de um mapeamento.

Evitando que um remapeamento externo quebre o plugin

Note que na linha 28 ':noremap' é usado para evitar que outros mapeamentos
causem problemas. Alguém poderia ter remapeado ':call' por exemplo.

Na linha, 24 usamos também ':noremap', mas nos queremos '<SID>Add()' ser remapeado. Isto é porque '<script>' foi usado aqui. Isto somente permite mapeamentos que são locais para o script.

O mesmo é feito na linha 26 para ':noremenu'.
24 noremap <unique> <script> <Plug>TypecorrAdd    <SID>Add
26 noremenu <script> Plugin.Add\ Correction <SID>Add
28 noremap <SID>Add :call <SID>Add(expand("<cword>"),1)<CR>

Adicionando um menu de plugin

Você pode adicionar um item no menu para fazer o mesmo que um mapeamento do
plugin faz.

Neste caso somente um item é usado. Quando tiver mais itens, criar um sub-menu
é recomendado. Por exemplo, 'Plugin.CVS' poderia ser usado para um plugin que
oferece os serviços de CVS: 'Plugin.checkin', 'Plugin.checkout', etc.
26 noremenu <script> Plugin.Add\ Correction <SID>Add

quinta-feira, 9 de abril de 2009

Dividindo um plugin grande em funções e mapeamentos

Se um plugin fica grande você vai querer dividi-lo em partes.
Você pode usar funções ou mapeamentos para isto.

Mas você não irá querer que essas funções e mapeamentos interfiram com os dos
outros scripts.

Para evitar isso definimos a função como local ao script prefixando-a com 's:':
Por exemplo, nos definiremos uma função que adiciona um novo tipo de correção:
30 function s:Add(from, correct)
31 let to = input("type the correction for " . a:from . ": ")
32 exe ":iabbrev " . a:from . " " . to
..
36 endfunction
Agora chamaremos a função 's:Add()' de dentro do script. Se um outro script
definir um 's:Add()' também ela será local para aquele script e só pode ser
chamado de dentro do script em que ele foi definido.
Pode também existir uma função 'Add()', a qual novamente é uma outra função.

<SID> pode ser usado com mapeamentos. Ele gera um script ID, o qual identifica o
script corrente. Em nosso plugin de correção de digitação nos usamos ele assim:
24 noremap <unique> <script> <Plug>TypecorrAdd  <SID>Add
..
28 noremap <SID>Add :call <SID>Add(expand("<cword>"),1)<CR>
Assim quando um usuário digita '\a', esta sequencia é invocada:
\a −> <Plug>TypecorrAdd −> <SID>Add −> :call <SID>Add()
Se um outro script também mapear <SID>Add, ele obterá um outro script ID e assim
definirá outro mapeamento.

Note que ao invés de 's:Add()' nos usamos '<SID>Add()' aqui. Isto é porque o
mapeamento é digitado pelo usuário, assim do lado de fora do script. O <SID> é
traduzido para o script ID, para que o vim saiba em qual script procurar pela
função 'Add()'.

Isto é um pouco complicado, mas necessário para o plugin funcionar com outros
plugins. A regra básica é que você use '<SID>Add()' em mapeamentos e 's:Add()'
em outros lugares (no script em si, autocomandos e comandos do usuário).

Tornando flexível a escolha das teclas num mapeamento do plugin

O plugin irá definir um mapeamento que permite adicionar uma correção para
a palavra sob o cursor. Poderia pegar um sequencia de teclas, mas o usuário
poderia já te-la pega para outra coisa.

Para permitir que o usuário defina quais teclas o plugin usará no mapeamento use
o item <Leader>:
22 map <unique> <Leader>a <Plug>TypecorrAdd
O usuário pode definir a variável 'mapleader' com a sequencia de teclas que ele
quer que esse mapeamento comece. Assim se o usuário tiver:
let mapleader = "_"
O mapeamento será definido como '_a'. Se o usuário não fizer isso, o valor
default será usado '\' (backslash) e o mapeamento será '\a'.

Mas se o usuário quiser definir a sua própria sequencia completa de teclas? Pode
permitir isso com:
21 if !hasmapto('<Plug>TypecorrAdd')
22 map <unique> <Leader>a <Plug>TypecorrAdd
23 endif
Isto verifica se um mapeamento para '<Plug>TypecorrAdd' existe e somente define
o mapeamento para '<Leader>a' se ele não existe. O usuário então tem a chance de
por isso em seu 'vimrc':
map ,c <Plug>TypecorrAdd
Então sequencia de teclas mapeada será ',c' ao invés de '_a' ou '\a'.

Permitindo carregar ou não o plugin

Dê a possibilidade do plugin ser carregado ou não. É possível que o usuário não queira carregar o pluign ou o administrador o colocou no diretório plugin a nível de sistema mas o usuário quer carregar seu próprio plugin.

Esse código torna isso possível:
6 if exists("loaded_typecorr")
7 finish
8 endif
9 let loaded_typecorr = 1
Isto também evita que o plugin seja carregado duas vezes causando erros nas
definições de funções e problemas com autocomandos adicionados duas vezes.

Lidando com opções do vim através do plugin

O plugin tem que rodar em ambientes variados, com configurações diversas que podem interferir com seu funcionamento:
14 iabbrev teh the
15 iabbrev otehr other
16 iabbrev wnat want
17 iabbrev synchronisation
18 \ synchronization
19 let s:count = 4
O uso de uma continuação de linha, como na linha 18 acima, pode causar problemas
com usuários com 'compatible' ligado.
Não podemos simplesmente desligar o 'compatible' pois tem uma série de efeitos
secundários.
Para evitar isso vamos definir a opção 'cpoptions' para seu valor default e
restaurar mais tarde. Isto permitirá usar a continuação de linha e fazer o
script trabalhar para a maioria das pessoas:
11 let s:save_cpo = &cpo
12 set cpo&vim
..
42 let &cpo = s:save_cpo
Primeiro salvamos o valor antigo de 'cpoptions' em s:save_cpo. No final o valor
é restaurado.
Note que uma variável local do script é usada. Uma variável global já poderia
ter estado em uso por alguma outra coisa. Sempre use variáveis locais de script
para coisas que são somente usadas no script.

Criando um header para o plugin

Use um cabeçalho que diga quem escreveu o plugin, quando foi a última alteração,
licença de uso:
1 " Vim global plugin for correcting typing mistakes
2 " Last Change: 2000 Oct 15
3 " Maintainer: Bram Moolenaar <Bram@vim.org>
4 " License: This file is placed in the public domain.

O nome do plugin

O nome deve fornecer a finalidade do plugin.
Procure limitar a 8 caracteres para suportar versões antigas do Windows.

O plugin e seus tipos

Você pode escrever um script vim de tal modo que muitas pessoas possam usa-lo.
Isto é chamado de plugin.
Usuários do vim podem baixar seu script no diretório plugin deles e usa-lo
imediatamente.

Existem dois tipos de plugins:
Plugin global - para todos tipos de arquivo.
Plugin filetype - somente para arquivos de um determinado tipo.

Eis um exemplo de um plugin global:
  1     " Vim global plugin for correcting typing mistakes
  2 " Last Change: 2000 Oct 15
  3 " Maintainer: Bram Moolenaar <Bram@vim.org>
  4 " License: This file is placed in the public domain.
  5
  6 if exists("loaded_typecorr")
  7 finish
  8 endif
  9 let loaded_typecorr = 1
 10
 11 let s:save_cpo = &cpo
 12 set cpo&vim
 13
 14 iabbrev teh the
 15 iabbrev otehr other
 16 iabbrev wnat want
 17 iabbrev synchronisation
 18 \ synchronization
 19 let s:count = 4
 20
 21 if !hasmapto('<Plug>TypecorrAdd')
 22 map <unique> <Leader>a <Plug>TypecorrAdd
 23 endif
 24 noremap <unique> <script> <Plug>TypecorrAdd <SID>Add
 25
 26 noremenu <script> Plugin.Add\ Correction <SID>Add
 27
 28 noremap <SID>Add :call <SID>Add(expand("<cword>"), 1)<CR>
 29
 30 function s:Add(from, correct)
 31 let to = input("type the correction for " . a:from . ": ")
 32 exe ":iabbrev " . a:from . " " . to
 33 if a:correct | exe "normal viws\<C−R>\" \b\e" | endif
 34 let s:count = s:count + 1
 35 echo s:count . " corrections now"
 36 endfunction
 37
 38 if !exists(":Correct")
 39 command −nargs=1 Correct :call s:Add(<q−args>, 0)
 40 endif
 41
 42 let &cpo = s:save_cpo