gardesk/gar / 0fded69

Browse files

Add sample init.lua configuration

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
0fded6932a081ba5595cb143c4fdc8eccc6aa513
Parents
8a1594a
Tree
6d5c0ef

1 changed file

StatusFile+-
A examples/init.lua 373 0
examples/init.luaadded
@@ -0,0 +1,373 @@
1
+-- gar default configuration
2
+-- Copy to ~/.config/gar/init.lua to customize
3
+
4
+-- Autostart applications (only run once per session)
5
+-- gar.exec_once("random-bg cold")  -- Pick random wallpaper from a themed directory
6
+-- garbg daemon is managed by systemd (garbg.service) with internal X11 retry
7
+gar.exec_once("garbg set ~/Pictures/background/cold/ --random")
8
+
9
+-- Screen locker daemon
10
+gar.exec_once("garlock daemon")
11
+
12
+-- Clipboard manager daemon
13
+gar.exec_once("garclip daemon --foreground")
14
+
15
+-- Uncomment the ones you want:
16
+-- gar.exec_once("picom")                      -- Compositor (for transparency/shadows)
17
+-- gar.exec_once("dunst")                      -- Notification daemon
18
+-- gar.exec_once("nm-applet")                  -- NetworkManager tray icon
19
+-- gar.exec_once("blueman-applet")             -- Bluetooth tray icon
20
+-- gar.exec_once("xss-lock -- i3lock -c 000000")    -- Auto-lock on suspend
21
+
22
+-- Appearance
23
+gar.set("border_width", 2)
24
+gar.set("border_color_focused", "#5294e2")
25
+gar.set("border_color_unfocused", "#2d2d2d")
26
+gar.set("gap_inner", 12)
27
+gar.set("gap_outer", 16)
28
+
29
+-- Visual Effects (picom compositor)
30
+-- gar auto-generates ~/.config/gar/picom.conf from these settings
31
+-- Changes take effect on reload (Mod+Shift+R) - picom is signaled automatically
32
+gar.set("corner_radius", 18)              -- 0 = square corners
33
+gar.set("blur_enabled", true)
34
+gar.set("blur_method", "dual_kawase")     -- "gaussian", "dual_kawase", "box"
35
+gar.set("blur_strength", 5)               -- 1-20 for dual_kawase
36
+gar.set("shadow_enabled", true)
37
+gar.set("shadow_radius", 12)
38
+gar.set("shadow_opacity", 0.75)
39
+gar.set("shadow_offset_x", -7)
40
+gar.set("shadow_offset_y", -7)
41
+gar.set("opacity_focused", 0.94)
42
+gar.set("opacity_unfocused", 0.6)         -- Set to 0.9 to dim unfocused windows
43
+gar.set("fade_enabled", true)
44
+gar.set("fade_delta", 3)
45
+
46
+-- Title bars (disabled by default)
47
+-- gar.set("titlebar_enabled", true)
48
+-- gar.set("titlebar_height", 20)
49
+-- gar.set("titlebar_color_focused", "#3d3d3d")
50
+-- gar.set("titlebar_color_unfocused", "#2d2d2d")
51
+-- gar.set("titlebar_text_color", "#ffffff")
52
+
53
+-- Border gradients (purple to blue theme)
54
+-- direction options: "vertical", "horizontal", "diagonal"
55
+gar.set("border_gradient_enabled", true)
56
+gar.set("border_gradient_start_focused", "#9b59b6")    -- Purple
57
+gar.set("border_gradient_end_focused", "#3498db")      -- Blue
58
+gar.set("border_gradient_start_unfocused", "#4a235a")  -- Dark purple
59
+gar.set("border_gradient_end_unfocused", "#1a5276")    -- Dark blue
60
+gar.set("border_gradient_direction", "diagonal")
61
+
62
+-- Animations (picom v12+)
63
+-- open options: "slide-in", "fly-in", "appear", "none"
64
+-- close options: "slide-out", "fly-out", "disappear", "none"
65
+gar.set("animation_open", "appear")
66
+gar.set("animation_close", "disappear")
67
+gar.set("animation_duration", 0.15)      -- seconds
68
+
69
+-- Custom GLSL shader (picom, requires GLX backend)
70
+-- Bundled shaders: ~/.config/gar/shaders/focused-glow.glsl, dim-unfocused.glsl
71
+-- gar.set("picom_shader", "~/.config/gar/shaders/focused-glow.glsl")
72
+
73
+-- Per-window picom rules
74
+-- NOTE: When using rules, picom ignores old-style options (inactive-opacity, shadow-exclude, etc.)
75
+-- Only enable rules if you want full control via rules-based config
76
+-- Available rule options: corner_radius, opacity, shadow, blur_background, shader
77
+-- Match syntax: class_g = 'ClassName', class_i = 'instance', name = 'title', window_type = 'type'
78
+-- gar.picom_rule({
79
+--     match = "class_g = 'Alacritty'",
80
+--     blur_background = true,
81
+--     opacity = 0.92,
82
+-- })
83
+-- gar.picom_rule({
84
+--     match = "class_g = 'firefox'",
85
+--     corner_radius = 8,
86
+-- })
87
+
88
+-- garbar status bar (native gar integration)
89
+-- When this table is present, gar automatically spawns and manages garbar
90
+gar.bar = {
91
+    height = 32,
92
+    position = "top",
93
+    background = "#1a1a1a",
94
+    foreground = "#ffffff",
95
+    opacity = 1.0,
96
+    fonts = {
97
+        "JetBrainsMono Nerd Font:size=10",
98
+        "Symbols Nerd Font:size=10",
99
+    },
100
+    padding = { left = 8, right = 16, top = 0, bottom = 0 },
101
+
102
+    -- Module layout
103
+    modules_left = { "workspaces", "window_title" },
104
+    modules_center = {},
105
+    modules_right = { "almanta", "filesystem", "memory", "cpu", "battery", "wlan", "volume", "datetime" },
106
+
107
+    -- Module configurations
108
+    modules = {
109
+        workspaces = {
110
+            font_size = 11,
111
+            focused = {
112
+                foreground = "#ffffff",
113
+                background = "transparent",
114
+                underline = { width = 2, color = "#33ccff" },
115
+            },
116
+            unfocused = {
117
+                foreground = "#666666",
118
+                background = "transparent",
119
+            },
120
+            urgent = {
121
+                foreground = "#ffffff",
122
+                background = "#ff5555",
123
+            },
124
+        },
125
+        window_title = {
126
+            max_length = 50,
127
+            empty_text = "Desktop",
128
+        },
129
+        datetime = {
130
+            format = " %a %b %d   %H:%M",
131
+        },
132
+        cpu = {
133
+            format = " {usage}%",
134
+        },
135
+        memory = {
136
+            format = " {percent}%",
137
+        },
138
+        battery = {
139
+            device = "auto",
140
+            format_charging = " {percent}%",
141
+            format_discharging = " {percent}%",
142
+            format_full = " Full",
143
+        },
144
+        -- Script modules (custom commands)
145
+        script = {
146
+            almanta = {
147
+            exec = [[
148
+HOST="espadon@almanta"
149
+SSH_OPTS="-T -o BatchMode=yes -o ConnectTimeout=2 -o ConnectionAttempts=1"
150
+if ! ssh $SSH_OPTS "$HOST" "echo ok" >/dev/null 2>&1; then
151
+  echo "almanta: down"
152
+  exit 0
153
+fi
154
+load=$(ssh $SSH_OPTS "$HOST" "cut -d' ' -f1 /proc/loadavg" 2>/dev/null || echo "?")
155
+mem=$(ssh $SSH_OPTS "$HOST" "free | grep '^Mem:' | awk '{printf \"%.0f\", (\$3/\$2)*100}'" 2>/dev/null || echo "?")
156
+disk=$(ssh $SSH_OPTS "$HOST" "df / | tail -1 | awk '{print \$5}' | tr -d '%'" 2>/dev/null || echo "?")
157
+echo "almanta L:$load M:$mem% D:$disk%"
158
+]],
159
+            interval = 30,
160
+        },
161
+        filesystem = {
162
+            exec = [[df -h / | awk 'NR==2 {print " " $4}']],
163
+            interval = 60,
164
+        },
165
+        wlan = {
166
+            exec = [[
167
+IFACE="wlp1s0f0"
168
+if [ -d "/sys/class/net/$IFACE" ]; then
169
+  STATE=$(cat /sys/class/net/$IFACE/operstate 2>/dev/null)
170
+  if [ "$STATE" = "up" ]; then
171
+    ESSID=$(iwgetid -r 2>/dev/null || echo "")
172
+    IP=$(ip -4 addr show $IFACE 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)
173
+    if [ -n "$ESSID" ]; then
174
+      echo " $ESSID $IP"
175
+    else
176
+      echo " connected"
177
+    fi
178
+  else
179
+    echo " offline"
180
+  fi
181
+else
182
+  echo " N/A"
183
+fi
184
+]],
185
+            interval = 5,
186
+        },
187
+        volume = {
188
+            exec = [[
189
+if command -v pamixer >/dev/null 2>&1; then
190
+  if pamixer --get-mute | grep -q true; then
191
+    echo " muted"
192
+  else
193
+    VOL=$(pamixer --get-volume)
194
+    echo " $VOL%"
195
+  fi
196
+elif command -v pactl >/dev/null 2>&1; then
197
+  VOL=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -oP '\d+%' | head -1)
198
+  MUTE=$(pactl get-sink-mute @DEFAULT_SINK@ | grep -oP 'yes|no')
199
+  if [ "$MUTE" = "yes" ]; then
200
+    echo " muted"
201
+  else
202
+    echo " $VOL"
203
+  fi
204
+else
205
+  echo " N/A"
206
+fi
207
+]],
208
+            interval = 1,
209
+        },
210
+        },
211
+    },
212
+}
213
+
214
+-- Behavior
215
+gar.set("follow_window_on_move", true)  -- Follow window when using Mod+Shift+number
216
+
217
+-- Mod key: "mod" = Super/Win, "alt" = Alt
218
+-- Use "mod" for real X session, "alt" for nested testing (Xephyr)
219
+local mod = "mod"
220
+
221
+-- Terminal
222
+gar.bind(mod .. "+Return", function()
223
+    gar.exec("alacritty || kitty || foot || xterm")
224
+end)
225
+
226
+-- Close window
227
+gar.bind(mod .. "+q", gar.close_window)
228
+
229
+-- Reload config
230
+gar.bind(mod .. "+shift+r", gar.reload)
231
+
232
+-- Exit gar (return to display manager)
233
+gar.bind(mod .. "+shift+e", gar.exit)
234
+
235
+-- Focus navigation (arrow keys)
236
+gar.bind(mod .. "+Left", gar.focus("left"))
237
+gar.bind(mod .. "+Right", gar.focus("right"))
238
+gar.bind(mod .. "+Up", gar.focus("up"))
239
+gar.bind(mod .. "+Down", gar.focus("down"))
240
+
241
+-- Focus navigation (vim keys)
242
+gar.bind(mod .. "+h", gar.focus("left"))
243
+gar.bind(mod .. "+l", gar.focus("right"))
244
+gar.bind(mod .. "+k", gar.focus("up"))
245
+gar.bind(mod .. "+j", gar.focus("down"))
246
+
247
+-- Swap windows
248
+gar.bind(mod .. "+shift+Left", gar.swap("left"))
249
+gar.bind(mod .. "+shift+Right", gar.swap("right"))
250
+gar.bind(mod .. "+shift+Up", gar.swap("up"))
251
+gar.bind(mod .. "+shift+Down", gar.swap("down"))
252
+
253
+gar.bind(mod .. "+shift+h", gar.swap("left"))
254
+gar.bind(mod .. "+shift+l", gar.swap("right"))
255
+gar.bind(mod .. "+shift+k", gar.swap("up"))
256
+gar.bind(mod .. "+shift+j", gar.swap("down"))
257
+
258
+-- Resize
259
+gar.bind(mod .. "+ctrl+Left", gar.resize("left", 0.05))
260
+gar.bind(mod .. "+ctrl+Right", gar.resize("right", 0.05))
261
+gar.bind(mod .. "+ctrl+Up", gar.resize("up", 0.05))
262
+gar.bind(mod .. "+ctrl+Down", gar.resize("down", 0.05))
263
+
264
+gar.bind(mod .. "+ctrl+h", gar.resize("left", 0.05))
265
+gar.bind(mod .. "+ctrl+l", gar.resize("right", 0.05))
266
+gar.bind(mod .. "+ctrl+k", gar.resize("up", 0.05))
267
+gar.bind(mod .. "+ctrl+j", gar.resize("down", 0.05))
268
+
269
+-- Equalize splits
270
+gar.bind(mod .. "+e", gar.equalize)
271
+
272
+-- Toggle floating
273
+gar.bind(mod .. "+f", gar.toggle_floating)
274
+
275
+-- Toggle fullscreen
276
+gar.bind(mod .. "+shift+f", gar.toggle_fullscreen)
277
+
278
+-- Cycle through floating windows
279
+gar.bind(mod .. "+grave", gar.cycle_floating)  -- Mod+` (backtick)
280
+
281
+-- Workspaces
282
+for i = 1, 9 do
283
+    gar.bind(mod .. "+" .. i, gar.workspace(i))
284
+    gar.bind(mod .. "+shift+" .. i, gar.move_to_workspace(i))
285
+end
286
+gar.bind(mod .. "+0", gar.workspace(10))
287
+gar.bind(mod .. "+shift+0", gar.move_to_workspace(10))
288
+
289
+-- Multi-monitor (comma/period = prev/next)
290
+gar.bind(mod .. "+comma", gar.focus_monitor("prev"))
291
+gar.bind(mod .. "+period", gar.focus_monitor("next"))
292
+gar.bind(mod .. "+shift+comma", gar.move_to_monitor("prev"))
293
+gar.bind(mod .. "+shift+period", gar.move_to_monitor("next"))
294
+
295
+-- Workspace cycling
296
+gar.bind(mod .. "+Tab", gar.workspace_next())
297
+gar.bind(mod .. "+shift+Tab", gar.workspace_prev())
298
+
299
+-- Launchers (garlaunch)
300
+local garlaunch = os.getenv("HOME") .. "/.cargo/bin/garlaunch"
301
+gar.bind(mod .. "+space", function()
302
+    gar.exec(garlaunch .. " --mode drun 2>/tmp/garlaunch-debug.log")
303
+end)
304
+gar.bind(mod .. "+shift+space", function()
305
+    gar.exec(garlaunch .. " --mode window 2>/tmp/garlaunch-debug.log")
306
+end)
307
+gar.bind(mod .. "+r", function()
308
+    gar.exec(garlaunch .. " --mode run 2>/tmp/garlaunch-debug.log")
309
+end)
310
+
311
+-- dmenu alternative (if rofi not available)
312
+gar.bind(mod .. "+p", function()
313
+    gar.exec("dmenu_run")
314
+end)
315
+
316
+-- Screenshot (requires scrot or maim)
317
+gar.bind("Print", function()
318
+    gar.exec("scrot -e 'mv $f ~/Pictures/' || maim ~/Pictures/screenshot-$(date +%s).png")
319
+end)
320
+gar.bind(mod .. "+Print", function()
321
+    gar.exec("scrot -s -e 'mv $f ~/Pictures/' || maim -s ~/Pictures/screenshot-$(date +%s).png")
322
+end)
323
+
324
+-- Screenshot (garshot)
325
+gar.bind("ctrl+shift+3", function()
326
+    gar.exec("garshot select --annotate")  -- Region selection with annotation editor
327
+end)
328
+gar.bind("ctrl+shift+4", function()
329
+    gar.exec("garshot select")  -- Interactive region selection with blur overlay
330
+end)
331
+gar.bind("ctrl+shift+5", function()
332
+    gar.exec("garshot screen")  -- Full screen capture
333
+end)
334
+gar.bind("ctrl+shift+6", function()
335
+    gar.exec("garshot window")  -- Active window capture
336
+end)
337
+
338
+-- Slideshow mode (Mod+Shift+P to avoid conflict with dmenu on Mod+P)
339
+gar.bind(mod .. "+shift+p", function() gar.exec("garbg set ~/Pictures/background/cold/ --random --interval 2m") end)
340
+
341
+-- Lock screen (requires i3lock, swaylock, or slock)
342
+gar.bind(mod .. "+Escape", function()
343
+    gar.exec("i3lock -c 000000 || swaylock -c 000000 || slock")
344
+end)
345
+
346
+-- Lock screen with garlock (via daemon)
347
+gar.bind(mod .. "+shift+q", function()
348
+    gar.exec("garlock lock")
349
+end)
350
+
351
+-- Volume controls (requires pactl/pamixer)
352
+gar.bind("XF86AudioRaiseVolume", function()
353
+    gar.exec("pactl set-sink-volume @DEFAULT_SINK@ +5% || pamixer -i 5")
354
+end)
355
+gar.bind("XF86AudioLowerVolume", function()
356
+    gar.exec("pactl set-sink-volume @DEFAULT_SINK@ -5% || pamixer -d 5")
357
+end)
358
+gar.bind("XF86AudioMute", function()
359
+    gar.exec("pactl set-sink-mute @DEFAULT_SINK@ toggle || pamixer -t")
360
+end)
361
+
362
+-- Brightness controls (requires brightnessctl or light)
363
+gar.bind("XF86MonBrightnessUp", function()
364
+    gar.exec("brightnessctl set +10% || light -A 10")
365
+end)
366
+gar.bind("XF86MonBrightnessDown", function()
367
+    gar.exec("brightnessctl set 10%- || light -U 10")
368
+end)
369
+
370
+-- Clipboard history (garclip)
371
+gar.bind(mod .. "+shift+v", function()
372
+    gar.exec("garclip-picker")
373
+end)