- PVSM.RU - https://www.pvsm.ru -
Как-то раз я спросила у пользователей Mastodon, что их не устраивает в работе с терминалом, и одним из ярких замечаний оказалось «редактирование уже введённой команды».
Мне эта проблема тоже реально знакома. Несмотря на то, что ввод текста и его редактирование является «базовой» задачей, мне потребовалось около 15 лет каждодневной работы с терминалом, чтобы привыкнуть к использованию Ctrl+A
для перехода к началу строки (или Ctrl+E
для перехода в конец — я использовала вместо этого Home
/End
).
Так что сегодня речь пойдёт о том, что ввод текста порой вызывает сложности. Я также поделюсь с вами кое-какими советами, которые сама была бы рада услышать давно.
В значительной степени ввод текста в терминале усложняет то, что разные программы обрабатывают его по-разному. Например:
cat
, nc
, git commit --interactive
и так далее) не поддерживают использование стрелок. Если вы будете нажимать в них соответствующие клавиши, то увидите лишь ^[[D^[[D^[[C^[[C^
.irb
, python3
в Linux и другие) используют библиотеку readline
, которая предоставляет богатую базовую функциональность (просмотр истории, клавиши стрелок и так далее)./usr/bin/python3
на моём Mac) поддерживают самые простые возможности ввода вроде использования стрелок, но не другие вроде Ctrl+влево
или обратного поиска с помощью Ctrl+R
.fish
, ipython3
, micro
или vim
) реализована собственная продуманная система ввода, специализированная конкретно под них.Так что вариаций получается множество, и, пожалуй, стоит проговорить каждый пункт подробнее.
Во-первых, есть «основа» — что происходит, если программа просто получает текст через вызов fgets()
или другую функцию и больше никак не стремится повысить удобство в работе. Для меня использование подобных инструментов обычно выглядит так — если я запускаю установленную на моей машине версию dash [1]
(довольно минималистичную оболочку) и нажимаю стрелку влево, то она просто выводит в терминал ^[[D
.
$ ls l-^[[D^[[D^[[D
Поначалу не кажется, что все эти инструменты «базового» уровня имеют много общего, но по факту есть несколько функциональных особенностей, которые вы получаете автоматически просто от самого терминала без какой-либо помощи со стороны программы.
Что же это за возможности:
Ctrl+W
для удаления предыдущего слова.Ctrl+U
для удаления всей строки.Ctrl+C
для прерывания процесса, Ctrl+Z
для его приостановки и так далее).
Такие возможности нельзя назвать крутыми, но их наличие означает, что если вы хотите удалить слово, то обычно можете сделать это с помощью Ctrl+W
вместо того, чтобы 15 раз нажимать возврат, даже если работаете в среде, которая не предлагает никакой функциональности. Список всех поддерживаемых вашим терминалом комбинаций с клавишей Ctrl
можно вывести командой stty -a
.
Следующей группой идут инструменты, использующие readline
. Readline — это широко используемая библиотека GNU, которая позволяет сделать текст более опрятным. Вот мои любимые комбинации, которые предоставляет эта библиотека:
Ctrl+E
(или End
) для перехода в конец строки.Ctrl+A
(или Home
) для перехода в начало строки.Ctrl+влево
/вправо
для перемещения вперёд/назад на 1 слово.Стрелка вверх
для возврата к предыдущей команде.Ctrl+R
для поиска по истории.
При этом вы также можете использовать Ctrl+W
/Ctrl+U
из «базового» списка, хотя Ctrl+U
вместо удаления всей строки удаляет только текст от курсора и до начала строки. Думаю, что Ctrl+W
также может несколько иначе трактовать понятие «слова».
Есть и многие другие комбинации (вот полный список). Я же перечислила только те, которые часто использую сама.
Наиболее известным инструментом, использующим readline
, наверняка является оболочка bash
(когда вы используете Ctrl+R
для поиска по истории в bash
, то эту возможность по факту предоставляет readline
), но есть и много других программ — например, psql
, irb
, python3
и так далее.
Одним из самых приятных моментов я нахожу то, что если у вас есть программа вроде nc
без поддержки readline
, то вы можете просто выполнить rlwrap nc
, чтобы эту поддержку в неё встроить.
Это невероятная возможность, которая делает многие почти непригодные для использования инструменты более удобными в работе. Можно даже включить в rlwrap [2]
собственные варианты автозавершения, хотя я никогда этого не пробовала.
Думаю, что поддержка readline
может отсутствовать в инструментах по следующим причинам:
cat
или nc
) и мейнтейнеры, возможно, не хотят привносить в неё относительно крупную зависимость.readline
имеет лицензию GPL, а не LGPL.readline
могли не счесть как значимый элемент. Например, в git
немного интерактивных функций (таких как git add -p
), и обычно вы просто вводите один символ вроде y
или n
— если же требуется ввести что-то более значительное, git
переносит вас в текстовый редактор.
Например, в idris2
говорят [3], что не задействуют readline
ради сокращения числа зависимостей и для получения более интерактивных возможностей предлагают использовать rlwrap
.
Простейший тест, какой мне приходит на ум, это нажатие Ctrl+R
. Если вы увидите:
(reverse-i-search)`':
Значит, наверняка используете readline
. Естественно, это не 100%-метод (некоторые иные библиотеки тоже могут использовать термин reverse-i-search
), но я не знаю другую систему, которая бы задействовала его для поиска по истории.
Поскольку я пользуюсь vim
, то далеко не сразу поняла, откуда взяты эти комбинации (почему Ctrl+A
используется для перехода в начало строки??? Очень странно).
Как понимаю я, эти привязки были позаимствованы из Emacs — Ctrl+A
и Ctrl+E
делают в Emacs то же, что и в Readline. Так что предполагаю, что и многие другие комбинации между ними тоже совпадут, хотя я пробовала Ctrl+W
и Ctrl+U
в Emacs, и в нём их действия отличаются от действий в терминале. В общем, отличия всё же есть.
Подробнее об истории проекта Readline можно почитать здесь [4].
На моём ноутбуке с Mac /usr/bin/python3
работает странным половинчатым образом, поддерживая лишь часть возможностей readline
(например, клавиши стрелок). Скажем, при нажатии Ctrl+влево
программа выводит ;5D
:
$ python3
>>> importt subprocess;5D
Разобраться с этим вопросом мне помогли ребята с Mastodon. Оказывается, в предустановленном на Mac дистрибутиве Python модуль readline
по факту заменён модулем libedit
, который представляет аналогичную библиотеку, но с менее широкой функциональностью. Причина может заключаться в том, что Readline имеет лицензию GPL [5].
В конечном итоге выяснить, что в моей версии Python используется libedit
, я смогла так:
$ python3 -c "import readline; print(readline.__doc__)"
Importing this module enables command line editing using libedit readline.
Тем не менее обычно Python использует именно readline
, если устанавливается под Linux или через Homebrew. Просто конкретная версия, которую инженеры Apple включают в свои системы, работает на libedit
.
Кроме того, в Python 3.13 собираются убрать [6] зависимость от readline
, заменив её кастомной библиотекой, так что вскоре выражение «Python использует readline» перестанет быть актуальным.
Предполагаю, что на Mac есть и другие программы, которые используют libedit
, но я в этом не разбиралась.
К последней группе программ относятся те, в которых есть собственная (а иногда и намного более изощрённая) система редактирования текста. К ним относятся:
nano
, micro
, vim
, emacs
и так далее).fish
. Например, fish
позволяет при вводе команды использовать отмену через нажатие Ctrl+Z
. В zsh
задействуется текстовый редактор zle [7]
.ipython
, в котором вместо readline
используется библиотека prompt_toolkit [8]
.atuin
).Вот некоторые из их особенностей:
readline
.
Я решила посмотреть, как обрабатывает ввод Atuin [9] (прекрасный инструмент для поиска по истории оболочки, которым я начала пользоваться недавно). Если взглянуть на код [10] и его обсуждение, то становится ясно, что хоть реализация этого инструмента и кастомная, основана она именно на readline
. На мой взгляд, это разумно, так как многие пользователи привыкли к используемым в ней комбинациям клавиш, и это обеспечивает для них дополнительное удобство при работе.
Аналогично дела обстоят с prompt_toolkit
(библиотекой, которую использует IPython) — фактически она поддерживает множество опций (включая привязки клавиш в стиле vi
), но по умолчанию в ней используются привязки именно как в readline
.
И есть немало программ, которые поддерживают самые простые привязки клавиш vim
(вроде j
для «вниз» и k
для «вверх»). Например, Fastmail поддерживает j
и k
, несмотря на то, что основная часть остальных его привязок не имеют отношения к vim
.
Предполагаю, что большинство кастомных систем ввода на основе readline
имеют различные тонкие расхождения с этой библиотекой, но меня это не волнует, поскольку я крайне плохо разбираюсь в большинстве возможностей readline
. Я использую всего где-то 5 комбинаций, поэтому до тех пор, пока такие системы поддерживают 5 базовых известных мне команд (которые в них есть всегда), меня это вполне устраивает. Причём эти кастомные системы зачастую предоставляют намного более качественное автозавершение, чем можно получить при использовании только readline
, поэтому обычно я предпочитаю именно их.
Bash
, zsh
и fish
предлагают для ввода текста «режим vi». В очень ненаучном опросе [11], который я провела на Mastodon, 12% людей сказали, что используют именно его. Так что, похоже, этот режим довольно популярен.
В readline
тоже есть «режим vi» (таким образом реализована её поддержка в Bash), то есть по аналогии эта поддержка есть и во многих других программах.
Я всегда считала, что режим vi
очень крут, но хоть я и пользуюсь vim
, почему-то его так и не освоила.
Я долгие годы недоумевала, почему используемое мной приложение командной строки не работает так, как я бы хотела. Поэтому хорошо, когда можешь в той или иной степени понять, с чем имеешь дело.
Думаю, что при вводе текста в командную строку я размышляю примерно так:
Ctrl+W
и Ctrl+U
, а также дополнить инструмент с помощью rlwrap
, если мне потребуется больше возможностей.Ctrl+R
выводить reverse-i-search
? Если да, то это наверняка readline
, и тогда я смогу использовать все привычные мне комбинации, а также выводить какую-то базовую историю и получать предыдущую команду нажатием клавиши вверх
.Ctrl+R
что-то другое? В этом случае, скорее всего, используется кастомная библиотека, которая будет работать более-менее схожим с readline
образом. При этом, если я захочу узнать, как конкретно она работает, то всегда могу заглянуть в документацию.Возможность подобным образом проверить, что конкретно происходит при использовании разных комбинаций, делает командную строку более предсказуемой и менее хаотичной.
При вводе текста существует и много других сложностей, о которых я не сказала. Например:
ssh
/ tmux
/ и прочим,TERM
,gnome
, iTerm
, xterm
и прочие) по-разному реализуют копирование/вставку текста,Автор: Bright_Translate
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/vim/393278
Ссылки в тексте:
[1] dash: https://wiki.archlinux.org/title/Dash
[2] rlwrap: https://github.com/hanslub42/rlwrap
[3] говорят: https://idris2.readthedocs.io/en/latest/tutorial/interactive.html#editing-at-the-repl
[4] здесь: https://twobithistory.org/2019/08/22/readline.html
[5] лицензию GPL: https://en.wikipedia.org/wiki/GNU_Readline#Choice_of_the_GPL_as_GNU_Readline
[6] собираются убрать: https://docs.python.org/3.13/whatsnew/3.13.html#a-better-interactive-interpreter
[7] zle: https://zsh.sourceforge.io/Guide/zshguide04.html
[8] prompt_toolkit: https://python-prompt-toolkit.readthedocs.io/
[9] Atuin: https://atuin.sh/
[10] код: https://github.com/atuinsh/atuin/blob/a67cfc82fe0dc907a01f07a0fd625701e062a33b/crates/atuin/src/command/client/search/interactive.rs#L382-L430
[11] ненаучном опросе: https://social.jvns.ca/@b0rk/112723846172173621
[12] Источник: https://habr.com/ru/companies/ruvds/articles/834780/?utm_source=habrahabr&utm_medium=rss&utm_campaign=834780
Нажмите здесь для печати.