Привет, коллеги. Сегодня я поделюсь своим опытом. Мне часто приходится работать с текстовой картой морского дна: каждая точка выражена целочисленной двузначной глубиной, а точек очень много: несколько сотен на несколько сотен. По этой карте была построена маска, в которой глубина была заменена на 00 там, где проблем не обнаружено и ** там, где обнаружено. Таких точек, с проблемами, нашлось около ста. Решение по каждой надо принимать лично, алгоритмизировать это сложно.
Итак, мне нужно:
- найти очередную точку с ** (легко делается через /\*\*)
- заменить ее на 00 (легко делается через 2s00<esc>)
- запомнить позицию в файле: номер строки и номер "столбца", то есть символа в строке. Числа большие: номера строк трехзначные, номера столбцов вообще четырехзначные.
- Прибавить к этим числам константы: дело в том, что в карте несколько первых строк служебные (четыре) и в начале каждой строки идет ее номер (еще четыре символа: три цифры и пробел).
- Перейти в другой файл (легко делается через gt) и найти нужную позицию (НОМЕР_СТРОКИ G, НОМЕР_СТОЛБЦА|)
- Принять решение, внести исправление и вернуться (gT).
Вопрос в том, как автоматизировать пункты 3-4, а лучше - все с первого по пятый.
Делается это довольно просто. Есть функция getpos, которая с аргументом '.' возвращает позицию курсора в виде списка из четырех элементов: [bufnum, lnum, col, off]
Первый (точнее, "номер нуль", так списки индексируются от нуля) элемент - номер буфера, но там обычно нуль, что означает "этот буфер". Не-нуль там при других аргументах: метках и т.п. Следующие два элемента и есть позиция курсора: строка и столбец, отсчитываются от единицы. Последний элемент нам не нужен: это для режима virtualedit, когда можно поставить курсор за пределы текста.
Итак, p=getpos('.') решает задачу №3.
Прибавить константы тоже несложно:
p[1]=p[1]+4
p[2]=p[2]+4
Помним, что в списке элементы отсчитываются от нуля.
Парная функция называется setpos: она принимает два аргумента. Первым будет '.', то есть позиция курсора, а вторым - тот самый список p:
call setpos('.', p)
Это решает задачу 5.
Собираем всё вместе:
map qq /\*\*<CR>:let p=getpos('.')<CR>2s00<ESC>:let p[1]=p[1]+4<CR>\|:let p[2]=p[2]+4<CR>gt:call setpos('.', p)<CR>
Разберем по частям:
map qq - определяет привязку. По нажатию qq будет срабатывать наш код.
Сначала осуществляем поиск /\*\*<CR>. Символ <CR> означает нажатие клавиши ввода.
Потом запоминание позиции через getpos. Потом замена на нули через режим вставки: 2s00<ESC>
Потом мы модифицируем список. Обратите внимание на конвейер команд \|.
Наконец, мы переходим в соседнюю вкладку (gt) и вызываем там функцию поиска позиции.
Всё.
Потом я немного дополнил команду, вставив gT в начало и запуская привязку из той карты, с которой работал. Тогда диагностический файл мне вообще не нужен, лишь бы был в соседней вкладке. Команда сходит в нее, найдет и запомнит что нужно, вернется, выставит позицию - а дальше моё дело. Так мне надо, помимо собственно экспертного неалгоритмизируемого решения, надо только два движения пальцем сделать, нажав qq.
Это очень удобно оказалось!
Нюанс: это всё работает для однобайтовых символов. Для русского языка, например, нужно немного не так, так как позиция в тексте - байтовая. Но у меня и не было ничего, кроме пробелов и цифр, так что всё хорошо.