11#! /usr/bin/env bash
22
3- # Load bash-completion if not loaded
4- # [ -f /usr/share/bash-completion/bash_completion ] && \
5- # . /usr/share/bash-completion/bash_completion
3+ # Anthon Open Source Community
4+ # Pinyin Completion Hook for Bash-Completion
65
76# Detect bash-completion
8- if ! declare -F _comp_compgen_filedir & > /dev/null; then
9- echo " No function _comp_compgen_filedir found. Please install bash-completion first."
7+ if ! declare -F _comp_compgen__call_builtin & > /dev/null; then
8+ echo " No function _comp_compgen__call_builtin found. Please install bash-completion first."
109 exit 1
1110fi
1211
13- eval " function __bak_comp_compgen_filedir() { $( declare -f _comp_compgen_filedir | tail -n +2) }"
14- eval " function __bak_comp_compgen_filedir_xspec() { $( declare -f _comp_compgen_filedir_xspec | tail -n +2) }"
15- eval " function __bak_comp_complete_minimal() { $( declare -f _comp_complete_minimal | tail -n +2) }"
16- eval " function __bak_comp_expand_glob() { $( declare -f _comp_expand_glob | tail -n +2) }"
17-
18- # replace _comp_compgen_filedir
19- _comp_compgen_filedir () {
20- __bak_comp_compgen_filedir " $@ "
21- _pinyin_completion " $@ "
22- }
23-
24- _comp_compgen_filedir_xspec () {
25- __bak_comp_compgen_filedir_xspec " $@ "
26- _pinyin_completion " $@ "
27- }
28-
29- _comp_complete_minimal () {
30- __bak_comp_complete_minimal " $@ "
31- _pinyin_completion " $@ "
32- }
33-
34- _comp_expand_glob () {
35- __bak_comp_expand_glob " $@ "
36- _pinyin_completion " $@ "
12+ # Backup the original function
13+ eval " function __bak_comp_compgen__call_builtin() { $( declare -f _comp_compgen__call_builtin | tail -n +2) }"
14+
15+
16+ _comp_compgen__call_builtin () {
17+ __bak_comp_compgen__call_builtin " $@ "
18+ local original_result=$?
19+
20+ # Only add pinyin completion for file/directory completions
21+ local is_file_completion=false
22+ local compgen_args=(" $@ " )
23+
24+ # Check for file completion indicators
25+ for arg in " ${compgen_args[@]} " ; do
26+ case " $arg " in
27+ -f|-d|-A|file|directory)
28+ is_file_completion=true
29+ break
30+ ;;
31+ esac
32+ done
33+
34+ # If this looks like file completion, add pinyin matches
35+ if [[ " $is_file_completion " == true ]]; then
36+ _add_completion " $@ "
37+ fi
38+
39+ return $original_result
3740}
3841
39- _pinyin_completion () {
40- # Check COMP_WORDS existence
41- if [ ${# COMP_WORDS[@]} -eq 0 ] || [ -z " ${COMP_CWORD+x} " ]; then
42+ # Function to add completion results
43+ _add_completion () {
44+ # Check if we have the necessary variables
45+ if [[ -z " ${_cur-} " ]] || [[ -z " ${_var-} " ]]; then
4246 return
4347 fi
44-
45- local cur=" ${COMP_WORDS[COMP_CWORD]} "
46-
47- # Detect "~/"
48- local homeStart
49- if [ " ${cur: 0: 2} " = " ~/" ]; then
50- homeStart=true
51- else
52- homeStart=false
53- fi
54-
55- # ignore empty
56- [ -z " $cur " ] && return
57-
58- _expand || return 0
59-
48+
49+ local cur=" $_cur "
50+ local var_name=" $_var "
51+
52+ # Skip empty
53+ [[ -z " $cur " ]] && return
54+ _expand || return 0
55+
56+ local dirpart basepart
6057 if [[ " ${cur: 0: 1} " == " '" || " ${cur: 0: 1} " == " \" " ]]; then
61- local dirpart=" $( dirname -- " ${cur: 1} " ) "
62- local basepart=" $( basename -- " ${cur: 1} " ) "
58+ dirpart=" $( dirname -- " ${cur: 1} " ) "
59+ basepart=" $( basename -- " ${cur: 1} " ) "
6360 else
64- local dirpart=" $( dirname -- " $cur " ) "
65- local basepart=" $( basename -- " $cur " ) "
61+ dirpart=" $( dirname -- " $cur " ) "
62+ basepart=" $( basename -- " $cur " ) "
6663 fi
67-
68- # realpath resolve current path as ".", if user did not enter "./" then ignore.
64+
6965 [[ " $dirpart " == " ." && " ${cur: 0: 2} " != " ./" ]] && dirpart=" "
70-
66+
7167 local savedPWD=" $PWD "
7268 local resolved_dir
7369 local compgen_opts=(-f)
74- [[ " ${1-} " == -d ]] && compgen_opts=(-d)
75-
70+
71+ local is_dir_only=false
72+ for arg in " $@ " ; do
73+ if [[ " $arg " == " -d" ]]; then
74+ is_dir_only=true
75+ compgen_opts=(-d)
76+ break
77+ fi
78+ done
79+
7680 if [[ -n " $dirpart " ]]; then
7781 resolved_dir=" $( realpath -- " $dirpart " 2> /dev/null) "
7882 if [[ -d " $resolved_dir " ]]; then
@@ -82,60 +86,50 @@ _pinyin_completion() {
8286 return
8387 fi
8488 fi
85-
89+
8690 local -a pinyin_matched
87- if [[ " ${compgen_opts[0]} " == -d ]]; then
91+ if [[ " $is_dir_only " == true ]]; then
8892 mapfile -t pinyin_matched < <(
89- compgen -d -- |
93+ compgen -d -- 2> /dev/null |
9094 bash-pinyin-completion-rs " $basepart " 2> /dev/null
91- )
95+ )
9296 else
9397 mapfile -t pinyin_matched < <(
94- compgen -f -- |
98+ compgen -f -- 2> /dev/null |
9599 bash-pinyin-completion-rs " $basepart " 2> /dev/null
96100 )
97- if [ ${# pinyin_matched[@]} -ne 0 ]; then
98- compopt -o filenames 2> /dev/null
99- fi
100- fi
101-
102- if [[ -n " $dirpart " ]]; then
103- local sep=" /"
104- # dirpart is root
105- if [[ " $dirpart " == " /" ]]; then
106- sep=" "
107- fi
108-
109- for i in " ${! pinyin_matched[@]} " ; do
110- pinyin_matched[$i ]=" ${dirpart}${sep}${pinyin_matched[$i]} "
111- done
112101 fi
113-
102+
103+ # Restore directory
114104 cd " $savedPWD " || return
115-
116- # merge result
117- local -a old_candidates=(" ${COMPREPLY[@]} " )
118- COMPREPLY=(" ${old_candidates[@]} " " ${pinyin_matched[@]} " )
119-
120- # mapfile -t COMPREPLY < <(printf "%s\n" "${COMPREPLY[@]}" | awk '!seen[$0]++')
121- declare -A seen
122- local -a unique_compreply=()
123- for item in " ${COMPREPLY[@]} " ; do
124- if [[ -z " ${seen[$item]} " ]]; then
125- seen[" $item " ]=1
126- unique_compreply+=( " $item " )
105+
106+ if [[ ${# pinyin_matched[@]} -gt 0 ]]; then
107+ if [[ -n " $dirpart " ]]; then
108+ local sep=" /"
109+ [[ " $dirpart " == " /" ]] && sep=" "
110+
111+ for i in " ${! pinyin_matched[@]} " ; do
112+ pinyin_matched[$i ]=" ${dirpart}${sep}${pinyin_matched[$i]} "
113+ done
127114 fi
128- done
129- COMPREPLY=( " ${unique_compreply[@]} " )
130-
131- if [[ " $homeStart " == true ]]; then
132- local home=" $HOME "
133- for i in " ${! COMPREPLY[@]} " ; do
134- case " ${COMPREPLY[$i]} " in
135- " $home " /* )
136- COMPREPLY[$i ]=" ~${COMPREPLY[$i]# " $home " } "
137- ;;
138- esac
115+
116+
117+ local current_results_var=" current_results"
118+ eval " local -a $current_results_var =(\"\$ {$var_name [@]}\" )"
119+
120+ # Merge results and remove duplicates
121+ local -a all_results
122+ eval " all_results=(\"\$ {$current_results_var [@]}\" \"\$ {pinyin_matched[@]}\" )"
123+
124+ declare -A seen
125+ local -a unique_results=()
126+ for item in " ${all_results[@]} " ; do
127+ if [[ -z " ${seen[$item]} " ]]; then
128+ seen[" $item " ]=1
129+ unique_results+=(" $item " )
130+ fi
139131 done
132+
133+ eval " $var_name =(\"\$ {unique_results[@]}\" )"
140134 fi
141135}
0 commit comments