修正する:

修正する:

私のファイルに次のエントリがあるとしましょう。/etc/hosts

192.168.1.10      server1.mydomain.com

SERVER-FILES現在のディレクトリにディレクトリがあります。私はscp特定のディレクトリが欲しいですSERVER-FILESSEディレクトリ名を完成させるために入力し、オートコンプリートを使用しました。

$ scp -rp SE<TAB>

この完了は完全に明確でなければなりません。ただし、zshオートコンプリートはスマートすぎるし、ホスト名を大文字と小文字を区別せずに処理するため、ホストSE名と一致しようとします。

$ scp -rp SE<TAB>
SERVER-FILES/
server1.mydomain.com

zshが大文字と小文字を区別しないホスト名を一致させてserver1.mydomain.comを完了しようとするこの面倒な機能を無効にするにはどうすればよいですかSE<TAB> to

修正する:

あなたの提案に従って@zeppelinSSH完了ファイルの次の行を変更しましたUnix/_ssh

- compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" $config_hosts
+ compadd "$@" $config_hosts

しかし、これは役に立ちません。まったく効果がありません。

そして私は答えを理解していません@Tomasz Pala。私のzsh補完は大文字と小文字を区別しません。

/usr/share/zsh/functions/Completion/Unix/_foo誰かがこの動作を変えるために何が変わるべきかを教えてください。

アップデート2

私はついに問題の範囲を絞り込み、その解決策が@Tomasz Pala彼には効果がありましたが、私には効果がなかった理由を見つけました。

Unix/_hostsこのソリューションは、新しく設定されたコンピュータ/ユーザーアカウントでファイルを変更するときに機能します。

scp -r SE<TAB>

上記のコマンドはserver1.mydomain.cominを無視し/etc/hosts、完了のためにローカルディレクトリのみを提供しますSERVER-FILES

ただし、アイテムを削除すると、すべてが期待どおりに機能するため、既存のユーザーアカウントでは機能しません server.mydomain.com~/.ssh/config

しかし、現在の状況でもこのハッキングをどのように機能させることができますか~/.ssh/config

答え1

2番目の答えは、次の2つのことを行う必要があることを示しています。

1_一般的な一致規則が大文字と小文字を区別しないことを確認してください(matcher-list)。更新された質問によると、そうではありません。

2_変化Unix/(タイプ/)_ホスト(実際の位置は異なる場合がありますが、いいえこれUnix/_ssh- これは~/.ssh/configホストを処理します。以下を参照)最後の2行:

_wanted hosts expl host \
   compadd -M 'm:{a-z}={A-Z} r:|.=* r:|=*' -a "$@" - _hosts

これらのすべてはすでに私の答えにまとめられているので、以前の根拠をすべて読んではいけません。また、グローバル構成は大文字と小文字を区別しないため、$ fpathを使用せずにホストからの小文字->大文字の一致も削除しても@zeppelinの答えも機能します。

アップデートの設定を使用してこれをテストしましたが、期待どおりに機能しました。

更新:zshその機能はロードされたままである必要があるため、変更後に_hosts再度ログインするか、次の手順を実行して再ロードする必要があります。

unfunction _hosts
autoload -Uz _hosts

また、zshスクリプトは()形式で「コンパイル」することができ、そのようなファイルが存在し、ソースファイルよりも最新の場合はそのファイルが使用されることに注意してください。zwczcompile [file]

開示する。アップデート2:

~/.ssh/config定義されたホストを処理することは実際に動作します_hosts- あなたによって異なります。zsh バージョンいずれにせよUnix/(コマンド/)_sshまたはUnix/(タイプ/)_ssh_hosts変化

compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" $config_hosts

並ぶ

compadd -M 'm:{a-z}={A-Z} r:|.=* r:|=*' "$@" $config_hosts

答え2

私はあなたが間違った行を編集していると思います。

AFAIKホスト構成存在するUnix/_sshホストエントリを表します。~./ssh/config、いいえ/etc/ホスト

完成ルールは/etc/ホスト次のブロックでもう少し早く定義されました。

# If users-hosts matches, we shouldn't complete anything else.
if [[ "$IPREFIX" == *@ ]]; then
  _combination -s '[:@]' my-accounts users-hosts "users=${IPREFIX/@}" hosts "$@" && return
else
  _combination -s '[:@]' my-accounts users-hosts \
    ${opt_args[-l]:+"users=${opt_args[-l]:q}"} hosts "$@" && return
fi

しかし、これは再利用されます。所有者スタイルは次に定義されています。Unix/_ホスト

だから編集するとコンパス最後に定義Unix/_ホスト次のファイル:

#_wanted hosts expl host \
#    compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' -a "$@" - _hosts
_wanted hosts expl host \
     compadd -a "$@" - _hosts

希望する行動を取る必要があります。

ポリスチレン

システム全体の完成ファイルを編集するのは一般的に良い習慣ではないので、上書きすることをお勧めします。所有者代わりに、ローカルZSH構成では、たとえば〜./zshに同様の機能を追加します。

_hosts() { compadd $(getent hosts | tr -s ' ' '\t' | cut -f2) }

答え3

この問題には2つの側面があります。

  1. 大文字と小文字を区別しないグローバルzsh完成。人気がありますが、IMHOでは双方向に進むには意味がありません。私は通常大文字を入力しないので(または間違って入力する)、すべての大文字を意図的なものとして扱います。

zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

mkdir DOC drone
ls D[tab] => DOC
ls d[tab] => drone DOC
ls Dr[tab] => [empty]

マッチリストの問題は次のとおりです。非常に早く呼び出され、コマンド/引数によって置き換えることはできません。

そして、マッチリストによって重複値が関連付けられます(文書から引用:このオプションは複数回与えられます。この場合、指定された一致するすべての仕様は、使用する仕様文字列を形成するためにスペースで連結されます。")、後で上書きできません。

compdef '_hosts -M m:' foo

_hosts ファイルの以前の定義は取り消されません。したがって、グローバル設定に対応するエントリがある場合は、使用しても{a-zA-Z}={A-Za-z}消去できませんmatcher。たとえば、次のようになります。

zstyle ':completion:*:scp:*:*' matcher "m:{A-Z}={A-Z}"

役に立ちません。申し訳ありません。この問題を完全に解決する必要があります。トレードオフソリューションは、世界中で2回通過することです。

zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' 'm:{A-Z}={a-z}'

ls d[tab] => DOC drone
ls D[tab] => DOC
ls Dr[tab] => drone
  1. 問題の2番目の部分は、関数によって定義された一致子のリストです。上記のようにこれは消去できないため、@zeppelinの回答ですでに説明したように、zshが提供するファイルを変更してこの問題を処理する必要があります。

_オーナー:

[....]
_wanted hosts expl host \
    compadd -M 'm:{a-z}={A-Z} r:|.=* r:|=*' -a "$@" - _hosts

システム全体のマッチリスト 'm:{az}={AZ}' を使用します。

scp d[tab] => /directory/ DOC drone /remote host name/ docker /user/ daemon
scp D[tab] => DOC

もともと完成ファイルを変更する提案された解決策は、@zeppelinが指摘したように正しいアプローチではありませんが、独自のホスト取得機能を作成することにも欠陥があります。残念ながら、正しい解決策は、マッチングクリーンアップオプションを追加したり、いくつかの新しいスタイルを定義したり、大文字と小文字を無視しないように補完機能を変更するzsh開発者によって異なります。グローバル設定に従うだけです。

しかし、この問題が存在しても、優れたクリーンな解決策があります。 (おそらくいくつかのディストリビューションパッケージが付属しています)/usr/share/zsh/...を変更するのではなく、/etc/zsh /functionsに固定コピーを置くことができ、zshに次の場所を使用するように指示しますfpath=(/etc/zsh/functions $fpath)。これにより、システム更新後にファイルが上書きされるのを防ぎます。

まとめる

  1. グローバルマッチングリストを変更します。

zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' 'm:{A-Z}={a-z}'

  1. 変更された_hostsファイルを/ etc / zshまたは$ HOMEの場所に配置します。

fpath=(/etc/zsh/functions $fpath)

/etc/zsh/functions/_hosts:

[....]
_wanted hosts expl host \
    compadd -M 'm:{a-z}={A-Z} r:|.=* r:|=*' -a "$@" - _hosts

答え4

必要なものを得るために完成機能を変更する必要はありません。ファイルに以下を追加するだけです~/.zshrc

# $PREFIX is the part of the current word that's to the left of the cursor.
# $SUFFIX is the part of the current word that's to the right of the cursor.
# Let's ignore all host completions that don't explicitly match what we've typed, 
# but allow for additional characters at the cursor position and at the end of what 
# we've typed. This makes the matching case sensitive.
# `(b)` escapes characters that are significant to globbing.
zstyle -e ':completion:*:hosts' ignored-patterns 'reply=(
  "^(${(b)PREFIX}*${(b)SUFFIX}*)"
)'

# But if that would lead to no results, then offer the ignored completions anyway.
zstyle ':completion:*' completer _expand _complete _ignored

公開した構成とテストケースを使用してこれをテストしましたが、うまくいきます。

文書:

関連情報