Comment puis-je me déplacer verticalement jusqu'à atteindre un caractère non blanc?

27

Dans un fichier très long avec du code en retrait (précis), il peut être utile de se déplacer directement vers une ligne de texte au-dessus ou en dessous du curseur qui délimite le retrait.

(Une façon de le faire pourrait être via la méthode de pliage en retrait, en pliant le niveau de retrait actuel, ce qui réduit les lignes délimitant le niveau de retrait pour être seulement à jou kloin du curseur. Cependant, j'ai trouvé des cas où le pliage en retrait n'a pas pu travailler sur le tiret qui m'intéresse.)

Voici un exemple, avec le curseur marqué par le trait de soulignement _(dans la deuxième colonne de caractères entre les définitions de class Bazzet class Qux), mais imaginez que le nombre de paragraphes ou de lignes dans le modules est inconnu ou variable:

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

... comment pourrais - je accéder rapidement au ode module Bardessus du curseur, ou ndu enddessous du curseur à la dernière ligne? Notez que la colonne verticale contient des espaces, mais également aucun caractère dans la deuxième colonne entre les classdéfinitions.

alxndr
la source
2
en relation: "Passer à la ligne suivante / précédente avec la même indentation" sur Wiki Vim Tips vim.wikia.com/wiki/Move_to_next/…
alxndr
Appuyer sur g puis sur la touche de direction peut éviter les tabulations et se déplacer entre les lignes
SibiCoder
1
La solution dans le lien de @ alxndr fonctionne bien sauf dans le cas où les espaces blancs sont mal entretenus (par exemple, il y a des lignes aléatoires qui n'ont que des espaces blancs) et où vous voulez ignorer les espaces blancs. La solution de superjer ci-dessous est meilleure si l'on est préoccupé par ce cas.
nukeguy

Réponses:

9

Et cette fonction?

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

Vous pouvez nnoremap gU :call FloatUp()<CR>( gUpour "monter"), puis invoquer avec gU.

Voici une explication:

  • Le code monte à plusieurs reprises le curseur (avec norm k) tant que la whilecondition est maintenue.
  • La whilecondition est vérifiée si ce n'est pas la première ligne ( line(".") > 1) et que
    • cette ligne est trop courte (probablement vide); ou
    • le caractère de la ligne en cours ( getline(".")) dans la colonne en cours ( [col(".") - 1]) est un espace (( =~ '\s'c'est-à-dire, correspond au modèle d'espace)).
wchargin
la source
1
Cela semble fonctionner parfaitement (et rapidement), et se transforme facilement en FloatDownfonction également. Dans mon .vimrc il va, merci! github.com/alxndr/dotfiles/commit/0e25a302
alxndr
1
Je viens de découvrir que cette solution ne fonctionne pas tout à fait en mode visuel (comportement légèrement différent selon le mode visuel, elle restera dans la même position ou se déplacera d'une seule ligne). Des conseils sur ce qui se passe là-bas?
alxndr
13

J'aime utiliser la recherche pour ces choses, car les expressions régulières de Vim ont une quantité insensée de choses que vous pouvez rechercher, comme des numéros de colonnes virtuelles spécifiques, dans ce cas:

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

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

Utilisez cdpour descendre et cupour monter. Je pense "colonne vers le haut" et "colonne vers le bas" ici. Je suis presque sûr à 100% qu'il ne s'agit pas d'opérations par défaut. Ou choisissez vos propres mappages.

Cela devrait fonctionner que vous utilisiez des tabulations, des espaces ou les deux.

superjer
la source
1
J'ai du mal à analyser ces commandes. Pourriez-vous les développer un peu?
davidlowryduda
1
/ ou ? pour rechercher vers le bas ou vers le haut, \% xv limite la recherche au numéro de colonne virtuelle 'x', le 'x' dans ce cas est '<CR> = virtcol (".") <CR>' qui exécute la commande virtcol et insère le numéro de colonne virtuelle dans lequel se trouve le curseur dans l'expression, \ S signifie tout caractère autre qu'un espace.
Chad
1
Merci d'avoir expliqué Chad. Je vais juste ajouter que <CR> en mode Insertion ou en mode ligne de commande saisit le contenu d'un registre. Le =registre est le registre d'expression qui évalue une expression en place. C'est très pratique, sinon un peu bizarre.
superjer
1
Un inconvénient de cette approche est que si vous avez mis en surbrillance la recherche, vous constaterez que tous les caractères de la colonne verticale du curseur sont maintenant mis en surbrillance après "colonne vers le haut" ou "colonne vers le bas".
alxndr
3
Si vous souhaitez protéger votre recherche existante, vous pouvez :let searchbak=@/<CR>ajouter et ajouter :let @/=searchbak<CR>. Mais à ce stade, cela devient un peu long et inaccessible et devrait peut-être juste être une fonction.
superjer
7

Vous pouvez utiliser le plugin JumpToVerticalOccurrence (mappé par défaut à ]|et [|). Il y en a peu d'autres ]V{char}qui fonctionnent comme f, mais verticalement. Vous pouvez bien sûr les remapper au besoin.


Si vous ne souhaitez pas utiliser de plugins, vous pouvez essayer de l'utiliser :searchavec virtcol(.), par exemple:

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

où:

  • virtcol('.') vous donne la colonne actuelle,
  • \S signifie non-blanc
  • bW est pour la recherche en arrière

Cochez :help searchpour en savoir plus.

Pour le rendre plus facile à utiliser, vous pouvez le cartographier, par exemple:

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

Par ailleurs, si votre code contient des crochets, utilisez %pour sauter entre eux correspondant (par exemple {, }, [, ], etc.) ou utiliser des sauts tout le paragraphe ( {, }avec le Shiftcas échéant).


Liens / sources:

kenorb
la source
De :h search(): wmoyens wrap around the end of the fileet Wmoyens don't wrap around the end of the file. Mais pourquoi les avez-vous réunis le deuxième :map?
Jair López
@JairLopez Correct, wne devrait pas être là, donc je l'ai supprimé, merci. J'ai probablement été confondu par le sens des touches de mouvement.
kenorb
3

J'utilise une version modifiée du plugin vim-indent-object pour fournir ce comportement. Mes modifications sont visibles ici .

Cela me permet de mapper [ipour aller au début du niveau de retrait actuel et ]ipour aller à la fin.

Steve Vermeulen
la source
2

Ce n'est pas exactement ce que vous avez demandé parce que ce n'est pas un mouvement vertical, mais quelque chose qui est semblable, rapide, et peut - être assez bon pour vous est en mouvement 2 arrière paragraphes: {{. Cela vous amènera à la ligne juste avant module Bar.

Arrêtez les dommages continus à Monica
la source
2
Imaginez qu'il existe un nombre inconnu de lignes et / ou de paragraphes entre le curseur et sa moduleligne de niveau supérieur . (Plus précisément, cette situation s'est produite lorsque je naviguais récemment dans un code tiers de plusieurs milliers de lignes, avec une indentation précise mais pas de lignes vides, et en essayant de trouver le contexte externe de la définition d'un module.)
alxndr
Sauter par paragraphes est ma façon préférée de se déplacer, mais ce n'était pas une option: le fichier entier était un "paragraphe".
alxndr
2

jeetsukumaran / vim-indentwise fonctionne bien pour les mouvements relatifs, absolus ou de portée de bloc à travers les blocs en retrait.

Harry
la source
1

J'utilise mon propre plugin move_until_char_changes.vim pour cela.

Je le mappe à gKet gJ.

Il sautera par-dessus de nombreuses lignes avec le même caractère dans la colonne actuelle (pas seulement les espaces blancs), ce qui peut être utile dans les fichiers journaux ou les vidages SQL avec des chaînes répétées.

Par défaut, il déplace d'abord une ligne, avant de prendre le caractère "recherche".

Il fonctionne en mode visuel à condition de ne pas l'utiliser deux fois et que vous ne soyez pas en mode visuel en ligne ou en bloc ... (correctifs bienvenus!)

joeytwiddle
la source
1

Puisque je ne le vois pas ici comme une réponse ( edit vient de remarquer que superjer a mentionné quelque chose de très similaire). Vous pouvez simplement le / ou? chercher.

Par exemple, vous pouvez rechercher vers le bas un caractère non blanc dans la 2ème colonne comme ceci:

/\%2v\S

La répartition est la suivante:

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

Ensuite, vous pouvez utiliser les opérateurs normaux pour répéter la recherche.

Pour plus d'informations sur le sujet, voir :help \%cet :help \%v.

Eric
la source