Герой обзора - утилита espanso, позволяющая на лету заменять текстовые фрагменты.
Опять прога на Rust. И опять впечатление "ух ты!", как от ruff и uv.
DRY! Не повторяйся при наборе текста!
У людей, которые целый день пишут тесты: кодеры, тестеры, админы, тех-писатели, тех-поддержка, наставники, кураторы и прочие - у всех, кто работает с клавиатурой весь день, часто возникает коллекция повторяющихся фрагментов, заготовок.
Зачем мне самому коллекция заготовок
Я ревьювер в ЯндексПрактикуме с 2020 года, комментирую коды студентов уже пять лет. 95%-90%-80% комментариев повторяются десятки-сотни-тысячи раз.
Расскажу, какие мне попадались организации такой коллекции, расставлю им "за" ➕ и "против" ➖ (имхо оценки). Надеюсь, в комментариях поделятся другими.
Примитивный файл с текстовыми фрагментами
➕ Придумал новый фрагмент, добавил в конец файла - все, можно пользоваться.
➖ Поиск фрагмента примитивный - по его словам средствами редактора.
➖ Вставка фрагмента низкотехнологичная - копипастой.
Личный опыт
Поразительно живучий формат. Мне не удалось от него избавиться - в нем застревают редко применяемые, но явно полезные фрагменты.
Дополнительные возможности утилит другого назначения
Punto предоставляет сервис "замены текста на текст".
AutoHotKey способен замороченным способом реализовывать замены.
➕ Годится для крохотной коллекции.
➖ Не масштабируется по размерам и числу фрагментов.
Личный опыт
Пунто-заменяльщик был моей первой попыткой. После мновенного разрастания коллекции до нескольких десятков замен стало понятно "это не годится". Но рудименты остались - десяток замен все еще выполняются Пунтой.
AHK настолько мало приспособлен для поставленной задачи, что попытки заглохли за пару дней.
Obsidian и подобные
➕ Богатый сервис: поиски, визуализации связей, плагины - красота!
➖ Вставка фрагмента - копипастой.
➖ Высокий порог входа.
Личный опыт
Обсидиан произвел сильное впечатление. Коллеги его применяют. Но мне он не годится, так как мой DRY включает, в том числе, и частые подстановки коротких фраз и даже отдельных слов – ходить в соседнюю прогу "за словами" это уже никакая не "личная продуктивность".
espanso
Специализированная утилита, работающая по юникс-принципу "решай одну задачу, но решай ее максимально хорошо".
➕ Вставка фрагмента автоматическая: демон следит за нажатиями клавиш, распознает фрагменты-триггеры и на лету заменяет их на новые фрагменты.
➕ Начать пользоваться “не просто, а очень просто!”
➕ Легко указать место каретки (курсора) после вставки.
➕ Есть подстановки содержимого буфера обмена.
➖ Триггеры нужно придумывать и потом вспоминать/искать.
➖ Триггеры могут срабатывать неуместно, нужна аккуратность при их создании.
Быстрый старт
Скачать и установить утилиту для своей ОС Win/Linux/Mac.
Открыть YAML-файл с триггерами
в Вин%AppData%\espanso\match\base.yml
в Линhome/$USER/.config/espanso/match/base.yml
в Мак/Users/$USER/Library/Application Support/espanso/match/base.yml
Удалить примеры от автора.
Заполнить своими триггерами.
Сохранить. Все! Можно пользоваться.
Замены будут доступны в любом месте, где возможен ввод текста: в редакторе, в браузере, в терминале, в окне выбора файла и т.п.
Два способа применения:
Либо набрать триггер-фрагмент – тут же выполнится подстановка.
-
Либо вызвать диалог для поиска по триггерам и заменам
Найдено пять вариантов в котором:
Набрать текст 1️⃣. Произойдет его фаззи-поиск в триггерах и заменяемых текстах.
Выбрать из найденных вариантов 2️⃣
– либо кликом,
– либо стрелками+ВВОД,
– либо через ускорители 4️⃣ для первых восьми вариантов.
Лучше запомнить триггер 3️⃣ примененной замены. Ведь если через две минуты нужна такая же замена, то применение этого триггера первым способом даст большую экономию.
Вызов диалога происходит
– либо по сочетанию клавиш (в Вин этоAlt+пробел
, настраивается),
– либо по специальному триггеру (можно настроить).
Пример.
Если заполнить файл base.yml
такmatches:
- trigger: Дд
replace: Добрый день!
- trigger: ддфио
replace: |
Добрый день!
С уважением
Имя Фамилия
- trigger: ч-т-о
replace: "c:\\users\\me\\Downloads\\что-то-особое\\"
то будут доступны три замены:
Дд
будет подменяться наДобрый день!
.
Пригодится для общения в чатах и письмах.ддфио
будет подменяться наДобрый день!
С уважением
Имя Фамилия
Пригодится для начала письма.ч-т-о
будет подменяться наc:\users\me\Downloads\что-то-особое\
.
Пригодится для ввода спец-папки при сохранении из браузера.
Вкусности
Через
$|$
можно указать место для каретки внутри вставленного фрагмента.Если описать триггер так
- trigger: "н"
replace: "новость"
word: true
то замена произойдет только, еслин
окажется полным словом.
Значит все буквы кроме тех, которые являются однобуквенными словами
а
,в
,и
,к
,о
,с
,у
,я
,
можно применять как триггеры. Максимальная экономия!
Свойствоleft_word: true
мягче - оно проверяет, что фрагмент не находится в начале слова.Если описать триггер так
- trigger: "нвст"
replace: "новость"
propagate_case: true
то замена будет учитывать регистр при вводе:
нвст
заменится нановость
,
Нвст
заменится наНовость
,
НВСТ
заменится наНОВОСТЬ
.Через
{{clipboard}}
можно добавить к тексту содержимое буфера обмена.
Для этого нужно к описанию триггера еще добавить новый атрибутvars
.
Пример- trigger: "змнб"
replace: "Замените {{clipboard}} на {{clipboard}}."
vars: [{"name": "clipboard", "type": "clipboard"}]
Можно вставлять результаты от работы консольных команд или от вызова Питона.
Можно вставить текст одного триггера в другой.
Это может пригодится, если вставляемый большой и/или нестабильный.Можно указать регулярку для триггера.
Автор эспансы рекомендует делать это осторожно и только если нет других способов.-
Если в подставляемый текст нужно добавить несколько значений, известных только в момент вставки, то это можно сделать через показ формы-диалога.
Например, после ввода триггера может появится такая формаЕсли в нее вписать два текстовых поля 1️⃣ и 2️⃣, выбрать вариант в выпадающем списке 3️⃣ и еще вариант в развернутом списке 4️⃣, то после ВВОД триггер заменится на
Добрый день, Андрей!
Обратите внимание на неудачный текст.
Если появятся вопросы, можете
написать мне в Пачку @me_pch,
либо наставнику @name2 в Пачке.
Для оформления такого триггера нужно больше разметки- trigger: "реакция1"
form: |
Добрый день, [[name]]!
Обратите внимание на [[fragment]].
Если появятся вопросы, можете
написать мне [[to_me]],
либо наставнику [[pch_tags]] в Пачке.
form_fields:
to_me:
type: choice
values:
- "в Пачку @me_pch"
- "в Телегу @me_tlg"
- "на почту me@me.ru"
pch_tags:
type: list
values:
- "@name1"
- "@name2"
- "@name3"
Да, разметки много.
Но! Если такой триггер-диалог уже создан, то развивать его легко - достаточно только менять текст послеform: |
и элементы в спискахvalues:
.Форма может быть минимальной - содержать лишь список вариантов. Так, например, удобно подставлять один из своих мейлов/телефонов/сайтов/...
Можно "подхватывать" через систему плагинов готовые наборы с hub.espanso.org.
Например, текущие дата/время, эмодзи-символы или эмодзи-фразы, куски TEX-формул и пр.
Проблемы и советы про создание триггеров
Есть противоречия при выборе триггер-фразы:
– Чтобы работала экономия, фраза должна быть как можно короче.
– Чтобы удобно применять триггер, фраза должна состоять из простых символов: в одном регистре, без спец-знаков.
– Но чтобы запомнить фразу, она должна быть содержательной, то есть длинной.
– Но чтобы триггер случайно не срабатывал, выгодно делать фразу сложнее или со спец-знаками.
Поэтому выбор триггеров требует баланса - каждый сам взвешивает риски и выбирает экономию/содержательность и простоту/надежность.
В примерах на сайте самой эспансы все триггеры начинаются с :
, то есть ради надежности страдает экономия+простота.
Личный опыт
Создал >1300 триггеров, сейчас в работе ~1000. Помню из них ~400, остальные применяю либо однократно через диалог поиска, либо в диалоге их вспоминаю.
Фразы сложились в почти язык: корни, приставки/суффиксы, глаголы/наречия и прочие связи.
Примеры.
(1) Для ревью нужны комментарии про ошибки - триггеры для них начинаются на приставки
ош
- любая ошибка,
лш
- логическая ошибка.
(2) Еще приставки:
ли
- про что-то лишнее,
ну
/до
- про нужно добавить,
уд
- про удачное место,
не
- про неудачное место.
(3) Суффиксб
указывает, что будет вставка из буфера обмена.Мой приоритет – простота применения.
Самый частый способ создания нового триггера - это обрезание текста до почти аббревиатуры. Удача, если получается яркое сокращение.
Примеры:
лиизба
= Лишний запрос в базу. Ответ известен заранее.
нупопа
= Мало подсказок для отчета о падении подтестов.
ужефан
= Лишняя функция. Уже есть штатная фикстура для анонима.
нутаз
= Не нужна какая-то случайная запись из базы. Нужна только та, которую редактировали.Очень удобно применять подмены для вставки нерусских терминов/кодов - почти всегда первые буквы на русской раскладке будут уникальной фразой
куй
= requests
оы
= json
зкш
= print()
юащ
= .format()
пуещ
= get_object()
Замены эспансой позволяют не переключать раскладку.Эспансо-замены отлично сочетаются с маркдауном.
Почти всегда вставляю короткие и многострочные примеры кодов через триггеры, подставляя код из буфера.
MAXH0