bash가 디렉토리 이름을 완성하는 방식을 구성 할 수 있습니까?


8

특정 디렉토리 이름에서 완료를 수행하기 위해 특별한 방법을 사용하도록 bash에 지시하고 싶습니다. 예를 들어, bash는 경로가 "$$"로 시작하면 내 프로그램을 호출하여 완료를 수행하고 그렇지 않으면 정상적으로 완료를 수행합니다.

이것이 가능합니까? 어떻게 구현하겠습니까?

현상금 : 나는 그 질문에 대한 답변을 정말로 고맙게 생각합니다. 사용자가 특정 접두어로 명령을 시작할 때 autojump 가 모든 명령의 경로를 완료 하도록하는 것이 목표입니다 . 예를 들어 원거리 디렉토리에서 파일을 복사 할 때 다음을 입력 할 수 있습니다.

cp $$patern + <Tab>

autojump는 완료 될 것입니다

cp /home/user/CompliCatedDireCTOry/long/path/bla/bla

파일을 저장할 위치를 추가하면됩니다. 물론 ott의 주석을 사용하여 몇 가지 특정 명령에 주석을 추가 할 수는 있지만 더 좋은 아이디어가 있다면 매우 감사 할 것입니다.


bash 매뉴얼 페이지의 "프로그램 완료"섹션을 참조하십시오.

내 질문을 끝내기 위해 투표한다면 그 이유를 설명하십시오.
Peltier

2
"complete"는 $$를 시작과 일치시키기위한 "-G pattern"및 자신의 함수를 호출하기위한 "-F func"를 지원하지만 작동하려면 하나 이상의 명령 이름이 필요합니다.

왜 환경 변수를 사용하지 않습니까? 예를 들면 다음과 같습니다. cp $ prefix / file / path / to / dest /
Xenoactive

@Xenoactive : autojump가 완전히 자동화되어 있고 둘 이상의 경로에서 작동하기 때문입니다. 수동으로 설정 한 환경 변수를 사용해도 도움이되지 않습니다. 아니면 내가 이해하지 못하는 강력한 아이디어가 있습니까?
Peltier

답변:


3

TAB (^ i)의 기본 바인딩을 대체하여이를 수행 할 수 있습니다. 먼저 TAB 바인딩을 재정의 한 다음 명령을 호출하는 함수를 작성해야합니다. 마지막으로 해당 명령의 출력을 가져 와서 현재 명령 행이 포함 된 변수를 업데이트해야합니다.

이 함수는 현재 명령 행을 사용하여 마지막 두 문자를 'huugs'로 변경합니다.

function my_awesome_tab_completion_function () {
  set -- $READLINE_LINE
  command="$1"
  shift
  argument="$*"
  argument_length=$(echo -n $argument | wc -c)
  if echo $argument | grep '^$$' >/dev/null 2>&1; then
    new_argument=$(echo $argument | sed 's/..$/huugs/') # put your autojump here
  else
    new_argument=$(compgen -d $argument)
  fi
  new_argument_length=$(echo -n $new_argument | wc -c)
  READLINE_POINT=$(( $new_argument_length - $argument_length + $READLINE_POINT ))
  READLINE_LINE="$command $new_argument"
}

예를 들어 new_argument 줄을 다음과 같이 변경하고 싶을 것입니다.

  new_argument=$(autojump $argument)

이제 ^ i 바인딩을 재정의하십시오.

$ bind -x '"\C-i"':'my_awesome_tab_completion_function'

이제 작동하는지 테스트하십시오.

$ cd /ro<TAB>
changes my command to:
$ cd /root

정상적인 완성이 여전히 작동하면 cd $$를 수행하여 $$ 부분을 테스트 할 수 있습니다 ... 등

문제가 발생하면 상세 모드를 켜십시오.

$ set -x

기능이 수행하는 모든 것을 인쇄합니다.

우분투 11에서 bash 4.2.8 (1) -release (기본값)를 사용하여 이것을 테스트했습니다.


이것은 명령의 첫 번째 매개 변수에서만 작동하며 탭이 예기치 않은 방식으로 사용되는 경우 (예 : $$$ 이후 또는 명령 이름 뒤에) 이상한 일을 할 수 있습니까?
harrymc

글쎄 그것은 $ *를 전달하기 때문에 첫 번째 매개 변수 이상에서 '작동'할 것입니다 (나는 autojump를 전혀 알지 못하므로 여러 인수를 취할 수 있는지 확실하지 않습니다). 끝으로 이동하여 마지막을 자동 점프로 보내거나 READLINE_POINT를 사용하여 커서가 명령 인수 중 어디에 있는지 확인하고 해당 단어 만 자동 점프로 보낼 수도 있습니다.
다항식

귀하의 솔루션은 흥미롭지 만 탭 키를 인수하는 것이 약간 극단적이라는 것을 인정해야합니다. 가능한 모든 경우를 예상 할 수있는 방법은 없습니다.
harrymc

귀하의 답변에 감사드립니다, 그것은 훌륭한 대안 솔루션이며, 내 질문의 "모든 명령에 대해"부분을 해결합니다. 나는 harrymc에 동의하지만 그것은 조금 극단적이라고 생각합니다. 아무도 더 좋은 해결책을 찾지 못하면 시도해보고 그것이 가능한지 알아 봅니다.
Peltier

Ya 나도 harrymc에 동의하지만 요청에 따라 질문에 대답하려고했습니다. 개인적으로 이것을 ^ G 또는 다른 것과 같은 다른 제어 키에 바인딩하여 탭을 그대로 두고이 기능을 계속 사용할 수 있습니다.
다항식

1

bash 완료 루틴은 쉘 스크립트로 프로그래밍 할 수 있습니다.

여기에 어떤 매개 변수에 대체 할 쉘 스크립트의 예 $$[Tab]에 의한 my replacement string하지만 특정 명령, mycommand만 매개 변수가 정확히 경우는 "$$"

_mycomplete()
{
        if [ ${COMP_WORDS[COMP_CWORD]} == \$\$ ]
        then
                COMPREPLY='my replacement string'
        fi
}
complete -o default -o bashdefault -F _mycomplete mycommand

스크립트를 소싱하여 source <file-name>(또는 dot 명령을 통해 ) 작동시킨 후 다음을 수행해야합니다.

mycommand $$[Tab] -> mycommand my replacement string
mycommand $$$[Tab] -> mycommand $$$ (beep)
mycommand whatever[Tab] -> (will complete "whatever" in the normal bash manner)

항상 일부 또는 모든 사용자에게 작동하게하려면이를 bash 프로파일 루틴 중 하나에 포함 시키십시오 .

complete명령 의 문제점 은 매개 변수로 지정된 하나 이상의 명령 이름에 대해서만 작동한다는 것입니다. 사용자가 사용할 수있는 모든 명령의 목록을 제공하거나 필사적 인 경우 expand를 지정할 수 있습니다 /bin/* /usr/bin/* ~/bin/*.

CentOS 5.5에서 테스트되었습니다.

이 간단한 스크립트는 다른 답변에 나와있는 소스 (중재자 스튜디오 핵에 의해 삭제 된 소스)를 기반으로합니다. 관심이 있으시면 삭제를 취소하도록 요청하십시오.


답변 주셔서 감사합니다. 내 질문은 실제로 새로운 것이 가능했기 때문에 그것에 관한 것이 아니었지만 모든 명령을 완료하지는 않습니다. 그러나 다항식 솔루션이 수용 할 수없는 것으로 판명되면 그와 같은 것을 구현하고 가장 일반적인 명령을 대상으로하려고합니다.
Peltier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.