dotfiles/.local/share/dabruh/libs/bash/i3.sh

138 lines
4.2 KiB
Bash
Raw Normal View History

#!/bin/bash
# This script contains utility functions related to i3 workspaces.
# Ensure required functions exist
if ! command -v monitor_exist >/dev/null 2>&1; then
echo "monitor_exist function is required but not found. Please source x.sh before i3.sh." 1>&2
exit 1
fi
# Get the list of empty i3 workspaces.
# Usage: get_empty_i3_workspaces
get_empty_i3_workspaces() {
set -euo pipefail
i3-msg -t get_tree | jq -r '
recurse(.nodes[]?) |
select(.type == "workspace") |
select(.name | test("^[^_].*")) |
select(.nodes | length == 0) |
.name
'
}
# Check if the i3 workspace is empty.
# Usage: i3_workspace_is_empty <workspace_name>
i3_workspace_is_empty() {
set -euo pipefail
local workspace_name=${1:?Workspace name not set}
local empty_workspace
empty_workspace=$(get_empty_i3_workspaces)
for workspace in $empty_workspace; do
if [ "$workspace" = "$workspace_name" ]; then
return 0
fi
done
return 1
}
# Get a comma separated list of i3 workspace names and the output they are on.
# Usage: get_i3_workspaces
get_i3_workspaces() {
set -euo pipefail
i3-msg -t get_workspaces | jq -r '.[] | .name + "," + .output'
}
# Get a property of an i3 workspace.
# Usage: get_i3_workspace_prop <workspace_name> <property>
get_i3_workspace_prop() {
set -euo pipefail
local workspace_name=${1:?Workspace name not set}
local prop=${2:?Property not set}
i3-msg -t get_workspaces | jq -r ".[] | select(.name == \"$workspace_name\") | .$prop"
}
# Check if an i3 workspace exists.
# Usage: i3_workspace_exists <workspace_name>
i3_workspace_exists() {
set -euo pipefail
local workspace_name=${1:?Workspace name not set}
if [[ -n "$(get_i3_workspace_prop "$workspace_name" name)" ]]; then
return 0
fi
return 1
}
# Move an i3 workspace to a different monitor.
# Usage: move_i3_workspace <workspace_name> <monitor_name> [increment]
move_i3_workspace() {
set -euo pipefail
local workspace_name=${1:?Workspace name not set}
local monitor_name=${2:?Monitor name not set}
local increment=${3:-0}
local new_workspace_name="$workspace_name"
if ! i3_workspace_exists "$workspace_name"; then
echo "Workspace $workspace_name not found" 1>&2
return 1
elif ! monitor_exist "$monitor_name"; then
echo "Monitor $monitor_name not found" 1>&2
return 1
fi
if [[ "$(get_i3_workspace_prop "$workspace_name" output)" == "$monitor_name" ]]; then
echo "Workspace $workspace_name is already on monitor $monitor_name" 1>&2
return 1
fi
if [[ "$workspace_name" =~ ^[0-9]+$ ]]; then
new_workspace_name=$((workspace_name + increment))
elif [ "$increment" -ne 0 ]; then
echo "Workspace name is not an integer. Unable to increment/decrement." 1>&2
return 1
fi
if i3_workspace_exists "$new_workspace_name"; then
if [[ "$new_workspace_name" != "$workspace_name" ]]; then
echo "Workspace $new_workspace_name already exists" 1>&2
return 1
fi
fi
echo "Moving workspace $workspace_name to monitor $monitor_name as $new_workspace_name"
i3-msg "workspace $workspace_name" 1>/dev/null
i3-msg "rename workspace $workspace_name to $new_workspace_name" 1>/dev/null
i3-msg "move workspace to output $monitor_name" 1>/dev/null
}
# Move all workspaces to a specified monitor.
# Usage: move_nonexistent_i3_workspaces <monitor_name> [increment]
move_nonexistent_i3_workspaces() {
set -euo pipefail
local monitor_name=${1:?Monitor name not set}
local increment=${2:-0}
local workspaces
workspaces=$(get_i3_workspaces)
echo "Moving workspaces to monitor $monitor_name"
for workspace in $workspaces; do
local workspace_name
local workspace_output
workspace_name=$(echo "$workspace" | cut -d',' -f1)
workspace_output=$(echo "$workspace" | cut -d',' -f2)
if i3_workspace_is_empty "$workspace_name"; then
echo "Skipping empty workspace $workspace_name"
continue
fi
if ! monitor_exist "$workspace_output"; then
move_i3_workspace "$workspace_name" "$monitor_name" "$increment"
fi
done
}