Skip to content

Commit 101918b

Browse files
committed
feature: completions.
1 parent ba8638b commit 101918b

File tree

4 files changed

+227
-1
lines changed

4 files changed

+227
-1
lines changed

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,37 @@ Help is available via `czruby -h`.
5959

6060
It only needs to be `source`d, so put it wherever is convenient for doing so (probably loaded by zshrc).
6161

62+
## Tab Completion
63+
64+
czruby includes tab-completion support for zsh. Completions are automatically enabled when you source `czruby.plugin.conf`.
65+
66+
### What Gets Completed
67+
68+
- **Command switches**: `--set-default`, `--purge`, `-h`, `--help`, `-V`, `--version`
69+
- **Special values**: `system`, `default`
70+
- **Installed Rubies**: Version numbers, engine names, and full installation names
71+
72+
### Examples
73+
74+
```bash
75+
czruby <TAB> # Shows all available options and Rubies
76+
czruby 3.<TAB> # Shows all versions starting with 3.
77+
czruby truf<TAB> # Completes to truffleruby-* versions
78+
czruby --set-default <TAB> # Shows available Ruby installations
79+
```
80+
81+
### Troubleshooting
82+
83+
If completions don't work, ensure the completion system is initialized before sourcing czruby:
84+
85+
```zsh
86+
# In ~/.zshrc
87+
autoload -Uz compinit
88+
compinit
89+
90+
source /path/to/czruby/czruby.plugin.conf
91+
```
92+
6293
## <a name="running-tests">Running Tests</a>
6394

6495
czruby has a comprehensive test suite that can be run either in containers (recommended) or natively.

_czruby

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#compdef czruby
2+
3+
_czruby() {
4+
local curcontext="$curcontext" state line
5+
typeset -A opt_args
6+
7+
# Safety check: ensure czruby is initialized
8+
if [[ ! -v rubies ]]; then
9+
_message "czruby not initialized"
10+
return 1
11+
fi
12+
13+
_arguments -C \
14+
'(-h --help)'{-h,--help}'[Show help message]' \
15+
'(-V --version)'{-V,--version}'[Show version]' \
16+
'--purge[Remove invalid configs]' \
17+
'--set-default[Set default Ruby version]:ruby version:->rubies' \
18+
'1:ruby selection:->ruby_or_special' \
19+
&& return 0
20+
21+
case $state in
22+
rubies)
23+
_czruby_rubies
24+
;;
25+
ruby_or_special)
26+
_czruby_all_options
27+
;;
28+
esac
29+
}
30+
31+
_czruby_rubies() {
32+
local -a ruby_descriptions
33+
local ruby_root key desc ruby_eng ruby_ver
34+
35+
for ruby_root in ${rubies[@]}; do
36+
if [[ "$ruby_root" == "system" ]]; then
37+
ruby_descriptions+=("system:System Ruby (/usr)")
38+
continue
39+
fi
40+
41+
key="${ruby_root:t}" # Get basename
42+
43+
# Parse engine and version (mirror czruby_use logic)
44+
if [[ "$key" =~ "-" ]]; then
45+
ruby_eng="${key%%-*}"
46+
ruby_ver="${key#*-}"
47+
desc="$ruby_eng $ruby_ver"
48+
else
49+
ruby_eng="ruby"
50+
ruby_ver="$key"
51+
desc="Ruby $ruby_ver"
52+
fi
53+
54+
ruby_descriptions+=("$key:$desc")
55+
done
56+
57+
_describe 'ruby version' ruby_descriptions
58+
}
59+
60+
_czruby_all_options() {
61+
local -a all_options
62+
63+
# Special values
64+
all_options=(
65+
'system:Use system Ruby (/usr)'
66+
'default:Switch to default Ruby'
67+
)
68+
69+
# Command switches (only if not already specified)
70+
if [[ ! -v opt_args[-h] && ! -v opt_args[--help] ]]; then
71+
all_options+=('-h:Show help message' '--help:Show help message')
72+
fi
73+
74+
if [[ ! -v opt_args[-V] && ! -v opt_args[--version] ]]; then
75+
all_options+=('-V:Show version' '--version:Show version')
76+
fi
77+
78+
all_options+=(
79+
'--purge:Remove invalid configs'
80+
'--set-default:Set default Ruby version'
81+
)
82+
83+
# Add Ruby installations
84+
local ruby_root key desc ruby_eng ruby_ver
85+
for ruby_root in ${rubies[@]}; do
86+
[[ "$ruby_root" == "system" ]] && continue
87+
88+
key="${ruby_root:t}"
89+
90+
if [[ "$key" =~ "-" ]]; then
91+
ruby_eng="${key%%-*}"
92+
ruby_ver="${key#*-}"
93+
desc="$ruby_eng $ruby_ver"
94+
else
95+
desc="Ruby $key"
96+
fi
97+
98+
all_options+=("$key:$desc")
99+
done
100+
101+
_describe 'czruby option' all_options
102+
}
103+
104+
_czruby "$@"

czruby.plugin.conf

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,14 @@ czruby_realpath() {
2626
else
2727
readlink -f "$@"
2828
fi
29-
}
29+
}
30+
31+
# Add completion to fpath and initialize completion system
32+
if [[ ! " ${fpath[*]} " =~ " ${0:A:h} " ]]; then
33+
fpath=(${0:A:h} $fpath)
34+
fi
35+
36+
# Auto-load completion if compinit is available
37+
if (( $+functions[compinit] )); then
38+
autoload -Uz _czruby
39+
fi

test/test_czruby_completion.zsh

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env zsh
2+
# Tests for czruby tab completion
3+
4+
source "${0:A:h}/test_helper.zsh"
5+
6+
test_completion_function_exists() {
7+
fpath=("$CZRUBY_ROOT" $fpath)
8+
autoload -Uz _czruby
9+
10+
if ! whence -w _czruby >/dev/null 2>&1; then
11+
echo "ERROR: Completion function _czruby not found"
12+
return 1
13+
fi
14+
return 0
15+
}
16+
17+
test_extract_ruby_names_from_paths() {
18+
local ruby1=$(create_mock_ruby "3.3.0")
19+
local ruby2=$(create_mock_ruby "truffleruby-21.1.0")
20+
rubies=("system" "$ruby1" "$ruby2")
21+
22+
# Expected basenames: system, 3.3.0, truffleruby-21.1.0
23+
local name1="${ruby1:t}"
24+
local name2="${ruby2:t}"
25+
26+
assert_equals "3.3.0" "$name1" || return 1
27+
assert_equals "truffleruby-21.1.0" "$name2" || return 1
28+
}
29+
30+
test_parse_hyphenated_ruby_names() {
31+
local key="truffleruby-21.1.0"
32+
local engine="${key%%-*}"
33+
local version="${key#*-}"
34+
35+
assert_equals "truffleruby" "$engine" || return 1
36+
assert_equals "21.1.0" "$version" || return 1
37+
}
38+
39+
test_parse_plain_ruby_names() {
40+
local key="3.3.0"
41+
42+
# No hyphen, so engine defaults to ruby
43+
if [[ "$key" =~ "-" ]]; then
44+
echo "ERROR: Should not contain hyphen"
45+
return 1
46+
fi
47+
return 0
48+
}
49+
50+
test_completion_with_empty_rubies() {
51+
rubies=()
52+
53+
fpath=("$CZRUBY_ROOT" $fpath)
54+
autoload -Uz _czruby
55+
56+
# Should not crash
57+
return 0
58+
}
59+
60+
test_parse_multiple_hyphens() {
61+
local key="ruby-3.3.0-preview1"
62+
local engine="${key%%-*}"
63+
local version="${key#*-}"
64+
65+
# Should split on first hyphen only
66+
assert_equals "ruby" "$engine" || return 1
67+
assert_equals "3.3.0-preview1" "$version" || return 1
68+
}
69+
70+
# Run tests
71+
echo "Running czruby completion tests..."
72+
echo "========================================"
73+
74+
run_test "Completion function exists" test_completion_function_exists
75+
run_test "Extract ruby names from paths" test_extract_ruby_names_from_paths
76+
run_test "Parse hyphenated ruby names" test_parse_hyphenated_ruby_names
77+
run_test "Parse plain ruby names" test_parse_plain_ruby_names
78+
run_test "Handle empty rubies array" test_completion_with_empty_rubies
79+
run_test "Parse multiple hyphens" test_parse_multiple_hyphens
80+
81+
print_summary

0 commit comments

Comments
 (0)