Найти в Дзене
Блокнот математика

Рубрика "Секреты Вим". Строка ввода

Привет, коллеги. В Вим есть функция input, которая даёт вам возможность создать свою строку ввода тех или иных данных. Давайте с нею познакомимся и посмотрим, для чего её можно применить.

Вводит и выводит))
Вводит и выводит))

Параметров от одного до трёх; обязательный параметр — приглашение, текстовая строка, подсказывающая, что вводить. Второй параметр, если присутствует и не пустая строка — значение по умолчанию. Третий описывает автодополнение: например, если там 'file', то предполагается имя файла и Вим поможет вам, предлагая имена файлов из текущего каталога, а если expression, то Вим будет предлагать варианты (скажем, введём si и нажмем Tab: увидим на выбор simplify, sin, sinh).

Функция возвращает то, что введено в командной строке. У строки этой своя история. Что тоже очень удобно, если вам надо вводить однотипные вещи.

Цветовое оформление задается командой :echohl, как и для :echo.

Есть важный аспект. Если функция вызывается из привязки, то она "съест" всё, что идет после нее. Это не то, что вы хотите, как правило: зачем предлагать ввод, если сами потом и вводите?

Например,

:map \x :let @@=eval(input('expression:'))<CR>p

не будет работать, как задумано. Предполагается, что пользователь введет выражение, оно будет вычислено, результат записан в безымянный регистр и вставлен в текст. Но в итоге p станет первым символом вводимого выражения, и его придется удалить, а вставить результат потом надо самому.

Чтобы этого избежать, надо вызвать перед input функцию inputsave(), а после вызвать inputrestore(). И лучше это делать из своей функции. Например, так:

function! EvalExpr()
call inputsave()
let s = string(eval(input('Expression: ', '', 'expression')))
call inputrestore()
return s
endfunc
map \x :let @@=EvalExpr()<CR>p
imap \x <esc>:let @@=EvalExpr()<CR>pa

И теперь вы можете вставить в текст значение выражения. Причём Вим ещё и поможет вам его вводить, автодополняя при возможности. Удобно.

Ещё один способ применения такой строки — ввод символов. Я уже много раз писал про диграфы — возможность вводить символы юникода парой легко запоминаемых символов. Например, все греческие буквы получаются сочетанием буквы и звездочки (a*=*a=α, s*=σ, *s=ς). Но если вам надо вводить много символов, надо запоминать много диграфов. Можно сделать меню, привязки, сокращения (в том числе умные) или замену, но все эти способы не лишены недостатков. Привязок надо много, в меню неудобно рыться, замена довольно сложна и работает "дискретно", а не на лету. Да и не годится такое длинное слово, как varsigma, для привязок, и сокращением это трудно назвать.

А я вот помню много команд ТеХ. Зачем мне запоминать диграф Sb, означающий ∙, если есть \cdot?

Так давайте сделаем одну привязку \s, и пусть она откроет строку ввода, а туда я введу желаемую команду. Сказано-сделано:

function! TeX()
let d={"alpha" : "α", "sigma": "σ","varsigma": "ς",'cdot': "∙"}
call inputsave()
let s = input('TeX command: ')
call inputrestore()
let @@ = d[s]
normal p
return @@
endfunction
imap \s <ESC>:call TeX()<CR>a

Конечно, можно проверить, есть ли введенный ключ в словаре, и если нету — ничего не вставлять. Команд можно добавить побольше. Но всё это делается, я просто показываю, как можно. Обратите внимание на безымянный регистр @@ и команду вставки нормального режима p.

Последнее применение. В юникоде есть много символов-модификаторов, которые сами не видны, но модифицируют символ перед ними. Это диакритика, например, или огласовки. Наши ё или й можно собрать из е и и с диакритикой, хотя есть и цельные символы.

Обычно то, что вам надо, у вас уже есть в раскладке клавиатуры. Но всяко бывает. Опять-таки, есть диграфы. Но почему бы не дать себе возможность вводить диакритику через свою строку так, как это вам удобно? Принцип точно такой же:

function! Diacrit()
let d={'`':0x0300, "'":0x0301,"^":0x0302,'~':0x0303, '-:0x0304,'v':0x0306,'"':0x0308}
call inputsave()
let s = input('`'^~-v"? ')
call inputrestore()
return d[s]
endfunction
imap ^^ <ESC>:let @@=nr2char(Diacrit())<CR>pa

Теперь функция сама ничего не вставляет, она только возвращает код символа-модификатора: обратная кавычка ` обозначает гравис, апостроф ' обозначает акут, крышечка ^ — циркумфлекс, тильда ~ — тильду, минус - — макрон, v — бреве (как у й), двойная кавычка " — умлаут, как у ё.

Вот что теперь можно вытворить:

я̀я́я̂я̃я̄я̆я̈

Ввожу букву, потом нажимаю ^^ и в командной строке ввожу символ. В строке раскладка английская, даже если я пишу по-русски — надо отдельно переключать. Это как раз удобно. Модификатор вставляется и модифицирует букву.

Не то чтобы это было вот прям каждый день надо... но мы Вим любим за то, что он работает так, как мы этого хотим, а не как за нас придумал умный дядя из отдела продаж.

Удачи, коллеги!

Научно-популярные каналы на Дзене: путеводитель
Новости популярной науки12 марта 2022