Diff
1diff --git a/.github/dependencies.yml b/.github/dependencies.yml
2index 4a3c89eb71ef262f113b936a39d3eca0a4c1e6b1..124c78eba0ef2f7dab86d63fb87cbc34362f8bd0 100644
3--- a/.github/dependencies.yml
4+++ b/.github/dependencies.yml
5@@ -46,7 +46,7 @@ dependencies:
6 plugins/z:
7 branch: master
8 repo: agkozak/zsh-z
9- version: 519e5796df3db6c68317c7a3901444fab3241bbc
10+ version: acd0e1984df350c189f8f9c4956ec586b6c73fca
11 precopy: |
12 set -e
13 test -e README.md && mv -f README.md MANUAL.md
14diff --git a/plugins/z/MANUAL.md b/plugins/z/MANUAL.md
15index 790d4d389289604c5d7ce23bcfef2abf682cd424..420535b275323683ed8f4655df5b38d1f1095552 100644
16--- a/plugins/z/MANUAL.md
17+++ b/plugins/z/MANUAL.md
18@@ -33,11 +33,13 @@ Zsh-z is a drop-in replacement for `rupa/z` and will, by default, use the same d
19 <details>
20 <summary>Here are the latest features and updates.</summary>
21
22+- May 1, 2026
23+ + Various tab completion bugs resolved.
24 - April 27, 2026
25- + Fixes a bug where re-sourcing the script caused an infinite loop when Tab was pressed. Props to @maheshpec for [successfully diagnosing the problem](https://github.com/ohmyzsh/ohmyzsh/pull/13715).
26- + Fixes a bug where the completion widget was not identifying flags correctly.
27+ + Fixes a bug where re-sourcing the script caused an infinite loop when tab was pressed. Props to @maheshpec for [successfully diagnosing the problem](https://github.com/ohmyzsh/ohmyzsh/pull/13715).
28+ + Fixes a bug where the completion widget was not identifying options correctly.
29 - March 31, 2026
30- + When the user hits Tab after entering a command-line argument that uses spaces as wildcards (e.g., `z us lo bi`), the command line is clear of detritus (i.e., it looks like `z /usr/local/bin` instead of `z us lo /usr/local/bin`).
31+ + When the user hits tab after entering a command-line argument that uses spaces as wildcards (e.g., `z us lo bi`), the command line is clear of detritus (i.e., it looks like `z /usr/local/bin` instead of `z us lo /usr/local/bin`).
32 + Improved test for Docker containers.
33 - August 24, 2023
34 + Zsh-z will now run when `setopt NO_UNSET` has been enabled (props @ntninja).
35diff --git a/plugins/z/z.plugin.zsh b/plugins/z/z.plugin.zsh
36index e1a9bd076e90ee23e50a17cf8fb47faf17ddac0f..6df49822e24cd4ca876637408f7bd3d5cf3d31bd 100644
37--- a/plugins/z/z.plugin.zsh
38+++ b/plugins/z/z.plugin.zsh
39@@ -96,7 +96,7 @@ With no ARGUMENT, list the directory history in ascending rank.
40 -t Match by recent access
41 -x Remove a directory from the database (by default, the current directory)
42 -xR Remove a directory and its subdirectories from the database (by default, the current directory)" |
43- fold -s -w $COLUMNS >&2
44+ fold -s -w $(( COLUMNS > 0 ? COLUMNS : 80 )) >&2
45 }
46
47 # Load zsh/datetime module, if necessary
48@@ -251,7 +251,7 @@ zshz() {
49 if (( ${ZSHZ_NO_RESOLVE_SYMLINKS:-${_Z_NO_RESOLVE_SYMLINKS}} )); then
50 [[ -d ${${*:-${PWD}}:a} ]] && xdir=${${*:-${PWD}}:a}
51 else
52- [[ -d ${${*:-${PWD}}:A} ]] && xdir=${${*:-${PWD}}:a}
53+ [[ -d ${${*:-${PWD}}:A} ]] && xdir=${${*:-${PWD}}:A}
54 fi
55
56 local -a lines_to_keep
57@@ -741,6 +741,9 @@ zshz() {
58 for opt in ${(k)opts}; do
59 case $opt in
60 --add)
61+ # Don't change the database when invoked via --complete (e.g., from
62+ # tab completion).
63+ (( ${+opts[--complete]} )) && continue
64 [[ ! -d $* ]] && return 1
65 local dir
66 # Cygwin and MSYS2 have a hard time with relative paths expressed from /
67@@ -764,6 +767,7 @@ zshz() {
68 ;;
69 -c) [[ $* == ${PWD}/* || $PWD == '/' ]] || prefix="$PWD " ;;
70 -h|--help)
71+ (( ${+opts[--complete]} )) && continue
72 _zshz_usage
73 return
74 ;;
75@@ -771,6 +775,7 @@ zshz() {
76 -r) method='rank' ;;
77 -t) method='time' ;;
78 -x)
79+ (( ${+opts[--complete]} )) && continue
80 # Cygwin and MSYS2 have a hard time with relative paths expressed from /
81 if [[ $OSTYPE == (cygwin|msys) && $PWD == '/' && $* != /* ]]; then
82 set -- "/$*"
83@@ -844,7 +849,8 @@ zshz() {
84
85 # New experimental "uncommon" behavior
86 #
87- # If the best choice at this point is something like /foo/bar/foo/bar, and the # search pattern is `bar', go to /foo/bar/foo/bar; but if the search pattern
88+ # If the best choice at this point is something like /foo/bar/foo/bar, and the
89+ # search pattern is `bar', go to /foo/bar/foo/bar; but if the search pattern
90 # is `foo', go to /foo/bar/foo
91 if (( ZSHZ_UNCOMMON )) && [[ -n $cd ]]; then
92 if [[ -n $cd ]]; then
93@@ -996,21 +1002,24 @@ _zshz_zle_completion_widget() {
94 # Only act when there are at least two words after the command
95 if [[ $LBUFFER == ${cmd}\ *\ * ]]; then
96 local after=${LBUFFER#${cmd} }
97- local -a parts flag_parts search_parts
98- local p past_flags=0
99+ local -a parts option_parts search_parts
100+ local p past_options=0
101
102 parts=( ${(z)after} )
103 for p in $parts; do
104- if (( ! past_flags )) && [[ $p == (-[cehlrRtx]##|--add|--complete|--help) ]]; then
105- flag_parts+=( $p )
106+ if (( ! past_options )) && [[ $p == (--|-[cehlrRtx]##|--add|--complete|--help) ]]; then
107+ option_parts+=( $p )
108+ # `--' terminates option parsing; subsequent tokens are positional,
109+ # even if they happen to look like options.
110+ [[ $p == -- ]] && past_options=1
111 else
112- past_flags=1
113+ past_options=1
114 search_parts+=( $p )
115 fi
116 done
117
118 if (( ${#search_parts} > 1 )); then
119- LBUFFER="${cmd}${flag_parts:+ ${(j: :)flag_parts}} ${(j:*:)search_parts}"
120+ LBUFFER="${cmd}${option_parts:+ ${(j: :)option_parts}} ${(j:*:)search_parts}"
121 fi
122 fi
123