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/