長くなった。 変数展開でうまいこと書けないかなぁ→書けた って記事
拝啓
zsh の global alias について軽く説明すると
通常のalias と違って、コマンド以外の場所でも 展開されるalias です
大体パイプと組み合わせて定義されてることが多いです
alias名には特にきまりはないですが、global alias名は大文字で定義するのが一般的ぽいですね
alias -g G='| grep'
alias -g H='| head'
alias -g L='| less'
このように定義しておくと、コマンド実行時に展開されます
$ cat log H -n2
# => cat log | head -n2
そのまま使ってても便利なのですが、 コマンドライン操作中に自動で展開したら個人的にスマートですね。履歴にも展開後のコマンドとして残るので
alias展開関数はいつくかの記事で紹介されてますが
- 展開バインドキーはSpace
- global alias だけ展開する
- 定義済みのaliasと比較して展開する
みたいなのが個人的にほしかったので勉強がてら作りました
作った
そんな関数がこちら
# !/usr/bin/env zsh
function main() {
emulate -L zsh
setopt aliases
local -a global_aliases=(${(@f)"$(alias -g)"})
local -a characters=(${global_aliases%%\=*})
if (($characters[(I)${(q)LBUFFER##* }])); then
zle _expand_alias
zle expand-word
fi
zle self-insert
}
main
趣味記法なので関数で囲わなくてもいいし、shebangもいらないかもです
こちらを fpathが通ったディレクトリに置いて、bindkeyを割り当てると使えます
autoload -Uz expand-alias-widget
zle -N expand-alias-widget
bindkey ' ' expand-alias-widget
解説
shellscript内でもaliasを使えるようにする
デフォだと使えないんです。なので オプションを指定してあげる
関数内でオプションを触る時は local_options
か emulate -L zsh
しましょう
setopt aliases
定義済みのglobal alias一覧を配列化
alias -g
で定義済みのglobal aliasが出力できます
出力は改行ありなので f
フラグで 改行文字区切りで単語展開
@
フラグで個々の要素を別々の要素として展開(いらないかも)
local -a global_aliases=(${(@f)"$(alias -g)"})
配列からalias 名のみ取り出す
L='| less'
から L
を抽出する。 ${*name*%%*pattern*}
記法
冒頭の例だとこの時点でcharactersの内容は (G H L)
こんな感じになる
local -a characters=(${global_aliases%%\=*})
カーソル左の文字列が、alias名配列に含まれるか調べる
if (( ${array[(I)pattern]} ))
で 配列に特定の要素が含まれるかチェックできる
if (($characters[(I)${(q)LBUFFER##* }]))
${(q)LBUFFER##* }
はカーソル左の空白区切り末尾文字を取得
(q)
が大事
${LBUFFER##* }
には *
や?
が展開されることもあるので
パターンマッチで条件式が意図せず真になってしまいます。
そこでqフラグで メタ文字をバックスラッシュでクォートして防ぎます
zleの組み込みウィジェット
alias を展開するだけだったら 既存でwidgetが用意されている
それが _expand_alias
expand-word
はシェル展開 (コマンド展開とかグロブ展開とか)
まとめ
え?「変数展開とかフラグが多すぎてわかんないよ〜」って?
まとめといたよ
https://gist.github.com/sho-t/d9cdf8271b3de7c4238739e523490542