aboutsummarylogtreecommitdiffstats
path: root/i3-lru.sh
blob: 65965e51f6a8fac5f7f35b579a29af5f884caf8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env bash

CACHE_FILE="${HOME}/.cache/i3-lru-order"

# 1) If the file doesn't exist, or is empty, bail.
[ -f "${CACHE_FILE}" ] || exit 0

# Read the entire i3 tree JSON just once.
i3_tree_json="$(i3-msg -t get_tree)"

# Build a mapping of con_id (as a string) -> label.
mapped_windows="$(
	echo "$i3_tree_json" | jq -r '
    def descend: recurse(.nodes[], .floating_nodes[]);
    descend
    | select(.window_properties? or .window?)
    | [
        (.id|tostring),
        (
          if .window_properties? and .window_properties.class? then
            "\(.name) (\(.window_properties.class))"
          else
            .name // ""
          end
        )
      ]
      | @tsv
  '
)"

declare -A id_to_label
while IFS=$'\t' read -r con_id con_label; do
	id_to_label["$con_id"]="$con_label"
done <<<"$mapped_windows"

# Build a list of valid labels in LRU order
declare -a valid_labels=()

while IFS= read -r wid; do
	[ -z "$wid" ] && continue
	label="${id_to_label["$wid"]}"
	[ -z "$label" ] && continue
	valid_labels+=("$label")
done <"$CACHE_FILE"

# If no valid windows remain, exit silently.
[ ${#valid_labels[@]} -eq 0 ] && exit 0

# Show them in rofi, with the second item (row index 1) selected by default.
# If there's only 1 item, rofi will silently fall back to row 0.
selection="$(
	printf '%s\n' "${valid_labels[@]}" |
		rofi -dmenu -i -p "Switch to" -selected-row 1
)"

# If the user canceled or made no selection, exit.
[ -z "$selection" ] && exit 0

# Reverse lookup: label -> ID
selected_id=""
for con_id in "${!id_to_label[@]}"; do
	if [[ "${id_to_label["$con_id"]}" == "$selection" ]]; then
		selected_id="$con_id"
		break
	fi
done

# Focus the chosen window
[ -n "$selected_id" ] && i3-msg "[con_id=\"${selected_id}\"] focus" >/dev/null