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

Рубрика "Секреты Вим". Модификаторы Юникода для в̲ы̲д̲е̲л̲е̲н̲и̲я̲ текста

Привет, коллеги. Нашел прекрасное и спешу поделиться. В Юникоде есть символы, которые сами по себе не изображаются, но модифицируют символ перед ними. Например, это могут быть значки над буквами (диакритика, в том числе ударèния), огласовки в иврите и арабском и всё в таком роде.

Есть среди прочих и такие символы, как:

  • U+0305 (COMBINING OVERLINE, черта над буквой)
  • U+0332 (COMBINING LOW LINE, подчеркивание под буквой)
  • U+0333 (COMBINING DOUBLE LOW LINE, двойное подчеркивание)
  • U+0336 (COMBINING LONG STROKE OVERLAY, перечеркивание буквы).

Если ввести такой символ после буквы, получится желаемый эффект:

П̲о̲д̲ч̲ё̲р̲к̲н̲у̲т̲ы̲й̲ или д̳в̳а̳ж̳д̳ы̳ ̳п̳о̳д̳ч̳ё̳р̳к̳н̳у̳т̳ы̳й̳, или даже в̶ы̶ч̶е̶р̶к̶н̶у̶т̶ы̶й̶ ̶т̶е̶к̶с̶т̶, а то и с̅ ̅л̅и̅н̅и̅е̅й̅ ̅н̅а̅в̅е̅р̅х̅у̅.

Даже так можно:

П̲̅о̲̅д̲̅ч̲̅е̲̅р̲̅к̲̅н̲̅у̲̅т̲̅о̲̅-̲̅н̲̅а̲̅д̲̅ч̲̅е̲̅р̲̅к̲̅н̲̅у̲̅т̲̅ы̲̅й̲̅ В̶̳ы̶̳ч̶̳е̶̳р̶̳н̶̳у̶̳т̶̳ы̶̳й̶̳ ̶̳с̶̳ ̶̳д̶̳в̶̳о̶̳й̶̳н̶̳ы̶̳м̶̳ ̶̳п̶̳о̶̳д̶̳ч̶̳е̶̳р̶̳к̶̳о̶̳м̶̳

Можно увеличить число допустимых модификаторов (по умолчанию два), увеличив значение maxcombine, и тогда и так можно:

з̶̲̳̅а̶̲̳̅м̶̲̳̅е̶̲̳̅с̶̲̳̅ (тут написано "замес")

Можно даже сделать |̲̅к̲̅о̲̅р̲̅о̲̅б̲̅о̲̅ч̲̅к̲̅у̲̅|̲̅, что не всегда выглядит красиво, но может быть полезно для чисел: |̲̅1̲̅2̲̅3̲̅4̲̅5̲̅6̲̅7̲̅8̲̅9̲̅0̲̅|̲̅

Вычеркнутый текст в Дзене есть (вот такой), а вот трех остальных нет, но нам доступно. Как это выглядит — сильно зависит от шрифта.

Можно сделать удобные средства, чтобы не вводить символы по коду после каждой буквы:

command! -range -nargs=0 Overline call s:CombineSelection(<line1>, <line2>, '0305')
command! -range -nargs=0 Underline call s:CombineSelection(<line1>, <line2>, '0332')
command! -range -nargs=0 DoubleUnderline call s:CombineSelection(<line1>, <line2>, '0333')
command! -range -nargs=0 Strikethrough call s:CombineSelection(<line1>, <line2>, '0336')

Здесь создаем :команды, работающие на диапазоне строк: они вызывают одну и ту же функцию, передавая ей выбранные строки и код символа-модификатора. А вот эта функция:

function! s:CombineSelection(line1, line2, cp)
execute 'let char = "\u'.a:cp.'"'
execute a:line1.','.a:line2.'s/\%V[^[:cntrl:]]/&'.char.'/ge'
endfunction

Функция присваивает значение переменной char: тот самый символ с кодом. Довольно артистично комбинируются кавычки и слеши. А затем функция просто выполняет замену на указанных строках. Символ \%V означает совпадение только внутри выделения, если оно есть, что позволяет работать не на строках, а на выделенном тексте. Класс [^[:cntrl:]] совпадает со всем, кроме управляющих символов. то есть любой символ, кроме управляющих, будет заменен на себя (&) с подклеенным (.) модификатором (переменная char). Замена глобальная (/g) и тихая (/e), то есть если совпадений нет — промолчит.

Теперь мы можем "вычеркнуть" целый абзац:

:5,9Strikethrough

Далее создаем привязки:

vnoremap OO :Overline<CR>
vnoremap UU :Underline<CR>
vnoremap DD :DoubleUnderline<CR>
vnoremap -- :Strikethrough<CR>

Это для режима выделения. Выделить слово или несколько и нажать UU — что может быть проще?

Можно создать оператор, работающий по движению:

function! OpUnder(type)
execute "normal! `[v`]y"
execute ":Underline"
endfunction
nnoremap UU :set opfunc=OpUnder<CR>g@

И потом подчеркивать что будет угодно, например, так: UUw или UU2W или UU$ или UU/^\s*$

При этом привязка UU в нормальном режиме и привязка UU в режиме выделения — это две разные вещи. Аналогично создайте привязки для трех других выделений.

Удалить вставленные символы не так просто. При выставленном флаге delcombine команды вроде x удаляют не весь сборный символ, а сначала снимают модификаторы. Но тогда надо нажать x на каждом символе, что может быть утомительно, если вы подчеркнули много. Можно убрать модификаторы заменой, ведь мы знаем коды. Можно применить Perl, в его регулярных выражениях есть возможность совпасть с модификатором. Будет мне надо — я сделаю.

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

Если хотите, можно сделать и специальный режим, в котором введенный символ будет сразу снабжаться таким модификатором, и можно прямо печатать подчеркивая. Но надо? Это же не Ворд.

Зачем эта технология может быть нужна? Я вижу несколько применений и одну причину философского плана.

  • Если вы работаете с текстом (список дел, например, держите открытым), дополнительные средства выделения могут пригодиться.
  • Можно выделить что-то в комментариях к программному коду (заодно удивив коллег).
  • Если вы, как я, пишете на Дзене (или где-то ещё, где ограниченные возможности выделения текста).
  • Если вы хотите сделать "неудаляемое" выделение, не зависящее от средств текстового процессора.
  • Наконец, мне как-то надо было создать много документов по списку трудов, и я сделал это скриптом на Перл. Текстовые документы, естественно. Подчеркивания пришлось ставить вручную в текстовом процессоре, а теперь бы я в Перл или в Вим бы сделал это с легкостью. Век живи — век учись.

А философская причина такая: мы хакеры в высоком смысле этого слова! Компьютер должен работать так, как нам это надо, а не как придумали дяди и тёти в отделе продаж. И если нам решили не давать возможности подчеркивать, то мы всё равно найдём такую возможность.

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

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