Zshでは、Bash機能が機能しません。

Zshでは、Bash機能が機能しません。

私は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 notenameVimは/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/barn b<TAB>COMPREPLYbfoo/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つです。

関連情報