diff options
author | Freya Murphy <freya@freyacat.org> | 2025-06-17 15:14:45 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-06-17 15:14:45 -0400 |
commit | 1173df26fd78fdd59679645004847237ed7a0a54 (patch) | |
tree | b75e6bd3ee1a878b1a3e74d94fb9ea0bb94c14a7 /pkgs | |
parent | add upowerd (diff) | |
download | dotfiles-nix-1173df26fd78fdd59679645004847237ed7a0a54.tar.gz dotfiles-nix-1173df26fd78fdd59679645004847237ed7a0a54.tar.bz2 dotfiles-nix-1173df26fd78fdd59679645004847237ed7a0a54.zip |
add astal package, update flake to support packages
Diffstat (limited to 'pkgs')
-rw-r--r-- | pkgs/astal/default.nix | 38 | ||||
-rw-r--r-- | pkgs/astal/src/init.lua | 16 | ||||
-rw-r--r-- | pkgs/astal/src/lib.lua | 78 | ||||
-rw-r--r-- | pkgs/astal/src/style/style.scss | 56 | ||||
-rw-r--r-- | pkgs/astal/src/style/theme.scss | 32 | ||||
-rw-r--r-- | pkgs/astal/src/style/widget/bar.scss | 48 | ||||
-rw-r--r-- | pkgs/astal/src/style/widget/corners.scss | 9 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/audio.lua | 20 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/battery.lua | 21 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/date.lua | 18 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/focusedClient.lua | 29 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/init.lua | 44 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/tray.lua | 34 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/wifi.lua | 24 | ||||
-rw-r--r-- | pkgs/astal/src/widget/bar/workspaces.lua | 28 | ||||
-rw-r--r-- | pkgs/astal/src/widget/corners.lua | 19 | ||||
-rw-r--r-- | pkgs/default.nix | 12 |
17 files changed, 526 insertions, 0 deletions
diff --git a/pkgs/astal/default.nix b/pkgs/astal/default.nix new file mode 100644 index 0000000..73ada9c --- /dev/null +++ b/pkgs/astal/default.nix @@ -0,0 +1,38 @@ +{ + pkgs, + inputs, + system, + runCommand, + dart-sass, + ... +}: + +let + apkgs = inputs.astal.packages.${system}; + scss = "${dart-sass}/bin/sass"; +in +inputs.astal.lib.mkLuaPackage { + pkgs = pkgs // { + # use luajit + lua = pkgs.luajit; + }; + src = runCommand "src" {} '' + mkdir -p $out + cp -r ${./src}/{*.lua,widget} $out/ + cp -r ${./src}/style/* . + cat theme.scss style.scss widget/* > main.scss + ${scss} main.scss $out/main.css + ''; + name = "astal"; + extraPackages = (with apkgs; [ + battery + hyprland + mpris + network + notifd + tray + wireplumber + ]) ++ (with pkgs; [ + networkmanager + ]); +} diff --git a/pkgs/astal/src/init.lua b/pkgs/astal/src/init.lua new file mode 100644 index 0000000..b350fbf --- /dev/null +++ b/pkgs/astal/src/init.lua @@ -0,0 +1,16 @@ +local astal = require("astal") +local App = require("astal.gtk3.app") +local lib = require("lib") + +local Bar = require("widget.bar") +local Corners = require("widget.corners") + +App:start({ + css = lib.src("main.css"), + main = function() + for _, mon in pairs(App.monitors) do + Bar(mon) + Corners(mon) + end + end, +}) diff --git a/pkgs/astal/src/lib.lua b/pkgs/astal/src/lib.lua new file mode 100644 index 0000000..93f4bc1 --- /dev/null +++ b/pkgs/astal/src/lib.lua @@ -0,0 +1,78 @@ +local Variable = require("astal").Variable + +local lib + +lib = { + --- get path to file in astal source + src = function(path) + local str = debug.getinfo(2, "S").source:sub(2) + local src = str:match("(.*/)") or str:match("(.*\\)") or "./" + return src .. path + end, + + --- map an array with a function + map = function(array, func) + local new_arr = {} + for i, v in ipairs(array) do + new_arr[i] = func(v, i) + end + return new_arr + end, + + --- filter an array with a function + filter = function(array, func) + local new_arr = {} + for i, v in ipairs(array) do + if func(v, i) then + new_arr[i] = v + end + end + return new_arr + end, + + --- sort an array of object on a key + sort = function(array, func) + + -- default func to sort on attr 'id' + if not func then + func = 'id' + end + + -- make function if just provided with attribute + if type(func) ~= 'function' then + local key = func + func = function(a, b) return a[key] < b[key] end + end + + -- copy to new array + local new_arr = {} + for i, v in ipairs(array) do + new_arr[i] = v + end + + -- sort and return + table.sort(new_arr, func) + return new_arr + end, + + --- returns length of table + count = function(array) + if not array then + return 0 + else + return #array + end + end, + + --- returns if a table is empty + empty = function(array) + return lib.count(array) == 0 + end, + + --- negates value + neg = function(val) + return not val + end, +} + +return lib diff --git a/pkgs/astal/src/style/style.scss b/pkgs/astal/src/style/style.scss new file mode 100644 index 0000000..77c8b36 --- /dev/null +++ b/pkgs/astal/src/style/style.scss @@ -0,0 +1,56 @@ +@use "sass:color"; +@use "sass:math"; + +@import "./theme"; + +* { + all: unset; +} + +window { + color: $text; + font-family: $font-name; +} + +button { + color: $text; + background: $surface-bg; + + &:hover { + color: $hover; + background: $hover-bg; + } + + &.primary { + color: $primary; + background: $primary-bg; + } +} + +menu { + background: $bg; + padding: $inner-gap 0; + border-radius: $outer-radius; + + menuitem { + color: $text; + margin: $inner-gap $outer-gap; + padding: $inner-gap; + border-radius: $inner-radius; + + &:hover, + &:selected { + background: $surface-bg; + } + + &:disabled { + color: $subtext; + } + } + + separator { + background-color: $surface-bg; + min-height: 1px; + margin: $inner-gap 0; + } +} diff --git a/pkgs/astal/src/style/theme.scss b/pkgs/astal/src/style/theme.scss new file mode 100644 index 0000000..2af74f5 --- /dev/null +++ b/pkgs/astal/src/style/theme.scss @@ -0,0 +1,32 @@ + +$text: #cdd6f4; +$subtext: #a6adc8; + +$bg: #1e1e2e; +$surface-bg: #313244; + +$hover: $text; +$hover-bg: #6c7086; + +$primary: $bg; +$primary-bg: #89b4fa; + +$success: #a6e3a1; +$success-bg: $bg; + +$warning: #f9e2af; +$warning-bg: $bg; + +$error: #f38ba8; +$error-bg: $bg; + +$border: 2px; + +$inner-radius: 4px; +$outer-radius: 8px; + +$inner-gap: 3px; +$outer-gap: 10px; + +$font-name: "JetBrains Mono", "monospace"; +$font-size: 14px; diff --git a/pkgs/astal/src/style/widget/bar.scss b/pkgs/astal/src/style/widget/bar.scss new file mode 100644 index 0000000..01e73ce --- /dev/null +++ b/pkgs/astal/src/style/widget/bar.scss @@ -0,0 +1,48 @@ + +.bar { + background: $bg; + + .workspaces { + margin: $inner-gap $outer-gap; + + .workspace { + margin: $inner-gap; + border-radius: $inner-radius; + min-width: $font-size + $outer-gap; + min-height: $font-size + $outer-gap; + font-weight: bold; + } + } + + .right { + margin: $inner-gap $outer-gap; + + .wifi, + .audio, + .battery, + .tray { + margin: $inner-gap $outer-gap; + margin-right: 0px; + background: $surface-bg; + border-radius: $inner-radius; + padding: 0px $outer-gap; + + icon { + margin-right: $inner-gap; + } + + } + + .tray { + padding-right: 0; + + icon { + margin-right: $outer-gap; + } + + .menubtn:hover { + background: transparent; + } + } + } +} diff --git a/pkgs/astal/src/style/widget/corners.scss b/pkgs/astal/src/style/widget/corners.scss new file mode 100644 index 0000000..53cdb9b --- /dev/null +++ b/pkgs/astal/src/style/widget/corners.scss @@ -0,0 +1,9 @@ + +.corners { + $radius: $outer-radius + $outer-gap; + + box { + box-shadow: 0 0 0 $radius $bg; + border-radius: $radius $radius 0 0; + } +} diff --git a/pkgs/astal/src/widget/bar/audio.lua b/pkgs/astal/src/widget/bar/audio.lua new file mode 100644 index 0000000..c1934f9 --- /dev/null +++ b/pkgs/astal/src/widget/bar/audio.lua @@ -0,0 +1,20 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") +local Wp = astal.require("AstalWp") +local bind = astal.bind + +return function() + local speaker = Wp.get_default().audio.default_speaker + + return Widget.Box({ + class_name = "audio", + Widget.Icon({ + icon = bind(speaker, "volume-icon"), + }), + Widget.Label({ + label = bind(speaker, "volume"):as(function(p) + return tostring(math.floor(p * 100)) .. '%' + end) + }), + }) +end diff --git a/pkgs/astal/src/widget/bar/battery.lua b/pkgs/astal/src/widget/bar/battery.lua new file mode 100644 index 0000000..d13143a --- /dev/null +++ b/pkgs/astal/src/widget/bar/battery.lua @@ -0,0 +1,21 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") +local Battery = astal.require("AstalBattery") +local bind = astal.bind + +return function() + local bat = Battery.get_default() + + return Widget.Box({ + class_name = "battery", + visible = bind(bat, "is-present"), + Widget.Icon({ + icon = bind(bat, "battery-icon-name"), + }), + Widget.Label({ + label = bind(bat, "percentage"):as(function(p) + return tostring(math.floor(p * 100)) .. '%' + end) + }), + }) +end diff --git a/pkgs/astal/src/widget/bar/date.lua b/pkgs/astal/src/widget/bar/date.lua new file mode 100644 index 0000000..b64d8bb --- /dev/null +++ b/pkgs/astal/src/widget/bar/date.lua @@ -0,0 +1,18 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") +local Variable = astal.Variable +local GLib = astal.require("GLib") + +local format = "%Y-%m-%d %a %H:%M:%S" +local date = Variable(""):poll( + 1000, function() + return GLib.DateTime.new_now_local():format(format) + end +); + +return function() + return Widget.Label({ + class_name = "date", + label = date(), + }) +end diff --git a/pkgs/astal/src/widget/bar/focusedClient.lua b/pkgs/astal/src/widget/bar/focusedClient.lua new file mode 100644 index 0000000..329cc4e --- /dev/null +++ b/pkgs/astal/src/widget/bar/focusedClient.lua @@ -0,0 +1,29 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") +local Hyprland = astal.require("AstalHyprland") +local bind = astal.bind + +local hypr = Hyprland.get_default() + +function Client(client) + -- sanity check + if not client then + return nil + end + + return Widget.Label({ + ellipsize = "END", + max_width_chars = 50, + label = bind(client, "title"):as(tostring), + }) +end + +return function() + local focused = bind(hypr, "focused-client") + + return Widget.Box({ + class_name = "focusedClient", + visible = focused, + focused:as(Client) + }) +end diff --git a/pkgs/astal/src/widget/bar/init.lua b/pkgs/astal/src/widget/bar/init.lua new file mode 100644 index 0000000..038ac90 --- /dev/null +++ b/pkgs/astal/src/widget/bar/init.lua @@ -0,0 +1,44 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") + +local Workspaces = require("widget.bar.workspaces") +local FocusedClient = require("widget.bar.focusedClient") +local Date = require("widget.bar.date") +local WiFi = require("widget.bar.wifi") +local Audio = require("widget.bar.audio") +local Battery = require("widget.bar.battery") +local Tray = require("widget.bar.tray") + +return function(gdkmonitor) + local Anchor = astal.require('Astal').WindowAnchor + + return Widget.Window({ + class_name = "bar", + gdkmonitor = gdkmonitor, + anchor = Anchor.TOP + Anchor.LEFT + Anchor.RIGHT, + exclusivity = "EXCLUSIVE", + Widget.CenterBox({ + Widget.Box({ + class_name = "left", + halign = "START", + hexpand = true, + Workspaces(), + FocusedClient(), + }), + Widget.Box({ + class_name = "center", + hexpand = true, + Date(), + }), + Widget.Box({ + class_name = "right", + halign = "END", + hexpand = true, + WiFi(), + Audio(), + Battery(), + Tray(), + }), + }) + }) +end diff --git a/pkgs/astal/src/widget/bar/tray.lua b/pkgs/astal/src/widget/bar/tray.lua new file mode 100644 index 0000000..9046494 --- /dev/null +++ b/pkgs/astal/src/widget/bar/tray.lua @@ -0,0 +1,34 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") +local Tray = astal.require("AstalTray") +local lib = require("lib") +local bind = astal.bind + +function Item(item) + return Widget.MenuButton({ + class_name = "menubtn", + tooltip_markup = bind(item, "tooltip_markup"), + use_popover = false, + menu_model = bind(item, "menu-model"), + action_group = bind(item, "action-group"):as( + function(ag) return { "dbusmenu", ag } end + ), + Widget.Icon({ + gicon = bind(item, "gicon"), + }), + }) +end + +function Items(items) + return lib.map(items, Item) +end + +return function() + local tray = Tray.get_default() + + return Widget.Box({ + class_name = "tray", + visible = bind(tray, "items"):as(lib.empty):as(lib.neg), + bind(tray, "items"):as(Items) + }) +end diff --git a/pkgs/astal/src/widget/bar/wifi.lua b/pkgs/astal/src/widget/bar/wifi.lua new file mode 100644 index 0000000..7a293a0 --- /dev/null +++ b/pkgs/astal/src/widget/bar/wifi.lua @@ -0,0 +1,24 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") +local Network = astal.require("AstalNetwork") +local bind = astal.bind + +return function() + local network = Network.get_default() + local wifi = bind(network, "wifi") + + return Widget.Box({ + class_name = "wifi", + visible = wifi, + wifi:as(function(wifi) + return Widget.Box({ + Widget.Icon({ + icon = bind(wifi, "icon-name"), + }), + Widget.Label({ + label = bind(wifi, "ssid"), + }), + }) + end), + }) +end diff --git a/pkgs/astal/src/widget/bar/workspaces.lua b/pkgs/astal/src/widget/bar/workspaces.lua new file mode 100644 index 0000000..8bc1785 --- /dev/null +++ b/pkgs/astal/src/widget/bar/workspaces.lua @@ -0,0 +1,28 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") +local Hyprland = astal.require("AstalHyprland") +local lib = require('lib') +local bind = astal.bind + +local hypr = Hyprland.get_default() + +function Workspace(ws) + return Widget.Button({ + class_name = bind(hypr, "focused-workspace"):as(function(fw) + return "workspace " .. (fw == ws and "primary" or "") + end), + on_clicked = function() ws:focus() end, + label = ws.id, + }) +end + +function Workspaces(wss) + return lib.map(lib.sort(wss, 'id'), Workspace) +end + +return function() + return Widget.Box({ + class_name = "workspaces", + bind(hypr, "workspaces"):as(Workspaces) + }) +end diff --git a/pkgs/astal/src/widget/corners.lua b/pkgs/astal/src/widget/corners.lua new file mode 100644 index 0000000..d1a7755 --- /dev/null +++ b/pkgs/astal/src/widget/corners.lua @@ -0,0 +1,19 @@ +local astal = require("astal") +local Widget = require("astal.gtk3.widget") + +return function(gdkmonitor) + local Anchor = astal.require('Astal').WindowAnchor + + return Widget.Window({ + class_name = "corners", + gdkmonitor = gdkmonitor, + anchor = Anchor.TOP + Anchor.BOTTOM + Anchor.LEFT + Anchor.RIGHT, + exclusivity = "EXCLUSIVE", + setup = function(self) + self.click_through = true + end, + Widget.Box({ + expand = true, + }) + }) +end diff --git a/pkgs/default.nix b/pkgs/default.nix new file mode 100644 index 0000000..042fc16 --- /dev/null +++ b/pkgs/default.nix @@ -0,0 +1,12 @@ +{ pkgs, inputs, system, ... }: + +let + build = (path: pkgs.callPackage path { + inherit pkgs; + inherit inputs; + inherit system; + }); +in +{ + astal = build ./astal; +} |