私はBashからZshにゆっくりと移行しており、例外を除いて私が経験したすべてがうまくいく点に達しました。
.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で動作するようにこれらの機能を移行する方法は?
答え1
local
キーワードではなく組み込み関数なので、local files=(…)
配列割り当てで解析せずに文字列割り当てで解析します。割り当てと宣言を別々に作成します。 (すでにlluaさんが見つけました。files
ただし、空の配列で初期化するか、宣言された変数を使用する必要がありますtypeset -a
。それ以外の場合、配列は虚空の要素で始まります。 )- Zsh配列はbashとkshのようにゼロではなく1から始まり番号が付けられているので、で
${files[0]}
書く必要があります。または、関数の先頭$files[1]
でzshにkshおよびbashと互換性のある方法で動作するように指示します。emulate -L ksh
emulate
このパスに従わない限り、デフォルトで_notes
は一致しない glob がエラーをトリガするため、関数が完了しない場合は印刷されます。次へ追加zsh: no matches found: foo*
foo
グローバル予選N
一致するものがない場合は空の配列を取得し、配列が空であるかどうかをテストします。- 関数には、サブディレクトリのコメントに影響を与える別のバグがあります。たとえば、存在し、と入力した場合は、代わりにcontainに設定さ
_notes
れるように完了するまでプレフィックスを削除する必要があります。~/notes/foo/bar
n b<TAB>
COMPREPLY
b
foo/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
答え2
zshのtypeset(local)コマンドは、その構文を使用して配列を定義することはできません。配列を作成できますが、1つのコマンドですべての値を同時に設定することはできません。
function n() {
local arg files; for arg; do files+=( ~/.notes/$arg ); done
vim ${files[@]}
}
修正する方法の1つです。