sábado, 14 de março de 2009

Qual método de folding usar ?

Se tiver um arquivo de sintaxe com folding, para a linguagem de programação que está se editando, essa é a melhor escolha.
Se a linguagem não tiver, pode ser se escrever um, mas precisa de bons conhecimentos de pesquisa.

Se o texto não for estruturado, pode-se criar regiões de fold manualmente e salva-lo com 'mkview'.

Se precisar definir precisamente a região de fold use o folding por marcas. A deficiência é que o arquivo precisa ser alterado, algo que pode não ser possível se for compartilhado ou as regras locais não permitirem.

Se outros métodos como por sintaxe não funcionam pode-se usar folding por indentação. Embora não funcione sempre. Ele é muito útil quando fazendo uma lista hierarquica com indentação.

Em textos estruturados, especialmente que contenham marcas que permitem definir a região do fold pode ser usar o folding por expressão. Mesmo que a expressão nao consiga definir todos os folds, use-o, mude para o método manual e delete ou crie folds manualmente para esses casos.

Folding de linhas não-alteradas

Isto é útil quando se usa também a opção 'diff' na mesma janela (junta a janela com um grupo de janelas para mostrar diferenças).

O comando 'vimdiff' faz isso para voce.

Por exemplo:
:setlocal diff foldmethod=diff scrollbind nowrap foldlevel=1

Faça isso em cada janela que mostra uma diferente versão para o mesmo arquivo.
As diferenças serão vistas claramente, enquanto o texto que não mudou fica dentro de folds.

Folding por expressão

Use:
:set foldmethod=expr
:set foldexpr=strlen(substitute(substitute(getline(v:lnum),'\\s','',\"g\"),'
[^>].*','',''))

Explicação da expressão de dentro para fora:
getline(v:lnum) - obtém a linha corrente.
substitute(...) - então substitui todos espaços por string vazio (deleta-os).
substitute(...) - então substitui tudo depois de um '>' no início da linha por string vazio (deleta-os)
strlen(...) - então conta o tamanho do string resultante, o qual é o número de '>' encontrados.

Note que um backslash (\) deve ser inserido antes de um espaço, aspas duplos e backslash no comando :set.

Para ver a expressão resultante sem backslashs use:
:set foldexpr

Para corrigir uma expressão complicada use:
:set foldexpr=<tab>
o vim preencherá o comando :set completo pronto para ser editado.

É similar ao folding por indentação, exceto que ao invés de uma indentação é usada uma função do usuário que calcula o nível de fold de uma linha.

Isso pode ser usado para textos que tem algo que indicam que certas linhas pertencem uma as outras. Por exemplo, texto de e-mail aonde um '>' antes da linha indica texto citado.

Se a expressão ficar complicada coloque-a dentro de uma função e faça 'foldexpr' chama-la.

Folding por sintaxe

Cada linguagem de programação tem um arquivo de sintaxe do Vim.
Além de definir as cores de itens do arquivo, é possível definir uma região para fold através do argumento 'fold'.

Isto não é uma tarefa fácil. Mas uma vez feito todos os folds acontecem automaticamente.

Felizmente há vários arquivos de sintaxe que já fazem isso. Basta abrir e fechar os folds criados por eles.

Opção para definir o texto que aparece num fold fechado

Use:
:set foldtext
A linha que aparece quando o fold está fechado pode mostrar um texto que indica o conteúdo do fold.

O default é:
:set foldtext=foldtext()
A função mostra a primeira linha não-branca do fold.

Folding com marcas no texto

Use:
:set foldmethod=marker

Use marcas no texto para definir o início e o fim da região do fold.
Isso dá controle preciso de qual linhas são incluídas no fold.

A desvantagem é que o texto precisa ser mudado.

Exemplo:
/* foobar () {{{ */
int foobar()
{
/* return a value {{{ */
return 42;
/* }}} */
}
/* }}} */

Um fold começa com a marca "{{{" e termina opcionalmente com "}}}". As marcas podem ter o número de nível do.

A opção 'foldmarker' define as marcas.

Regras para delimitar folds:

Se um outra marca com o mesmo nível de fold é encontrada, o fold anterior termina e começa outra fold com o mesmo nível.
Se uma marca com nível de fold maior é encontrada, um fold aninhado é iniciado.
Se uma marca com nível de fold menor é encontrada, todos os folds acima incluindo este nível terminam e o fold com nível menor começa.

Marcas com número de nível de fold:
{{{1
nível de fold aqui é 1
{{{3
nível de fold aqui é 3
}}}3
nível de fold aqui é 2

O 'zf' pode ser usado para inserir marcas de início e fim. As marcas são apendadas no final da linha.
Use uma seleção visual ou outra seleção para definir o fold.
Atenção que isso pode não funcionar sempre.

sexta-feira, 13 de março de 2009

Desabilitando / habilitando folds

zn - desabilita os folds temporariamente.
zN - restaura os folds que foram desabilitados.
zi - desabilita (zn) ou retorna todos os folds (zN).

Deletando folds manuais

zd - deleta um fold na linha do cursor.
zD - deleta todos folds aninhados na linha do cursor.

Abrindo e fechando folds

zo - abre um fold sob o cursor.
zO - abre todos folds aninhados sob o cursor.
zc - fecha um fold sob o cursor.
zC - fecha todos folds aninhados sob o cursor.

zr - abre todos os folds em um nível de aninhamento.
zm - fecha todos os folds em um nível de aninhamento.
Repetindo os comandos, eles abrem e fecham os níveis seguintes de fold.

zR - abre todos folds em todos níveis de uma só vez.
zM - fecha todos folds em todos níveis de uma só vez.

Então existem 2 formas de abrir/fechar folds>

Definindo o nível de fold:
Isto permite 'encolher' o texto para rapidamente ver a estrutura do texto, mover o cursor e 'expandir' o texto novamente.

Usando 'zo' e 'zc' para abrir e fechar folds específicos:
Isto permite abrir somente os folds que interessam, mantendo os demais fechados.

Isto pode ser combinado:
Primeiro, fechar a maioria dos folds com 'zm' algumas vezes e abrir um fold específico com 'zo'.
Ou abrir todos os folds com 'zR' e fechar folds específicos com 'zc'.

Opção para definir o nível de fold

Use:
:set foldlevel=valor

Os comandos 'zm' e 'zr' aumenta e diminuem a opção 'foldlevel'. Também poderia alterar diretamente:
:set foldlevel=3

Isto significa que folds com nível mais alto serão fechados.

Quanto mais baixo o valor do 'foldlevel', mais folds serão fechados. Quando o 'foldlevel' é zero, todos folds serão fechados.

'zM' faz o nível de folding ser 0 e 'zR' faz o nível ser o mais baixo que existe no arquivo.

Folding por indentação

Se o texto está estruturado para dar aos itens de menor nível a maior indentação, então pode-ser usar o método de folding por indentação:
:set foldmethod=indent

Isto criará folds para cada sequencia de linhas de mesma indentação. Para linhas com indentação maior os folds serão aninhados.

Isto funciona com muitas linguagens de programação.

Após isso use 'zm' para mais folds e 'zr' para reduzir folds.

A opção 'shiftwidth' define o valor da indentação. E a cada indentação adiciona um ao nível de fold.

Com esse método de folding, não se pode criar manualmente folds.

Salvando e restaurando folds

Quando um buffer é abandonado, o estado dos folds é perdido. Quando voltar ao mesmo arquivo, os folds abertos e fechados voltam no seu default.

Quando os folds são criados manualmente, todos somem.

Para salva-los use o comando:
:mkview

Pode-se mudar o que é salvo com a opção:
:set viewoptions

Para restaurar, use:
:loadview

Pode-se armazenar até 10 views de um arquivo.
Salvando a configuração atual como a 3ª view:
:mkview 3
Carregando uma 2ª view salva:
:loadview 2

Se linhas forem inseridas ou deletadas, a view se torna inválida.
Veja a opção 'viewdir' para ver aonde as views são salvas e para limpa-las de tempos em tempos.

Opção para definir o tipo de folding a ser usado

Use:
:set foldmethod=valor
manual
indent - linhas com indentação igual formam um fold
fold-expr - a opção 'foldexpr' dá o nível de fold de uma linha.
fold-marker - marcas são usadas para especificar folds.
fold-syntax - itens colorizados por sintaxe especificam folds.
fold-diff - faz fold de texto que não foi mudado.

Opção para definir quando os folds abrem/fechem automaticamente

Use:
:set foldopen=valor

Fazendo com que o fold se abra quando o cursor estiver sobre ele:
set foldopen=all

No entanto não será possível mover folds fechados. Use-o temporariamente e depois volte para o valor default:
set foldopen&

Fazendo com que o fold se feche quando o cursor sair dele:
set foldclose=all

quinta-feira, 12 de março de 2009

Opção para mostrar uma coluna indicando os folds abertos e fechados

Use:
:set foldcolumn=4
defina o tamanho da coluna.

Um '+' indica um fold aberto, um '-' um fold fechado.

Trabalhando com folds

Um bom fluxo de trabalho com folds:
Crie folds para obter uma visão geral do arquivo.
Faça um 'zi' para olhar o texto dentro do fold e edita-lo.
Faça um outro 'zi' para voltar os folds e se movimentar entre eles.

Voce pode copiar, deletar e colar folds fechados como se fossem uma linha.
Pode-se movimentar sobre os folds fechados como comandos como 'j' ou 'k'.

Por exemplo, reordenando funções de um programa usando folds:

Certifique que cada fold contém uma função completa (ou um pouco menos)
selecionando o valor correto da função 'foldmethod'.
Então, delete a função com 'dd', mova o cursor e cole com 'p'.

Se algumas linhas da função estão acima ou abaixo do fold, voce pode
usar seleção visual:
coloque o cursor na 1ª linha a ser movida.
V
coloque o cursor na última linha a ser movida.
d
mova o cursor para novo local
p

quarta-feira, 11 de março de 2009

Criando folds manuais

zfmovimento ou seleção visual + zf :
cria um fold
Por exemplo, zfap , cria um fold para o objeto parágrafo corrente.

Folds podem ser aninhados: folds de parágrafos dentro de um fold de seção, etc.

Folding

Folding é uma forma de mostrar um intervalo de linhas como um só linha na tela.
É como se fosse um papel que tem uma dobra (fold) para que ele fique menor.

O texto ainda está no buffer, inalterado.

A vantagem é que se tem uma visão geral melhor com as linhas seções 'dobradas' e vistas como uma linha.

Procurando um identificador de programa

Use:
\<\h\w*\>
ancora início-de-palavra, seguida de um caracter inicial de palavra (a_zA_z_), seguido de zero ou mais caracteres de palavra (0_9a_zA_z_), seguido de uma ancora fim-de-palavra.

Mas, as ancoras acima dependem da opção 'iskeyword'. Se ela incluir '-', 'ident-' não será obtida.
Use então:
/\w\@<!\h\w*\w\@!
não precede com um caracter de palavra um caracter inicial de palavra, seguido de zero ou mais caracteres de palavra, não seguido de um caracter de palavra.

terça-feira, 10 de março de 2009

Expressão regular: agrupamento atomico

O item precedente age como se fosse um padrão completo. Se obtiver a ocorrência ela é tratada com uma coisa só (atomica), não pode ser fracionada fora dos parenteses para completar o resto do padrão.

\(a*\)\@>a

O padrão não retorna nenhum ocorrência, pois 'a*' dentro de um grupo atomico consome todos os 'a' como se fosse o padrão completo e não há nenhum 'a' para passar.

Ele pode ser usado para otimizar o regexp ou controlar precisamente o que deve ser obtido ou não.

segunda-feira, 9 de março de 2009

Expressão regular: lookbehind negativo - testa a não existência de um item antes de outro.

\(foo\)\@<!bar
Testa se o item precedente ('foo') não está imediatamente antes do item que o segue ('bar').
Somente a linha corrente (que contém o item que segue) e uma linha antes são testadas.

Só obtém a ocorrência do item que segue ('bar').

Um item precedente que termine '.*' funciona, mas pode ser lento.

\(\/\/.*\)\@<!in

Obtém uma ocorrência se 'in' não está depois de '//'.