Как я могу двигаться вертикально, пока не достигну непробельного символа?

27

В очень длинном файле с (точно) кодом с отступом может быть полезно перейти непосредственно к строке текста над или под курсором, который ограничивает отступ.

(Один из способов сделать это может быть через метод отступа, сворачивая текущий уровень отступа, который сворачивает линии, ограничивающие уровень отступа, чтобы быть только от курсора jили kот него. Однако я нашел случаи, когда сворачивание отступа не смог поработать на интересующий меня отступ.)

Вот пример с курсором, помеченным подчеркиванием _(во втором символьном столбце между определениями class Bazzи class Qux), но представьте, что количество абзацев или строк внутри modules неизвестно или переменно:

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

... как я мог быстро перемещаться к oиз module Barвыше курсора, или nиз endпод курсором в самой последней строке? Обратите внимание, что вертикальный столбец содержит пробелы, но также не содержит символов во втором столбце между classопределениями.

alxndr
источник
2
связанные: «Перейти к следующей / предыдущей строке с таким же отступом» в Vim Tips Wiki vim.wikia.com/wiki/Move_to_next/…
alxndr
Нажатие клавиши g, а затем клавиши со
стрелкой
1
Решение в ссылке @ alxndr работает хорошо, за исключением случая, когда пробел поддерживается плохо (например, есть случайные строки, которые имеют только пробелы), и вы хотите игнорировать пробел. Решение superjer's ниже лучше, если кто-то обеспокоен этим случаем.
nukeguy

Ответы:

9

Как насчет этой функции?

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

Вы можете nnoremap gU :call FloatUp()<CR>( gUдля «идти вверх»), а затем вызвать с gU.

Вот объяснение:

  • Код многократно перемещается вверх по курсору (с norm k), пока выполняется whileусловие.
  • whileУсловие выполняется , если это не первая линия ( line(".") > 1) и либо
    • эта строка слишком короткая (возможно, пустая); или
    • getline(".")символ текущей строки ( ) в текущем столбце ( [col(".") - 1]) является пробелом ( =~ '\s'то есть соответствует пробелу).
wchargin
источник
1
Кажется, это работает отлично (и быстро), и также легко превращается в FloatDownфункцию. В мой .vimrc это идет, спасибо! github.com/alxndr/dotfiles/commit/0e25a302
alxndr
1
Только что обнаружил, что это решение не совсем работает в визуальном режиме (немного другое поведение в зависимости от того, в каком визуальном режиме оно будет оставаться в той же позиции или перемещаться только на одну строку). Есть указания на то, что там происходит?
alxndr
13

Мне нравится использовать поиск этих вещей, потому что регулярные выражения Vim имеют безумное количество вещей, которые вы можете искать, например, конкретные номера виртуальных столбцов, в этом случае:

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

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

Используйте, cdчтобы спуститься и cuподняться. Я думаю, «колонна вверх» и «колонка вниз» здесь. Я почти на 100% уверен, что это по умолчанию. Или выберите свои собственные сопоставления.

Это должно работать независимо от того, используете вы табуляцию, пробелы или и то, и другое.

superjer
источник
1
У меня проблемы с анализом этих команд. Не могли бы вы немного рассказать о них?
Давидлоурыдуда
1
/ или ? чтобы искать вниз или вверх, \% xv ограничивает поиск виртуальным столбцом с номером 'x', в этом случае 'x' - это '<CR> = virtcol (".") <CR>', который запускает команду virtcol и вставляет номер виртуального столбца, в котором находится курсор в выражении, \ S означает любой непробельный символ.
Чад
1
Спасибо за объяснение Чад. Я просто добавлю, что <CR> в режиме вставки или командной строки захватывает содержимое регистра. =Регистр является регистром выражения , которое вычисляет выражение на месте. Это очень удобно, если не странно.
Супергерой
1
Одним из недостатков этого подхода является то, что если у вас есть подсветка поиска, вы обнаружите, что все символы в вертикальном столбце курсора теперь подсвечиваются после «увеличения или уменьшения столбца».
alxndr
3
Если вы хотите защитить существующий поиск, вы можете добавить :let searchbak=@/<CR>и добавить :let @/=searchbak<CR>. Но в этот момент он становится длинным и недоступным и, возможно, должен быть просто функцией.
Супер
7

Вы можете использовать плагин JumpToVerticalOccurrence (по умолчанию отображается на ]|и [|). Есть несколько других, ]V{char}которые работают как f, но вертикально. Вы можете, конечно, переназначить их по мере необходимости.


Если вы не хотите использовать плагин, вы можете попробовать использовать :searchс virtcol(.), например ,

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

где:

  • virtcol('.') дает вам текущий столбец,
  • \S обозначает не пропуски
  • bW для обратного поиска

Проверьте, :help searchчтобы узнать больше.

Чтобы упростить использование, вы можете отобразить его, например:

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

С другой стороны , если ваш код содержит скобки, использовать %для перехода между сопоставляя их (например {, }, [, ]и т.д.) или использовать весь пункт подскакивает ( {, }с , Shiftесли это необходимо).


Ссылки / источники:

kenorb
источник
От :h search(): wзначит wrap around the end of the fileи Wзначит don't wrap around the end of the file. Но почему вы собрали их вместе на втором :map?
Jair López
@JairLopez Правильно, wне должно быть там, поэтому я удалил его, спасибо. Наверное меня смутило значение клавиш движения.
Кенорб
3

Я использую модифицированную версию плагина vim-indent-object для обеспечения этого поведения. Мои модификации можно увидеть здесь .

Это позволяет мне [iперейти к началу текущего уровня отступа и ]iперейти к концу.

Стив Вермейлен
источник
2

Это не совсем то , что вы просили , потому что это не вертикальное движение, но что - то , что похоже, быстро, и может быть достаточно хорош для вас , движется назад на 2 пункта: {{. Это приведет вас к линии прямо перед module Bar.

Прекратить постоянный вред Монике
источник
2
Представьте, что между курсором и его moduleлинией верхнего уровня существует неизвестное количество строк и / или абзацев . (В частности, эта ситуация возникла, когда я недавно просматривал сторонний код длиной в несколько тысяч строк с точным отступом, но без пустых строк и пытался найти внешний контекст определения модуля.)
alxndr
Прыжки по абзацам - мой любимый способ передвижения, но это не вариант: весь файл был одним «абзацем».
alxndr
2

jeetsukumaran / vim-indentwise хорошо работает для относительных, абсолютных перемещений или перемещений в пределах блока через блоки с отступом.

Гарри
источник
1

Для этого я использую свой собственный плагин move_until_char_changes.vim .

Я сопоставляю это с gKи gJ.

Он будет перепрыгивать через много строк с одним и тем же символом в текущем столбце (не только с пробелами), что может быть полезно в лог-файлах или дампах SQL с повторяющимися строками.

По умолчанию он сначала перемещается на одну строку, прежде чем поднять символ «поиск».

Он работает в визуальном режиме, если вы не пытаетесь использовать его дважды, и вы не находитесь в линейном или блочном визуальном режиме ... (исправления приветствуются!)

joeytwiddle
источник
1

Так как я не вижу здесь ответа ( редакция только что заметила, что superjer упомянул нечто очень похожее). Вы можете просто / или? поиск.

Например, вы можете искать вниз символ без пробелов во 2-м столбце, например:

/\%2v\S

Разбивка это:

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

Затем вы можете использовать обычные операторы, чтобы повторить поиск.

Для получения дополнительной информации по этому вопросу см :help \%cи :help \%v.

Эрик
источник