выполнение команды в zsh в зависимости от синтаксиса введённой строки


ia аватар

ia - Posted on 14 Декабрь 2008

Бывает так, что надоедает дописывать к началу скопированной в терминал, к примеру, из браузера, ссылки, саму команду, которая должна эту ссылку обработать. Например, вот так (где | - текущее положение курсора):

Если Вам это знакомо, то Вы понимаете, о чём я. Причём речь не обязательно о 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 :-)

0
Ваша оценка: Ничего

Поправочка.
Оказывается, 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() ).

Итого:

precmd ()
{
    local cmd type_path
    cmd=`fc -ln -1`;			# Определяем текущую введённую команду
    type_path="${cmd%%://*}"		# Обработка URL://
    test "$LINENO" -le 1 || case "$type_path" in
        git) git clone "$cmd";;
	bzr|bzr+ssh|lp) bzr branch "$cmd";;
	http) aria2c "$cmd";;
	file) cd "$(echo "${cmd#file://}" | ascii2uni -qa J)";;
	*) ;;
    esac
    # Теперь можно обрабатывать cmd ещё как-нибудь :)
    return 0;
}

Happy zsh'ing. Кстати, от zsh осталось только сама precmd и fc :-)

It's actually a great and useful piece of info. I am satisfied that
you simply shared this helpful info with us. Please keep
us informed like this. Thanks for sharing.

It's going to be finish of mine day, but before finish I am reading this fantastic piece of writing to increase my know-how.

whoah this weblog is great i like studying your articles.

Stay up the great work! You already know, a lot of people are hunting round for this info, you can help them greatly.

What's Going down i'm new to this, I stumbled upon this
I have found It positively useful and it has aided me out loads.
I'm hoping to contribute & aid different customers like its aided me.

Great job.

For the reason that the admin of this web site
is working, no hesitation very soon it will be renowned, due to its quality
contents.

Hello every one, here every one is sharing such know-how, therefore it's nice to read
this web site, and I used to visit this blog daily.

Hello are using Wordpress for your blog platform?

I'm new to the blog world but I'm trying to get started
and set up my own. Do you require any html coding expertise
to make your own blog? Any help would be really appreciated!

hello!,I really like your writing so a lot!

share we keep in touch extra about your post on AOL? I need an expert on this area to solve my problem.
Maybe that is you! Having a look ahead to look you.

This web site definitely has all the information I wanted concerning this subject and
didn't know who to ask.

В принципе работает, но есть парочка недачетов:
1) если по завершению действия не водить каких либо команд а нажать Enter, то начнется повторная загрузка предыдущей команды
2) если резко прервать команду закрытием терминала, по последующее его открыти автоматическа запускает прерванную команду на повтор.

Hello there! This article couldn't be written much better! Going
through this post reminds me of my previous roommate! He constantly kept preaching about this.
I will forward this post to him. Fairly certain he'll have a great read.
Many thanks for sharing!

Hey there, You have done an incredible job. I'll definitely digg it and personally recommend to my friends.
I am sure they will be benefited from this website.

отличные улучшения Ж:-)
1. а нельзя это в preexec загнать, тогда команда будет уже в $*
2. зачем test "LINENO"? я так понимавю все равно в *) вывалится?

Отправить комментарий

Google Friend Connect (leave a quick comment)
loading...
Содержание этого поля является приватным и не предназначено к показу.