私はゆっくりとBashからZshに移行し、1つの例外を除いて、移動したすべてのものがうまく機能するようになりました。
私の.bashrc
には、1日に数十回使用する関数がいくつかあり、そのうちの2つはZshで動作しません。 3つの機能は、基本的なメモ取り機能を構成します。
現在.config/zsh/functions
にあります:
function n() {
local arg files=(); for arg; do files+=( ~/".notes/$arg" ); done
${EDITOR:-vi} "${files[@]}"
}
function nls() {
tree -CR --noreport $HOME/.notes | awk '{
if (NF==1) print $1;
else if (NF==2) print $2;
else if (NF==3) printf " %s\n", $3
}'
}
# TAB completion for notes
function _notes() {
local files=($HOME/.notes/**/"$2"*)
[[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]##~/.notes/}" )
}
complete -o default -F _notes n
.zshrc
からのソースは次のとおりです。
autoload bashcompinit
bashcompinit
# source zshrc functions file
source "$HOME/.config/zsh/functions"
nls
は期待どおりに動作しますが、n
も Tab 完成作業。
私はman zshcompsys
を読みます:
関数bashcompinitは、bashのプログラム可能な完了システムとの互換性を提供します。実行すると、同じ名前のbashビルトインに対応する関数、compgen、completeが定義されます。その後、bash用に作成された補完仕様と関数を使用することができます。
しかし、私がしようとすると Tab 完了しても何も起こらず、n notename
に入ると、Vimはファイルブラウザモードで/home
を開きます-期待どおりの動作ではありません。
定義されている他のすべての関数はうまく機能します。これらの関数をZshで動作するように移行するにはどうすればよいですか?
local
は組み込みであり、キーワードではないため、local files=(…)
は配列割り当てとしてではなく、文字列割り当てとして解析されます。宣言とは別に割り当てを記述します。 (すでに lluaで見つかりました ですが、files
を空の配列に初期化するか、変数をtypeset -a
で宣言する必要があることに注意してください。そうしないと、配列は偽の空の要素で始まります。)${files[0]}
は$files[1]
と記述する必要があります。または、kshおよびbashとより互換性のある方法で動作するようにzshに指示します。関数の先頭にemulate -L ksh
を置きます。emulate
ルートを使用しない限り、foo
の補完がない場合、_notes
関数はzsh: no matches found: foo*
を出力します。 glob qualifierN
を追加して、一致するものがない場合は空の配列を取得し、配列が空かどうかをテストします。_notes
関数には、サブディレクトリ内のメモに影響を与える別のエラーがあります。たとえば、次のように、プレフィックスを最後まで削除する必要があります。 ~/notes/foo/bar
が存在し、n b<TAB>
と入力すると、COMPREPLY
はfoo/b
ではなくb
を含むように設定されます。Bashとzshの両方で読み取り可能なファイルを保持したい場合:
type emulate >/dev/null 2>/dev/null || alias emulate=true
function n() {
emulate -L ksh
local arg; typeset -a files
for arg; do files+=( ~/".notes/$arg" ); done
${EDITOR:-vi} "${files[@]}"
}
function nls() {
tree -CR --noreport $HOME/.notes | awk '{
if (NF==1) print $1;
else if (NF==2) print $2;
else if (NF==3) printf " %s\n", $3
}'
}
# TAB completion for notes
function _notes() {
emulate -L ksh
local x files
files=($HOME/.notes/**/"$2"*)
[[ -e ${files[0]} ]] || return 1
COMPREPLY=()
for x in "${files[@]}"; do
COMPREPLY+=("$2${x#$HOME/.notes*/$2}")
done
}
complete -o default -F _notes n
コードをzshに移植する場合:
function n() {
local files
files=(${@/#/~/.notes/})
${EDITOR:-vi} $files
}
function nls() {
tree -CR --noreport $HOME/.notes | awk '{
if (NF==1) print $1;
else if (NF==2) print $2;
else if (NF==3) printf " %s\n", $3
}'
}
# TAB completion for notes
function _notes() {
setopt local_options bare_glob_qual
local files
files=(~/.notes/**/$2*(N))
((#files)) && COMPREPLY=($2${^files##~/.notes*/$2})
}
complete -o default -F _notes n
zshのtypeset(local)コマンドは、その構文で配列を定義できません。配列を作成することはできますが、1つのコマンドですべての値を設定することもできません。
function n() {
local arg files; for arg; do files+=( ~/.notes/$arg ); done
vim ${files[@]}
}
それを修正する1つの方法です。