Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] completion: use `zformat -q` for formatting
- X-seq: zsh-workers 54768
- From: dana <dana@xxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: [PATCH] completion: use `zformat -q` for formatting
- Date: Sun, 14 Jun 2026 04:07:37 +0000
- Archived-at: <https://zsh.org/workers/54768>
- Feedback-id: i9be146f9:Fastmail
- List-id: <zsh-workers.zsh.org>
this is an alternative to w/54573 which makes use of `zformat -q` + the
new spec syntax from w/54767 (obv requires that patch)
basically all spec strings passed to _description etc are now quoted by
default. helpers that want to avoid this can prefix a spec with %%. atm
_numbers's %x is the only example of this
third-party completion functions that currently use % in certain places
like _arguments optarg descriptions may find that those %s are doubled
now. but that seems uncommon
technically this also changes the semantics of e.g. the descriptions
format style, but i don't think it will break anything in practice
(these warnings applied to w/54573 as well, just wanted to be clear)
dana
diff --git a/Completion/Base/Core/_description b/Completion/Base/Core/_description
index 368b41ee2..586b1590d 100644
--- a/Completion/Base/Core/_description
+++ b/Completion/Base/Core/_description
@@ -86,7 +86,7 @@ elif [[ -n "$format" ]]; then
[[ -n $match[3] ]] && argv+=( o:$match[3] )
fi
- zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}"
+ zformat -Fq format "$format" "d:$1" "${(@)argv[2,-1]}"
fi
if [[ -n "$gname" ]]; then
diff --git a/Completion/Base/Core/_main_complete b/Completion/Base/Core/_main_complete
index 408a66ee3..11b7972de 100644
--- a/Completion/Base/Core/_main_complete
+++ b/Completion/Base/Core/_main_complete
@@ -366,7 +366,7 @@ elif [[ nm -eq 0 && -z "$_comp_mesg" &&
esac
_setup warnings
- zformat -f mesg "$format" "d:$str" "D:${(F)${(@)_lastdescr:#}}"
+ zformat -fq mesg "$format" "d:$str" "D:${(F)${(@)_lastdescr:#}}"
compadd -x "$mesg"
fi
diff --git a/Completion/Base/Core/_message b/Completion/Base/Core/_message
index dbeed4a88..b80aa4237 100644
--- a/Completion/Base/Core/_message
+++ b/Completion/Base/Core/_message
@@ -39,7 +39,7 @@ else
fi
if [[ -n "$format$raw" ]]; then
- [[ -z "$raw" ]] && zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}"
+ [[ -z "$raw" ]] && zformat -Fq format "$format" "d:$1" "${(@)argv[2,-1]}"
builtin compadd "$gopt[@]" -x "$format"
_comp_mesg=yes
fi
diff --git a/Completion/Base/Utility/_numbers b/Completion/Base/Utility/_numbers
index 257e267a8..1ddace15a 100644
--- a/Completion/Base/Utility/_numbers
+++ b/Completion/Base/Utility/_numbers
@@ -73,12 +73,13 @@ elif [[ -prefix $~pat || $PREFIX = $~partial ]]; then
zstyle -s ":completion:${curcontext}:unit-suffixes" format suffixfmt || \
suffixfmt='%(d.%U.)%x%(d.%u.)%(r..|)'
for ((i=0;i<$#;i++)); do
- zformat -f suffix "$suffixfmt" "x:${${${argv[i+1]#:}%%:*}//\%/%%}" \
- "X:${${${argv[i+1]#:}#*:}//\%/%%}" "d:${#${argv[i+1]}[1]#:}" \
+ zformat -fq suffix "$suffixfmt" "x:${${argv[i+1]#:}%%:*}" \
+ "X:${${argv[i+1]#:}#*:}" "d:${#${argv[i+1]}[1]#:}" \
i:i r:$(( $# - i - 1))
suffixes+=$suffix
done
- [[ -n $suffixes ]] && formats+=( x:$suffixes )
+ # don't quote %x so we can pass formatting through
+ [[ -n $suffixes ]] && formats+=( %%x:$suffixes )
_comp_mesg=yes
_description -x $tag expl "$desc" $formats
diff --git a/Completion/Debian/Command/_git-buildpackage b/Completion/Debian/Command/_git-buildpackage
index 81bf7dac9..7c81e0ff2 100644
--- a/Completion/Debian/Command/_git-buildpackage
+++ b/Completion/Debian/Command/_git-buildpackage
@@ -13,8 +13,8 @@ _arguments \
'--git-sign-tags[sign tags]' \
'--git-no-sign-tags[negates --git-sign-tags]' \
'--git-keyid=-[GPG keyid to sign tags with]:GPG key:' \
- '--git-debian-tag=-[format string for debian tags]:format string [debian/%%(version)s]' \
- '--git-upstream-tag=-[format string for upstream tags]:format string [upstream/%%(version)s]' \
+ '--git-debian-tag=-[format string for debian tags]:format string [debian/%(version)s]' \
+ '--git-upstream-tag=-[format string for upstream tags]:format string [upstream/%(version)s]' \
'--git-pristine-tar[use pristine-tar to create .orig.tar.gz]' \
'--git-no-pristine-tar[negates --git-pristine-tar]' \
'--git-force-create[force creation of orig.tar.gz]' \
diff --git a/Completion/Linux/Command/_valgrind b/Completion/Linux/Command/_valgrind
index 47fced1fd..638b29cf5 100644
--- a/Completion/Linux/Command/_valgrind
+++ b/Completion/Linux/Command/_valgrind
@@ -20,7 +20,7 @@ common_own_malloc=(
'--alignment=-[set minimum alignment of heap allocations]:number [16]'
'--redzone-size=-[set minimum size of redzones added before/after heap blocks]:size (bytes) [16]'
'--xtree-memory=-[profile heap memory in an xtree [none]:(none allocs full)'
- '--xtree-memory-file=-[specify xtree memory report file]:file [xtmemory.kcg.%%p]:_files'
+ '--xtree-memory-file=-[specify xtree memory report file]:file [xtmemory.kcg.%p]:_files'
)
common_read_varinfo=(
@@ -67,7 +67,7 @@ args_addrcheck=(
'(--show-leak-kinds)--show-reachable=-[show reachable blocks in leak check]:enable:(yes no)'
'(--show-leak-kinds)--show-possibly-lost=-:enable:(yes no)'
'--xtree-leak=-[output leak result in xtree format]:enable [no]:(yes no)'
- '--xtree-leak-file=-[specify xtree leak report file]:file [xtleak.kcg.%%p]:_files'
+ '--xtree-leak-file=-[specify xtree leak report file]:file [xtleak.kcg.%p]:_files'
'--undef-value-errors=-[check for undefined value errors]:enable [yes]:(yes no)'
'--track-origins=-[show origins of undefined values]:enable [no]:(yes no)'
$common_partial
@@ -124,11 +124,11 @@ args_cachegrind=(
'--LL=-[set LL cache manually]:size,assoc,line_size'
'--cache-sim=-[collect cache stats]:enable [yes]:(yes no)'
'--branch-sim=-[collect branch prediction stats]:enable [no]:(yes no)'
- '--cachegrind-out-file=-[specify output file name]:file name [cachegrind.out.%%p]:_files'
+ '--cachegrind-out-file=-[specify output file name]:file name [cachegrind.out.%p]:_files'
)
args_callgrind=(
- '--callgrind-out-file=-[specify output file name]:file name [callgrind.out.%%p]:_files'
+ '--callgrind-out-file=-[specify output file name]:file name [callgrind.out.%p]:_files'
'--dump-line=-[perform event counting at source line granularity]:enable [yes]:(yes no)'
'--dump-instr=-[perform event counting at instruction granularity]:enable [no]:(yes no)'
'--compress-strings=-[identify file and function names by numbers]:enable [yes]:(yes no)'
@@ -202,7 +202,7 @@ args_massif=(
))"
'--detailed-freq=-[every Nth snapshot should be detailed]:snapshot interval [10]'
'--max-snapshots=-[specofy maximum number of snapshots recorded]:maximum [100]'
- '--massif-out-file=-[specify output file name]:filename [massif.out.%%p]:_files'
+ '--massif-out-file=-[specify output file name]:filename [massif.out.%p]:_files'
)
args_exp_bbv=(
diff --git a/Completion/Unix/Command/_csplit b/Completion/Unix/Command/_csplit
index b0ba1d7f4..eb354bd83 100644
--- a/Completion/Unix/Command/_csplit
+++ b/Completion/Unix/Command/_csplit
@@ -17,7 +17,7 @@ specs=(
if _pick_variant gnu='(GNU|uutils)' unix --version; then
# GNU coreutils 8.32
specs+=(
- '(hv -b --suffix-format -n --digits)'{-b+,--suffix-format=}'[specify format for numbers in output file names]:format [%%02d]: '
+ '(hv -b --suffix-format -n --digits)'{-b+,--suffix-format=}'[specify format for numbers in output file names]:format [%02d]: '
'(hv)--suppress-matched[suppress the lines matching the pattern]'
'(hv -z --elide-empty)'{-z,--elide-empty-files}'[remove empty output files]'
+ hv
@@ -44,7 +44,7 @@ case $state in
elif compset -P '[0-9]*'; then
_message 'line number' && ret=0
elif [[ ${words[CURRENT]} != -* ]] then
- _message "line_number, '/regex/[offset]', '%%regex%%[offset]', or '{count}'" && ret=0
+ _message "line_number, '/regex/[offset]', '%regex%[offset]', or '{count}'" && ret=0
fi
esac
diff --git a/Completion/Unix/Command/_gcore b/Completion/Unix/Command/_gcore
index ef3afd919..4e5041f3b 100644
--- a/Completion/Unix/Command/_gcore
+++ b/Completion/Unix/Command/_gcore
@@ -56,7 +56,7 @@ case $OSTYPE in
'-v[report progress on the dump as it proceeds]' \
'-b+[specify maximum size of core file]:size (MiB): ' \
'(-c)-o+[write core file to specified file]:file:_files' \
- '(-o)-c+[specify format of core file name]:format (%%N\:program name, %%U\:uid, %%P\:pid, %%T\:time stamp)' \
+ '(-o)-c+[specify format of core file name]:format (%N\:program name, %U\:uid, %P\:pid, %T\:time stamp)' \
'1:pid:_pids'
;;
*)
diff --git a/Completion/Unix/Command/_mpc b/Completion/Unix/Command/_mpc
index 45b181f55..83700d828 100644
--- a/Completion/Unix/Command/_mpc
+++ b/Completion/Unix/Command/_mpc
@@ -234,7 +234,7 @@ _mpc_play() {
}
_mpc_seek() {
- _message -e position 'position ([+-][HH:MM:SS]|<0-100>%%)'
+ _message -e position 'position ([+-][HH:MM:SS]|<0-100>%)'
}
_mpc_seekthrough() {
diff --git a/Completion/Unix/Command/_nano b/Completion/Unix/Command/_nano
index e2333b9f4..4f6bd8b0d 100644
--- a/Completion/Unix/Command/_nano
+++ b/Completion/Unix/Command/_nano
@@ -20,7 +20,7 @@ args=(
'(-N --noconvert -u --unix)'{-N,--noconvert}"[don't convert files from DOS/Mac format]"
'(-O --bookstyle)'{-O,--bookstyle}'[when justifying, leading whitespace means new paragraph]'
'(-P --positionlog)'{-P,--positionlog}'[remember cursor position]'
- '(-Q --quotestr)'{-Q+,--quotestr=}'[specify regular expression to match quoting]:quoting regex [^([ \t]*([!#%%\:;>|}]|//))+]'
+ '(-Q --quotestr)'{-Q+,--quotestr=}'[specify regular expression to match quoting]:quoting regex [^([ \t]*([!#%\:;>|}]|//))+]'
'(-R --restricted)'{-R,--restricted}'[restrict access to the file system]'
'(-S --softwrap)'{-S,--softwrap}'[soft-wrap long lines]'
'(-T --tabsize)'{-T+,--tabsize=}'[specify tab width]: :_numbers -u columns -l1 -d8 "tab width"'
diff --git a/Completion/Unix/Command/_opustools b/Completion/Unix/Command/_opustools
index 1fd97798a..c860a170f 100644
--- a/Completion/Unix/Command/_opustools
+++ b/Completion/Unix/Command/_opustools
@@ -14,7 +14,7 @@ case $service in
'--cvbr[use constrained variable bitrate encoding]' \
'--downmix-mono[downmix to mono]' \
'--downmix-stereo[downmix to stereo (if >2 channels)]' \
- '--expect-loss[set expected packet loss]:expected packet loss (%%) (0-100) [0]' \
+ '--expect-loss[set expected packet loss]:expected packet loss (%) (0-100) [0]' \
'--framesize[set maximum frame size]:maximum frame size (milliseconds) [20]:(2.5 5 10 20 40 60)' \
'--hard-cbr[use hard constant bitrate encoding]' \
'--max-delay[set maximum container delay]:maximum container delay (milliseconds) (0-1000) [1000]' \
@@ -57,7 +57,7 @@ case $service in
'--no-dither[do not dither 16-bit output]' \
'--float[output 32-bit floating-point samples]' \
'--force-wav[force RIFF wav header on output]' \
- '--packet-loss[simulate random packet loss]:packet loss probability (%%) (0-100)' \
+ '--packet-loss[simulate random packet loss]:packet loss probability (%) (0-100)' \
'--save-range[save check values for every frame to a file]:output for check values:_files'
;;
opusinfo)
diff --git a/Completion/Unix/Type/_date_formats b/Completion/Unix/Type/_date_formats
index 0527d706c..2b7139492 100644
--- a/Completion/Unix/Type/_date_formats
+++ b/Completion/Unix/Type/_date_formats
@@ -107,6 +107,6 @@ done
_describe -t date-format-specifier 'date format specifier' specs \
-p "${(Q)PREFIX:-%}" -S '' && ret=0
-[[ $1 == zsh ]] && _message -e date-format-precision 'precision for %%. (1-9)'
+[[ $1 == zsh ]] && _message -e date-format-precision 'precision for %. (1-9)'
return ret
diff --git a/Test/Y01completion.ztst b/Test/Y01completion.ztst
index 53d49df37..1e0f0a60c 100644
--- a/Test/Y01completion.ztst
+++ b/Test/Y01completion.ztst
@@ -393,6 +393,11 @@ F:regression test workers/31611
>NO:{y}
>NO:{z}
+ comptesteval '_tst() { _message "%foo %BAR" }'
+ comptest $'tst \t'
+0:% in message
+>line: {tst }{}
+>MESSAGE:{%foo %BAR}
%clean
diff --git a/Test/Y03arguments.ztst b/Test/Y03arguments.ztst
index 6e423bfe5..f58fa4123 100644
--- a/Test/Y03arguments.ztst
+++ b/Test/Y03arguments.ztst
@@ -811,6 +811,17 @@ F:shouldn't offer -t in the first case (with stacked options)
>DESCRIPTION:{option}
>NO:{-b}
+ tst_arguments : '-x+[%2Fxdesc%f]:%2Fxargdesc%f' -y '1:%2F1desc%f'
+ comptest $'tst -\t'
+ comptest $'tst -x\t'
+0:% in descriptions
+>line: {tst -}{}
+>DESCRIPTION:{%2F1desc%f}
+>DESCRIPTION:{option}
+>NO:{-x -- %2Fxdesc%f}
+>NO:{-y}
+>line: {tst -x}{}
+>DESCRIPTION:{%2Fxargdesc%f}
%clean
diff --git a/Test/Y05describe.ztst b/Test/Y05describe.ztst
index ee8717a24..72953af7c 100644
--- a/Test/Y05describe.ztst
+++ b/Test/Y05describe.ztst
@@ -92,6 +92,14 @@
>NO:{x}
>line: {tst cx}{}
+ tst_describe %2Fdesc%f '(a:adesc b:%2Fbdesc%f)'
+ comptest $'tst \t'
+0:% in descriptions
+>line: {tst }{}
+>DESCRIPTION:{%2Fdesc%f}
+>NO:{a -- adesc}
+>NO:{b -- %2Fbdesc%f}
+
%clean
zmodload -ui zsh/zpty
diff --git a/Test/Y06values.ztst b/Test/Y06values.ztst
index b80cc2927..720f990a5 100644
--- a/Test/Y06values.ztst
+++ b/Test/Y06values.ztst
@@ -233,6 +233,14 @@
>NO:{a}
>NO:{d}
+ tst_values %2Fdesc%f 'a[adesc]' 'b[%2Fbdesc%f]'
+ comptest $'tst \t'
+0:% in descriptions
+>line: {tst }{}
+>DESCRIPTION:{%2Fdesc%f}
+>NO:{a -- adesc}
+>NO:{b -- %2Fbdesc%f}
+
%clean
zmodload -ui zsh/zpty
Messages sorted by:
Reverse Date,
Date,
Thread,
Author