Closed kdeldycke closed 2 years ago
Hey @kdeldycke, thanks for such a thorough issues description.
Let me try to explain what is hapening under the hood.
First step, parse this thing:
Test 1 | terminal=true shell=python3 param1=-m param2=pip param3=install param4=--upgrade param5=meta-package-manager>=4.2.0
|
is a parameters string.=
is parameter name, tabs and spaces are trimmed=
and before a space
is parameter value=
is a value. The quotes are not considered to be a part of the value and being strippedThat's why the internal shell command, before it is run will look like this:
python3 -m pip install --upgrade meta-package-manager>=4.2.0
... --upgrade \"meta-package-manager>=4.2.0\"
... --upgrade \'meta-package-manager>=4.2.0\'
... --upgrade \\"meta-package-manager>=4.2.0\\"
... --upgrade \\'meta-package-manager>=4.2.0\\'
... --upgrade meta-package-manager\>=4.2.0
Second step, execute the the shell command we've formed on the previous step. ~Unfortunately~ We have two options:
Run in background is more or less straightforward(not really), and doesn't mess with the escaping any further, run in terminal on the other hand is going through Apple Script. To make things a bit more complicated, there two, slightly different Apple Script srcipts, one for Terminal and one for iTerm.
switch PreferencesStore.shared.terminal {
case .Terminal:
appleScript = """
tell application "Terminal"
activate
tell application "System Events" to keystroke "t" using {command down}
delay 0.2
do script "\(runInTerminalScript)" in front window
activate
end tell
"""
case .iTerm:
appleScript = """
tell application "iTerm"
activate
try
select first window
set onlywindow to false
on error
create window with default profile
select first window
set onlywindow to true
end try
tell the first window
if onlywindow is false then
create tab with default profile
end if
tell current session to write text "\(runInTerminalScript)"
end tell
end tell
"""
}
Because of that, as far as I can tell here is what we have:
terminal=true
and terminal=false
, because the string is not escaped after SwiftBar strips the quotationterminal=true
, but will fail with terminal=false
. (a)... --upgrade \"meta-package-manager>=4.2.0\"
becomes (b)... --upgrade "meta-package-manager>=4.2.0"
after going though Apple Script, if (a) goes directly to zsh it will failterminal=true
because the escaping pattern causes a syntax error in Apple Script. These will not work with terminal=false
either because zsh will not be happy with \
\
is escaped with another \
and Apple Script doesn't fail, but the end result is the same - zsh is not happy with \
terminal=true
due to escaping issue in Apple Script, but they will run with terminal=false
because zsh is happy to run this ... --upgrade "meta-package-manager\>=4.2.0
All in all Test 4 is OK for terminal run and 8-9 for background.
I haven't time to thorougly test this, but I almost sure everything above is correct. Didn't look into bash instead zsh either, but I hope it helps.
@kdeldycke hey, do you have any suggestions on how to make it easier for you to use?
Might be related to: https://github.com/swiftbar/SwiftBar/issues/366
In the
meta_package_manger.7h.py
plugin I'm maintaining for the last 5 years, I'm trying to execute apython3 -m pip
command.Which works for
bash
, but not forzsh
as you can see:The trick is to quote the last parameter or escape the angle-bracket within:
These examples have the advantage of working for both
bash
andzsh
.Now I'd like to transpose that workaround in SwiftBar. But no amount of tweaking let me have one of this CLI executed as-is.
Here is a Python-based SwiftBar plugin exploring the possibilities:
On execution, it returns:
Which renders into SwiftBar as:
Some of these 9 tests properly executes my command, others fails:
❌ Tests
#1
,#2
and#3
runs:✅ Tests
#4
succeeded:❌ Tests
#7
runs:❌ Tests
#5
,#6
,#8
and#9
don't work at all and fails to launch a terminal.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 xbar but the results are completely different.