2011-01-25 3 views
2

배쉬 스크립트 기반의 파일 이름 자동 완성을 발견하고 내가 가장 잘 실현하는 방법에 대해 생각했습니다,하지만 난 ... 아무것도 없어나는 오랫동안 싶었어요 명령 줄 기능이 있습니다

그래서

# git add Foo<tab> 

은 내 명령에 일치하는 파일의 전체 경로를 find . -name "*$1*"을 실행하고 기본적으로 자동 완성을 싶습니다 내가 예를 들어, 파일 이름을 입력을 시작하고 탭을 쳤을 때 내가 가지고 싶은 것은 선. 내가 지금까지 무엇을 가지고

:

나는 내가 원하는 매개 변수, 예를 git add에 대한 와 응용 프로그램을 호출하는 함수를 작성해야합니다 알고 있습니다. 그 후 탭 키 스트로크 이벤트를 잡아 위에서 언급 한 찾기를 수행하고 결과가 많은 경우 결과를 표시하거나 결과가 있으면 입력하십시오. 내가 알아낼 수 없었다 무엇

:

어떻게 함수 내 함수 내에서 탭 키 이벤트를 잡으려고. 의사의

그래서 기본적으로 :

gadd() {git add autocomplete_file_search($1)} 

autocomplete_file_search(keyword) { 
    if(tab-key-pressed){ 
    files = find . -name "*$1*"; 
    if(filecount > 1) { 
     show list; 
    } 
    if(files == 1) { 
     return files 
    } 
    } 
} 

어떤 아이디어가?

감사합니다.

답변

1

너는 introduction to bash completion을 봐야한다. 간단히 말해, bash에는 탭 완성을 구성하고 확장하는 시스템이 있습니다. 다른 쉘도이 작업을 수행하며, 각 쉘마다 다른 방법을 사용합니다. 이 시스템을 사용하면 모든 것을 직접 수행 할 필요가 없으며 사용자 정의 인수 완성을 명령에 추가하는 것이 상대적으로 쉽습니다.

+0

굉장합니다. 감사! –

0

나는 쓸데없는 파일을 지정할 때 탭을 치지 않아도되도록 git-number을 썼다.

git-number를 사용하면 git이 처리 할 파일 이름을 나타내는 숫자를 사용할 수 있습니다.

0

이 방법이 효과가 있습니까?

2

파일 이름의 어느 곳에서나 일치하는 것은 다소 복잡합니다. 실제로는 그다지 유용하지는 않습니다. 파일 이름의 시작 부분에서의 매칭은 더 이해하기 쉽고 재귀 적으로 구현하는 것이 훨씬 쉽습니다.

이제 find를 요구 사항으로 언급했지만 bash (버전 4.0부터)는 재귀 적으로 파일을 찾을 수 있으며 bash가 해당 부분을 수행하게하는 것이 더 효율적이어야합니다. bash에서 재귀 적으로 일치 시키려면 shopt -s globstar을 실행하여 globstar 쉘 옵션을 사용하면 두 개의 연속 된 별표 **이 재귀 적으로 일치합니다.

다음은 git 저장소 내에서 파일을 재귀 적으로 일치시키려는 경우 실제로 우리가 git 저장소에 있다는 것을 감지하는 것이 가장 좋습니다. 그렇지 않으면 우연히 /에서 bash가 전체 파일 시스템을 검색하기를 기다리는 동안 프롬프트가 멈 춥니 다. 다음 함수는 우리가 자식 저장소에 있는지 결정할 때 상당히 효율적이어야합니다. 주어진 현재 작업 디렉토리, 예를 들면./foo/bar/baz 일 경우 /foo/bar/baz/.git, /foo/bar/.git, /foo/.git, /.git을 찾아서 찾으면 true를 반환하고 그렇지 않으면 false를 반환합니다.

isgit() { 
    local p=$PWD 
    while [[ $p ]]; do 
     [[ -d $p/.git ]] && return 
     p=${p%/*} 
    done 
    return 1 
} 

은 단순화하기 위해, 우리의 완료를 추가하는 gadd 명령을 만듭니다. 완료 기능은 명령의 첫 번째 단어에만 적용 할 수 있습니다. 예 : git에 대한 완료를 추가 할 수 있지만 git add에 대한 완료를 추가 할 수 없으므로 git add을 하나의 단어로 바꾸는 새로운 명령을 만듭니다.

gadd() { 
    git add "[email protected]" 
} 

이제 실제 완성 기능을 위해. Tab 키를 눌러 트리거하면 함수가 세 개의 인수로 호출됩니다. $1은 완료되는 명령이고 $2은 완료되는 명령 행의 현재 단어이고 $3은 그 행의 이전 단어입니다. 따라서 우리가 검색하고자하는 파일은 glob **/"$2"*과 일치합니다. "$2"으로 시작하는 모든 파일. 이 파일 이름을 반복하여 COMPREPLY 배열에 추가합니다. 함수가 완료 될 때 COMPREPLY 배열에 하나의 값만 포함되어 있으면 해당 값으로 바뀝니다. 둘 이상의 값이 포함 된 경우 다른 탭을 탭하여 모든 일치 항목의 목록을 가져옵니다.

shopt -s globstar 
_git_add_complete() { 
    local file 
    isgit || return 
    for file in **/"$2"*; do 
     # If the glob doesn't match, we'll get the glob itself, so make sure 
     # we have an existing file 
     [[ -e $file ]] || continue 

     # If it's a directory, add a trailing/
     [[ -d $file ]] && file+=/ 
     COMPREPLY+=("$file") 
    done 
} 
complete -F _git_add_complete gadd 

는, 새로운 터미널을 열고, 당신의 ~/.bashrc에 위의 세 가지 코드 블록을 추가 자식 저장소를 입력하고 gadd something<tab>을 시도합니다.

+0

문제는 repo 내부에서 모든 종류의 명령, 편집기, ls, git 등을 사용하고 싶습니다. – chx

+0

@chx 그런 다음 모든 명령에 해당 함수를 사용하거나 기본 완료로 설정하십시오. 기본 완료는 이미 정의 된 완료가없는 모든 명령에 적용되므로, 예를 들어 bash-completion 패키지를 사용하는 경우에는 작동하지 않습니다. 기본 완료 설정하기 :'complete -F _git_add_complete -o default -o bashdefault -D' 함수의 이름을 좀 더 맞추기 바란다. – geirha

+0

이렇게 bash-completion이 사용될 때 이것을 할 수있는 깨끗한 방법이 없습니까? – chx