matryer / xbar

Put the output from any script or program into your macOS Menu Bar (the BitBar reboot)
https://xbarapp.com
MIT License
17.51k stars 642 forks source link

Shell parameters over-escaping #831

Open kdeldycke opened 2 years ago

kdeldycke commented 2 years ago

In the meta_package_manger.7h.py plugin I'm maintaining for the last 5 years, I'm trying to execute a python3 -m pip command.

Which works for bash, but not for zsh as you can see:

❯ bash
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.

bash-3.2$ mpm --version
bash: mpm: command not found

bash-3.2$ python3 -m pip install --upgrade meta-package-manager>=4.2.0

bash-3.2$ mpm --version
mpm, version 4.12.1
❯ zsh --version
zsh 5.8.1 (arm-apple-darwin21.3.0)

❯ python3 -m pip install --upgrade meta-package-manager>=4.2.0
zsh: 4.2.0 not found

The trick is to quote the last parameter or escape the angle-bracket within:

❯ python3 -m pip install --upgrade "meta-package-manager>=4.2.0"
(...)
Successfully installed meta-package-manager-4.12.1

❯ python3 -m pip install --upgrade meta-package-manager\>=4.2.0
(...)
Requirement already satisfied: meta-package-manager>=4.2.0
bash-3.2$ python3 -m pip install --upgrade "meta-package-manager>=4.2.0"
(...)
Requirement already satisfied: meta-package-manager>=4.2.0

bash-3.2$ python3 -m pip install --upgrade meta-package-manager\>=4.2.0
(...)
Requirement already satisfied: meta-package-manager>=4.2.0

These examples have the advantage of working for both bash and zsh.

Now I'd like to transpose that workaround in xbar. But no amount of tweaking let me have one of this CLI executed as-is.

Here is a Python-based xbar plugin exploring the possibilities:

#!/usr/bin/env python3

print("Escape Test | dropdown=false")
print("---")

base_cmd = " | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade "

# Bare argument
print("Test 1" + base_cmd + "param5=meta-package-manager>=4.2.0")

# Quoted argument
print("Test 2" + base_cmd + "param5='meta-package-manager>=4.2.0'")
print("Test 3" + base_cmd + 'param5="meta-package-manager>=4.2.0"')

# Quote hacks
print("Test 4" + base_cmd + 'param5=\\"meta-package-manager>=4.2.0\\"')
print("Test 5" + base_cmd + "param5=\\'meta-package-manager>=4.2.0\\'")
print("Test 6" + base_cmd + 'param5=\\\\"meta-package-manager>=4.2.0\\\\"')
print("Test 7" + base_cmd + "param5=\\\\'meta-package-manager>=4.2.0\\\\'")

# Angle bracket hacks
print("Test 8" + base_cmd + "param5=meta-package-manager\>=4.2.0")
print("Test 9" + base_cmd + "param5=meta-package-manager\\>=4.2.0")

On execution, it returns:

❯ ./escape_test.1d.py
Escape Test | dropdown=false
---
Test 1 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=meta-package-manager>=4.2.0
Test 2 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5='meta-package-manager>=4.2.0'
Test 3 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5="meta-package-manager>=4.2.0"
Test 4 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=\"meta-package-manager>=4.2.0\"
Test 5 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=\'meta-package-manager>=4.2.0\'
Test 6 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=\\"meta-package-manager>=4.2.0\\"
Test 7 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=\\'meta-package-manager>=4.2.0\\'
Test 8 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=meta-package-manager\>=4.2.0
Test 9 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=meta-package-manager\>=4.2.0

Which renders into xbar as:

Screen Shot 2022-04-13 at 14 35 40

But none of these 9 tests properly executes my command.

❌ Tests #1, #2 and #3 runs:

❯  'python3' -m pip install --upgrade meta-package-manager>=4.2.0
zsh: 4.2.0 not found

❌ Tests #4 runs:

❯  'python3' -m pip install --upgrade \\\"meta-package-manager>=4.2.0\\\"
zsh: 4.2.0\" not found

❌ Tests #5 and #7 runs:

❯  'python3' -m pip install --upgrade \\\\'meta-package-manager>=4.2.0\\\\'

ERROR: Invalid requirement: '\\\\meta-package-manager>=4.2.0\\\\\\\\'

❌ Tests #6 runs:

❯  'python3' -m pip install --upgrade \\\\\"meta-package-manager>=4.2.0\\\\\"
zsh: 4.2.0\\" not found

❌ Tests #8 and #9 runs:

❯  'python3' -m pip install --upgrade meta-package-manager\\\\>=4.2.0
zsh: 4.2.0 not found

Looking at these examples, it seems there is something inconsistent in the way xbar is parsing parameters, handling outer quotes and/or over-escaping special characters.

Here is my environment:

For the record, I tested the same test suite on SwiftBar but the results are completely different.

Overload119 commented 7 months ago

Thanks for such an exhaustive write up - it seems I won't be able to get this to work either.