Como me movo verticalmente até atingir um caractere que não seja um espaço em branco?

27

Em um arquivo muito longo com código recuado (com precisão), pode ser útil mover diretamente para uma linha de texto acima ou abaixo do cursor que delimita o recuo.

(Uma maneira de fazer isso pode ser através do método de indent fold, dobrando o nível de indentação atual, que recolhe as linhas que delimitam o nível de indentação a ficar apenas a um distância jou kfora do cursor. No entanto, encontrei casos em que a indentação não foi foi capaz de trabalhar no travessão no qual estou interessado.)

Aqui está um exemplo, com o cursor marcado pelo sublinhado _(na segunda coluna de caracteres entre as definições de class Bazze class Qux), mas imagine que o número de parágrafos ou linhas dentro de modules seja desconhecido ou variável:

module Foo
  # lots of code...
end

module Bar
  class Baz
    # ...
  end

  class Bazz
    # lots of code...
  end
 _
  class Qux
    # ...
  end

  class Quux
    # lots of code...
  end
end

... como eu poderia navegar rapidamente para o ode module Barcima do cursor, ou a ndo endabaixo o cursor na última linha? Observe que a coluna vertical contém espaços em branco, mas também nenhum caractere na segunda coluna entre as classdefinições.

alxndr
fonte
2
related: "Mover para a próxima linha / anterior com o mesmo recuo" na Vim Dicas Wiki vim.wikia.com/wiki/Move_to_next/...
alxndr
Pressionando g e, em seguida, tecla de sentido pode evitar abas e mover através das linhas
SibiCoder
11
A solução no link do @ alxndr funciona bem, exceto no caso em que o espaço em branco é mal mantido (por exemplo, existem linhas aleatórias que possuem apenas espaços em branco) e você deseja ignorar o espaço em branco. A solução do superjoker abaixo é melhor se alguém estiver preocupado com esse caso.
Nukeguy

Respostas:

9

E essa função?

function FloatUp()
    while line(".") > 1
                \ && (strlen(getline(".")) < col(".")
                \ || getline(".")[col(".") - 1] =~ '\s')
        norm k
    endwhile
endfunction

Você pode nnoremap gU :call FloatUp()<CR>( gUpara "subir") e depois invocar com gU.

Aqui está uma explicação:

  • O código move o cursor repetidamente para cima (com norm k) enquanto a whilecondição se mantiver.
  • A whilecondição é válida se esta não for a primeira linha ( line(".") > 1) e se
    • esta linha é muito curta (provavelmente vazia); ou
    • o caractere da linha atual ( getline(".")) na coluna atual ( [col(".") - 1]) é um espaço em branco ( =~ '\s'; isto é, corresponde ao padrão de espaço em branco).
wchargin
fonte
11
Isso parece funcionar perfeitamente (e rapidamente) e também é facilmente modificado para uma FloatDownfunção. No meu .vimrc vai, obrigado! github.com/alxndr/dotfiles/commit/0e25a302
alxndr
11
Acabei de descobrir que esta solução não funciona no modo visual (comportamento ligeiramente diferente, dependendo de qual modo visual, ele permanecerá na mesma posição ou moverá apenas uma linha). Alguma dica sobre o que está acontecendo lá?
alxndr
13

Eu gosto de usar a pesquisa por essas coisas, porque as regexs do Vim têm uma quantidade insana de coisas que você pode procurar, como números de colunas virtuais específicos, neste caso:

nnoremap cd /\%<C-R>=virtcol(".")<CR>v\S<CR>

nnoremap cu ?\%<C-R>=virtcol(".")<CR>v\S<CR>

Use cdpara descer e cusubir. Estou pensando em "coluna acima" e "coluna abaixo" aqui. Estou quase 100% confiante de que essas não são ops por padrão. Ou escolha seus próprios mapeamentos.

Isso deve funcionar se você estiver usando guias ou espaços ou ambos.

superjer
fonte
11
Estou tendo problemas para analisar esses comandos. Você se importaria de expandir um pouco neles?
Davidlowryduda
11
/ ou? para pesquisar para baixo ou para cima, \% xv limita a pesquisa para o número da coluna virtual 'x', o 'x' nesse caso é '<CR> = virtcol (".") <CR>' que executa o comando virtcol e insere o número da coluna virtual em que o cursor está na expressão, \ S significa qualquer caractere que não seja um espaço em branco.
Chad
11
Obrigado por explicar o Chade. Acrescentarei apenas que <CR> no modo Inserir ou no modo de linha de comando captura o conteúdo de um registro. O =registro é o registro de expressão que avalia uma expressão no local. É muito útil, se não um pouco estranho.
Super
11
Uma desvantagem dessa abordagem é que, se você tiver destaque de pesquisa, verá que todos os caracteres na coluna vertical do cursor agora serão destacados após "subir a coluna" ou "descer a coluna".
Alxndr
3
Se você deseja proteger sua pesquisa existente, você pode anexar :let searchbak=@/<CR>e anexar :let @/=searchbak<CR>. Mas neste momento está ficando meio longo e inacessível e talvez deva ser apenas uma função.
Super
7

Você pode usar o plugin JumpToVerticalOccurrence (padrão mapeado para ]|e [|). Existem poucos outros ]V{char}que funcionam f, mas verticalmente. É claro que você pode remapear conforme necessário.


Se você não quiser usar plug-ins, tente usar :searchcom virtcol(.), por exemplo:

:call search('\%' . virtcol('.') . 'v\S', 'bW')

Onde:

  • virtcol('.') fornece a coluna atual,
  • \S significa espaço não em branco
  • bW é para pesquisa reversa

Verifique :help searchpara saber mais.

Para facilitar o uso, você pode mapeá-lo, por exemplo:

:map <C-k> :call search('\%' . virtcol('.') . 'v\S', 'bW')<CR>
:map <C-j> :call search('\%' . virtcol('.') . 'v\S', 'W')<CR>

Alternativamente, se o seu código contém parênteses, o uso %de saltar entre combiná-los (por exemplo {, }, [, ], etc.) ou usar parágrafo inteiro salta ( {, }com Shiftse necessário).


Links / fontes:

kenorb
fonte
De :h search(): wmeios wrap around the end of the filee Wmeios don't wrap around the end of the file. Mas por que você os juntou no segundo :map?
Jair López #
@JairLopez Correto, wnão deveria estar lá, então eu o removi, obrigado. Provavelmente eu estava confuso com o significado das teclas de movimento.
kenorb
3

Eu uso uma versão modificada do plug - in vim-indent-object para fornecer esse comportamento. Minhas modificações podem ser vistas aqui .

Isso me permite mapear [ipara ir para o início do nível de recuo atual e ]ipara o final.

Steve Vermeulen
fonte
2

Não é exatamente o que você pediu, porque não é o movimento vertical, mas algo que é semelhante, rápido, e pode ser bom o suficiente para você está se movendo para trás 2 parágrafos: {{. Isso levará você para a linha logo antes module Bar.

Pare o dano contínuo a Monica
fonte
2
Imagine que haja um número desconhecido de linhas e / ou parágrafos entre o cursor e sua modulelinha de nível superior . (Especificamente, esta situação surgiu quando eu estava recentemente a navegação de código de terceiros vários milhares de linhas de comprimento, com recuo precisos, mas há linhas vazias, e tentando encontrar o contexto externo da definição de um módulo.)
alxndr
Pular por parágrafos é minha maneira preferida de se movimentar, mas não era uma opção: o arquivo inteiro era um "parágrafo".
alxndr
2

jeetsukumaran / vim-indentwise funciona bem para movimentos relativos, absolutos ou de escopo de bloco entre blocos recuados.

Harry
fonte
1

Eu uso meu próprio plugin move_until_char_changes.vim para isso.

Eu mapeio para gKe gJ.

Irá pular muitas linhas com o mesmo caractere na coluna atual (não apenas espaço em branco), o que pode ser útil em arquivos de log ou dumps SQL com sequências repetidas.

Por padrão, ele primeiro move uma linha, antes de selecionar o caractere "pesquisar".

Funciona no modo Visual, desde que você não tente usá-lo duas vezes e não esteja no modo Visual em linha ou em bloco ... (correções bem-vindas!)

joeytwiddle
fonte
1

Como não vejo aqui como resposta (a edição acabou de notar que a superjer mencionou algo muito semelhante). Você pode simplesmente o / ou? procurar.

Por exemplo, você pode procurar para baixo por um caractere que não seja espaço em branco na 2ª coluna como esta:

/\%2v\S

A repartição é:

/    "search downward (use ? for upward movement)
\%2v "for the following char in the 2nd virtual column
\S   "any non white space character

Em seguida, você pode usar os operadores normais para repetir a pesquisa.

Para mais informações sobre o assunto, consulte :help \%ce :help \%v.

Eric
fonte