summary refs log tree commit diff
path: root/bin/swq
diff options
context:
space:
mode:
Diffstat (limited to 'bin/swq')
-rwxr-xr-xbin/swq318
1 files changed, 185 insertions, 133 deletions
diff --git a/bin/swq b/bin/swq
index 11128ee..4d8ac4c 100755
--- a/bin/swq
+++ b/bin/swq
@@ -4,157 +4,209 @@
 #  convenience queries into the sway container tree
 #
 
-swtree()
-{
-    swaymsg -t get_tree
+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_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_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"
+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"
 }
+
 has_ws() {
-    swtree | jq "[ .. | select(.type?==\"workspace\" and .name?==\"$1\") ]"
+	swtree | jq --arg name "$1" '[ .. | select(.type?=="workspace" and .name?==$name) ]'
 }
 
-latest()
-{
-    type="$1"
-    swtree | jq "[ .. | select(.type?==\"$type\") ] | max_by(.id)"
+has_id() {
+	swtree | jq --argjson arg "{\"id\":$1}" '[ .. | select(.id?==$arg.id) ]'
 }
 
-list()
-{
-    swtree | jq "[ .. | select(.type?==\"$1\") | .nodes=[\"...\"] ]"
+locate_output_for_con() {
+	swtree | jq --argjson arg "{\"con_id\":$1}" '[ .. | select(.type?=="output") as $o | .. | select(.id?==$arg.con_id) | $o ]'
 }
 
-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
+latest() {
+	swtree | jq --arg type "$1" '[ .. | select(.type? and (.type|test($type))) ] | max_by(.id)'
 }
 
-# meta commands
-
-_has()
-{
-    case "$1" in
-        appid) has_appid "$2" ;;
-        pid) has_pid "$2";;
-        exe) has_exe "$2";;
-        ws) has_ws "$2";;
-        *)
-            printf 'usage: swq has COMMAND <args>\n'
-            printf '\nCOMMANDS:\n'
-            printf ' appid: returns the json of the window filtered by app_id/class (fuzzy matching)\n'
-            printf ' pid:   returns json of the window filtered by pid\n'
-            printf ' exe:   returns json of the window filtered by process name\n'
-            printf ' ws:    returns json of the window filtered by workspace\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 <con|workspace|output>\n\n'
-            exit 2 ;;
-    esac
+list() {
+	swtree | jq --arg type "$1" '[ .. | select(.type? and (.type|test($type))) ]'
 }
-_list()
-{
-    [ -n "$1" ] || { echo "usage: swq list <con|workspace>"; exit 1; }
-    [ "$1" == "ws" ] && _list workspace
-    list "$1"
-}
-_current()
-{
-    case "$1" in
-        window) _current con ;;
-        con) swtree | jq '.. | select((.type? | test("con")?) and .focused?)' ;;
-
-        ws) _current workspace ;;
-        workspace) swtree | jq '.. | select(.type?=="workspace") | . as $parent | .. | select(.focused?==true) | $parent' ;;
-        output) $0 current workspace | jq -r '.output'  ;;
-        output-full) $0 list output | jq ".[] | select((.type?==\"output\") and (.name?==\"$($0 current output)\"))" ;;
-        *)
-            printf 'usage: swq current <con|workspace|output>\n\n'
-            exit 2 ;;
-    esac
+
+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
 }
 
 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 $@ ;;
-
-    -h|--help|help)
-        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 <appid> <ws>:  move container with <appid> to <ws>\n'
-        printf '\n'
-        exit 2 ;;
-
-    *) swtree ;;
+has)
+	shift
+	case "$1" in
+	appid) has_appid "$2" ;;
+	pid) has_pid "$2" ;;
+	exe) has_exe "$2" ;;
+	ws) has_ws "$2" ;;
+	id) has_id "$2" ;;
+	*)
+		printf 'usage: swq has COMMAND <args>\n'
+		printf '\nCOMMANDS:\n'
+		printf ' appid: returns json of the window filtered by app_id/class (fuzzy matching)\n'
+		printf ' pid:   returns json of the window filtered by pid\n'
+		printf ' exe:   returns json of the window filtered by process name\n'
+		printf ' ws:    returns json of the window filtered by workspace\n'
+		printf ' id:    returns json of the window filtered by id\n'
+		printf '\n'
+		exit 2
+		;;
+	esac
+	;;
+
+locate)
+	shift
+	case "$1" in
+	output-for-con) locate_output_for_con "$2" ;;
+	*)
+		printf 'usage: swq locate COMMAND <args>\n'
+		printf '\nCOMMANDS:\n'
+		printf ' output-for-con: returns output containing con_id\n'
+		printf '\n'
+		exit 2
+		;;
+	esac
+	;;
+
+latest)
+	shift
+	case "$1" in
+	workspace | ws) latest workspace ;;
+	container | con) latest con ;;
+	output) latest output ;;
+	*)
+		printf 'usage: swq latest <con|workspace|output>\n\n'
+		exit 2
+		;;
+	esac
+	;;
+
+list | ls)
+	shift
+	[ -n "$1" ] || {
+		echo "usage: swq list <con|workspace|output>"
+		exit 1
+	}
+	[ "$1" == "ws" ] && list workspace
+	list "$1"
+	;;
+
+current | cur)
+	shift
+	case "$1" in
+	window) _current con ;;
+	con) swtree | jq '.. | select((.type? | test("con")?) and .focused?)' ;;
+
+	ws) _current workspace ;;
+	workspace) swtree | jq '.. | select(.type?=="workspace") | . as $parent | .. | select(.focused?==true) | $parent' ;;
+	output) $0 current workspace | jq -r '.output' ;;
+	output-full) $0 list output | jq ".[] | select((.type?==\"output\") and (.name?==\"$($0 current output)\"))" ;;
+	*)
+		printf 'usage: swq current <con|workspace|output|output-full>\n\n'
+		exit 2
+		;;
+	esac
+	;;
+
+pick)
+	shift
+	pos=$(slurp -p -f '{"x":%x,"y":%y}')
+	case "${1:-con}" in
+	con)
+		swtree | jq --argjson p "$pos" '[.. | select((.type? | test("con")?) and .visible?==true and ($p.x >= .rect.x and $p.x <= (.rect.x + .rect.width)) and ($p.y >= .rect.y and $p.y <= (.rect.y + .rect.height)))]'
+		;;
+	*)
+		printf 'usage: swq pick <con|workspace|output>\n\n'
+		exit 2
+		;;
+	esac
+	;;
+
+geometry)
+	shift
+	first_or_last=${1:-last}
+	jq -r "[..|select(.type? and (.type|test(\"con\")))]|${first_or_last}|.rect|[([.x,.y]|join(\",\")),([.width,.height]|join(\"x\"))]|join(\" \")"
+	;;
+
+focus)
+	shift
+	first_or_last=${1:-last}
+	jq -r "[..|select(.type? and (.type|test(\"con\")))]|${first_or_last}|.id" | xargs -I{} sway [con_id={}] focus
+	;;
+
+moveto)
+	shift
+	moveto $@
+	;;
+
+-h | --help | help)
+	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 ' pick:          use slurp to identify\n'
+
+	printf '\n'
+	printf 'ACTION COMMANDS:\n'
+	printf ' focus: focus a container (takes stdin)\n'
+	printf ' moveto <appid> <ws>: move container with <appid> to <ws>\n'
+	printf ' geometry: print slurp-like `%%x,%%y %%w,%%h` expression (takes stdin)\n'
+	printf '\n'
+	exit 2
+	;;
+
+*) swtree ;;
 esac