Krolyxon
Commit 2495d96

Branches

Refs →

aurora2495d96

aurora: add runner and aurora-run, replace fuzzel

- Runner.qml: SUPER+R launcher (desktop apps + actions with icons, aurora
  commands, session actions, $PATH executables, =calc, >cmd, frecency)
- dmenu mode over the new `dmenu` IPC; .local/bin/aurora-run is a
  fuzzel-compatible front end (-d -p -l --placeholder --password --index)
- Fuzzy.qml / Session.qml shared with PowerMenu
- scripts use aurora-run; askpass-fuzzel -> aurora-askpass,
  fuzzelunicode -> aurora-chars
- drop fuzzel config, wal template and package
Author
krolyxon
Date
2026-10-19 22:20 +0530
Parent
15f3e25
Commit
2495d9653691ed55994c859be28d8d595bb0f64b

+733 −123

27 files changed

  1. D .config/fuzzel/fuzzel.ini +0 −31
  2. M .config/hypr/hyprland.lua +1 −1
  3. M .config/hypr/source/keybinds.lua +1 −2
  4. A .config/quickshell/aurora/Fuzzy.qml +25 −0
  5. M .config/quickshell/aurora/PowerMenu.qml +3 −46
  6. A .config/quickshell/aurora/Runner.qml +564 −0
  7. A .config/quickshell/aurora/Session.qml +35 −0
  8. M .config/quickshell/aurora/Theme.qml +5 −0
  9. M .config/quickshell/aurora/shell.qml +16 −0
  10. M .config/shell/profile +1 −1
  11. D .config/wal/templates/colors-fuzzel.ini +0 −11
  12. D .local/bin/askpass-fuzzel +0 −12
  13. A .local/bin/aurora-askpass +13 −0
  14. R .local/bin/fuzzelunicode → .local/bin/aurora-chars +1 −1
  15. A .local/bin/aurora-run +51 −0
  16. M .local/bin/bcn +1 −1
  17. M .local/bin/campus-login +1 −1
  18. M .local/bin/envyswitch +1 −1
  19. M .local/bin/hypr/hypr_screenshot.sh +1 −1
  20. M .local/bin/hypr/hypr_shader_menu.sh +3 −3
  21. M .local/bin/madd +2 −2
  22. M .local/bin/mounter +3 −3
  23. M .local/bin/movie +1 −1
  24. M .local/bin/unmounter +1 −1
  25. M .local/bin/waldl +1 −1
  26. M README.md +2 −2
  27. M packages/desktop.txt +0 −1
D .config/fuzzel/fuzzel.ini View
@@ -1,31 +0,0 @@
1−include=~/.cache/wal/colors-fuzzel.ini
2−
3−[main]
4−dpi-aware=no
5−lines=10
6−filter-desktop=yes
7−icon-theme=Papirus-Dark
8−font=JetBrains Mono Nerd Font:size=12
9−terminal=foot -e
10−list-executables-in-path=yes
11−password-character=*
12−width=80
13−horizontal-pad=10
14−vertical-pad=10
15−inner-pad=5
16−
17−# [colors]
18−# background=1e1e2edd
19−# text=cdd6f4ff
20−# prompt=bac2deff
21−# placeholder=7f849cff
22−# input=cdd6f4ff
23−# match=89b4faff
24−# selection=585b70ff
25−# selection-text=cdd6f4ff
26−# selection-match=89b4faff
27−# counter=7f849cff
28−# border=89b4faff
29−
30−[key-bindings]
31−execute-input=Control+Return Shift+KP_Enter
M .config/hypr/hyprland.lua View
@@ -1,5 +1,5 @@
11 terminal = "foot"
2−menu = "fuzzel"
2+menu = "aurora-run" -- aurora's runner
33 browser = "librewolf"
44 mainMod = "SUPER"
55
M .config/hypr/source/keybinds.lua View
@@ -37,7 +37,7 @@ hl.bind(mainMod .. " + SHIFT + b", hl.dsp.exec_cmd("systemctl --user restart aur
3737 hl.bind(mainMod .. " + R", hl.dsp.exec_cmd(menu))
3838 -- bind = $mainMod SHIFT, P, pseudo, # dwindle
3939 hl.bind(mainMod .. " + Tab", hl.dsp.window.cycle_next({ next = false }), { repeating = true })
40−hl.bind(mainMod .. " + grave", hl.dsp.exec_cmd("fuzzelunicode"))
40+hl.bind(mainMod .. " + grave", hl.dsp.exec_cmd("aurora-chars"))
4141 hl.bind(mainMod .. " + escape", hl.dsp.exec_cmd("qs -c aurora ipc call shell power"))
4242
4343 -- Applications
@@ -63,7 +63,6 @@ hl.bind(mainMod .. " + k", hl.dsp.window.resize({ x = 0, y = -30, relative = tru
6363 hl.bind(mainMod .. " + j", hl.dsp.window.resize({ x = 0, y = 30, relative = true }), { repeating = true })
6464
6565 -- Clipboard menu (cliphist)
66−-- hl.bind(mainMod .. " + v", hl.dsp.exec_cmd("sh -c \"cliphist list | fuzzel --dmenu --with-nth 2 | cliphist decode | wl-copy\""))
6766 hl.bind(mainMod .. " + v", hl.dsp.exec_cmd("qs -c aurora ipc call shell clip"))
6867
6968 -- -----------------------------------------------------
A .config/quickshell/aurora/Fuzzy.qml View
@@ -0,0 +1,25 @@
1+pragma Singleton
2+import QtQuick
3+import Quickshell
4+
5+// fuzzel-style matching shared by PowerMenu and Runner.
6+Singleton {
7+ // query chars must appear in order; prefix > word start > contiguous > scattered. q must be lowercase.
8+ function score(label, q) { return scoreLow(label.toLowerCase(), q) }
9+ // same, for an already lowercased s (big dmenu lists lowercase once, not per keystroke)
10+ function scoreLow(s, q) {
11+ if (q === "") return 1
12+ if (s.indexOf(q) === 0) return 1000
13+ var w = s.indexOf(" " + q)
14+ if (w >= 0) return 500
15+ if (s.indexOf(q) >= 0) return 300
16+ var pos = 0, gaps = 0
17+ for (var i = 0; i < q.length; i++) {
18+ var f = s.indexOf(q[i], pos)
19+ if (f < 0) return 0
20+ gaps += f - pos
21+ pos = f + 1
22+ }
23+ return 100 - gaps
24+ }
25+}
M .config/quickshell/aurora/PowerMenu.qml View
@@ -27,16 +27,7 @@ PanelWindow {
2727 onCleared: win.closeRequested()
2828 }
2929
30− readonly property var actions: [
31− { id: "lock", icon: Theme.iLock, label: "lock", confirm: false },
32− { id: "leave", icon: Theme.iLogout, label: "leave Hyprland", confirm: true },
33− { id: "renew", icon: Theme.iRefresh, label: "renew Hyprland", confirm: false },
34− { id: "hibernate", icon: Theme.iHibernate, label: "hibernate", confirm: true },
35− { id: "reboot", icon: Theme.iReboot, label: "reboot", confirm: true },
36− { id: "shutdown", icon: Theme.iPower, label: "shutdown", confirm: true },
37− { id: "sleep", icon: Theme.iSleep, label: "sleep", confirm: false },
38− { id: "display", icon: Theme.iMonitor, label: "display off", confirm: false }
39− ]
30+ readonly property var actions: Session.actions
4031
4132 property int current: 0
4233 property string armed: ""
@@ -50,27 +41,10 @@ PanelWindow {
5041 filter.forceActiveFocus()
5142 }
5243
53− // fuzzel-style: query chars must appear in order; prefix > word start > contiguous > scattered
54− function score(label, q) {
55− if (q === "") return 1
56− var s = label.toLowerCase()
57− if (s.indexOf(q) === 0) return 1000
58− var w = s.indexOf(" " + q)
59− if (w >= 0) return 500
60− if (s.indexOf(q) >= 0) return 300
61− var pos = 0, gaps = 0
62− for (var i = 0; i < q.length; i++) {
63− var f = s.indexOf(q[i], pos)
64− if (f < 0) return 0
65− gaps += f - pos
66− pos = f + 1
67− }
68− return 100 - gaps
69− }
7044 readonly property var shown: {
7145 var q = filter.text.toLowerCase().trim(), out = []
7246 for (var i = 0; i < actions.length; i++) {
73− var sc = score(actions[i].label, q)
47+ var sc = Fuzzy.score(actions[i].label, q)
7448 if (sc > 0) out.push({ a: actions[i], sc: sc, i: i })
7549 }
7650 out.sort(function (x, y) { return y.sc - x.sc || x.i - y.i })
@@ -86,24 +60,7 @@ PanelWindow {
8660 if (a.confirm && armed !== a.id) { armed = a.id; disarm.restart(); return }
8761 armed = ""
8862 closeRequested()
89− run(a.id)
90− }
91− function run(id) {
92− switch (id) {
93− case "lock": Quickshell.execDetached(["loginctl", "lock-session"]); break
94− case "leave": Hypr.logout(); break
95− case "renew": Quickshell.execDetached(["hyprctl", "reload"]); break
96− case "hibernate": Quickshell.execDetached(["systemctl", "hibernate", "-i"]); break
97− case "reboot": Quickshell.execDetached(["systemctl", "reboot", "-i"]); break
98− case "shutdown": Quickshell.execDetached(["systemctl", "poweroff", "-i"]); break
99− case "sleep": Quickshell.execDetached(["systemctl", "suspend", "-i"]); break
100− case "display": dpmsDelay.restart(); break // let the Enter key-up pass first, it would wake the screen
101− }
102− }
103− Timer {
104− id: dpmsDelay
105− interval: 400
106− onTriggered: Quickshell.execDetached(["hyprctl", "dispatch", 'hl.dsp.dpms({action="off"})'])
63+ Session.run(a.id)
10764 }
10865
10966 Rectangle {
A .config/quickshell/aurora/Runner.qml View
@@ -0,0 +1,564 @@
1+import QtQuick
2+import QtQuick.Layouts
3+import Quickshell
4+import Quickshell.Io
5+import Quickshell.Wayland
6+import Quickshell.Hyprland
7+
8+// App / command runner (replaced fuzzel on SUPER+R). One fuzzy list of desktop apps (+ their actions),
9+// aurora commands and every executable on $PATH, ranked by match and launch count.
10+// `=expr` calculator (Enter copies), `>cmd` runs a shell command. Ctrl+Enter runs in the terminal.
11+// dmenu mode (`aurora-run -d`, `dmenu` IPC): plain list from the script's stdin, the choice goes back over a fifo.
12+PanelWindow {
13+ id: win
14+ property bool opened: false
15+ property var shell // shell.qml root: toggleOverlay / openTab / barShown
16+ signal closeRequested()
17+ signal openRequested() // a dmenu request is loaded and wants the window
18+
19+ readonly property int rowH: 36
20+ readonly property int rows: 10
21+ readonly property int maxShown: 60
22+ readonly property string home: Quickshell.env("HOME")
23+
24+ // ---- dmenu mode ----
25+ property string mode: "run" // run | dmenu
26+ property var dmItems: [] // [{kind:"dm", name, low, i}]
27+ property string dmPrompt: ""
28+ property string dmPlaceholder: ""
29+ property int dmLines: -1 // -1 default, 0 = input only (no list)
30+ property bool dmPassword: false
31+ property bool dmIndex: false
32+ property string dmFifo: "" // pending request's reply fifo, "" when none
33+ readonly property bool dmenu: mode === "dmenu"
34+ readonly property int rowsShown: !dmenu ? rows
35+ : dmLines === 0 ? 0 : Math.min(dmLines > 0 ? dmLines : rows, 15, Math.max(1, dmItems.length))
36+
37+ // dir holds `opts` (key=value lines) and `items` (stdin of the script), see ~/.local/bin/aurora-run
38+ function startDmenu(dir) {
39+ if (dmFifo !== "") reply(false, "") // a newer request replaces a pending one
40+ loadProc.dir = dir
41+ loadProc.command = ["sh", "-c", 'cat "$1/opts"; printf "\\036\\n"; [ -f "$1/items" ] && cat "$1/items"', "sh", dir]
42+ loadProc.running = true
43+ }
44+ Process {
45+ id: loadProc
46+ property string dir
47+ stdout: StdioCollector {
48+ onStreamFinished: {
49+ var sep = text.indexOf("\x1e\n")
50+ if (sep < 0) return
51+ var o = {}, ol = text.substring(0, sep).split("\n")
52+ for (var i = 0; i < ol.length; i++) {
53+ var eq = ol[i].indexOf("=")
54+ if (eq > 0) o[ol[i].substring(0, eq)] = ol[i].substring(eq + 1)
55+ }
56+ var items = [], l = text.substring(sep + 2).split("\n")
57+ for (var j = 0; j < l.length; j++)
58+ if (l[j] !== "") items.push({ kind: "dm", key: "", name: l[j], low: l[j].toLowerCase(), i: j,
59+ sub: "", icon: "", glyph: "", tag: "" })
60+ win.dmPrompt = o.prompt || ""
61+ win.dmPlaceholder = o.placeholder || ""
62+ win.dmLines = o.lines !== undefined && o.lines !== "" ? parseInt(o.lines) : -1
63+ win.dmPassword = o.password === "1"
64+ win.dmIndex = o.index === "1"
65+ win.dmItems = items
66+ win.dmFifo = loadProc.dir + "/reply"
67+ win.mode = "dmenu"
68+ filter.text = ""
69+ win.current = 0
70+ win.openRequested()
71+ filter.forceActiveFocus()
72+ }
73+ }
74+ }
75+ // "<0|1>\n<value>\0" to the fifo through stdin, so a password never shows up in a process's argv
76+ function reply(ok, value) {
77+ replyProc.payload = (ok ? "0" : "1") + "\n" + value + "\0"
78+ replyProc.command = ["sh", "-c", 'cat > "$1"', "sh", dmFifo]
79+ replyProc.stdinEnabled = true
80+ replyProc.running = true
81+ dmFifo = ""
82+ }
83+ Process {
84+ id: replyProc
85+ property string payload
86+ onStarted: { write(payload); payload = ""; stdinEnabled = false }
87+ }
88+ function endDmenu() {
89+ mode = "run"
90+ dmItems = []
91+ dmPassword = false
92+ filter.text = ""
93+ }
94+
95+ visible: opened
96+ implicitWidth: dmenu ? 640 : 560
97+ implicitHeight: 24 + 36 + rowsShown * rowH + 22
98+ exclusiveZone: 0
99+ color: "transparent"
100+ WlrLayershell.layer: WlrLayer.Overlay
101+ WlrLayershell.namespace: "aurora-runner"
102+ WlrLayershell.keyboardFocus: opened ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
103+
104+ HyprlandFocusGrab {
105+ windows: [win]
106+ active: win.opened
107+ onCleared: win.closeRequested()
108+ }
109+
110+ property int current: 0
111+ property string armed: ""
112+ Timer { id: disarm; interval: 3000; onTriggered: win.armed = "" }
113+
114+ onOpenedChanged: {
115+ if (!opened) {
116+ // closed without a choice (esc, outside click, another overlay): the script gets "cancelled"
117+ if (dmFifo !== "") reply(false, "")
118+ if (dmenu) endDmenu()
119+ return
120+ }
121+ armed = ""
122+ filter.forceActiveFocus()
123+ if (dmenu) return // startDmenu already reset the input
124+ filter.text = ""
125+ current = 0
126+ if (Date.now() - binsAt > 60000) binProc.running = true
127+ }
128+
129+ // ---- sources ----
130+ function basename(p) { p = String(p); return p.substring(p.lastIndexOf("/") + 1) }
131+
132+ // desktop entries + their actions ("Librewolf: New Private Window")
133+ property var apps: []
134+ function loadApps() {
135+ var out = [], l = DesktopEntries.applications.values
136+ for (var i = 0; i < l.length; i++) {
137+ var e = l[i]
138+ if (e.noDisplay) continue
139+ var ic = e.icon ? Quickshell.iconPath(e.icon, true) : ""
140+ var bin = e.command && e.command.length ? basename(e.command[0]) : ""
141+ out.push({ kind: "app", key: "app:" + e.id, name: e.name, sub: e.genericName || e.comment || "",
142+ icon: ic, glyph: Theme.iApp, tag: "app", entry: e, action: null, bin: bin,
143+ hay: [e.genericName || "", (e.keywords || []).join(" "), bin] })
144+ var acts = e.actions || []
145+ for (var j = 0; j < acts.length; j++)
146+ out.push({ kind: "act", key: "act:" + e.id + ":" + acts[j].id, name: e.name + ": " + acts[j].name, sub: "",
147+ icon: ic, glyph: Theme.iApp, tag: "app", entry: e, action: acts[j], bin: "", hay: [] })
148+ }
149+ apps = out
150+ }
151+ Component.onCompleted: loadApps()
152+ Connections {
153+ target: DesktopEntries
154+ function onApplicationsChanged() { win.loadApps() }
155+ }
156+
157+ // executables on $PATH (first one wins, like the shell). Apps whose binary is already listed are skipped.
158+ property var bins: []
159+ property double binsAt: 0
160+ Process {
161+ id: binProc
162+ command: ["sh", "-c", 'set -f; IFS=:; for d in $PATH; do [ -d "$d" ] && find -L "$d" -maxdepth 1 -type f -executable -printf "%f\\t%p\\n" 2>/dev/null; done']
163+ stdout: StdioCollector {
164+ onStreamFinished: {
165+ var seen = {}, out = [], l = text.split("\n")
166+ for (var i = 0; i < l.length; i++) {
167+ var t = l[i].indexOf("\t")
168+ if (t <= 0) continue
169+ var n = l[i].substring(0, t)
170+ if (seen[n]) continue
171+ seen[n] = true
172+ out.push({ kind: "bin", key: "bin:" + n, name: n, sub: l[i].substring(t + 1),
173+ icon: "", glyph: Theme.iConsole, tag: "bin", hay: [] })
174+ }
175+ win.bins = out
176+ win.binsAt = Date.now()
177+ }
178+ }
179+ }
180+
181+ // aurora's own actions. Session ones come from Session (same confirm rules as the power menu).
182+ readonly property var commands: {
183+ var c = [
184+ { id: "panel", glyph: Theme.iHome, name: "control panel" },
185+ { id: "audio", glyph: Theme.iVolHigh, name: "audio settings" },
186+ { id: "net", glyph: Theme.iWifi, name: "network settings" },
187+ { id: "bt", glyph: Theme.iBt, name: "bluetooth settings" },
188+ { id: "sys", glyph: Theme.iChip, name: "system info" },
189+ { id: "notif", glyph: Theme.iBell, name: "notifications" },
190+ { id: "settings", glyph: Theme.iCog, name: "aurora settings" },
191+ { id: "wall", glyph: Theme.iImage, name: "wallpaper picker" },
192+ { id: "wallrnd", glyph: Theme.iShuffle, name: "random wallpaper" },
193+ { id: "clip", glyph: Theme.iClipboard, name: "clipboard history" },
194+ { id: "overview", glyph: Theme.iWindow, name: "window overview" },
195+ { id: "cal", glyph: Theme.iCal, name: "calendar" },
196+ { id: "power", glyph: Theme.iPower, name: "power menu" },
197+ { id: "caffeine", glyph: Theme.iCoffee, name: "toggle caffeine" },
198+ { id: "dnd", glyph: Theme.iBellOff, name: "toggle do not disturb" },
199+ { id: "bar", glyph: Theme.iMonitor, name: "toggle bar" },
200+ { id: "picker", glyph: Theme.iPicker, name: "colour picker" },
201+ { id: "shot", glyph: Theme.iCrop, name: "screenshot region" },
202+ { id: "ocr", glyph: Theme.iCrop, name: "screenshot ocr" }
203+ ]
204+ if (Rec.available) c.push({ id: "rec", glyph: Theme.iRec, name: Rec.busy ? "stop recording" : "record screen" })
205+ var out = []
206+ for (var i = 0; i < c.length; i++)
207+ out.push({ kind: "aurora", key: "aur:" + c[i].id, id: c[i].id, name: c[i].name, sub: "", icon: "",
208+ glyph: c[i].glyph, tag: "aurora", confirm: false, hay: [] })
209+ var s = Session.actions
210+ for (var j = 0; j < s.length; j++)
211+ out.push({ kind: "session", key: "ses:" + s[j].id, id: s[j].id, name: s[j].label, sub: "session", icon: "",
212+ glyph: s[j].icon, tag: "aurora", confirm: s[j].confirm, hay: [] })
213+ return out
214+ }
215+
216+ // ---- frecency: launch counts in ~/.cache/aurora/runner.json ----
217+ property var counts: ({})
218+ FileView {
219+ id: store
220+ path: win.home + "/.cache/aurora/runner.json"
221+ printErrors: false
222+ onLoaded: { try { win.counts = JSON.parse(text()) } catch (e) { win.counts = {} } }
223+ }
224+ function bump(key) {
225+ var c = {}
226+ for (var k in counts) c[k] = counts[k]
227+ c[key] = (c[key] || 0) + 1
228+ counts = c
229+ store.setText(JSON.stringify(c))
230+ }
231+
232+ // ---- calculator ----
233+ readonly property var mathFns: ["sqrt", "cbrt", "abs", "sin", "cos", "tan", "asin", "acos", "atan",
234+ "log", "log2", "log10", "exp", "floor", "ceil", "round", "min", "max", "pow"]
235+ function calc(expr) {
236+ if (!/^[0-9a-z\s.+\-*\/%^(),]+$/i.test(expr) || !/\d|pi/i.test(expr)) return ""
237+ var bad = false
238+ var js = expr.replace(/\^/g, "**").replace(/[a-z][a-z0-9]*/gi, function (w) {
239+ var l = w.toLowerCase()
240+ if (l === "pi") return "Math.PI"
241+ if (l === "e") return "Math.E"
242+ if (l === "ln") return "Math.log"
243+ if (win.mathFns.indexOf(l) >= 0) return "Math." + l
244+ bad = true
245+ return w
246+ })
247+ if (bad) return ""
248+ try {
249+ var r = (new Function("return (" + js + ")"))()
250+ if (typeof r !== "number" || !isFinite(r)) return ""
251+ return String(Number(r.toPrecision(12)))
252+ } catch (e) { return "" }
253+ }
254+
255+ // ---- ranking ----
256+ function rank(it, q) {
257+ var s = Fuzzy.score(it.name, q)
258+ for (var i = 0; i < it.hay.length; i++)
259+ if (it.hay[i] !== "") s = Math.max(s, Fuzzy.score(it.hay[i], q) * 0.6)
260+ if (s <= 0) return 0
261+ var w = it.kind === "app" ? 1 : it.kind === "bin" ? 0.6 : 0.85
262+ return s * w + 60 * Math.log(1 + (counts[it.key] || 0))
263+ }
264+ readonly property var shown: {
265+ var raw = filter.text, q = raw.toLowerCase().trim(), res = []
266+ if (dmenu) {
267+ if (dmLines === 0) return res
268+ var cap = 1000, dl = dmItems, di
269+ if (q === "") return dl.length > cap ? dl.slice(0, cap) : dl
270+ var hits = []
271+ for (di = 0; di < dl.length; di++) {
272+ var dsc = Fuzzy.scoreLow(dl[di].low, q)
273+ if (dsc > 0) hits.push({ it: dl[di], sc: dsc })
274+ }
275+ hits.sort(function (x, y) { return y.sc - x.sc || x.it.i - y.it.i })
276+ for (di = 0; di < hits.length && di < cap; di++) res.push(hits[di].it)
277+ return res
278+ }
279+ if (q.charAt(0) === ">") {
280+ var cmd = raw.trim().substring(1).trim()
281+ if (cmd !== "") res.push({ kind: "sh", key: "", name: cmd, sub: "run in sh", icon: "", glyph: Theme.iShell, tag: "sh" })
282+ return res
283+ }
284+ if (q.charAt(0) === "=") {
285+ var r = calc(q.substring(1))
286+ res.push({ kind: "calc", key: "", name: r !== "" ? r : "...", sub: q.substring(1).trim(), icon: "",
287+ glyph: Theme.iCalc, tag: "=", value: r })
288+ return res
289+ }
290+ if (/[\d)]\s*[+\-*\/%^]\s*[\d(.]/.test(q)) {
291+ var v = calc(q)
292+ if (v !== "") res.push({ kind: "calc", key: "", name: v, sub: q, icon: "", glyph: Theme.iCalc, tag: "=", value: v })
293+ }
294+
295+ var all = [], i
296+ var appBins = {}
297+ for (i = 0; i < apps.length; i++) { all.push(apps[i]); if (apps[i].bin) appBins[apps[i].bin] = true }
298+ for (i = 0; i < commands.length; i++) all.push(commands[i])
299+ var scored = []
300+ if (q === "") {
301+ // most used first, then apps A-Z; no actions / bins / commands unless used before
302+ for (i = 0; i < bins.length; i++) if (counts[bins[i].key]) all.push(bins[i])
303+ for (i = 0; i < all.length; i++) {
304+ var n = counts[all[i].key] || 0
305+ if (n > 0 || all[i].kind === "app") scored.push({ it: all[i], sc: n })
306+ }
307+ scored.sort(function (x, y) { return y.sc - x.sc || x.it.name.localeCompare(y.it.name) })
308+ } else {
309+ for (i = 0; i < bins.length; i++) if (!appBins[bins[i].name]) all.push(bins[i])
310+ for (i = 0; i < all.length; i++) {
311+ var sc = rank(all[i], q)
312+ if (sc > 0) scored.push({ it: all[i], sc: sc })
313+ }
314+ scored.sort(function (x, y) { return y.sc - x.sc || x.it.name.length - y.it.name.length })
315+ }
316+ for (i = 0; i < scored.length && res.length < maxShown; i++) res.push(scored[i].it)
317+ // nothing matched: offer to run the text as a command, like fuzzel's execute-input
318+ if (res.length === 0 && q !== "")
319+ res.push({ kind: "sh", key: "", name: raw.trim(), sub: "run in sh", icon: "", glyph: Theme.iShell, tag: "sh" })
320+ return res
321+ }
322+
323+ // ---- launching ----
324+ function exec(cmd, term) {
325+ Quickshell.execDetached({ command: term ? ["foot", "-e"].concat(cmd) : cmd, workingDirectory: home })
326+ }
327+ function trigger(i, term) {
328+ if (dmenu) {
329+ // like fuzzel: the selected line, or the typed text when nothing matches / Ctrl+Enter
330+ var sel = term ? null : shown[i]
331+ if (dmIndex) reply(true, sel ? String(sel.i) : "-1")
332+ else reply(true, sel ? sel.name : filter.text)
333+ closeRequested()
334+ return
335+ }
336+ var it = shown[i]
337+ if (!it) return
338+ current = i
339+ if (it.confirm && armed !== it.key) { armed = it.key; disarm.restart(); return }
340+ armed = ""
341+ if (it.key !== "") bump(it.key)
342+ closeRequested()
343+ switch (it.kind) {
344+ case "app":
345+ if (term || it.entry.runInTerminal) exec(it.entry.command, true)
346+ else it.entry.execute()
347+ break
348+ case "act": it.action.execute(); break
349+ case "bin": exec([it.name], term); break
350+ case "sh": exec(["sh", "-c", it.name], term); break
351+ case "calc": if (it.value !== "") Quickshell.execDetached(["wl-copy", "--", it.value]); break
352+ case "session": Session.run(it.id); break
353+ case "aurora": command(it.id); break
354+ }
355+ }
356+ function command(id) {
357+ switch (id) {
358+ case "panel": shell.openTab("home"); break
359+ case "audio": case "net": case "bt": case "sys": case "notif": case "settings":
360+ shell.openTab(id); break
361+ case "wall": case "clip": case "overview": case "cal": case "power":
362+ shell.toggleOverlay(id); break
363+ case "wallrnd": Wall.random(); break
364+ case "caffeine": Toggles.caffeine = !Toggles.caffeine; break
365+ case "dnd": Notifs.dnd = !Notifs.dnd; break
366+ case "bar": shell.barShown = !shell.barShown; break
367+ case "picker": Toggles.pickColour(); break
368+ case "shot": Shot.take("region"); break
369+ case "ocr": Shot.take("ocr"); break
370+ case "rec": Rec.toggle("screen"); break
371+ }
372+ }
373+
374+ // ---- UI ----
375+ Rectangle {
376+ anchors.fill: parent
377+ color: Theme.bgA
378+ border.width: 2
379+ border.color: Theme.accent
380+
381+ ColumnLayout {
382+ anchors.fill: parent
383+ anchors.margins: 12
384+ spacing: 2
385+
386+ Rectangle {
387+ Layout.fillWidth: true
388+ Layout.bottomMargin: 6
389+ implicitHeight: 30
390+ color: Theme.surface
391+ border.width: 1
392+ border.color: filter.activeFocus ? Theme.accent : Theme.line
393+ Text {
394+ id: promptText
395+ anchors.left: parent.left
396+ anchors.leftMargin: 10
397+ anchors.verticalCenter: parent.verticalCenter
398+ text: win.dmenu && win.dmPrompt !== "" ? win.dmPrompt : (win.dmPassword ? Theme.iLock : Theme.iSearch)
399+ color: win.dmenu && win.dmPrompt !== "" ? Theme.accent : Theme.dim
400+ font.family: Theme.font
401+ font.pixelSize: Theme.fontSize
402+ }
403+ Text {
404+ anchors.left: filter.left
405+ anchors.verticalCenter: parent.verticalCenter
406+ visible: filter.text === "" && win.dmenu && win.dmPlaceholder !== ""
407+ text: win.dmPlaceholder
408+ color: Theme.dim
409+ font.family: Theme.font
410+ font.pixelSize: Theme.fontSize
411+ }
412+ TextInput {
413+ id: filter
414+ anchors.fill: parent
415+ anchors.leftMargin: Math.max(32, promptText.implicitWidth + 20)
416+ anchors.rightMargin: 10
417+ verticalAlignment: TextInput.AlignVCenter
418+ echoMode: win.dmPassword ? TextInput.Password : TextInput.Normal
419+ passwordCharacter: "*"
420+ color: Theme.fg
421+ selectionColor: Theme.accent
422+ selectedTextColor: Theme.bg
423+ font.family: Theme.font
424+ font.pixelSize: Theme.fontSize
425+ clip: true
426+ onTextChanged: { win.current = 0; win.armed = "" }
427+ Keys.onEscapePressed: win.closeRequested()
428+ Keys.onReturnPressed: event => win.trigger(win.current, event.modifiers & Qt.ControlModifier)
429+ Keys.onEnterPressed: event => win.trigger(win.current, event.modifiers & Qt.ControlModifier)
430+ Keys.onPressed: event => {
431+ var n = win.shown.length
432+ if (!n) return
433+ var step = 0
434+ if (event.key === Qt.Key_Down || event.key === Qt.Key_Tab) step = 1
435+ else if (event.key === Qt.Key_Up || event.key === Qt.Key_Backtab) step = -1
436+ else if (event.key === Qt.Key_PageDown) step = Math.max(2, win.rowsShown)
437+ else if (event.key === Qt.Key_PageUp) step = -Math.max(2, win.rowsShown)
438+ else if ((event.modifiers & Qt.ControlModifier) && (event.key === Qt.Key_N || event.key === Qt.Key_J)) step = 1
439+ else if ((event.modifiers & Qt.ControlModifier) && (event.key === Qt.Key_P || event.key === Qt.Key_K)) step = -1
440+ if (step === 0) return
441+ if (Math.abs(step) === 1) win.current = (win.current + step + n) % n
442+ else win.current = Math.max(0, Math.min(n - 1, win.current + step))
443+ win.armed = ""
444+ event.accepted = true
445+ }
446+ }
447+ }
448+
449+ ListView {
450+ id: list
451+ Layout.fillWidth: true
452+ Layout.fillHeight: true
453+ visible: win.rowsShown > 0
454+ clip: true
455+ spacing: 0
456+ boundsBehavior: Flickable.StopAtBounds
457+ model: win.shown
458+ currentIndex: win.current
459+ highlightFollowsCurrentItem: false
460+ onCurrentIndexChanged: positionViewAtIndex(currentIndex, ListView.Contain)
461+ delegate: Rectangle {
462+ id: row
463+ required property var modelData
464+ required property int index
465+ readonly property bool selected: win.current === index
466+ readonly property bool isArmed: win.armed !== "" && win.armed === modelData.key
467+ width: list.width
468+ height: win.rowH
469+ color: isArmed ? Theme.err : (selected ? Theme.surfaceHi : (rm.containsMouse ? Theme.surface : "transparent"))
470+ border.width: selected ? 1 : 0
471+ border.color: isArmed ? Theme.err : Theme.accent
472+
473+ Rectangle { // selection marker, like ClipWindow
474+ visible: row.selected
475+ width: 2
476+ height: parent.height
477+ color: row.isArmed ? Theme.bg : Theme.accent
478+ }
479+ Item {
480+ id: icoBox
481+ anchors.left: parent.left
482+ anchors.leftMargin: row.modelData.kind === "dm" ? 2 : 10
483+ anchors.verticalCenter: parent.verticalCenter
484+ visible: row.modelData.kind !== "dm"
485+ width: visible ? 24 : 0
486+ height: 24
487+ Image {
488+ id: img
489+ anchors.fill: parent
490+ visible: row.modelData.icon !== "" && status === Image.Ready
491+ source: row.modelData.icon
492+ sourceSize.width: 48
493+ sourceSize.height: 48
494+ asynchronous: true
495+ smooth: true
496+ }
497+ Text {
498+ anchors.centerIn: parent
499+ visible: !img.visible
500+ text: row.modelData.glyph
501+ color: row.isArmed ? Theme.bg : Theme.accent
502+ font.family: Theme.font
503+ font.pixelSize: Theme.fontSize + 4
504+ }
505+ }
506+ Text {
507+ id: tag
508+ anchors.right: parent.right
509+ anchors.rightMargin: 10
510+ anchors.verticalCenter: parent.verticalCenter
511+ text: row.isArmed ? "sure?" : row.modelData.tag
512+ color: row.isArmed ? Theme.bg : Theme.dim
513+ font.family: Theme.font
514+ font.pixelSize: Theme.fontSize - 2
515+ }
516+ Text {
517+ id: nameText
518+ anchors.left: icoBox.right
519+ anchors.leftMargin: 10
520+ anchors.verticalCenter: parent.verticalCenter
521+ width: Math.min(implicitWidth, tag.x - x - 12)
522+ elide: Text.ElideRight
523+ text: row.modelData.name
524+ color: row.isArmed ? Theme.bg : Theme.fg
525+ font.family: Theme.font
526+ font.pixelSize: Theme.fontSize
527+ font.bold: row.modelData.kind === "calc"
528+ }
529+ Text {
530+ anchors.left: nameText.right
531+ anchors.leftMargin: 10
532+ anchors.right: tag.left
533+ anchors.rightMargin: 12
534+ anchors.verticalCenter: parent.verticalCenter
535+ elide: Text.ElideRight
536+ text: row.modelData.sub
537+ color: row.isArmed ? Theme.bg : Theme.dim
538+ font.family: Theme.font
539+ font.pixelSize: Theme.fontSize - 2
540+ }
541+ MouseArea {
542+ id: rm
543+ anchors.fill: parent
544+ hoverEnabled: true
545+ cursorShape: Qt.PointingHandCursor
546+ onEntered: if (win.current !== row.index) { win.current = row.index; win.armed = "" }
547+ onClicked: win.trigger(row.index, false)
548+ }
549+ }
550+ }
551+
552+ Text {
553+ Layout.fillWidth: true
554+ Layout.topMargin: 6
555+ text: !win.dmenu ? (win.shown.length ? "enter run ctrl+enter terminal =calc >cmd esc close" : "no match")
556+ : win.rowsShown === 0 ? "enter ok esc cancel"
557+ : win.shown.length ? "enter select ctrl+enter typed text esc cancel" : "no match enter typed text esc cancel"
558+ color: win.shown.length || win.dmenu ? Theme.dim : Theme.err
559+ font.family: Theme.font
560+ font.pixelSize: Theme.fontSize - 2
561+ }
562+ }
563+ }
564+}
A .config/quickshell/aurora/Session.qml View
@@ -0,0 +1,35 @@
1+pragma Singleton
2+import QtQuick
3+import Quickshell
4+
5+// Session / power actions shared by PowerMenu and Runner. `confirm` ones need the two-press "sure?" arm.
6+Singleton {
7+ readonly property var actions: [
8+ { id: "lock", icon: Theme.iLock, label: "lock", confirm: false },
9+ { id: "leave", icon: Theme.iLogout, label: "leave Hyprland", confirm: true },
10+ { id: "renew", icon: Theme.iRefresh, label: "renew Hyprland", confirm: false },
11+ { id: "hibernate", icon: Theme.iHibernate, label: "hibernate", confirm: true },
12+ { id: "reboot", icon: Theme.iReboot, label: "reboot", confirm: true },
13+ { id: "shutdown", icon: Theme.iPower, label: "shutdown", confirm: true },
14+ { id: "sleep", icon: Theme.iSleep, label: "sleep", confirm: false },
15+ { id: "display", icon: Theme.iMonitor, label: "display off", confirm: false }
16+ ]
17+
18+ function run(id) {
19+ switch (id) {
20+ case "lock": Quickshell.execDetached(["loginctl", "lock-session"]); break
21+ case "leave": Hypr.logout(); break
22+ case "renew": Quickshell.execDetached(["hyprctl", "reload"]); break
23+ case "hibernate": Quickshell.execDetached(["systemctl", "hibernate", "-i"]); break
24+ case "reboot": Quickshell.execDetached(["systemctl", "reboot", "-i"]); break
25+ case "shutdown": Quickshell.execDetached(["systemctl", "poweroff", "-i"]); break
26+ case "sleep": Quickshell.execDetached(["systemctl", "suspend", "-i"]); break
27+ case "display": dpmsDelay.restart(); break // let the Enter key-up pass first, it would wake the screen
28+ }
29+ }
30+ Timer {
31+ id: dpmsDelay
32+ interval: 400
33+ onTriggered: Quickshell.execDetached(["hyprctl", "dispatch", 'hl.dsp.dpms({action="off"})'])
34+ }
35+}
M .config/quickshell/aurora/Theme.qml View
@@ -159,6 +159,11 @@ Singleton {
159159 readonly property string iStop: cp(0xF04DB)
160160 readonly property string iDock: cp(0xF10A9)
161161 readonly property string iCog: cp(0xF0493)
162+ readonly property string iApps: cp(0xF003B)
163+ readonly property string iApp: cp(0xF08C6)
164+ readonly property string iConsole: cp(0xF018D)
165+ readonly property string iShell: cp(0xF07B7)
166+ readonly property string iCalc: cp(0xF00EC)
162167
163168 // workspace icons: the exact Font Awesome glyphs from your waybar config.
164169 // 1 browser, 2 code, 3 book, 4 cog, 5 chat, 6 file, 7 folder, 8 terminal, 9 flask, 10 image
M .config/quickshell/aurora/shell.qml View
@@ -131,6 +131,20 @@ ShellRoot {
131131 onCloseRequested: root.closeOverlay()
132132 }
133133
134+ Runner {
135+ id: runner
136+ screen: root.overlayScreen
137+ opened: root.overlay === "runner"
138+ shell: root
139+ onCloseRequested: root.closeOverlay()
140+ onOpenRequested: {
141+ root.close()
142+ if (root.overlay === "runner") return // already open (run mode): it just switched to the list
143+ root.overlayScreen = root.focusedScreen()
144+ root.overlay = "runner"
145+ }
146+ }
147+
134148 NotifPopups { screen: root.focusedScr; suppressed: root.opened }
135149
136150 Osd { id: osd; screen: root.focusedScr; suppressed: root.opened }
@@ -160,6 +174,8 @@ ShellRoot {
160174 function clip(): void { root.toggleOverlay("clip") }
161175 function wall(): void { root.toggleOverlay("wall") }
162176 function power(): void { root.toggleOverlay("power") }
177+ function run(): void { root.toggleOverlay("runner") }
178+ function dmenu(dir: string): void { runner.startDmenu(dir) } // used by ~/.local/bin/aurora-run -d
163179 function bar(): void { root.barShown = !root.barShown }
164180 function wallrandom(): void { Wall.random() }
165181 function wallset(path: string): void { Wall.apply(path) } // absolute path (setwall resolves it)
M .config/shell/profile View
@@ -33,7 +33,7 @@ export MYSQL_HISTFILE="$XDG_CACHE_HOME/.mariadb_history"
3333 export CUDA_CACHE_PATH="$XDG_CACHE_HOME/nv"
3434
3535 # Other program settings
36−export SUDO_ASKPASS="$HOME/.local/bin/askpass-fuzzel"
36+export SUDO_ASKPASS="$HOME/.local/bin/aurora-askpass"
3737 export FZF_DEFAULT_OPTS="--layout=reverse --height 40%"
3838 export ANDROID_SDK_HOME="${XDG_CONFIG_HOME:-$HOME/.config}/android"
3939 export ANDROID_HOME="$HOME/Android/Sdk/"
D .config/wal/templates/colors-fuzzel.ini View
@@ -1,11 +0,0 @@
1−[colors]
2−background={background.strip}ff
3−prompt={foreground.strip}ff
4−text={foreground.strip}ff
5−placeholder={foreground.strip}ff
6−input={foreground.strip}ff
7−match={foreground.strip}ff
8−selection={color1.strip}ff
9−selection-text={foreground.strip}ff
10−selection-match={background.strip}ff
11−border={color1.strip}ff
D .local/bin/askpass-fuzzel View
@@ -1,12 +0,0 @@
1−#!/bin/bash
2−
3−prompt="${1:-Password:}"
4−
5−password=$(fuzzel --dmenu --password --prompt="" --placeholder="$prompt" --width=60 --lines=0 --keyboard-focus=on-demand --no-exit-on-keyboard-focus-loss --cache /dev/null)
6−
7−if [ $? -eq 0 ]; then
8− echo "$password"
9− exit 0
10−else
11− exit 1
12−fi
A .local/bin/aurora-askpass View
@@ -0,0 +1,13 @@
1+#!/bin/bash
2+# SUDO_ASKPASS helper: password prompt in aurora's runner.
3+
4+prompt="${1:-Password:}"
5+
6+password=$(aurora-run --dmenu --password --prompt="" --placeholder="$prompt" --lines=0)
7+
8+if [ $? -eq 0 ]; then
9+ echo "$password"
10+ exit 0
11+else
12+ exit 1
13+fi
R .local/bin/fuzzelunicode → .local/bin/aurora-chars View
@@ -3,7 +3,7 @@
33 # The famous "get a menu of emojis to copy" script.
44
55 # Get user selection via dmenu from emoji file.
6−chosen=$(cut -d ';' -f1 ~/.local/share/chars/* | fuzzel -d -i -l 30 | sed "s/ .*//")
6+chosen=$(cut -d ';' -f1 ~/.local/share/chars/* | aurora-run -d -l 15 -p "char" | sed "s/ .*//")
77
88 # Exit if none chosen.
99 [ -z "$chosen" ] && exit
A .local/bin/aurora-run View
@@ -0,0 +1,51 @@
1+#!/bin/bash
2+# aurora-run: fuzzel-compatible front end for aurora's runner (needs aurora running).
3+# aurora-run open the app runner (same as SUPER+R)
4+# aurora-run -d [opts] dmenu: lines on stdin, the choice on stdout, exit 1 when cancelled
5+# dmenu opts (fuzzel/dmenu spelling): -p/--prompt TEXT, -l/--lines N (0 = input only), --placeholder TEXT,
6+# --password, --index (print the line number instead). Other fuzzel flags (-i, --width, -fn, ...) are ignored.
7+
8+dmenu=0 prompt="" placeholder="" lines="" password=0 index=0
9+while [ $# -gt 0 ]; do
10+ case $1 in
11+ -d | --dmenu) dmenu=1 ;;
12+ -p | --prompt) prompt=$2; shift ;;
13+ --prompt=*) prompt=${1#*=} ;;
14+ -l | --lines) lines=$2; shift ;;
15+ --lines=*) lines=${1#*=} ;;
16+ --placeholder) placeholder=$2; shift ;;
17+ --placeholder=*) placeholder=${1#*=} ;;
18+ --password | --password=*) password=1 ;;
19+ --index) index=1 ;;
20+ # ignored flags that take a separate value
21+ -fn | -f | --font | -w | --width | --cache | --with-nth | --nth-delimiter | -a | --anchor | -o | --output) shift ;;
22+ *) ;;
23+ esac
24+ shift
25+done
26+
27+pid=$(pgrep -nf 'quickshell.*/aurora$|qs -c aurora$')
28+[ -n "$pid" ] || { echo "aurora-run: aurora is not running" >&2; exit 2; }
29+
30+if [ "$dmenu" = 0 ]; then
31+ exec qs -c aurora ipc call shell run
32+fi
33+
34+# private dir on tmpfs: items, opts and the reply fifo (a password only ever passes through the fifo)
35+dir=$(mktemp -d "${XDG_RUNTIME_DIR:-/tmp}/aurora-run.XXXXXX") || exit 2
36+trap 'rm -rf "$dir"' EXIT
37+[ -t 0 ] || cat > "$dir/items"
38+printf 'prompt=%s\nplaceholder=%s\nlines=%s\npassword=%s\nindex=%s\n' \
39+ "${prompt//$'\n'/ }" "${placeholder//$'\n'/ }" "$lines" "$password" "$index" > "$dir/opts"
40+mkfifo "$dir/reply"
41+exec 3<> "$dir/reply" # read-write: never blocks aurora's writer, and lets us time out below
42+
43+err=$(qs -c aurora ipc call shell dmenu "$dir" 2>&1)
44+[ -z "$err" ] || { echo "aurora-run: $err" >&2; exit 2; }
45+
46+# reply is "<0|1>\n<value>\0"; give up if aurora goes away while we wait
47+until IFS= read -r -d '' -t 1 -u 3 reply; do
48+ kill -0 "$pid" 2>/dev/null || { echo "aurora-run: aurora exited" >&2; exit 2; }
49+done
50+[ "${reply%%$'\n'*}" = 0 ] || exit 1
51+printf '%s\n' "${reply#*$'\n'}"
M .local/bin/bcn View
@@ -15,7 +15,7 @@ else
1515 names=$(printf '%s\n' "${devices[@]}" | sed 's/^Device [^ ]* //')
1616
1717 selected=$(printf '%s\n' "$names" |
18− fuzzel --dmenu -l 10 -fn Monospace-15)
18+ aurora-run --dmenu -l 10)
1919
2020 [[ -z "$selected" ]] && exit 0
2121
M .local/bin/campus-login View
@@ -68,7 +68,7 @@ else
6868 fi
6969
7070 # --- pick a browser ---------------------------------------------------------
71−# $BROWSER is often unset when launched from fuzzel/rofi, so fall back.
71+# $BROWSER is often unset when launched from a menu (aurora-run, rofi), so fall back.
7272 launch=()
7373 if [[ -n "${BROWSER:-}" ]]; then
7474 read -ra launch <<< "$BROWSER"
M .local/bin/envyswitch View
@@ -1,6 +1,6 @@
11 #!/bin/env bash
22
3−mode="$(printf "Integrated\nHybrid\nNvidia" | fuzzel --dmenu -p "Select the graphics mode:")"
3+mode="$(printf "Integrated\nHybrid\nNvidia" | aurora-run --dmenu -p "Select the graphics mode:")"
44
55 # Exit if no selection was made
66 [ -z "$mode" ] && exit 1
M .local/bin/hypr/hypr_screenshot.sh View
@@ -2,7 +2,7 @@
22
33 ocr_cmd="wl-copy"
44
5−case "$(printf "a selected area (copy)\ncurrent window (copy)\nfull screen (copy)\na selected area\na selected area (tmp dir)\ncurrent window\nfull screen\na selected area (OCR)" | fuzzel -d -l 7 -i -p "Screenshot which area?")" in
5+case "$(printf "a selected area (copy)\ncurrent window (copy)\nfull screen (copy)\na selected area\na selected area (tmp dir)\ncurrent window\nfull screen\na selected area (OCR)" | aurora-run -d -l 8 -p "Screenshot which area?")" in
66 "a selected area (copy)") hyprshot -m region --clipboard-only ;;
77 "current window (copy)") hyprshot -m window --clipboard-only ;;
88 "full screen (copy)") hyprshot -m output --clipboard-only ;;
M .local/bin/hypr/hypr_shader_menu.sh View
@@ -2,7 +2,7 @@
22 set -euo pipefail
33
44 # Check deps
5−command -v fuzzel >/dev/null || { echo "fuzzel not found"; exit 1; }
5+command -v aurora-run >/dev/null || { echo "aurora-run not found"; exit 1; }
66 command -v hyprshade >/dev/null || { echo "hyprshade not found"; exit 1; }
77
88 # Get shader list
@@ -11,9 +11,9 @@ mapfile -t SHADERS < <(hyprshade ls)
1111 # Add "off" at top
1212 SHADERS=("off" "${SHADERS[@]}")
1313
14−# Show in fuzzel
14+# Show in aurora's runner (|| true: cancelling must not trip set -e)
1515 CHOICE=$(printf "%s\n" "${SHADERS[@]}" \
16− | fuzzel --dmenu --prompt "Hyprshade > " \
16+ | { aurora-run --dmenu --prompt "Hyprshade > " || true; } \
1717 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
1818
1919 # User cancelled
M .local/bin/madd View
@@ -1,6 +1,6 @@
11 #!/bin/sh
22 # mpd-add: fuzzy-pick a track from the MPD library and play it right away.
3−# Works in a terminal (fzf) or launched from a menu (fuzzel).
3+# Works in a terminal (fzf) or launched from a menu (aurora-run).
44 #
55 # Usage: mpd-add [-q]
66 # -q queue the track right after the current one, but don't jump to it
@@ -34,7 +34,7 @@ fi
3434 if [ -t 0 ]; then
3535 filename=$(printf '%s\n' "$library" | fzf)
3636 else
37− filename=$(printf '%s\n' "$library" | fuzzel -d -l 30 -p 'play: ')
37+ filename=$(printf '%s\n' "$library" | aurora-run -d -l 30 -p 'play: ')
3838 fi
3939
4040 # Cancelled (Esc): nothing to do.
M .local/bin/mounter View
@@ -8,16 +8,16 @@
88 getmount() { \
99 [ -z "$chosen" ] && exit 1
1010 # shellcheck disable=SC2086
11− mp="$(find $1 2>/dev/null | fuzzel -d -i -p "Type in mount point.")" || exit 1
11+ mp="$(find $1 2>/dev/null | aurora-run -d -p "Type in mount point.")" || exit 1
1212 test -z "$mp" && exit 1
1313 if [ ! -d "$mp" ]; then
14− mkdiryn=$(printf "No\\nYes" | fuzzel -d -i -p "$mp does not exist. Create it?") || exit 1
14+ mkdiryn=$(printf "No\\nYes" | aurora-run -d -p "$mp does not exist. Create it?") || exit 1
1515 [ "$mkdiryn" = "Yes" ] && (mkdir -p "$mp" || sudo -A mkdir -p "$mp")
1616 fi
1717 }
1818
1919 mountusb() { \
20− chosen="$(echo "$usbdrives" | fuzzel -d -i -p "Mount which drive?")" || exit 1
20+ chosen="$(echo "$usbdrives" | aurora-run -d -p "Mount which drive?")" || exit 1
2121 chosen="$(echo "$chosen" | awk '{print $1}')"
2222 sudo -A mount "$chosen" 2>/dev/null && notify-send "💻 USB mounting" "$chosen mounted." && exit 0
2323 alreadymounted=$(lsblk -nrpo "name,type,mountpoint" | awk '$3!~/\/boot|\/home$|SWAP/&&length($3)>1{printf "-not ( -path *%s -prune ) ",$3}')
M .local/bin/movie View
@@ -4,7 +4,7 @@
44 if [ -t 0 ]; then
55 filename="$(find ~/remote/movies/ -type f -regex ".*\.\(mkv\|mp4\|mpeg\|avi\|mov\|webm\)" -printf "%f\n" | sort | fzf)"
66 else
7− filename="$(find ~/remote/movies/ -type f -regex ".*\.\(mkv\|mp4\|mpeg\|avi\|mov\|webm\)" -printf "%f\n" | sort | fuzzel -d -l 25)"
7+ filename="$(find ~/remote/movies/ -type f -regex ".*\.\(mkv\|mp4\|mpeg\|avi\|mov\|webm\)" -printf "%f\n" | sort | aurora-run -d -l 25)"
88 fi
99
1010 filepath="$(find ~/remote/movies/ -type f -regex ".*\.\(mkv\|mp4\|mpeg\|avi\|mov\|webm\)")"
M .local/bin/unmounter View
@@ -6,7 +6,7 @@
66
77 unmountusb() {
88 [ -z "$drives" ] && exit
9− chosen="$(echo "$drives" | fuzzel -d -i -p "Unmount which drive?")" || exit 1
9+ chosen="$(echo "$drives" | aurora-run -d -p "Unmount which drive?")" || exit 1
1010 chosen="$(echo "$chosen" | awk '{print $1}')"
1111 [ -z "$chosen" ] && exit
1212 sudo -A umount "$chosen" && notify-send "💻 USB unmounting" "$chosen unmounted."
M .local/bin/waldl View
@@ -34,7 +34,7 @@ atleast=1920x1080
3434 # the menu command used when no query is provided
3535 sh_menu () {
3636 # : | dmenu -p "search wallhaven: "
37− fuzzel --lines=0 --dmenu -p "search wallhaven: "
37+ aurora-run --lines=0 --dmenu -p "search wallhaven: "
3838 # ROFI: comment the previous line and uncomment the next line for rofi
3939 # rofi -dmenu -l 0 -p "search wallpapers"
4040 }
M README.md View
@@ -22,7 +22,7 @@ You don't need the installer for that. Browse the repo and copy what you like, f
2222 - `.config/quickshell/aurora/`: the shell (needs Quickshell; it reads its colours from `~/.cache/wal/colors.json`)
2323 - `.config/hypr/`: Hyprland in the new Lua config format
2424 - `.local/bin/`: small scripts (`setwall`, `brictl`, `sysact`, `tms`, ...)
25−- `.config/wal/templates/`: pywal16 templates for Hyprland, fuzzel, zathura, cava
25+- `.config/wal/templates/`: pywal16 templates for Hyprland, zathura, cava
2626
2727 ## Installing (fresh Arch only)
2828 ```bash
@@ -67,7 +67,7 @@ The lists live in `packages/*.txt`: one package per line, `#` for comments, and
6767 | Theming | pywal16: picking a wallpaper in aurora (or `setwall`) re-themes everything |
6868 | Terminal / shell | foot, zsh |
6969 | Editor | Neovim (LazyVim) |
70−| Launcher / menus | fuzzel |
70+| Launcher / menus | aurora's runner (`aurora-run`, also a dmenu replacement for scripts) |
7171 | Files | lf, pcmanfm |
7272 | Music / video | mpd + ncmpcpp, mpv |
7373 | Font / icons | JetBrainsMono Nerd Font, Yaru |
M packages/desktop.txt View
@@ -33,7 +33,6 @@ wireplumber
3333
3434 # Apps the configs/keybinds assume
3535 foot
36−fuzzel
3736 kanshi
3837 nsxiv
3938 xdg-utils