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

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

Привет, друзья. Как я уже рассказывал, в Юникоде есть символы-модификаторы, которые сами по себе не изображаются, но меняют вид предыдущего символа. Это различная диакритика, включая ударение, кратку над й и точки над ё, хотя эти символы есть и "в сборе" (сравните Ё и Ё: первый символ составной, а второй цельный), а также огласовки, подчерки, вычёркивание и всякое прочее в таком роде. Мы обсуждали средство вставлять в текст неудаляемое выделение вроде в̲о̲т̲ ̲т̲а̲к̲о̲г̲о̲.

Но как его убрать?

Из открытых источников
Из открытых источников

Прежде всего, давайте вспомним, как посмотреть на состав сложного символа. Для этого есть команды ga (и g8). Первая покажет символ и все модификаторы. Например, если вы нажмете A<C-V>U0332 и пробел, то увидите A̲. Поместив курсор на этот составной символ, вы получите такую информацию:

<A> 65, Hex 41, Octal 101 < ̲> 818, Hex 0332, Octal 1462

Теперь видно, что сложный символ состоит из A с кодом 65 и модификатора с кодом 818. Команда g8 выдаст байты, из которых состоит символ: 41 + cc b2

Далее, выставляем флаг delcombine (set delcombine) и теперь команды x, <BS>, <Del> будут удалять не весь составной символ, а модификаторы, по одному, и только под конец сам символ. Только помните, что xx на первом символе в тексте A̲A̲ удалит этот первый символ: сначала модификатор, потом А; а вот 2x удалит оба составных символа.

Это уже вариант удалить модификаторы. Но только он неудобный, если текст большой, а модификаторов много. Ну и помним, что есть символы в сборе, как Й, никак из него И не сделать.

Помним, что по умолчанию модификаторов не более двух, но это можно поменять, задав опцию maxcombine (но больше шести всё равно нельзя). Без этого вы не сможете монстрячить в таком духе: Я̶̲̅. В иврите и арабском четыре модификатора - это нормально.

Я заметил, что редактор Дзен работает в режиме delcombine, удаляя модификаторы. Это прикольно.

Вот здесь описана функция, которая либо очищает текст от заданного модификатора, либо добавляет его после каждого символа. Вот она:

function! ToggleCombining( character, text )
let l:cleanedText = ''
let l:idx = 0
while l:idx < len(a:text)
let l:codepoint = nr2char(char2nr(a:text[l:idx :]))
if l:codepoint !=# a:character
let l:cleanedText .= l:codepoint
endif
let l:idx += len(l:codepoint)
endwhile
if l:cleanedText !=# a:text
return l:cleanedText
else
return substitute(a:text, '[^[:cntrl:]]', '&' . a:character, 'g')
endif
endfunction

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

Создаются две переменные: в одной будет очищенный текст, другая просто номер символа в строке.

Запускается цикл по тексту: указатель идет от начала до конца текста.

Выражение a:text[l:idx :] берет текст от указателя до конца. Помним, что префикс a: - для аргументов функции. Функция char2nr берет первый символ текста и возвращает его код, а парная nr2char превращает код опять в символ: так мы изящно отцепляем символы по одному.

Условие if l:codepoint !=# a:character сравнивает отцепленный символ с указанным модификатором, а символ решетки означает игнорирование регистра. То есть условие выполнено, если символ - не данный модификатор.

Если так, то добавляем символ к очищенному тексту оператором "точка", совмещенным с присваиванием.

Сдвигаем указатель на столько байт, сколько было в отцепленном символе.

Теперь смотрим, совпадает ли очищенный текст с исходным. Если нет, то надо возвратить очищенный текст. Если же да, то надо добавить модификатор к каждому символу в тексте. Это делает функция замены, которая всё, что не управляющий символ, заменяет на него же плюс модификатор.

Пользоваться ею можно так:

echo ToggleCombining( "\u0332", "sample text" )

или более изощренно, например, через привязку:

vmap UU d:let @q=ToggleCombining( "\u0332", @")<CR> \| "qp

Теперь можно выделить текст и, нажав UU, подчеркнуть все символы в нем. А потом так же точно убрать.

Не забудьте про регистр-выражение, он тоже бывает удобен в этом контексте.

Удачи!

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