我经常克隆git存储库,然后进入其根目录。例如:
$ git clone https://github.com/hpjansson/chafa && cd chafa
为了使它更容易一些,我有一个zsh缩写– cc
–扩展为&& cd !#:2:t
:
typeset -Ag abbrev
abbrev=(
'G' '| grep -v grep | grep'
'L' '2>&1 | less'
'V' '2>&1 | vipe >/dev/null'
'ac' '| column -t'
'bl' '; tput bel'
'cc' '&& cd !#:2:t'
'fl' "| awk '{ print $"
'ne' '2>/dev/null'
'pf' "printf -- '"
'sl' '>/dev/null 2>&1'
'tl' '| tail -20'
)
__abbrev_expand() {
emulate -L zsh
setopt EXTENDED_GLOB
local MATCH
LBUFFER=${LBUFFER%%(#m)[a-zA-Z]#}
if [[ "${LBUFFER: -1}" == ' ' ]]; then
LBUFFER+=${abbrev[$MATCH]:-$MATCH}
if [[ $MATCH = 'fl' ]]; then
RBUFFER="}'"
elif [[ $MATCH = 'pf' ]]; then
RBUFFER="\n'"
fi
else
LBUFFER+=$MATCH
fi
zle self-insert
}
zle -N __abbrev_expand
bindkey ' ' __abbrev_expand
bindkey -M isearch ' ' self-insert
!#
指的是当前命令行,如man zshexpn
(小节HISTORY EXPANSION
,小节Event Designators
)所述:
!#
请参考到目前为止键入的当前命令行。该行被视为已完成,直到该行包含!#
参考号之前的单词。
:2
指的是命令行中的第二个单词(当我键入$ git clone
命令时是URL ):
n
第n个参数。
并:t
指代该词的尾部:
t
删除所有前导路径名组件,保留结尾。这就像basename
。
通常,我将git clone
在命令行上键入,然后复制粘贴项目的url,然后插入一个空格cc
和另一个空格,以提供所需的命令。
但是,有时,我复制粘贴的URL以extension结尾.git
。当发生这种情况时,的扩展!#:2:t
包含不希望的.git
扩展:
$ git clone https://github.com/hpjansson/chafa.git cc
→
$ git clone https://github.com/hpjansson/chafa.git && cd !#:2:t
→
$ git clone https://github.com/hpjansson/chafa.git && cd chafa.git
cd: no such file or directory: chafa.git
一种解决方案是还使用:r
修饰符删除.git
扩展名:
r
删除保留根名称的文件扩展名。没有文件扩展名的字符串不会更改。文件名扩展名.
后跟任意数量的字符(包括零),既不是也不.
是/
,并且一直持续到字符串的末尾。例如,扩展名为foo.orig.c
is.c
,dir.c/foo
没有扩展名。
vv
$ git clone https://github.com/hpjansson/chafa.git && cd !#:2:t:r
→
$ git clone https://github.com/hpjansson/chafa.git && cd chafa
但是,如果路径不以.git
扩展名结尾,则扩展将失败,并且git
命令和cd
命令均不会执行。
这是一个说明问题的最小示例:
$ echo /foo/bar.baz !#:1:t:r
/foo/bar.baz bar
$ echo /foo/bar !#:1:t:r
zsh: modifier failed: r
第一条命令成功,因为最后一个路径组件包含extension .baz
,但是第二条命令失败,因为不再有扩展名。OTOH,在bash中4.3.48
,两个命令均按预期工作。
我不明白为什么:r
没有扩展名时会失败,因为其文档中包含以下语句:
没有文件扩展名的字符串不会更改。
它不是说:r
对不包含扩展名的字符串使用是错误的。
我尝试了另一种方法;使用:s
修饰符删除扩展名。我认为这需要设置HIST_SUBST_PATTERN
选项:
setopt HIST_SUBST_PATTERN
使用此选项,可以编写:s/.*
删除扩展的代码:
vvvvv
$ echo /foo/bar.baz !#:1:t:s/.*
/foo/bar.baz bar
有扩展名时,它可以工作,但没有扩展名时,它又会失败:
$ setopt HIST_SUBST_PATTERN
$ echo /foo/bar !#:1:t:s/.*
zsh: substitution failed
是否有单个修饰语序列可以同时引用bar
in/foo/bar.baz
和bar
in /foo/bar
?
我正在使用zsh 5.7.1-dev-0 (x86_64-pc-linux-gnu)
。
我想不出一种通过历史扩展来做到这一点的方法。但是我不认为历史扩展是这里最好的工具。这是非常有限的。在zle小部件中,您可以访问命令行并使用任意代码对其进行操作。利用这一点。
一种方法是对缩写进行扩展:而不是$abbrev[$MATCH]
使用${(e)abbrev[$MATCH]}
。显然,您需要更改您的缩写以适当地引用特殊字符。对于cc
,请使用类似
&& cd ${${(z)BUFFER}[3]}
对于的特定情况git clone
,更一般而言,对于在当前目录中创建目录的任何内容,可以使用不同的缩写:切换到新创建的目录。这适用于git clone https://example.com/foo.git
,forgit clone https://example.com/foo
和forgit clone https://example.com/foo.git bar
以及for tar xf foo.tar
(如果归档文件具有单个顶级目录)和mv /some/directory .
。
&& cd *(/oc[1])
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句