выполнение команды в zsh в зависимости от синтаксиса введённой строки
Бывает так, что надоедает дописывать к началу скопированной в терминал, к примеру, из браузера, ссылки, саму команду, которая должна эту ссылку обработать. Например, вот так (где | - текущее положение курсора):
> |<c-v> > git://github.com/pieter/git-bzr.git|<home> > git clone |git://github.com/pieter/git-bzr.git
Если Вам это знакомо, то Вы понимаете, о чём я. Причём речь не обязательно о git:// для git clone; это может быть lp: или bzr:// для bzr branch, http:// - для wget или aria2c, file:/// - для cd ну и т.д. и т.п. - вариантов множество и примеры использования могут зависеть от того, с какими видами пар ссылка/действие приходится работать. Конечно, можно настроить короткие алиасы для команд, но можно и пойти чуть дальше - можно настроить, что же должен выполнить zsh в зависимости от синтаксиса введённой строки. Для этого нужно отредактировать .zshrc файл, добавив туда функцию precmd (чуть подробнее про precmd можно прочитать в комментариях к коду в этом совете - http://linsovet.com/content/настройка-приглашений-zsh) примерно следующего содержания:
... function precmd { cmd=`cat $HISTFILE | tail -1`; #определяем текущую введённую команду if [ "`echo $cmd | grep -e "^git://" -e "^lp:" -e "^bzr://" -e "^bzr+ssh://" -e "^http://" -e "^file:///"`" != "$NULL" ]; then #если команда начинается с нужного нам текста, то #записываем в переменную type_path тип ссылки type_path=`echo $cmd | cut -d ":" -f -1`; case "$type_path" in #в зависимости от типа ссылки, делаем соостветствующее действие #в конце каждого действия echo "" >> $HISTFILE нужно для того, #чтобы при закрытии терминала и открытии его в следующий раз команда не выполнилась повторно git ) git clone $cmd; echo "" >> $HISTFILE ;; bzr | bzr+ssh | lp ) bzr branch $cmd; echo "" >> $HISTFILE ;; http ) aria2c $cmd; echo "" >> $HISTFILE ;; file ) cd "`echo "$cmd" | sed 's/\%20/\ /' | cut -d "/" -f 3-`"; echo "" >> $HISTFILE ;; * ) ;; esac; else type_path=""; fi # ... return 0; } ...
Теперь можем проверить, как это работает:
> <c-v> > git://github.com/pieter/git-bzr.git|<enter> zsh: no such file or directory: git://github.com/pieter/git-bzr.git Initialized empty Git repository in /home/ia/Templates/git-bzr/.git/ remote: Counting objects: 19, done. remote: Compressing objects: 100% (12/12), done. remote: Total 19 (delta 6), reused 19 (delta 6) Receiving objects: 100% (19/19), 11.47 KiB, done. Resolving deltas: 100% (6/6), done. >
Думаю, суть ясна, и доработать выполнение собственных команд-ссылок для собственных нужд при базовых знаниях shell-комманд труда не составит.
Happy zsh'ing :-)
- 1946 просмотров
Страница для печати


Поправочка.
Оказывается,
fc-- это тоже POSIX sh.Сначала о хорошем. Замечательная идея, правда!
Довольно странный метод вычисления последней команды -- поиском по HISTFILE. Не ровён час два человека одновременно работают -- вот смеху-то будет.
В zsh есть штатное средство работы с историей команд:
fc. То, что вам нужно, делается с помощью`fc -ln -1`.Для определения того, является ли команда первой в свежеоткрытом терминале не нужно ломать $HISTFILE (а если там timestamp-ы?), достаточно проверить $LINENO.
Выделение type_path также выглядит непрямовато. Зачем выкрутасы с grep-ом, а затем -- с cut-ом, когда со времён POSIX sh есть выделяющая подстановка вида
"${cmd%%://*}"? То же самое касается обработкиfile:///.Ещё про
file:///. Замена "%20" на пробел -- далеко не самый надёжный способ urldecode. Другое дело, что правильный инструмент для этого найти непросто. Я пользуюсь http://www.billposer.org/Software/uni2ascii.html .Мелкий недочёт:
aria2c $cmdи т. п. А если в cmd будут вопросительные знаки?Отдельно расстроило использование нигде не определённой переменной "NULL" (
export NULL="тыква"немножко меняют стиль работы этой precmd() ).Итого:
Happy zsh'ing. Кстати, от zsh осталось только сама precmd и fc :-)
В принципе работает, но есть парочка недачетов:
1) если по завершению действия не водить каких либо команд а нажать Enter, то начнется повторная загрузка предыдущей команды
2) если резко прервать команду закрытием терминала, по последующее его открыти автоматическа запускает прерванную команду на повтор.
отличные улучшения Ж:-)
1. а нельзя это в preexec загнать, тогда команда будет уже в $*
2. зачем test "LINENO"? я так понимавю все равно в *) вывалится?
Отправить комментарий