Open aidenlangley opened 2 years ago
my jq
clone:
def camel_to_snake: gsub("(?<x>[[:upper:]])"; "_\(.x|ascii_downcase)");
def dump_object: to_entries[] | "\(.key|camel_to_snake)\t-> \(.value)";
.monitors[] | (
{ monitorName: .name, windowGap, borderWidth, padding } |
dump_object
), "", (
.desktops[] | (
{ desktopName: .name, splitRatio } |
dump_object
), "", (
.root | [ .. | .client? | values ] | select(length != 0) | (
.[] |
{ className, instanceName } |
dump_object
), ""
)
)
invoke with:
bspc wm -d | jq -rf ./bspcd.jq
EDIT:
the desktops' split ratios are all null because bspwm is not including desktop split ratios in wm -d
's output apparently :D
Nice, yeah, I am going for something user friendly and easy on the eyes with a rich output.
Fair warning, there's a lot code...
Here's the wrapper, and a snippet of the meat & potatoes:
#! /usr/bin/env sh
# This is the default behaviour of the script, calling me without any arguments
# will invoke the same command with an argument provided.
if [ -z "$1" ]; then
bspcd node
exit 0
fi
case "$1" in
# These arguments are valid, append to this list to support more.
monitor | m | desktop | d | node | n | all | a)
for mon_id in $(bspc query -M); do
case "$1" in
monitor | m)
bspcq "$(bspc query -T -m $mon_id)" -d monitor
;;
desktop | d)
bspcq "$(bspc query -T -m $mon_id)" -d desktop
;;
node | n)
bspcq "$(bspc query -T -m $mon_id)" -d node
;;
all | a)
bspcq "$(bspc query -T -m $mon_id)" -d node -a
;;
esac
done
;;
*)
echo "Unrecognised argument: $1"
exit 1
;;
esac
def get_node_info(bsp_tree: dict[str, Any]) -> dict[str, Any]:
"""
Curated list of `node` properties that will be returned by our
application.
"""
# This is a system call to `xtitle`, given the ID of the node, and output is
# sent to /dev/null and read back from stdout later.
xtitle_proc = subprocess.run([
'xtitle', str(bsp_tree['id']), '&>', '/dev/null'
], capture_output=True)
node_info = {
'id': bsp_tree['id'],
'class_name': bsp_tree['client']['className'],
'instance_name': bsp_tree['client']['instanceName'],
'xtitle': xtitle_proc.stdout.decode('utf-8').rstrip()
}
return node_info
def recurse_nodes(
bsp_tree: dict[str, Any],
nodes: list[dict[str, Any]],
all: bool,
properties: list[str]
) -> list[dict[str, Any]]:
"""`bspwm` is simple, but it isn't easy. -zyk
Probably the most complex piece of the puzzle - we repeatedly
`get_node_info` here, since in theory we can have an infinite number of
`node`s.
"""
# Absence of `firstChild` means there is only a single active `node` on the
# `desktop`, so we don't have to go fishing for children.
if bsp_tree['firstChild'] is None:
nodes.append(get_info('node', bsp_tree, all, properties))
else:
if bsp_tree['firstChild'].get('client'):
nodes.append(get_info('node', bsp_tree['firstChild'], all, properties))
# In the event that there is a `firstChild`, there will be a
# `secondChild`. A `secondChild` can have a `firstChild`, and so on.
recurse_nodes(bsp_tree['secondChild'], nodes, all, properties)
# A `firstChild` without a `client` is a branch without leaves - no
# `node`s but there are more branches...
else:
recurse_nodes(bsp_tree['firstChild'], nodes, all, properties)
return nodes
Edit:
Then when you're like, hey, this window ought go to desktop 3, what's it called? What's the bspc syntax again? man this
& man that
, but instead you can run bspcd
and:
M: 4194308 HDMI-A-0
└── D: 4194310 1
├── N: 33554476 Firefox: Inbox | Fastmail — Mozilla Firefox
└── N: 33554508 Firefox: Wondering where I might be able to share a tool I've created,
`bspcd` (d for dump), `bspcq` (q for query) · Issue #1354 · baskerville/bspwm — Mozilla
Firefox
M: 4194306 DisplayPort-0
├── D: 4194311 2
│ ├── N: 44040193 Code: bspcq - bspcq - Visual Studio Code
│ ├── N: 94371842 Alacritty: bspcq -s ~
│ └── N: 104857602 Alacritty: ~/Code/bspcq
├── D: 4194312 3
│ └── N: 44040227 Code: bspcq - bin - Visual Studio Code
├── D: 4194313 4
├── D: 4194314 5
│ ├── N: 58720259 Google-chrome: Inbox - aiden@wowhub.co.nz - wowhub Mail - Google Chrome
│ └── N: 58720271 Google-chrome: Aiden Langley Service Agreement - Google Docs - Google Chrome
└── D: 4194315 6
Here's an update: https://github.com/aidenlangley/bspcq
It's not trivial to try to find the className, or 'flags', on a node, or other relevant information about any bsp domain. I wrote some code that makes life a little easier, and I'm wondering if it'll be of any use to a wider audience, and if so, where might it go?
This is the kind of information it produces - the idea is it's for humans, but it shouldn't be all that difficult to be consumed by other applications. If it's useful, it can of course be enhanced in a number of ways.
It's in Python, with a sh wrapper for invocation via
bspcd n
for node info,bspcd d/m
for desktop/monitor, yada yada. I'm adding a--fancy
flag so a very human readable format can be output instead.Edit: Removed previews, more up to date images below.