私はしばしばgitリポジトリを複製し、そのルートディレクトリに移動します。たとえば、
$ git clone https://github.com/hpjansson/chafa && cd chafa
cc
これをより簡単にするために、次のように拡張されるzsh略語があります&& 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
コマンドラインの2番目の単語を参照します(コマンドを入力したときのURLです$ git clone
)。
n
n番目のパラメータです。
そして:t
単語の終わりを示します。
t
すべての先行パス名コンポーネントを削除し、後続コンポーネントはそのまま残します。まるでbasename
。
通常、git clone
コマンドラインに入力してプロジェクトのURLをコピーして貼り付け、スペースを挿入してから別cc
のスペースを挿入すると、必要なコマンドが表示されます。
ただし、コピーして貼り付けたURLが拡張子で終わる場合があります.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
1つの解決策は、修飾子を使用して.git
拡張を削除することです。
r
ファイル拡張子を削除し、ルート名を保持します。ファイル拡張子のない文字列は変更されません。ファイル拡張子の後には、いずれも.
任意の数の文字(0を含む)が続き、文字列の最後まで続きます。たとえば、拡張子はisであり、拡張子はありません。.
/
foo.orig.c
.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
最初のコマンドは最後のパスコンポーネントに拡張子が含まれているため成功します.baz
が、2番目のコマンドは拡張子がないため失敗します。 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
/foo/bar.baz
inとto inの両方を参照できるbar
単一の修飾子シーケンスはありますか/foo/bar
?
私はそれを使用していますzsh 5.7.1-dev-0 (x86_64-pc-linux-gnu)
。
答え1
履歴拡張によってこれを行う方法は思い出されません。しかし、私は履歴拡張が最高のツールだとは思わない。これは非常に制限的です。からリングウィジェットを使用すると、コマンドラインにアクセスして任意のコードを操作できます。これを活用してください。
一つの方法は略語を拡張することです。$abbrev[$MATCH]
代替を使用してください${(e)abbrev[$MATCH]}
。明らかに特殊文字を正しく参照するには、略語を変更する必要があります。の場合は、cc
次のようなものを使用してください。
&& cd ${${(z)BUFFER}[3]}
の特定の場合、git clone
およびより一般的には、現在のディレクトリ内にディレクトリを作成するすべての場合には、別の略語を使用できます。新しく作成したディレクトリに切り替えます。git clone https://example.com/foo.git
、for、およびgit clone https://example.com/foo
forgit clone https://example.com/foo.git bar
だけでなく、for tar xf foo.tar
(アーカイブに最上位のディレクトリがある場合)およびでも機能しますmv /some/directory .
。
&& cd *(/oc[1])