-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathworkspaces
executable file
·114 lines (99 loc) · 3.24 KB
/
workspaces
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env bb
(require '[babashka.process :as p :refer [shell process destroy-tree]]
'[clojure.java.io :as io])
(def workspace-stream
(process
{:err :inherit
:shutdown destroy-tree}
(str "swaymsg -t subscribe -m \"['workspace', 'window']\"")))
(defn- sway-cmd [type]
(as-> (str "swaymsg -t " type) clients
(shell {:out :string} clients)
(:out clients)
(json/parse-string clients true)))
(defn- get-tree []
(sway-cmd "get_tree"))
(defn- get-displays []
(as-> (get-tree) tree
(:nodes tree)
(remove (fn [cand] (#{"__i3"} (:name cand))) tree)))
(defn gtk-theme []
(-> {:out :string}
(shell "gsettings get org.gnome.desktop.interface icon-theme")
:out
str/split-lines
first
(str/replace #"'" "")))
(defn flatpak-name [class]
(->> (shell {:out :string} "flatpak list --app")
:out
str/split-lines
(some
(fn [line]
(let [[name id & _] (str/split line #"\t")]
(when (= name class)
id))))))
(defn find-icon [name]
(when name
(first
(remove
nil?
(flatten
(for [theme [(gtk-theme) "hicolor"]]
(for [path ["scalable/apps" "apps/scalable"]]
(for [file [name (str/lower-case name) (flatpak-name name)]]
(for [root ["/usr/local/share/icons" "/usr/share/icons" "~/.icons" "~/.local/share/icons" "/var/lib/flatpak/exports/share/icons"]]
(let [file (fs/expand-home (fs/path root theme path (str file ".svg")))]
(when (fs/exists? file)
(str file))))))))))))
(def get-icon (memoize find-icon))
(defn- parse-client [client]
(merge
(select-keys client [:name :focused :urgent :visible])
{:icon (or (get-icon (:app_id client))
(get-icon (get-in client [:window_properties :instance]))
(get-icon (get-in client [:window_properties :class]))
"")}))
(defn- representation->clients [workspace]
(reduce
(fn [clients client]
(conj
clients
(if (#{"splitv" "splith" "tabbed"} (:layout client))
(map parse-client (:nodes client))
(parse-client client))))
[]
(:nodes workspace)))
(defn- some-in-tree [key tree]
(true? (or (some key tree)
(some (fn [container]
(some key (:nodes container)))
tree))))
(defn workspace-tree []
(reduce
(fn [result display]
(let [nodes (:nodes display)]
(conj
result
(map (fn [workspace]
{:name (:name workspace)
:clients (representation->clients workspace)
:focused (or (and (empty? (:nodes workspace))
(some-in-tree :focused (:nodes display)))
(some-in-tree :focused (:nodes workspace)))
:visible (or (empty? (:nodes workspace))
(some-in-tree :visible (:nodes workspace)))})
nodes))))
[]
(get-displays)))
(defn output []
(->> (workspace-tree)
json/generate-string
println))
(output)
(with-open [rdr (io/reader (:out workspace-stream))]
(binding [*in* rdr]
(loop []
(when-let [line (-> (read-line) (json/parse-string true))]
(output)
(recur)))))