長くなった。 変数展開でうまいこと書けないかなぁ→書けた
って記事
拝啓
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
