diff --git a/.github/dependencies.yml b/.github/dependencies.yml index ff239c657..7794e3346 100644 --- a/.github/dependencies.yml +++ b/.github/dependencies.yml @@ -46,7 +46,7 @@ dependencies: plugins/z: branch: master repo: agkozak/zsh-z - version: cf9225feebfae55e557e103e95ce20eca5eff270 + version: ae10ba3f4674c24ac353fd34deb2fd9f7b061055 precopy: | set -e test -e README.md && mv -f README.md MANUAL.md diff --git a/plugins/z/LICENSE b/plugins/z/LICENSE index b36aeb408..8befb303b 100644 --- a/plugins/z/LICENSE +++ b/plugins/z/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2025 Alexandros Kozak +Copyright (c) 2018-2026 Alexandros Kozak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/plugins/z/MANUAL.md b/plugins/z/MANUAL.md index eddf787dd..9984d3b1f 100644 --- a/plugins/z/MANUAL.md +++ b/plugins/z/MANUAL.md @@ -24,16 +24,18 @@ Zsh-z is a drop-in replacement for `rupa/z` and will, by default, use the same d - [Case Sensitivity](#case-sensitivity) - [`ZSHZ_UNCOMMON`](#zshz_uncommon) - [Making `--add` work for you](#making---add-work-for-you) -- [Other Improvements and Fixes](#other-improvements-and-fixes) +- [Other Improvements to the Original Functionality of `rupa/z`](#other-improvements-to-the-original-functionality-of-rupa-z) - [Migrating from Other Tools](#migrating-from-other-tools) - [`COMPLETE_ALIASES`](#complete_aliases) -- [Known Bugs](#known-bugs) ## News
Here are the latest features and updates. +- March 31, 2026 + + 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`). + + Improved test for Docker containers. - August 24, 2023 + Zsh-z will now run when `setopt NO_UNSET` has been enabled (props @ntninja). - August 23, 2023 @@ -50,7 +52,7 @@ Zsh-z is a drop-in replacement for `rupa/z` and will, by default, use the same d + A bug was fixed which was preventing paths with spaces in them from being updated ([#61](https://github.com/agkozak/zsh-z/issues/61)). + If writing to the temporary database file fails, the database will not be clobbered (props @mafredri). - December 19, 2021 - + ZSH-z will now display tildes for `HOME` during completion when `ZSHZ_TILDE=1` has been set. + + Zsh-z will now display tildes for `HOME` during completion when `ZSHZ_TILDE=1` has been set. - November 11, 2021 + A bug was fixed which was preventing ranks from being incremented. + `--add` has been made to work with relative paths and has been documented for the user. @@ -71,7 +73,7 @@ Zsh-z is a drop-in replacement for `rupa/z` and will, by default, use the same d - July 29, 2021 + Temporarily disabling the use of `print -v`, which was mangling CJK multibyte strings. - July 27, 2021 - + Internal escaping of path names now works with older versions of ZSH. + + Internal escaping of path names now works with older versions of Zsh. + Zsh-z now detects and discards any incomplete or incorrectly formatted database entries. - July 10, 2021 + Setting `ZSHZ_TRAILING_SLASH=1` makes it so that a search pattern ending in `/` can match the end of a path; e.g. `z foo/` can match `/path/to/foo`. @@ -79,12 +81,12 @@ Zsh-z is a drop-in replacement for `rupa/z` and will, by default, use the same d + Setting `ZSHZ_TILDE=1` displays the `HOME` directory as `~`. - May 7, 2021 + Setting `ZSHZ_ECHO=1` will cause Zsh-z to display the new path when you change directories. - + Better escaping of path names to deal paths containing the characters ``\`()[]``. + + Better escaping of path names to deal with paths containing the characters ``\`()[]``. - February 15, 2021 + Ranks are displayed the way `rupa/z` now displays them, i.e. as large integers. This should help Zsh-z to integrate with other tools. - January 31, 2021 + Zsh-z is now efficient enough that, on MSYS2 and Cygwin, it is faster to run it in the foreground than it is to fork a subshell for it. - + `_zshz_precmd` simply returns if `PWD` is `HOME` or in `ZSH_EXCLUDE_DIRS`, rather than waiting for `zshz` to do that. + + `_zshz_precmd` simply returns if `PWD` is `HOME` or in `ZSHZ_EXCLUDE_DIRS`, rather than waiting for `zshz` to do that. - January 17, 2021 + Made sure that the `PUSHD_IGNORE_DUPS` option is respected. - January 14, 2021 @@ -171,7 +173,7 @@ is uncommented. Then find the section that specifies which modules are to be loa 'completion' \ 'prompt' -Add a backslash to the end of the last line add `'zsh-z'` to the list, e.g., +Add a backslash to the end of the last line and add `'zsh-z'` to the list, e.g., zstyle ':prezto:load' pmodule \ 'environment' \ @@ -279,7 +281,7 @@ Zsh-z has environment variables (they all begin with `ZSHZ_`) that change its be * `ZSHZ_OWNER` allows usage when in `sudo -s` mode (default: empty) * `ZSHZ_TILDE` displays the name of the `HOME` directory as a `~` (default: `0`) * `ZSHZ_TRAILING_SLASH` makes it so that a search pattern ending in `/` can match the final element in a path; e.g., `z foo/` can match `/path/to/foo` (default: `0`) -* `ZSHZ_UNCOMMON` changes the logic used to calculate the directory jumped to; [see below](#zshz_uncommon`) (default: `0`) +* `ZSHZ_UNCOMMON` changes the logic used to calculate the directory jumped to; [see below](#zshz_uncommon) (default: `0`) ## Case sensitivity @@ -324,7 +326,7 @@ A good example might involve a directory tree that has Git repositories within i (As a Zsh user, I tend to use `**` instead of `find`, but it is good to see how deep your directory trees go before doing that.) -## Other Improvements and Fixes +## Other Improvements to the Original Functionality of `rupa/z` * `z -x` works, with the help of `chpwd_functions`. * Zsh-z is compatible with Solaris. @@ -336,6 +338,7 @@ A good example might involve a directory tree that has Git repositories within i * Completions now work with options `-c`, `-r`, and `-t`. * If `~/foo` and `~/foob` are matches, `~/foo` is no longer considered the common root. Only a common parent directory can be a common root. * `z -x` and the new, recursive `z -xR` can now accept an argument so that you can remove directories other than `PWD` from the database. +* Zsh-z inherits `rupa/z`'s behavior of allowing spaces as wildcards (e.g., `z us lo bi` might take you to `/usr/local/bin`), but now completion of such command lines does not result in visual detritus. ## Migrating from Other Tools @@ -347,7 +350,7 @@ If you are coming to Zsh-z (or even to the original `rupa/z`, for that matter) f ## `COMPLETE_ALIASES` -`z`, or any alternative you set up using `$ZSH_CMD` or `$_Z_CMD`, is an alias. `setopt COMPLETE_ALIASES` divorces the tab completion for aliases from the underlying commands they invoke, so if you enable `COMPLETE_ALIASES`, tab completion for Zsh-z will be broken. You can get it working again, however, by adding under +`z`, or any alternative you set up using `$ZSHZ_CMD` or `$_Z_CMD`, is an alias. `setopt COMPLETE_ALIASES` divorces the tab completion for aliases from the underlying commands they invoke, so if you enable `COMPLETE_ALIASES`, tab completion for Zsh-z will be broken. You can get it working again, however, by adding under setopt COMPLETE_ALIASES @@ -356,10 +359,3 @@ the line compdef _zshz ${ZSHZ_CMD:-${_Z_CMD:-z}} That will re-bind `z` or the command of your choice to the underlying Zsh-z function. - -## Known Bug -It is possible to run a completion on a string with spaces in it, e.g., `z us bi` might take you to `/usr/local/bin`. This works, but as things stand, after the completion the command line reads - - z us /usr/local/bin. - -You get where you want to go, but the detritus on the command line is annoying. This is also a problem in `rupa/z`, but I am keen on eventually eliminating this glitch. Advice is welcome. diff --git a/plugins/z/_z b/plugins/z/_z index a493f35ba..a109841d6 100644 --- a/plugins/z/_z +++ b/plugins/z/_z @@ -5,7 +5,7 @@ # # https://github.com/agkozak/zsh-z # -# Copyright (c) 2018-2023 Alexandros Kozak +# Copyright (c) 2018-2026 Alexandros Kozak # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -37,25 +37,10 @@ emulate -L zsh (( ZSHZ_DEBUG )) && setopt LOCAL_OPTIONS WARN_CREATE_GLOBAL NO_WARN_NESTED_VAR 2> /dev/null -# TODO: This routine currently reproduces z's feature of allowing spaces to be -# used as wildcards in completions, so that -# -# z us lo bi -# -# can expand to -# -# z /usr/local/bin -# -# but it also reproduces z's buggy display on the commandline, viz. -# -# z us lo /usr/local/bin -# -# Address. - local completions expl completion local -a completion_list -completions=$(zshz --complete ${(@)words:1}) +completions=$(zshz --complete "${(@)words:1}") [[ -z $completions ]] && return 1 for completion in ${(f)completions[@]}; do diff --git a/plugins/z/z.plugin.zsh b/plugins/z/z.plugin.zsh index 39b832292..456802d3d 100644 --- a/plugins/z/z.plugin.zsh +++ b/plugins/z/z.plugin.zsh @@ -4,7 +4,7 @@ # # https://github.com/agkozak/zsh-z # -# Copyright (c) 2018-2025 Alexandros Kozak +# Copyright (c) 2018-2026 Alexandros Kozak # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -294,9 +294,9 @@ zshz() { owner=${ZSHZ_OWNER:-${_Z_OWNER}} if (( ZSHZ[USE_FLOCK] )); then - # An unsual case: if inside Docker container where datafile could be bind + # An unusual case: if inside Docker container where datafile could be bind # mounted - if [[ -r '/proc/1/cgroup' && "$(< '/proc/1/cgroup')" == *docker* ]]; then + if [[ -f '/.dockerenv' || ( -r '/proc/1/cgroup' && "$(< '/proc/1/cgroup')" == *docker* ) ]]; then print "$(< "$tempfile")" > "$datafile" 2> /dev/null ${ZSHZ[RM]} -f "$tempfile" # All other cases @@ -960,6 +960,62 @@ add-zsh-hook chpwd _zshz_chpwd (( ${fpath[(ie)${0:A:h}]} <= ${#fpath} )) || fpath=( "${0:A:h}" "${fpath[@]}" ) +# Save the existing Tab binding +ZSHZ[TAB_BINDING]="${$(bindkey -M main '^I')##* }" + +############################################################ +# ZLE widget to fix spaces-as-wildcards completion +# +# When completing a Zsh-z command with multiple search terms +# (e.g. `z us lo bi'), collapse the terms into a single +# wildcard-joined word (e.g. `z us*lo*bi') before triggering +# completion. This causes compadd to replace the whole query +# with the matched path rather than just the last word. +# +# Globals: +# ZSHZ_CMD +############################################################ +_zshz_zle_completion_widget() { + emulate -L zsh + local cmd=${ZSHZ_CMD:-${_Z_CMD:-z}} + + # If a trailing space was added after an already-completed absolute path + # (e.g. `z /usr/local/bin '), a second Tab would otherwise re-trigger + # completion on an empty word and insert a duplicate. Bail out early. + if [[ $LBUFFER[-1] == ' ' && ${${LBUFFER% }##* } == [/~]* ]]; then + return + fi + + # Only act when there are at least two words after the command + if [[ $LBUFFER == ${cmd}\ *\ * ]]; then + local after=${LBUFFER#${cmd} } + local -a parts flag_parts search_parts + local p past_flags=0 + + parts=( ${(z)after} ) + for p in $parts; do + if (( ! past_flags )) && [[ $p == -[cehlrRtx]## ]]; then + flag_parts+=( $p ) + else + past_flags=1 + search_parts+=( $p ) + fi + done + + if (( ${#search_parts} > 1 )); then + LBUFFER="${cmd}${flag_parts:+ ${(j: :)flag_parts}} ${(j:*:)search_parts}" + fi + fi + + # If Tab had a non-default binding, continue to use it; otherwise the default + # expand-or-complete gets used. + zle ${ZSHZ[TAB_BINDING]:-expand-or-complete} +} + +zle -N _zshz_zle_completion_widget + +bindkey -M main '^I' _zshz_zle_completion_widget + ############################################################ # zsh-z functions ############################################################ @@ -974,7 +1030,8 @@ ZSHZ[FUNCTIONS]='_zshz_usage zshz _zshz_precmd _zshz_chpwd - _zshz' + _zshz + _zshz_zle_completion_widget' ############################################################ # Enable WARN_NESTED_VAR for functions listed in @@ -1004,6 +1061,16 @@ zsh-z_plugin_unload() { add-zsh-hook -D precmd _zshz_precmd add-zsh-hook -d chpwd _zshz_chpwd + zle -D _zshz_zle_completion_widget + + # Only restore Tab binding if it is still bound to our widget; otherwise + # leave it alone. + local _zshz_current_tab + _zshz_current_tab="$(bindkey -M main '^I' 2>/dev/null || true)" + if [[ ${_zshz_current_tab##* } == _zshz_zle_completion_widget ]]; then + bindkey -M main '^I' "${ZSHZ[TAB_BINDING]:-expand-or-complete}" + fi + local x for x in ${=ZSHZ[FUNCTIONS]}; do (( ${+functions[$x]} )) && unfunction $x