고쳐 쓰다:

고쳐 쓰다:

내 파일에 다음 항목이 있다고 가정해 보겠습니다./etc/hosts

192.168.1.10      server1.mydomain.com

SERVER-FILES현재 디렉토리에 디렉토리가 있습니다 . 나는 scp특정 디렉토리를 원한다 SERVER-FILES. SE디렉터리 이름을 완성하기 위해 입력 하고 자동 완성을 사용했습니다.

$ 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

두 번째 답변은 다음 두 가지 작업을 수행해야 함을 설명합니다.

1_ 일반 일치 규칙이 대소문자를 구분하지 않는지 확인하세요( matcher-list). 업데이트된 질문에 따르면 그렇지 않습니다.

2_변화유닉스/(유형/)_호스트(실제 위치는 다를 수 있지만아니요이것유닉스/_ssh- 이것은 ~/.ssh/config호스트를 처리합니다. 아래 참조) 마지막 두 줄:

_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 버전어떤 경우에도유닉스/(명령/)_ssh또는유닉스/(유형/)_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호스트 구성존재하다유닉스/_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

하지만 이는 다시 재사용됩니다.주인스타일은 다음에 정의되어 있습니다.유닉스/_호스트

그래서 편집을 하면나침반마지막에 정의됨유닉스/_호스트다음과 같은 파일:

#_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

이 문제에는 두 가지 측면이 있습니다.

  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}"

도움이 안돼. 죄송합니다. 이 문제를 전체적으로 해결해야 합니다. 절충 솔루션은 전 세계적으로 두 번 통과하는 것일 수 있습니다.

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. 문제의 두 번째 부분은 함수에 의해 정의된 일치자 목록입니다. 위에서 언급했듯이 이는 지울 수 없으므로 @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

게시한 구성 및 테스트 사례를 사용하여 이를 테스트했는데 작동합니다.

문서:

관련 정보