Skip to content

ENH: Support quotes and bug fix #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ Ensure that `bash-completion` and rust toolchains(cargo, etc.) are installed cor
bash scripts/install_completion.sh
```

And add these to your `.bashrc` file:
```bash
bind 'set show-all-if-ambiguous on'
bind 'TAB:menu-complete'
For better experience, add these to your inputrc (/etc/inputrc, ~/.inputrc):
```
set show-all-if-ambiguous on
set menu-complete-display-prefix on
TAB: menu-complete
set colored-completion-prefix on
set colored-stats on
"\e[Z": menu-complete-backward
```

## Requirements
Expand Down
13 changes: 10 additions & 3 deletions scripts/bash_pinyin_completion
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,18 @@ _pinyin_completion() {
# ignore empty
[ -z "$cur" ] && return

_expand || return 0

local dirpart="$(dirname -- "$cur")"
local basepart="$(basename -- "$cur")"
if [[ "${cur:0:1}" == "'" || "${cur:0:1}" == "\"" ]]; then
local dirpart="$(dirname -- "${cur:1}")"
local basepart="$(basename -- "${cur:1}")"
else
local dirpart="$(dirname -- "$cur")"
local basepart="$(basename -- "$cur")"
fi

[[ "$dirpart" == "." && "$cur" != */* ]] && dirpart=""
# realpath resolve current path as ".", if user did not enter "./" then ignore.
[[ "$dirpart" == "." && "${cur:0:2}" != "./" ]] && dirpart=""

local savedPWD="$PWD"
local resolved_dir
Expand Down
50 changes: 30 additions & 20 deletions scripts/bash_pinyin_completion_debug
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ debug() {
}
debug "Debug Session:"

# Load bash-completion if not loaded
# [ -f /usr/share/bash-completion/bash_completion ] && \
# . /usr/share/bash-completion/bash_completion

# Detect bash-completion
if ! declare -F _comp_compgen_filedir &>/dev/null; then
echo "No function _comp_compgen_filedir found. Please install bash-completion first."
Expand All @@ -24,32 +20,36 @@ eval "function __bak_comp_compgen_filedir_xspec() { $(declare -f _comp_compgen_f

# replace _comp_compgen_filedir
_comp_compgen_filedir() {
debug "Pre _comp_compgen_filedir: $*"
__bak_comp_compgen_filedir "$@"
debug "Original COMPREPLY: ${COMPREPLY[*]}"
_pinyin_completion "$@"
debug "Post COMPREPLY: ${COMPREPLY[*]}"
}

_comp_compgen_filedir_xspec() {
debug "Pre _comp_compgen_filedir: $*"
__bak_comp_compgen_filedir_xspec "$@"
debug "Original COMPREPLY: ${COMPREPLY[*]}"
_pinyin_completion "$@"
debug "Post COMPREPLY: ${COMPREPLY[*]}"
}

_pinyin_completion() {
local cur="${COMP_WORDS[COMP_CWORD]}"

# ignore empty
[ -z "$cur" ] && return

_expand || return 0

local dirpart="$(dirname -- "$cur")"
local basepart="$(basename -- "$cur")"
if [[ "${cur:0:1}" == "'" || "${cur:0:1}" == "\"" ]]; then
local dirpart="$(dirname -- "${cur:1}")"
local basepart="$(basename -- "${cur:1}")"
else
local dirpart="$(dirname -- "$cur")"
local basepart="$(basename -- "$cur")"
fi

[[ "$dirpart" == "." && "$cur" != */* ]] && dirpart=""
debug "After extracting: dirpart='$dirpart', basepart='$basepart', cur='$cur'"

# realpath resolve current path as ".", if user did not enter "./" then ignore.
[[ "$dirpart" == "." && "${cur:0:2}" != "./" ]] && dirpart=""
debug "Adjusted dirpart: '$dirpart'"

local savedPWD="$PWD"
local resolved_dir
Expand All @@ -58,6 +58,7 @@ _pinyin_completion() {

if [[ -n "$dirpart" ]]; then
resolved_dir="$(realpath -- "$dirpart" 2>/dev/null)"
debug "resolved_dir: '$resolved_dir'"
if [[ -d "$resolved_dir" ]]; then
cd -- "$resolved_dir" 2>/dev/null || return
else
Expand All @@ -83,8 +84,11 @@ _pinyin_completion() {
fi
done | bash-pinyin-completion-rs "$basepart" 2>/dev/null
)
if [ ${#pinyin_matched[@]} -ne 0 ]; then
compopt -o filenames 2>/dev/null
fi
fi

debug "Before join, pinyin_matched: $(declare -p pinyin_matched)"
if [[ -n "$dirpart" ]]; then
local sep="/"
# dirpart is root
Expand All @@ -93,16 +97,20 @@ _pinyin_completion() {
fi

for i in "${!pinyin_matched[@]}"; do
debug "Before join: pinyin_matched[$i]='${pinyin_matched[$i]}'"
pinyin_matched[$i]="${dirpart}${sep}${pinyin_matched[$i]}"
debug "After join: pinyin_matched[$i]='${pinyin_matched[$i]}'"
done
fi

cd "$savedPWD" || return

# merge result
debug "Final COMPREPLY before merge: $(declare -p COMPREPLY)"
local -a old_candidates=("${COMPREPLY[@]}")
COMPREPLY=("${old_candidates[@]}" "${pinyin_matched[@]}")
debug "Final COMPREPLY after merge: $(declare -p COMPREPLY)"

debug "Final COMPREPLY before deduplication: $(declare -p COMPREPLY)"
# mapfile -t COMPREPLY < <(printf "%s\n" "${COMPREPLY[@]}" | awk '!seen[$0]++')
declare -A seen
local -a unique_compreply=()
Expand All @@ -113,9 +121,11 @@ _pinyin_completion() {
fi
done
COMPREPLY=( "${unique_compreply[@]}" )
debug "Final COMPREPLY after deduplication: $(declare -p COMPREPLY)"


# fix space postfix
if ((${#COMPREPLY[@]} == 1)) && [[ ${COMPREPLY[0]} != */ ]]; then
compopt -o nospace 2>/dev/null
fi
# # fix space postfix
# if ((${#COMPREPLY[@]} == 1)) && [[ ${COMPREPLY[0]} != */ ]]; then
# compopt -o nospace 2>/dev/null
# fi
}
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ fn main() {
eprintln!("Usage: {} <pinyin>", args[0]);
std::process::exit(1);
}
let han_re = regex::Regex::new(r"\p{Han}").unwrap();

let input: &str = &args[1];
if han_re.is_match(input) {return};
let matcher = PinyinMatcher::builder(input)
.pinyin_notations(PinyinNotation::Ascii | PinyinNotation::AsciiFirstLetter)
.build();

let han_re = regex::Regex::new(r"\p{Han}").unwrap();

let stdin = std::io::stdin();
let reader = BufReader::new(stdin.lock());
for line_result in reader.lines() {
Expand Down