what utility or command/s can be used to transform the following output:
wmctrl -l -i -p
0x01000003 -1 3208 user xfce4-panel
0x01400013 -1 3217 user Desktop
0x00e00615 0 3212 user shared - Thunar
0x0540011b 2 5263 user Firefox Developer Edition
0x00e8421b 2 3212 user scripts - Thunar
into:
[
{ "windowId": "0x01000003", "desktop": -1, "windowsPid": 3208, "label": "xfce4-panel" },
{ "windowId": "0x01400013", "desktop": -1, "windowsPid": 3217, "label": "Desktop" },
{ "windowId": "0x00e00615", "desktop": 0, "windowsPid": 3212, "label": "shared - Thunar" },
{ "windowId": "0x0540011b", "desktop": 2, "windowsPid": 5263, "label": "Firefox Developer Edition" },
{ "windowId": "0x00e8421b", "desktop": 2, "windowsPid": 3212, "label": "scripts - Thunar" }
]
?
Ages ago, I wrote this short script which tried to clone wmctrl
but format the output for -m
, -l
, and -d
as JSON. Try it out to see if it already works for you.
#!/bin/sh
# Fall back to default if neither `-m`, `-l`, or `-d` is the first argument
{ { { { wmctrl "$@" "${1+-pGx}"; echo $? >&3; } | case "$1" in
-m*)
jq -Rn '[inputs | capture("(?<key>.+?):\\s+(?<value>.*)")] | from_entries'
;;
-l*)
jq -Rn '[
inputs | capture([
"(?<window_ID>\\S+)",
"(?<desktop_ID>\\S+)",
"(?<PID>\\d+|N/A)",
"(?<geometry>\\d+\\s+\\d+\\s+\\d+\\s+\\d+|N/A)",
"(?<WM_CLASS>\\S+)",
"(?<client_machine>\\w+)",
"(?<window_title>.*)$"
] | join("\\s+"))
| (.window_ID, .desktop_ID, .PID) |= (tonumber? // .)
| (.geometry) |= [scan("\\d+") | tonumber]
| (.WM_CLASS) /= "."
]'
;;
-d*)
jq -Rn '[
inputs | capture([
"(?<desktop_ID>\\S+)",
"(?<current_desktop>-|\\*)",
"DG:", "(?<geometry>\\d+x\\d+|N/A)",
"VP:", "(?<viewport>\\d+,\\d+|N/A)",
"WA:", "(?<workarea>\\d,\\d\\s+\\d+x\\d+|N/A)",
"(?<title>.*)$"
] | join("\\s+"))
| (.desktop_ID) |= (tonumber? // .)
| (.current_desktop) |= . == "*"
| (.geometry, .viewport, .workarea) |= [scan("\\d+") | tonumber]
]'
;;
*) cat ;;
esac >&4; } 3>&1; } | { read -r status; exit "$status"; } } 4>&1
# pipefail for posix shells: https://unix.stackexchange.com/a/70675
If not, here's how I would adopt it to just match your sample input while using your field names:
wmctrl -lip | jq -Rn '[inputs | capture([
"(?<windowId>\\S+)",
"(?<desktop>\\S+)",
"(?<windowsPid>\\S+)",
"\\S+",
"(?<label>.*)"
] | join("\\s+")) | (.desktop, .windowsPid) |= (tonumber? // .)]'
[
{
"windowId": "0x01000003",
"desktop": -1,
"windowsPid": 3208,
"label": "xfce4-panel"
},
{
"windowId": "0x01400013",
"desktop": -1,
"windowsPid": 3217,
"label": "Desktop"
},
{
"windowId": "0x00e00615",
"desktop": 0,
"windowsPid": 3212,
"label": "shared - Thunar"
},
{
"windowId": "0x0540011b",
"desktop": 2,
"windowsPid": 5263,
"label": "Firefox Developer Edition"
},
{
"windowId": "0x00e8421b",
"desktop": 2,
"windowsPid": 3212,
"label": "scripts - Thunar"
}
]