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