Як рухатись вертикально до досягнення символу, який не пробігає?


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визначеннями.


2
пов'язано: "Перехід до наступного / попереднього рядка з тим же відступом" на Vim Tips Wiki vim.wikia.com/wiki/Move_to_next/…
alxndr

Натискання клавіш g, а потім клавіша напряму може уникнути вкладок і переміщення по лініях
SibiCoder

1
Розв’язання посилання @ alxndr працює добре, за винятком випадків, коли пробіл погано підтримується (наприклад, є випадкові лінії, які мають лише пробіли) і ви хочете ігнорувати пробіли. Розв’язання супержера нижче є кращим, якщо когось турбує цей випадок.
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'тобто відповідає шаблону пробілів).

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% впевнений, що це не за замовчуванням. Або виберіть власні відображення.

Це повинно працювати, чи використовуєте ви вкладки чи пробіли чи обидва.


1
У мене проблеми з розбором цих команд. Чи не могли б ви трохи розширити їх?
davidlowryduda

1
/ або? для пошуку вниз або вгору, \% xv обмежує пошук віртуального номера стовпця 'x', 'x' в цьому випадку - '<CR> = virtcol (".") <CR>', який запускає команду virtcol і вставляє номер віртуального стовпця, на якому курсор знаходиться у виразі, \ S означає будь-який символ, який не є пробілом.
Чад

1
Дякуємо за пояснення Чаду. Я просто додам, що <CR> в режимі Вставка або Командний рядок захоплює вміст регістра. =Регістр є регістром вираження , яке обчислює вираз на місці. Це дуже зручно, якщо не трохи дивно виглядати.
superjer

1
Одним із недоліків такого підходу є те, що якщо у вас підсвічування пошуку, ви побачите, що всі символи вертикальної колонки курсора тепер виділяються після "стовпця вгору" або "стовпця вниз".
alxndr

3
Якщо ви хочете захистити свій існуючий пошук, ви можете :let searchbak=@/<CR>додати його та додати :let @/=searchbak<CR>. Але в цей момент це стає настільки довгим і неприступним, і, можливо, це просто функція.
superjer

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якщо це необхідно).


Посилання / джерела:


З :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не повинно бути там, тому я його видалив, дякую. Напевно, мене збентежило значення клавіш руху.
kenorb

3

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

Це дозволяє мені скласти карту [iдля початку поточного рівня відступу та ]iдо кінця.


2

Це не зовсім те , що ви просили , тому що це не вертикальний рух, але що - то , що схоже, швидко, і може бути досить хороший для вас , рухається назад на 2 пункти: {{. Це відведе вас до лінії прямо раніше module Bar.


2
Уявіть, що між курсором та його верхнім рівнем невідома кількість рядків та / або абзаців module. (Зокрема, така ситуація виникла, коли я нещодавно переглядав сторонній код довжиною кілька тисяч рядків з точним відступом, але без порожніх рядків, і намагався знайти зовнішній контекст визначення модуля.)
alxndr

Стрибки по абзацах - це мій бажаний спосіб пересування, але це був не варіант: весь файл був одним "абзацом".
alxndr


1

Для цього я використовую власний плагін move_until_char_changes.vim .

Я відображаю його в gKі gJ.

Він буде переходити через безліч рядків з однаковим символом у поточному стовпці (а не лише пробіли), що може бути корисним у журналах реєстрації або скидах у SQL з повторними рядками.

За замовчуванням він спочатку переміщує один рядок, перш ніж підбирати символ "Пошук".

Він працює у візуальному режимі за умови, що ви не намагаєтесь його використовувати двічі, і ви не перебуваєте в лінійному або блочному візуальному режимі ... (виправлення вітаються!)


1

Оскільки я не бачу це як відповідь ( редагування щойно помітив, що супержер згадував щось дуже схоже). Ви можете просто / або? пошук.

Наприклад, у другому стовпці можна шукати символ, який не пробілює, вниз:

/\%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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.