Open cnt0 opened 5 months ago
~
❯ event_data='some,strange,name,layout'
~
❯ echo "${event_data%,*}"
some,strange,name
~
❯ echo "${event_data#*,}"
strange,name,layout
~
❯ echo "${event_data##*,}"
layout
But if we're talking about this - there are apparently layouts with commas too e.g.:
https://gist.github.com/MahouShoujoMivutilde/8a12c0d40e7b262f2c78ef6e01193542
because who cares about keyboard names anyway
I care*, because wtype, power button, my bluetooth headphones and possibly other unexpected things are "keyboards".
Here is wtype working:
activelayout>>cvirtualkeyboard,English (US)
activelayout>>cvirtualkeyboard,English (US)
activelayout>>cvirtualkeyboard,none
activelayout>>cvirtualkeyboard,error
* but it's obviously not mutually exclusive thing where we all have to settle to some ONE event to rule 'em all.
This is indeed a very annoying issue for IPC clients. I see the event is posted in InputManager.cpp:
and two other places in this file.
We could maybe replace the ','
in this line with something like a ;
, but I feel this is not a very robust as some keyboard names or layout could contain a ;
as well.
Maybe a better solution could be to escape the existing commas in the keyboard name and layout with a \
? Does that make sense to do?
Since issue title is quite generic, i'll add another improvement request: also output layout index. Otherwise it is harder to translate name to index for use in hyprctl switchxkblayout
:
activelayoutv2>>KEYBOARD_NAME;LAYOUT_INDEX;LAYOUT_NAME
encountered this ,
issue, but with window titles ;w;
I'd rather make separators globally use a value which can't be found in text, like \xFD
, which can't be used as a character, so any conflict is avoided and its easy enough to parse, but with the possible problem which it is not a valid character, so not sure if would be handled correctly everywhere...
I think it's better to rewrite the way IPC events are handled in general, to never run into the same issue ever again with any other event.
How?
For example
SHyprIPCEvent.data
a vector of strings, and change all its mentions accordinglyCEventManager::formatEvent()
with some separator, (hopefully) escaping it with some replaceAll(string, 'sep', '\sep')
before that.What separator?
Considering it's going to be used in scripts too - something reasonable, but rare. I think tab (\t
) works well for this purpose. It's clean, it's easy to input ($'\t'
in shell), and you're unlikely to see it anywhere unintentionally.
But, since this obviously breaks the API, might as well make some "socket3" with JSON, like waybar does.
JSON is awesome, because all the (un)escaping (can be) done for you, and typically there is some library lets you parse it automatically in some native object, bypassing the need to deal with (de)serialization entirely.
I like your second proposal: printing the data as JSON. It basically works with everything and it's very easy to parse.
I'm actually surprised that this whole IPC is not a json in the first place (like in i3/sway)
Json isn't all that handy to deal with in shell (unless you just string a bunch of external tools on a pipe and call it a day). Radical notion: unit separator rules:
Oct Dec Hex Char Oct Dec Hex Char
───────────────────────────────────────────────────────────────────────
034 28 1C FS (file separator) 134 92 5C \ '\\'
035 29 1D GS (group separator) 135 93 5D ]
036 30 1E RS (record separator) 136 94 5E ^
037 31 1F US (unit separator) 137 95 5F _
Json isn't all that handy to deal with in shell
But the goal is to use it in IPC, I don't see any problems with JSON in that context? As far as external tools go for handling it in a shell, simply using jq
can get you most of the way there.
Unit seperators are pretty cool but I feel like JSON is much more universally supported and understood.
Unit seperators are pretty cool but I feel like JSON is much more universally supported and understood.
But, since this obviously breaks the API, might as well make some "socket3" with JSON
Unit separators could be an [initially] optional upgrade to socket2
.
Btw, as a workaround, you could use
```bash #!/usr/bin/env bash event_data="some-weird,keyboard,Some,Layout" # so like # hyprctl devices -j | jq -r '.keyboards.[] | select(.main == true).name' kbd1="some-weird,keyboard" case "$event_data" in "$kbd1"*) echo "matched keyboard" echo "Layout is '${event_data##"$kbd1",}'" ;; *) echo "not our keyboard, skipping" ;; esac ```
to get
matched keyboard
Layout is 'Some,Layout'
This could be expanded to something generic, like
```bash #!/usr/bin/env bash attached_keyboards=('some,kbd,(1)' 'some,kbd,(2)' 'some,kbd,(3)' 'some-kbd-4') parse_layout() { local event_data="$1" for kbd in "${attached_keyboards[@]}"; do case "$event_data" in "$kbd"*) echo "-> keyboard = '$kbd'" echo "-> layout = '${event_data##"$kbd",}'" ;; esac done } ## TEST VALUES event_datas=( 'some,kbd,(1),Aawdmkawdm,(Phonetic)' 'some,kbd,(2),Atrhjhyt Bryjytjjy,,wemrmmggr 4t43 t34t43 t3t54' 'some,kbd,(2),English (US)' 'some,kbd,(3),error' 'some-kbd-4,AAAAAA,AAAAAAAAA' 'some-kbd-4,YES' ) for data in "${event_datas[@]}"; do echo "$data" parse_layout "$data" done ```
Resulting in
``` some,kbd,(1),Aawdmkawdm,(Phonetic) -> keyboard = 'some,kbd,(1)' -> layout = 'Aawdmkawdm,(Phonetic)' some,kbd,(2),Atrhjhyt Bryjytjjy,,wemrmmggr 4t43 t34t43 t3t54 -> keyboard = 'some,kbd,(2)' -> layout = 'Atrhjhyt Bryjytjjy,,wemrmmggr 4t43 t34t43 t3t54' some,kbd,(2),English (US) -> keyboard = 'some,kbd,(2)' -> layout = 'English (US)' some,kbd,(3),error -> keyboard = 'some,kbd,(3)' -> layout = 'error' some-kbd-4,AAAAAA,AAAAAAAAA -> keyboard = 'some-kbd-4' -> layout = 'AAAAAA,AAAAAAAAA' some-kbd-4,YES -> keyboard = 'some-kbd-4' -> layout = 'YES' ```
attached_keyboards
could be populated like so
attached_keyboards=($(hyprctl devices -j | jq -r '.keyboards.[].name'))
And updated on ....device(added|removed)
events that doesn't exist. Well. Updated on every function call then.
Description
Hello. Hyprland IPC has the following event emitted on the layout change
KEYBOARDNAME
andLAYOUTNAME
are separated by comma. The problem is thatKEYBOARDNAME
can contain commas as well. At least it does in my case, it starts withmistel-co.,ltd.-
.Such behavior complicates parsing, for example, shellevents can't correctly handle it right now.
I believe that instead of polluting IPC clients with workarounds we can fix the IPC itself. For example we can introduce the
activelayoutv2>>LAYOUTNAME
event, because who cares about keyboard names anyway. But I'd listen to suggestion first.