web-dev-qa-db-ja.com

zshコマンドラインですべてのエイリアスを解決する

ネストされたエイリアスがあり、コマンドを実行する前にそれらをすべて解決したいと思います。それ、どうやったら出来るの?

キーにバインドされていない関数がある場合、M-x foobarも私にとっては問題ありません。外部コマンド(typecommandwhich、何でも)を使用することもできました。私はスレッドからすべてを試しました なぜ「which」を使用しないのですか?次に何を使用するのですか? しかし何も機能しません。

bashのCtrl-Alt-Eはエイリアスを展開するだけではないことに注意してください。また、変数、コマンド置換(!)、プロセス置換(!)、算術拡張を展開し、引用符を削除します(ファイル名の生成(グロビング)またはチルダ展開は行いません)。

常にエイリアスを展開できるとは限りません。したがって、その用途はありますが、その結果がコマンドラインの意味を潜在的に変更し、副作用があり、潜在的に危険であることを認識することが重要です。

たとえば、

$ a=';w' b=1
$ alias foo=bar
$ b=2; echo $b $a; cd /tmp/dir && for i do foo $(pwd) <(ls); done

ここでM-C-Eを押すと、次のようになります。

$ b=2; echo 1 ;w; cd /tmp/dir && for i do foo / /dev/fd/63; done

これにより、完全に異なるコマンドラインが得られ(上記のpwdの代わりにrm -rf *を使用した場合はどうなるか想像してみてください)、fooエイリアスは展開されません。

zshを使用して、関数内で展開されたエイリアスに関するGillesのメモを作成するには、次のようにします。

expand-aliases() {
  unset 'functions[_expand-aliases]'
  functions[_expand-aliases]=$BUFFER
  (($+functions[_expand-aliases])) &&
    BUFFER=${functions[_expand-aliases]#$'\t'} &&
    CURSOR=$#BUFFER
}

zle -N expand-aliases
bindkey '\e^E' expand-aliases

これは、現在のコマンドラインが構文的に有効な場合にのみエイリアスを展開します(したがって、構文チェッカーとしても機能します)。

bashのM-C-Eとは異なり、エイリアスも完全に解決されます。たとえば、次の場合:

$ alias ll='ls -l'; alias ls='ls --color'
$ ll

以下に拡張されます:

$ ls --color -l

また、構文もカノニカライズされているため、次のようになります。

$ for i (*) cmd $i; foo

次のように変更されます:

$ for i in *
        do
                cmd $i
        done
        foo
10

コマンドラインを関数定義に詰め込んでから関数を出力すると、エイリアスが展開されます。また、正規化された空白も取得します。

% alias foo='bar -1'
% alias bar='qux -2'
% f () foo -3
% which f
f () {
        qux -2 -1 -3
}

これらすべてを対話型コマンドに入れるには、zleウィジェットを作成します。 functions 配列のエントリにコードを詰め込むことにより、関数を直接定義できます。読み返すと正規化効果が得られます。

normalize-command-line () {
  functions[__normalize_command_line_tmp]=$BUFFER
  BUFFER=${${functions[__normalize_command_line_tmp]#$'\t'}//$'\n\t'/$'\n'}
  ((CURSOR == 0 || CURSOR = #BUFFER)
  unset 'functions[__normalize_command_line_tmp]'
}
zle -N normalize-command-line
bindkey … normalize-command-line

preexecフック でも同じ正規化効果が得られます。エイリアスは、関数がオートロードされるときにも展開されます(autoload -Uは、エイリアスの展開を避けるために一般的に使用されます)。

_expand_alias 補完関数は、エイリアスの場合、カーソルの下のWordを展開します。 aliases array を使用します。再帰的ではありません。 aliasesを使用してより一般的なエイリアスエキスパンダーを実装することもできますが、エイリアスが展開される場所を理解することはシェル構文と密接に関連しているため、多少困難です。

ネストされたファンシーエイリアスが多数あり、zshが実際にそれらを使用して何をしているか、およびオプションがコマンドに渡される順序がわからない場合は、常に-xオプションを使用してzshを起動できます。これにより、コマンドと引数が実行されるときに出力されます。

ただし、このオプションはデバッグ用ではなく、zsh -xの呼び出し直後(基本的には.zshrcのすべての関数/ウィジェット/プラグイン)に多くの役に立たないものを出力することに注意してください。特にpreexecprecmdフックを定義している場合は、冗長になります。

onlyが最終的に実行されるコマンドを出力し、分離されたコマンドが個別に出力されるため、

alias a='echo a'
alias b='echo b'
alias c='echo c'
alias d='echo d'
a && b || c; d

あなたは見るでしょう

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
2
jimmij