[О блоге]
[наверх]
[пред]
[2025-03-22 09:43:48+03:00]
[d10384ded77deee2c7101c6aa2c02d5408cd9015]
Темы: [tmux][vim][zsh]
Новичку про vi(m), shell и tmux
В этом году я как-то несколько писем одному новичку отправил с
рекомендациями инструментов для программиста. Почему бы не сдублировать сюда?
------------------------ >8 ------------------------
Я думаю, что Vim многих отпугивает тем по началу, что если его
запустить, то увидишь голое окно. И типа... и это всё? В отличии от
приборной панели шаттла как в GUI IDE всяких. Конечно же причина тут
одна: минимум ненужной и явно не запрашиваемой информации. В современных
Microsoft Office же даже делают снимки экрана, показывая чуть ли не с
полдюжины панелей с кнопочками, которые занимают почти четверть экрана
рабочего. Но под капотом Vim скрывается практически самый мощный
редактор текста, инструмент для работы с текстом, коим являются все наши
программы, письма, документация.
Вначале все познают базовые команды по передвижению по тексту и
редактированию. Я уже тебе на словах говорил, что это, как правило,
команда (yank, delete, change, follow, и т.д.), после которой идёт
motion (слово, СЛОВО, внутри слова, предложение, абзац, внутри кавычек,
внутри скобок, и т.д.). Перед этим может идти указание кол-ва повторов
команды. "Удали ка мне три слова с окружающими их знаками препинания".
Если суммарно команд в каком-нибудь Блокноте или IDE от силы 2-3 десятка
наверное наберётся, то в Vim их сотни.
Вместо нажатия "влево, влево, влево, удалить букву, ещё раз", ты будешь
стараться делать "перейди на начало предыдущего слова, удали до его
конца слог". И это нужно для того, чтобы можно было повторить действие,
нажатием точки. Если твоим действием было "удалить букву", то с этим
много не сделаешь полезных повторов, а "удали слово" -- уже будет
актуально для многих контекстов применения. Так начнёшь пользоваться
макросами: это буквально запись твоих действий. Например тебе надо из
конца предложения найти вторую фразу с конца, но которая в кавычках,
переместить её в начало предложения, сменить кавычки на скобочки, и
внутри все слова поменять с camelCase на kebab-case, плюс порядковый
номер в начале строки увеличить на единицу. Всё это будет сделано одним
макросом, в котором каждое высокоуровневое действие у меня точками
разделено в описании. Подобные вещи сплошь и рядом встречаются во время
рефакторинга того же.
Сколько буферов обмена в Windows? Я им конечно пользовался в последний
раз четверть века назад, но вроде бы больше одного у них не стало. В X11
(графическая система в UNIX-ах) их два. А в Vim их больше трёх десятков.
Найди мне среди строк начинающихся с описания вот такого вот класса,
заканчивающихся на docstring в конце класса, строки описываемые такой то
регуляркой, и примени к каждой строке макрос который мы только что
написали в предыдущем абзаце, но при этом оригинальные версии строк
добавляй ка в регистр "m". Всё это делается одной командой в командной
строке Vim. Зачем всё сохраняли в регистр m? Чтобы из него удобно
сформировать changelog для нашего log message коммита, чтобы потом не
выуживать вручную их git diff-а.
Нашли запоминающиеся места в нашем исходном коде, о которых не надо
забывать и быстро между ними перемещаться? В Vim есть метки, по которым
можно как в Wikipedia моментально перемещаться. Вернутся на последнее
изменение? Вернутся на последнее место с которого мы сделали jump из
другого файла? Всё это пара нажатий клавиш. Посмотреть список последних
сделанных высокоуровневых изменений и среди них выбрать вот то 20-е, где
я правил странный метод в другом проекте? Пожалуйста, пара команд.
Как угодно делать mapping клавиш и слов? Я не пишу "и т.д.", а пишу
"итд", который автоматом раскрывается. Тьма команд у меня тоже
сокращены, заалиасены. У каждого тьма сокращений и мини команд
накапливается. Например если мне надо "обернуть" какую-то переменную в
скобочки, то я парой нажатий оборачиваю слово в кавычки, а дальше ещё
парой нажатий меняю кавычки на скобочки. Звучит как двойная команда,
много нажатий, но это занимает доли секунды, ибо на рефлексах всё.
Кто-то может считать, что идеально когда минимальное количество нажатий
клавиш делается. Я убеждён что нет: более длинные последовательности
рефлекторно отработанные могут быть эффективнее. Плюс многие действия
могут быть менее эффективны для конкретного узкоспециализированного
здесь-и-сейчас случая, но зато их можно будет удобно применить в макросе
или хитрой команде командной строки Vim.
Про повтор действий/команд многие пишут, но многие умалчивают что в Vim
есть, очевидно, и отмена действий, но организованная в виде дерева
изменений. Такого вроде нет ни в одном редакторе. У всех история
изменений по которой можно туда-сюда перемещаться линейна.
Искать текст по всякому, подсвечивать, перемещаться по меткам, в том
числе среди множества файлов -- это всё банально. Vim умеет перемещаться
по тэгам. Тэги это по сути аналог индекса из СУБД. Это отдельные заранее
сгенерированные файлы. Хочешь прыгнуть на определение функи под
курсором, или по названию -- два нажатия клавиш. Название фунок
совпадают/похожи с названиями переменных или констант? Два нажатие и
тебе меню с выбором куда ты хочешь перейти. Это возможно единственное
что умеют IDE в отличии от тупых редакторов (Nano, Блокнот, и подобных).
Но более того: поддержка навигации по тэгам появилась не в Vim, а в Vi,
который был задолго до него (просто любопытный факт насколько старая эта
фича (вовсю в 1980х), которой так любят хвастаться современные IDE из
2020-х :-)). Причём я вот как-то себе делал Zettelkästen систему, где
проще простого было написать скрипт, который бы генерировал бы файл с
тэгами для моего формата заметок, чтобы я в Vim мог как в броузере
прыгать по заметкам как по ссылкам.
В Vim есть jump-list и quickfix-list. Это отдельные окошки в которых
зачастую выводят результат работы поиска типа grep или git grep. Или там
выводят список ошибок во время компиляции или linter-а. По которым можно
удобно перемещаться и прыгать. А можно одной командой выкинуть ошибки
связанные с PEP8. А второй командой для каждой ошибки linter-а во всём
проекте применить команду комментирующую проблемную строку или например
сразу исправляющую вызов os.exit на os_exit например. Выставить пометки
рядом со словами или строками о проблемах -- тоже пожалуйста.
Подключить LSP плагин для работы с LSP сервером и получить по сути весь
per-language функционал для рефакторинга и linting-а? Без проблем. Иметь
автодополнение методов или аргументов? Показывать сигнатуры функций во
время набора кода и сразу же lint-ить? Все эти свистоперделки и полезные
вещи (опять же, которыми любят хвастать IDE) включаются на раз два.
Конечно же в Vim есть возможность показывать множество окон и как угодно
тасовать/изменять их. Есть и табы, хотя лично я не вижу в них смысла,
особенно при использовании мультиплексора терминала. Хочется сохранить
полностью от и до всё размещение окон, табов, курсора, содержимого
регистров и jump/change-списков? Одной командной Vim может сохранить
файл с сессией и одной командной продолжить эту сессию. А можно
сохранить только расположение окон/файлов, для часто используемого
проекта.
Отредактировать кусок кода изолированно в отдельном буфере/окне? Без
проблем. Скрывать часть текста, чтобы глаза не мозолил? Скрывать
определённые символы (ну например URL при редактировании Markdown, чтобы
только название ссылки оставалось)? Выводить всплывающие окна рядом с
курсором или словами? Все есть из коробки.
Молчу про многие сотни опций и настроек. Даже такой мелочи как добавлять
ли пробел после объединения строк или нет? Оставлять ли отступ после
ввода перевода строки? Но я молчу про это, молчу ибо слишком много.
Мы вроде с тобой использовали не просто вставку из файла, а вставку
вывода команды -- это частое действие.
Возможность проверки орфографии? Из коробки, встроена. Ну только словари
подложить надо.
Vim может быть запущен в режиме сервера и из командной строки в него
можно посылать команды. Например ты в терминале видишь вывод Python
traceback-а и можешь послать команду на открытие уже запущенного Vim-а
заданного файла на данном месте с подсветкой проблемного слова. А можно
редактировать файлы по прозрачно запущенному SSH на удалённой машине. А
можно и прямо в Vim запустить терминал и в нём работать, прямо на месте
выуживая или редактируя вывод программ.
Открывать и искать файлы как в эффективном shell-е, не задалбывая Tab
для автодополнения? Всё можно. Но ты наверное ещё тут не в теме, так как
и в shell ещё не использовал эффективное перемещение по директориям и
поиск/выбор файлов. В Vim я себе делал fuzzy-matching файлов как в zsh,
всё возможно. А может быть для поиска или выбора файлов хочется
буквально использовать fzf (https://github.com/junegunn/fzf) -- легко.
Интегрироваться с tmux мультиплексором терминала и общаться с его
встроенными буферами обмена? Плагин на пару экранов кода, без проблем.
Автоматическое форматирование текста, перенос строк, соблюдение отступов
в многоуровневых списках? Всё из коробки, настраиваемое. Зависимое от
языка комментирование строк и снятие комментариев? Пара нажатий. Ведь не
везде же достаточно добавить "#" в начало строки, а надо обрамлять и с
начала и с конца "/*" какими-нибудь.
Запустить компилятор/сборку, отловить ошибки в выводе, заполнить ими
quickfix окно -- при должной настройке из пары команд это можно сделать
вызовом :make. Из коробки, всё заточено под дружелюбность к разработчику.
Иметь возможность навешивать hook-и и автоматически выполняемые команды
на разных действиях? Без проблем. Например когда у меня открывается
письмо (email), то у меня сразу из цитируемого содержимого вырезается
подпись человека и курсор сразу же перемещается после конца цитаты.
И я ещё даже не упомянул про чуть ли не самую важнейшую часть Vim: его
встроенный язык программирования. Конечно, обязательно многие про свои
Atom, PyCharm, VSC могут начать говорить что там тоже можно писать на
JS/whatever и добавлять/изменять функционал. А теперь покажите мне хоть
одного человека кто это бы делал на практике. На этом "а у нас так тоже
можно делать" можно закрывать. Если бы было РЕАЛЬНО удобно и легко это
делать, то делали бы. А вот в Vim его язык очень интегрирован с самим
редактором и на vimscript регулярно и постоянно пишутся какие-нибудь
плагины многими людьми под свои нужды.
Разбить длинную сигнатуру функи на много строчек с корректным indent,
соблюдением нетривиального формата Python "foo: [bar, baz]", с
добавлением всех нужных запятых в конце? Написал плагин. Добавить все
недостающие import-ы о которых нам сказал linter из quickfix окна,
основываясь на статистике их применений через банальный git grep вызов?
Написал плагин. Открывать файлы которые указаны как
путь/к/файлу:строка:столбец? Что часто выдаётся компиляторами. Написал
плагин. Добавить дополнительные интерактивные команды для навигации по
indent-ам в тексте, что часто нужно в Python коде? Написал плагин.
Подсвечивать не человековводимые Unicode символы, которые могут
представлять опасность? Написал плагин. Выравнивать удобно по всяким
вертикальным разделителям? Написал плагин. Находясь в произвольном месте
unittest метода Python, нажать пару клавиш, чтобы в буфере обмена
оказался полный python-path вида path/to/file:TestCaseName.test_method?
Снова плагин. Тоже самое делать для Си кода, чтобы в буфере обмена
оказывалась строчка пригодная для вставки в отладчик, чтобы он
останавливался на строке где курсор? Плагин. И почти все вышеназванные
плагины написаны что-то типа за десятки минут или пару часов. Это не
очередной долбанный framework с которым нужно хорошенько пострадать
чтобы от него добиться того, что ты хочешь, а это инструмент сделанный
программистами для программистов, чтобы делать новые инструменты и
программы :-)
Когда-то можно было услышать критику vimscript: мол он странно выглядит
и не удобен. Не спорю: даже перенос строк в нём выполнялся добавлением
слэша в начале строки. И нельзя было в конце списков/словарей оставлять
запятую. Эти времена в прошлом, так как уже не мало времени существует
vim9script, который уже полностью похож на современный и привычный нам
язык программирования. Почти все мои плагины были написаны ещё на старом
vimscript, но я всё полностью перевёл на vim9 -- он хорош.
А кроме самого языка, Vim может и запускать асинхронные задачи. Есть как
в Go и каналы для коммуникации между асинхронными процессами. Сделать
instant messenger внутри Vim? Да я десятки видел и пробовал, не проблема
уже 20 лет назад была.
Из коробки интеграции с Git нет, но есть замечательнейший плагин
fugitive, без которого многие из нас не представляют уже возможным
разрешение конфликтов. Не скажу что он супер-пупер выделяющийся, но он
сильно помогает при работе с Git. И, в отличии от IDE, не скрывает его
от пользователя, ограничивая его действия или скрывая важные
предупреждения и сообщения.
И из коробки в Vim есть инструмент для сравнения, создания, отображения
и вообще работы с diff-ами. Видел в блогах что не редко Emacs
пользователи используют именно vimdiff для визуализации и правки
diff-ов, а не свой родной Emacs. Может что-то уже и поменялось и у них
появились свои достойные решения.
Как минимум vi, есть на любом уважающем себя UNIX. Поэтому, зная хотя бы
vi ты сможешь эффективно править конфиги на серверах во время
администрирования. Работая в командной строке, в zsh, в bash, whatever,
ты всегда одним нажатием можешь вызвать vi/vim для редактирования
многострочной строки в вызванном редакторе. Работая в PostgreSQL, введя
\e в его psql клиенте, ты будешь редактировать SQL запрос в Vim. Я
наверное лет 20 в самом окне web-обозревателя уже ничего не редактировал
и одним нажатием у меня вызывался Vim чтобы отредактировать textarea,
которая вставится назад в web после выхода из редактора. Мало кто из
опытных пользователей набирает/отвечает на почту в окне почтового
клиента: для этого де-факто всё равно будет вызываться внешний редактор
(типа Vim или Emacs). *Любой* POSIX совместимый shell по стандарту
обязан иметь два режима редактирования командной строки: либо vi, либо
emacs. Других вариантов нет. Огромная часть интерактивных CLI программ
реализует свой интерфейс через libedit или GNU readline, оба из которых
имеют возможность использования vi режима. Это не полноценный vi(m)
редактор, но базовые команды там будут одинаковы. То есть, почти всё в
UNIX мире, на котором строятся все современные серьёзные решения, ЦОДы,
сети, backend-ы и HPC -- имеет только два режима работы с пользователем:
или vi или emacs. Другого не дано, ибо за ~35 лет никто не изобрёл
ничего хотя бы отдалённо лучшего.
Если что, то в Vim одна из самых лучших документаций что я встречал. С
введением безумно дружелюбным к пользователю, даже с графическими
объяснениями (чего не было в документации в моё время когда я начинал им
пользоваться).
Но начать стоит с получасового vimtutor (это прям команда в терминале),
после которого ты сможешь уже без проблем использовать редактор где бы
то ни было.
От меня есть важнейший (как я считаю) совет: не усердствовать с
визуальным режимом выделения текста ("v" команда), не злоупотреблять ею.
Для начала вообще забыть про её существование. Ибо я со стороны видел,
что именно из-за неё люди убивают почти все возможности редактора типа
повторение действия, создания макросов или выполнения команд в ":g".
Визуальное выделение это уже не высокоуровневое действие, а буквально
"выдели вот ровно вот именно такой длины строки/символы". Но тянуть к
нему будет, так как в Microsoft Windows программах стрелочки с зажатым
shift-ом используются крайне часто.
Ну и рекомендую сразу же включить режим показа относительной нумерации
строчек. 5ff1b3c8c76be6e7691defe34a7e18c4d753f4f2
Без этой фичи ещё будет проблематично совместно с кем-то работать, так
как сказать "на минус 19-ой строке забыл вот то то" можно моментально,
ибо на экране прям будет "19" число написано. А если бы были абсолютные
номера строчек, то они и трёхзначные бывают и просто устанешь
произносить их.
Есть большущий миф о том, что Vim нельзя использовать без массы
плагинов. Как человек с 20+ летним стажем работы в нём, знакомый с
другими опытными его пользователями с не меньшим стажем, однозначно
заявляю что это миф/бред/враньё. Чаще всего люди обвешиваются плагинами
только для того (иногда и сами того не понимая), чтобы из Vim сделать
другой редактор. Людям дают болид Формулы-1, а они сразу начинают
модифицировать его, чтобы сделать знакомый им Жигуль. Многие, включая
меня, проходили этот этап, когда 20-30 плагинов стояло. Но с годами об
этом только жалели, ибо многие из них только скрывают настоящую мощь
Vim, препятствуют гибкому использованию. Сейчас у меня 15 моих
собственных самописных плагинов: но они связаны или уже с выработанными
привычками или же для узкоспециализированных задач (особых языков,
форматов и прочего) -- тут я не вижу проблем в установке task-specific
помощников. Вот только для языков программирования есть LSP, поэтому
Python/Go/C/whatever-specific плагины вряд ли могут потребоваться, ибо
достаточно одного LSP клиента, ну и LSP-сервера для языка, который от
редактора уже никак не зависит.
Ещё можно найти много рекомендаций для новичков начинающихся с совета
установки менеджера плагинов. Это абсолютно устаревший и не имеющий
смысла совет, так как уже много лет назад в нём появилась встроенная
система пакетов, очень удобная.
------------------------ >8 ------------------------
Всё что я написал касательно Vim также наверняка полностью относится и к
Emacs -- второму из "профессиональных" редакторов. Хотя многие и не
считают Emacs редактором, а скорее чуть ли не операционной системой,
неким desktop environment.
Самое большое отличие между ними в том, что Emacs с самого начала был по
сути интерпретатором и окружением для работы с Lisp (свой диалект),
поверх которого как бы реализован редактор. Vim, в котором не сразу
появился vimscript, же это развитие Vi -- а Vi это просто редактор, без
какого либо встроенного языка программирования (VI VI VI -- editor of
the Beast :-)). Vim это редактор в который добавили возможность
программирования/расширения, а Emacs это наоборот штука для
программирования на Lisp, поверх которой, на которой сделали редактор.
Реализовать внутри Emacs-а почтовые и новостные клиенты, IM-ы и всякое
такое: это абсолютно штатное его использование.
Плюс главнейшая разность Emacs и Vi(m) как редакторов: в Vi используется
несколько переключаемых режимов работы (вставка, выделение, командный,
командная строка), тогда как в Emacs сплошные сочетания и комбинации
клавиш (Ctrl+то, Ctrl+сё). Физиологически за ними работается по разному.
И есть известный статистический факт: частота проблем с запястьями у
Emacs-еров существенно выше чем у пользователей другого редактора.
------------------------ >8 ------------------------
Коротко упомяну про shell-ы. Я видел как большинство новичков работают в
терминале. Собственно, как и все мы когда-то начинали. Постоянный cd
туда, cd сюда, ls и всякое подобное. Наверное возникает вопрос: и чем же
это удобнее чем тыкать мышкой в GUI проводнике или IDE? Ничем.
А удобнее это становится тогда, когда начинает использоваться эффективно :-)
Пока работа в режиме cd/cd/cd/ls/cd/cd/ls ничем не отличается от DOS, в
котором просто было мало ресурсов для чего-то более серьёзного.
Надо сразу понимать: есть shell который используется для исполнения
скриптов, а есть интерактивный shell, в котором ты, человек,
интерактивно с ним взаимодействуешь. Иногда эти две задачи может
выполнять один и тот же shell. Не редко два совершенно разных и
несовместимых. shell скрипты де-факто пишутся на POSIX shell, который
/bin/sh. Но например в FreeBSD по умолчанию для интерактивного
использования выставляется tcsh, который вообще не совместим с /bin/sh.
Многие писаются от FISH shell-а, который тоже никоим образом не
совместим с POSIX/bin/sh -- и это не страшно, ибо интерактивная работа и
скрипты это зачастую не пересекающиеся задачи.
Первое что узнают люди для хоть какой-то эффективной работы с
интерактивным shell-ом это автодополнение имён файлов и названий команд.
Никто не пишет "main.go", все напишут "ma" и нажмут TAB, который
дополнит имя файла (если нет коллизий) до "main.go". Это всё научились
делать shell-ы ещё в 1980-е, насколько знаю.
Второе что узнают: наличие истории команд. Хотя бы нажимать стрелочками
вверх/вниз. А затем узнают про Ctrl+r, в котором можно написать часть
команды и будет произведён поиск только по этой части. Например ты
помнишь что что-то вводил касательно "build". Ctrl+r, "bui" а дальше
тебе предлагают команду "go build", нажимаешь enter.
90% людей на этом и останавливается. Хотя это всё лишь только 5% от всех
возможностей современных интерактивных shell-ов. Что прискорбно и
удручает, видя как много времени теряется впустую на сплошную ручную
работу.
Исторически как бы существовало два больших семейства shell-ов: Bourne
shell и C shell (1978 появился). "sh" и "csh". POSIX shell это Bourne
shell. BASH это Bourne Again Shell (что читается как "born again", игра
слов). Не то чтобы Bourne shell чем-то был сильно удобнее и выделялся,
но просто так исторически сложилось, что именно он стал стандартом для
написания скриптов, так как появился первым.
https://en.wikipedia.org/wiki/Comparison_of_command_shells
Одним из самых продвинутых shell-ов (и для интерактивной работы и для
скриптоваяния) долгое время был Korn shell, появившийся аж в 1983.
Однако он был проприетарным (закрытым). Сейчас появились свободные
версии, но по сути после появления Z shell это уже не так актуально.
Хотя некоторые BSD системы используют ksh по умолчанию, который я очень
уважаю.
В tcsh (TENEX C shell) впервые появилась возможность дополнения имён
команд и файлов. В csh появилась впервые история команд,
дополнение/подстановка из истории, алиасы, стэк директорий посещённых,
~-нотация (~/ это домашняя директория например) которая сверх часто
используется. В tcsh это всё развилось ещё сильнее. Job control в csh
был почти с самого начала, тогда как в том же GNU Bash оно появилось
только в 1989.
Почти всё вышенаписанное перекочевало и в ksh, который был более менее
ещё и совместим с bourne shell синтаксисом, позволяя и удобно/привычно
скрипты писать и интерактивно работать. В нём появились ассоциативные
массивы как тип данных. Очень продвинутые возможности по подстановке и
перенаправлению всяких файлов. Иерархичные вложенные переменные.
Ссылочные переменные. И многое другое.
Сложно описать насколько более продвинут ksh/zsh/bash относительно POSIX
shell. Простейший пример: у тебя "foo | bar" команда в скрипте. Если у
тебя foo упадёт и вернёт плохой код возврата, то для POSIX/bin/sh кодом
возврата всей этой конструкции pipeline-а будет результат только bar.
Например bar это "grep". Если у тебя упал "foo", то с точки зрения
"grep" ему просто подали на вход пустоту, ничего ошибочного, всё
валидно, мы успешно выходим. Тогда как более продвинутые для
скриптования shell-ы имеют возможность "выкинуть" плохой код возврата
pipeline-а любой команды. Это делает скриптовании и куда безопаснее и
куда компактнее/короче без тьмы костылей.
Вот например табличка с сравнением некоторых возможностей разных
shell-ов, довольно старая уже, древняя можно сказать:
sh csh ksh bash tcsh zsh rc es
Job control N Y Y Y Y Y N N
Aliases N Y Y Y Y Y N N
Shell functions Y(1) N Y Y N Y Y Y
"Sensible" Input/Output redirection Y N Y Y N Y Y Y
Directory stack N Y Y Y Y Y F F
Command history N Y Y Y Y Y L L
Command line editing N N Y Y Y Y L L
Vi Command line editing N N Y Y Y(3) Y L L
Emacs Command line editing N N Y Y Y Y L L
Rebindable Command line editing N N N Y Y Y L L
User name look up N Y Y Y Y Y L L
Login/Logout watching N N N N Y Y F F
Filename completion N Y(1) Y Y Y Y L L
Username completion N Y(2) Y Y Y Y L L
Hostname completion N Y(2) Y Y Y Y L L
History completion N N N Y Y Y L L
Fully programmable Completion N N N N Y Y N N
Mh Mailbox completion N N N N(4) N(6) N(6) N N
Co Processes N N Y N N Y N N
Builtin artithmetic evaluation N Y Y Y Y Y N N
Can follow symbolic links invisibly N N Y Y Y Y N N
Periodic command execution N N N N Y Y N N
Custom Prompt (easily) N N Y Y Y Y Y Y
Sun Keyboard Hack N N N N N Y N N
Spelling Correction N N N N Y Y N N
Process Substitution N N N Y(2) N Y Y Y
Underlying Syntax sh csh sh sh csh sh rc rc
Freely Available N N N(5) Y Y Y Y Y
Checks Mailbox N Y Y Y Y Y F F
Tty Sanity Checking N N N N Y Y N N
Can cope with large argument lists Y N Y Y Y Y Y Y
Has non-interactive startup file N Y Y(7) Y(7) Y Y N N
Has non-login startup file N Y Y(7) Y Y Y N N
Can avoid user startup files N Y N Y N Y Y Y
Can specify startup file N N Y Y N N N N
Low level command redefinition N N N N N N N Y
Has anonymous functions N N N N N N Y Y
List Variables N Y Y N Y Y Y Y
Full signal trap handling Y N Y Y N Y Y Y
File no clobber ability N Y Y Y Y Y N F
Local variables N N Y Y N Y Y Y
Lexically scoped variables N N N N N N N Y
Exceptions N N N N N Y N Y
Не так часто делают просто переход cd, cd, cd. Или имеют алиасы для
директорий (например "cd ~pyg" у меня перейдёт в /home/stargrave/work/pygost),
или имеют стэк директорий и при перемещении добавляют директори в стэк,
позволяя одной командой (у меня это буквально одно нажатие клавиши)
перейти назад по стэку. "cd -" вернёт в предыдущее место.
tcsh (как и zsh) имел встроенный spellchecker и он мог исправлять
опечатки в командах или названиях файлов (но лично я не рекомендовал бы
такое, ибо у меня не раз случались губительные исправления).
Если пользователь набирает полностью снова целые слова или команды, то
скорее всего делает что-то не так и не эффективно. "!$" подставит
последний аргумент из последней команды -- эту штуку даже наши
технические писатели, которые сидят под Астрой и в Word, вовсю
используют. !:1 подставит первый аргумент из прошлой команды.
!!:gs/foo/bar выполнит заново предыдущую команду, но заменив в ней все
foo на bar.
Иногда ты точно не помнишь с чего начиналась команда, но помнишь что это
было связано с ffmpeg и blablabla фильмом. А тебе надо повторить команду
связанную с перекодированием видео. У себя я могу просто набрать "ffm
blabla", нажать кнопку "вверх" и у меня по сути будет выведен список
команд с поиском по ".*ffm.*blabla" регулярке без учёта регистра букв.
Набрав "s/2/r2s/auth/init" и нажав TAB у меня этот путь раскроется до
"src/rik2utils/rik2s/request_auther/__init__.py". Причём между слэшами
можно даже опускать написание букв вообще (зависит от наличия коллизий с
другими файлами/директорий, конечно же).
"**.mod" в ksh/zsh подставит все go.mod файлы проекта.
"**.php(.om[1]:h)" у тебя возьмёт все .php файлы рекурсивно из всех
поддиректорий, отсортирует по времени изменения и возьмёт самый свежий и
подставит директорию где он находится.
"**.{js,php,css}~(libs|temp|tmp|test)/*" подставит рекурсивно всей .js,
.php, .css файлы, но за исключением директорий libs, temp, tmp, test.
"!#$:t:r" -- подставит у *текущей* команды последний аргумент, но только
с отрезанной директорией из пути и без расширения. "**(#ia2)readme"
подставить все "readme" файлы где допустимо до двух опечаток в названии.
Ничто с подобным мощным раскрытием wildcard-ов и работой с историей не
сравнится по эффективности. Именно подобными вещами и мощны командные
интерпретаторы, чего невозможно сделать в графических приложениях.
GNU Bash по умолчанию во многих дистрибутивах GNU/Linux используется по
сути исключительно из-за политических причин. Многое мною написанное
выше в bash не работает и невозможно сделать. Да и для скриптования он
не сильно лучше голого POSIX shell. Самая частая проблема при
скриптовании shell-а это возня с пробелами. Например у тебя в переменной
foo есть имя файла с пробелами: foo="hello world.txt". И сделав cat $foo
ты получишь ошибку, так как $foo раскроется в два слова, которые станут
двумя аргументами, что означает что ты хочешь вывести файл hello и файл
world.txt. В zsh почти во всех случаях с этим нет проблем, за счёт чего
на нём на порядок проще писать скрипты, надёжнее их писать.
В zsh есть возможность иметь объединённую историю команд между разными
instance-ами, чего тоже нет в bash. Сидишь в двух разных окнах, и у тебя
у каждого запущенного bash будет своя история. Для многих именно эта
фича zsh является главной для перехода на него. Для меня главной фичей
являлось autopushd: когда у тебя каждый "cd" начинает работать как
"pushd" -- добавляет директорию автоматически в стэк. Дальше я бы
выделил инкрементальный поиск истории по шаблону. Дальше бы выделил
fuzzy раскрытие wildcard-ов в путях. И только потом уже наверное
вспомнил бы про shared history. http://strcat.de/zsh/
https://www.arp242.net/why-zsh.html
Но чаще всего про zsh упомянут его мега-гипер-убер-мощнейшую систему
дополнений и https://ohmyz.sh/
https://adam-drake-frontend-developer.medium.com/supercharge-your-terminal-with-oh-my-zsh-4fb102ca5005
https://old.reddit.com/r/zsh/comments/1iu8bz8/is_ohmyzsh_worth_it/
Да, в zsh сверх крутая-как-нигде гибкая система completion-а. Которую я
активно использую и написал свои completer-ы. Но рекомендовать oh-my-zsh,
как и все пользователи с опытом -- однозначно не могу. Типа да,
прикольно что на каждой позиции кучи команд ты можешь нажать tab и у
тебя разукрашенные свистопердящие менюшки показывающие опции команд,
дополняющие имена хостов на основе данных из ~/.ssh/known_hosts,
дополняющие пути до файлов на других хостах (прозрачно логинясь через
ssh на них), но это всё жутко тормозит на практике и не даёт заметного
profit. Время не сильно экономит. Часто только вредит тем, что не
показывает все возможные опции/аргумент для команд и пользователь будет
думать что их и нет. А также это скрывает много деталей которые бы нужно
было знать. Вот человек знает как подставить PID процесса через
автодополнение zsh-а, но этом без наличия свистопердящего zsh он вообще
не в курсе как вывести хотя бы список процессов ("ps" команда). Всех
кого я знаю -- отключают oh-my-zsh и полный спектр completer-ов со
временем, ибо оно не даёт profit-а. Я не к тому что система completion
не нужна, а к тому, что нужно включать только то что нужно, осознанно и
с пониманием дела.
Не редко слышал фразы о том, что zsh медленный. Это, опять же, с чистой
совестью заявляю, что произносят только некомпетентные и не понимающие
люди. В 100% случаях они говорят про обвешанный плагинами свистопердящий
oh-my-zsh. Сам по себе zsh гораздо компактнее, проще, меньше по размеру
и существенно более быстрый чем тот же bash. И не смотря на меньшее
кол-во кода, zsh при этом умеет в десятки раз больше всего.
------------------------ >8 ------------------------
Ещё рекомендую начать посматривать на https://github.com/tmux/tmux/
https://en.wikipedia.org/wiki/Tmux
Это такая штука, которая притворяется обычным терминалом для запущенных
под ним программ. Но при этом он позволяет иметь множество вкладок,
множество окон, жонглировать ими по всякому, всякие там менюшки и popup
окна делать для автоматизации, иметь scrollback буфер и путешествовать
по нему или редактировать, иметь буфер обмена в котором менюшкой можно
выбирать что хочется вставить (штатные же буферы обмена это стэк из
одного элемента как бы).
Хотя многие впервые знакомятся с мультиплексорами терминалов
исключительно для того, чтобы можно было на сервере их запустить и
спокойно отключиться от сети, а подключившись снова увидеть всё как там
было запущено в точно таком же виде. Штатно при отключении сети, SSH
грохнет все запущенные в сессии процессы.
Многое из вышеназванного умеют делать эмуляторы терминалов: scrollback
буфер, разбиение на окна и их жонглирование, множество вкладок. Но
эмуляторы запускаются только под GUI, а значит на сервере их не будет.
Плюс у каждого второго обязательно да будет какой-то незнакомый тебе
эмулятор, поэтому будет неудобно за чужим компьютером. С другой стороны,
конечно, и нечего делать за чужим :-). Но изучив tmux ты будешь в своей
тарелке на любой системе где он установлен (да и собрать его не
проблема, ибо зависимостей почти нет).
Плюс ты сможешь скриптовать своё рабочее окружение. Я то как-раз именно
поэтому начал пробовать tmux. Когда я работал с одним проектом, то хотел
чтобы мне сразу создалось несколько вкладок, сразу в нужной директории,
в других вкладках всякие просмотрщики журналов сразу были запущены, в
третьих сразу подготовленные строчки с командами запуска. Даже если и
какие-то GUI эмуляторы терминалов и позволяют себя как-то
автоматизировать, то я не встречал кто бы это реально использовал, плюс
это зависимость от чётко заданного конкретного GUI эмулятора терминалов
(тогда как tmux под голой консолью можно запустить без проблем).
Я активно использую его popup окна для следующего: хочу вставить путь до
файла, но даже с возможностями zsh не всегда быстро можно указать путь
до нужного (много коллизий в именах), поэтому парой клавиш у меня
появляется popup окно, где запускается bfind (breadth-first штука типа
find-а, https://github.com/tavianator/bfs), которая на лету в real-time
подаёт данные в "fzf" fuzzy matcher (https://github.com/junegunn/fzf) и
fuzzy поиском позволяет выбрать мне нужный файл частенько за доли
секунды. Выбрав, нажав enter, он подставится в основное рабочее окно, а
popup закроется. Никакого дополнительного места на экране не будет
отъедено во время поиска.
Ну и с коллегами все его используем для парного программирования или
администрирования. Настраиваем специальную SSH учётную запись, при
логине в которую автоматически форсированно будет запускаться tmux
клиент, подключённый к твоему tmux серверу, но в read-only режиме. И мы
видим рабочие экраны друг друга. Но под своим графическим терминалом, со
своими удобными нам шрифтами. Если бы это была передача графической
информации (как удалённый доступ к Windows рабочему столу), то на
мониторах с разными DPI это было бы неюзабельно, либо дико неудобно тому
кому придётся перевести свою рабочую сессию на HiDPI мониторе в "low"
DPI, плюс шрифты регулярно многим не нравятся (на вкус и цвет товарища
никогда нет). Плюс GUI требовал бы очень неплохое Интернет соединение,
тогда как tmux это реально просто просасывание видимой текстовой
информации -- мизер.
Кроме Emacs пользователей, у нас вроде все коллеги с кем мы работали и
работаем, даже когда не идёт речь про связь по сети или удалённого
доступа, используют tmux локально запускаемый. Собственно, прям
настраиваются эмуляторы терминалов так, что после их запуска там сразу
же оказывается tmux. Ничего не отжирающая штука, но добавляющая
офигенное кросс-платформенное удобство, можно сказать сетевую
прозрачность и по сути window manager в терминале. Но штука
опциональная -- она уже не настолько значимую роль играет в отличии от
shell и текстового редактора.
[оставить комментарий]