From 29c9e7817f4ec0d2edd7d319090bfb5642315c18 Mon Sep 17 00:00:00 2001 From: Andrii Furmanets Date: Wed, 14 Oct 2026 10:40:12 +0300 Subject: [PATCH] Escape $ and backticks in zsh completion descriptions The generated _arguments specs are double-quoted, so a description such as "costs $5" or one mentioning `cmd` was expanded, or run, by zsh when the completion file was loaded. --- lib/optparse.rb | 4 +++- test/optparse/test_zsh_completion.rb | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 97178e2..65a2d1f 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1049,7 +1049,9 @@ def compsys(to, name = File.basename($0)) # :nodoc: to << "#compdef #{name}\n" to << COMPSYS_HEADER visit(:compsys, {}, {}) {|o, d| - to << %Q[ "#{o}[#{d.gsub(/[\\\"\[\]]/, '\\\\\&')}]" \\\n] + # Escape what zsh would expand inside the double quotes ($ and `), as + # well as the characters _arguments treats specially. + to << %Q[ "#{o}[#{d.gsub(/[\\\"\[\]$`]/, '\\\\\&')}]" \\\n] } to << " '*:file:_files' && return 0\n" end diff --git a/test/optparse/test_zsh_completion.rb b/test/optparse/test_zsh_completion.rb index 76f0a73..12f0a9c 100644 --- a/test/optparse/test_zsh_completion.rb +++ b/test/optparse/test_zsh_completion.rb @@ -18,4 +18,10 @@ def test_compsys assert_match(/\"--bar\[\]\"/, compsys) assert_match(/\"--for\[\]\"/, compsys) end + + def test_compsys_escapes_shell_expansion + @opt.define("--price", "costs $HOME and `date`") {} + compsys = @opt.compsys("", "zshcompsys") + assert_include(compsys, %q["--price[costs \\$HOME and \\`date\\`]"]) + end end