Как я могу заставить 'n' идти вперед, даже если я начал искать с '?' или '#'?

19

Vim имеет (как минимум) два набора команд, которые ищут в противоположных направлениях. Ввод, /а затем шаблон будет искать вперед в документе для шаблона; набрав, ?а затем шаблон будет искать в обратном направлении. Же зависимость существует между *и #командами.

То , что мне не нравится то , что эти команды также задать направление поиска для nи Nкоманд. После использования /, nидет вперед по документу и Nидет в обратном направлении; после использования ?, nидет назад и Nидет вперед. (Другими словами, nвсегда идет в том же направлении, что и исходный поиск, и Nвсегда идет в другом направлении.)

Как я могу nпройти вперед по документу и Nвернуться назад, независимо от того, в каком направлении я начал поиск?

bdesham
источник

Ответы:

29

Вы можете изменить поведение nи Nосуществлять последовательный поиск вниз / вверх, используя следующее:

nnoremap <expr> n 'Nn'[v:searchforward]
nnoremap <expr> N 'nN'[v:searchforward]

Обновление: как это работает?

При этом используются карты выражений, которые отображают lhs карты на выражение, которое будет оцениваться каждый раз, когда встречается lhs. Смотри :h map-expressionв помощь.

Что происходит, так это то, что переменная v: searchforward (которая определяет внутреннее состояние, в каком направлении был последний поиск, см. :h v:searchforward) Используется в качестве индекса для строки перед ней. Таким образом, в случае первой карты, если последнее направление поиска было вперед, n будет отображаться в 'n' (индекс 1, означающий возвращение второго символа), а если оно было обратным, 'n' будет отображаться в «N» (потому что переменная v: searchforward равна 0 и, следовательно, «N» будет возвращено.

Альтернативный способ написания этих карт будет (что может быть более понятным):

nnoremap <expr> n (v:searchforward ? 'n' : 'N')
nnoremap <expr> N (v:searchforward ? 'N' : 'n')

Есть также некоторые плагины, которые делают это (то есть плагин SearchRepeat и, возможно, другие).

Кристиан Брабандт
источник
Спасибо за упоминание моего плагина; Я как раз собирался рекомендовать это как альтернативу :-)
Инго Каркат
2
Умное использование подписки!
wchargin
6
Не могли бы вы добавить объяснение? Я не видел этот синтаксис раньше, и я хотел бы знать, как он работает.
EvergreenTree
1
@EvergreenTree: добавлено еще несколько объяснений
Кристиан Брабандт,
2
@ChristianBrabandt Это очень умно. Я никогда не думал, что вы используете v:searchforwardв качестве индекса.
EvergreenTree
1

Основываясь на решении Кристиана Брабандта, я придумал

nnoremap <expr> n 'Nn'[v:searchforward].(&fdo=~'search\\|all'?'zv':'')
nnoremap <expr> N 'nN'[v:searchforward].(&fdo=~'search\\|all'?'zv':'')

Эти отображения также подчиняются foldopenнастройке

Науманн
источник
0

Я использую плагин SearchIndex . Чтобы использовать ответ Кристиана Брабандта, но сохранить функциональность плагина для отображения номера совпадения каждый раз, когда я набираю nили N, я помещаю это в свой vimrc:

nnoremap <silent><expr> n (v:searchforward ? 'n' : 'N') . ":SearchIndex<CR>"
nnoremap <silent><expr> N (v:searchforward ? 'N' : 'n') . ":SearchIndex<CR>"
bdesham
источник