예를 들어 bash에서 git 명령 다음에 파일 경로를 완성하려면 탭을 누를 때마다 파일에 있는 하위 폴더 수에 따라 실제 파일 이름을 완성하기 위해 여러 번 git add
눌러야 합니다 .<TAB>
예: 파일을 추가 my/example/file
하고 다음을 입력하고 싶습니다.
git add <TAB>
git add my/<TAB>
git add my/example/<TAB>
git add my/example/file
my/example/file
이는 변경된 유일한 파일의 경우에도 마찬가지이므로 현재 사용할 수 있는 유일한 탭 완성 옵션입니다. 이 경우 bash는 첫 번째 path 로 전체 경로를 완료할 수도 있지만 <TAB>
그렇지 않습니다.
물고기이는 실제로 기본적으로 수행됩니다.
git add <TAB>
git add my/example/file
Bash에서 이 동작을 구성하는 방법이 있습니까?
저는 기본 bash 완성을 사용하여 Ubuntu 20.04를 사용하고 있습니다.
답변1
이를 달성하는 한 가지 방법은 git 완성 스크립트를 복사하고
/usr/share/bash-completion/completions/git
전체
~/.local/share/bash-completion/completions/
인덱스 경로 완성을 사용하도록 수정하는 것입니다.
mkdir -p ~/.local/share/bash-completion/completions
cd ~/.local/share/bash-completion/completions
cp /usr/share/bash-completion/completions/git .
# See diff below
patch -lp0 </tmp/index_paths.diff
echo GIT_COMPLETION_FULL_INDEX_PATHS=1 >>~/.bashrc
exec bash
내가 아는 한, 필요한 변경 사항은 다음과 같습니다.
__git_index_files()
첫 번째 경로 구성 요소뿐만 아니라 전체 인덱스 경로를 출력하도록 수정하세요 .에서는 set을 사용하므로 기본 이름만 출력하므로
__git_complete_index_file()
사용을 중지합니다 . 이 옵션은 쉘 인용도 처리하므로 지금은 수동으로 수행하십시오.__gitcomp_file_direct
COMPREPLY
compopt -o filenames
__git_complete_index_file
, , 및 이외의 다른 여러 git 명령을 완료하는 데 사용되므로 add
전체 경로 완성 clean
은 해당 명령에서도 작동합니다. 쉘 변수 뒤에 기능을 추가하는 이러한 변경 시도의 차이점은 다음과 같습니다 .commit
rm
GIT_COMPLETION_FULL_INDEX_PATHS
--- git
+++ git
@@ -39,6 +39,11 @@
# When set to "1", do not include "DWIM" suggestions in git-checkout
# and git-switch completion (e.g., completing "foo" when "origin/foo"
# exists).
+#
+# GIT_COMPLETION_FULL_INDEX_PATHS
+#
+# Normally index path completions return only the next path component. When
+# set to "1", the whole path will be completed.
case "$COMP_WORDBREAKS" in
*:*) : great ;;
@@ -435,6 +440,19 @@
__gitcomp_nl_append "$@"
}
+# Shell quotes each word and fills the COMPREPLY array.
+# 1: List of newline-separated completion words.
+__gitcomp_quote_direct ()
+{
+ local IFS=$'\n'
+ local quoted="$1"
+ [[ -n $1 ]] && quoted=$(printf '%q\n' $1)
+
+ COMPREPLY=($quoted)
+
+ compopt +o nospace 2>/dev/null || true
+}
+
# Fills the COMPREPLY array with prefiltered paths without any additional
# processing.
# Callers must take care of providing only paths that match the current path
@@ -503,10 +521,12 @@
__git_index_files ()
{
local root="$2" match="$3"
+ local field=1
+ [ "$GIT_COMPLETION_FULL_INDEX_PATHS" = "1" ] && field=0
__git_ls_files_helper "$root" "$1" "$match" |
awk -F / -v pfx="${2//\\/\\\\}" '{
- paths[$1] = 1
+ paths[$f] = 1
}
END {
for (p in paths) {
@@ -518,19 +538,13 @@
# The path is quoted.
p = dequote(p)
- if (p == "")
- continue
- # Even when a directory name itself does not contain
- # any special characters, it will still be quoted if
- # any of its (stripped) trailing path components do.
- # Because of this we may have seen the same directory
- # both quoted and unquoted.
- if (p in paths)
- # We have seen the same directory unquoted,
- # skip it.
- continue
- else
+ # When not using full index paths, p in paths is checked
+ # because the dequoted directory name may already be in
+ # paths. This is the case when the directory name itself
+ # does not contain special characters, but a (stripped)
+ # trailing path component does.
+ if (p != "" && (f == 0 || !(p in paths)))
print pfx p
}
}
@@ -573,7 +587,7 @@
out = out p
return out
- }'
+ }' "f=$field"
}
# __git_complete_index_file requires 1 argument:
@@ -595,7 +609,11 @@
cur_="$dequoted_word"
esac
- __gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")"
+ if [ "$GIT_COMPLETION_FULL_INDEX_PATHS" = "1" ]; then
+ __gitcomp_quote_direct "$(__git_index_files "$1" "$pfx" "$cur_")"
+ else
+ __gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")"
+ fi
}
# Lists branches from the local repository.