#!/usr/bin/env bash swtree() { swaymsg -t get_tree } has_appid() { swtree | jq "[ .. | (select(.app_id?) | select(.app_id | test(\"$1\"))) // (select(.window_properties?.class?) | select(.window_properties.class | test(\"$1\"))) ]" } has_pid() { q='' IFS=$' '; for pid in $1; do if [[ -n $q ]]; then q=".pid?==$pid or $q" else q=".pid?==$pid" fi done swtree | jq "[ .. | select($q) ]" } has_exe() { pid_of_win="$(pgrep -x "$1" -d' ')" if [[ -z "$pid_of_win" ]]; then echo "process not found" >&2 exit 1 fi ppid_of_proc="$(ps -q "$(echo "$pid_of_win" | tr ' ' ',')" -o ppid= |tr -d ' '| tr '\n' ','| sed 's/,$//')" if [[ -z "$ppid_of_proc" ]]; then echo "parent process not found" >&2 fi IFS=$'\n'; for comm in $(ps -q "$ppid_of_proc" -o pid=,comm=); do if [[ "$comm" =~ ^.*sh$ ]]; then # parent process is a shell # need to get parent process of shell (the terminal emulator) pid_of_win="$pid_of_win $(ps -p "$(echo "$comm" | awk '{print $1}')" -o ppid= | tr -d ' ')" fi done if [[ -z "$pid_of_win" ]]; then echo "process not found" >&2 exit 1 fi has_pid "$pid_of_win" } latest() { type="$1" swtree | jq "[ .. | select(.type?==\"$type\") ] | max_by(.id)" } list() { swtree | jq "[ .. | select(.type?==\"$1\") | .nodes=[\"...\"] ]" } moveto() { if [ ! -t 0 ]; then read -r -i -e conId sway [con_id="$conId"] move to workspace "$1" else sway [app_id="$1"] move to workspace "$2" fi } # meta commands _has() { case "$1" in appid) has_appid "$2" ;; pid) has_pid "$2";; exe) has_exe "$2";; *) printf 'usage: swq has COMMAND \n' printf '\nCOMMANDS:\n' printf ' appid: returns the json of the window filtered by app_id/class (fuzzy matching)\n' printf ' pid: returns the json of the window filtered by pid\n' printf ' exe: returns the json of the window filtered by process name\n' printf '\n' exit 2 ;; esac } _latest() { case "$1" in workspace|ws) latest workspace ;; container|con) latest con ;; output) latest output ;; *) printf 'usage: swq latest \n\n' exit 2 ;; esac } _list() { [ -n "$1" ] || { echo "usage: swq list "; exit 1; } [ "$1" == "ws" ] && _list workspace list "$1" } _current() { case "$1" in window) _current con ;; con) swtree | jq '.. | select(.type?=="con" and .focused?==true)' ;; ws) _current workspace ;; workspace) swtree | jq '.. | select(.type?=="workspace") | . as $parent | .nodes[]? | if .focused then $parent else empty end' ;; output) $0 current workspace | jq -r '.output' ;; *) printf 'usage: swq current \n\n' exit 2 ;; esac } case "$1" in has) shift; _has $@ ;; latest) shift; _latest $@ ;; list|ls) shift; _list $@ ;; current|cur) shift; _current $@ ;; focus-latest-con) sway [con_id="$(latest con | jq -r '.id')"] focus ;; moveto) shift; moveto $@ ;; *) printf 'usage: swq COMMAND\n' printf '\n' printf 'QUERY COMMANDS:\n' printf ' has: get object by criteria\n' printf ' latest: get newest objects\n' printf ' list: list objects\n' printf ' current: get focused objects\n' printf '\n' printf 'ACTION COMMANDS:\n' printf ' focus-latest-con\n' printf ' moveto : move container with to \n' printf '\n' exit 2 ;; esac