initial commit
All checks were successful
Deploy docs / build-and-deploy (push) Successful in 3s

This commit is contained in:
sid 2026-02-23 20:34:35 +01:00
commit 95a533c876
451 changed files with 18255 additions and 0 deletions

View file

@ -0,0 +1,21 @@
{
config,
lib,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.applauncher.default;
inherit (lib) mkIf;
in
{
imports = [ ../../../bemenu ];
config = mkIf (cfg.enable && app == "bemenu") {
programs.bemenu = {
enable = true;
};
};
}

View file

@ -0,0 +1,202 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
apps = cfg.applications;
# dynamically create a set of default app assignments
defaultApps = mapAttrs (name: app: app.default) apps;
# function to generate the attribute set for each application
mkAppAttrs =
{
default,
bind ? [ "" ],
windowrule ? [ "" ],
}:
{
default = mkOption {
type = types.str;
default = default;
description = "The default application to use for the ${default}.";
};
bind = mkOption {
type = types.listOf types.str;
default = bind;
description = "The keybinding to use for the ${default}.";
};
windowrule = mkOption {
type = types.listOf types.str;
default = windowrule;
description = "The window rule to use for the ${default}.";
};
};
# generate lists of all binds and window rules and remove empty strings
binds = filter (s: s != "") (
builtins.concatLists (map (app: app.bind or [ "" ]) (attrValues apps))
);
windowrules = filter (s: s != "") (
builtins.concatLists (map (app: app.windowrule or [ "" ]) (attrValues apps))
);
inherit (lib)
attrValues
filter
getExe
mapAttrs
mkOption
types
;
in
{
imports = [
./bemenu
./dmenu-bluetooth
./element-desktop
./feh
./kitty
./libreoffice
./librewolf
./mpv
./ncmpcpp
./networkmanager_dmenu
./newsboat
./passwordmanager
./powermenu-bemenu
./presentation-mode-bemenu
./qbittorrent
./screenshot
./thunderbird
./yazi
./zathura
# add your application directories here
];
options.wayland.windowManager.hyprland.applications = with defaultApps; {
applauncher = mkAppAttrs {
default = "bemenu";
bind = [ "$mod, d, exec, ${applauncher}-run" ];
};
audiomixer = mkAppAttrs {
default = "pulsemixer";
bind = [ "$mod, a, exec, ${terminal} -T ${audiomixer} -e ${pkgs.pulsemixer}/bin/pulsemixer" ];
windowrule = [
"float, title:^${audiomixer}$"
"size 50% 50%, title:^${audiomixer}$"
];
};
bluetoothsettings = mkAppAttrs {
default = "dmenu-bluetooth";
bind = [ "$mod SHIFT, b, exec, ${bluetoothsettings}" ];
};
browser = mkAppAttrs {
default = "librewolf";
bind = [ "$mod, b, exec, ${browser}" ];
};
calculator = mkAppAttrs {
default = "octave";
bind = [
", XF86Calculator, exec, ${terminal} -T ${calculator} -e ${pkgs.octave}/bin/octave"
];
};
emailclient = mkAppAttrs {
default = "thunderbird";
bind = [ "$mod, m, exec, ${emailclient}" ];
};
equalizer = mkAppAttrs {
default = "easyeffects";
bind = [ "$mod CTRL, e, exec, ${getExe pkgs.easyeffects}" ];
};
filemanager = mkAppAttrs {
default = "yazi";
bind = [ "$mod, e, exec, ${terminal} -T ${filemanager} -e ${filemanager}" ];
};
matrix-client = mkAppAttrs {
default = "element-desktop";
bind = [ "$mod SHIFT, e, exec, ${matrix-client}" ];
};
musicplayer = mkAppAttrs {
default = "ncmpcpp";
bind = [ "$mod SHIFT, m, exec, ${terminal} -T ${musicplayer} -e ${musicplayer}" ];
};
networksettings = mkAppAttrs {
default = "networkmanager_dmenu";
bind = [ "$mod SHIFT, n, exec, ${networksettings}" ];
};
notes = mkAppAttrs {
default = "quicknote";
bind = [ "$mod CTRL, n, exec, ${terminal} -T ${notes} -e ${getExe pkgs.synix.quicknote}" ];
};
office = mkAppAttrs {
default = "libreoffice";
bind = [ "$mod SHIFT, o, exec, ${office}" ];
};
password-manager = mkAppAttrs {
default = "passmenu-bemenu";
bind = [ "$mod, p, exec, ${password-manager}" ];
};
imageviewer = mkAppAttrs { default = "feh"; };
pdfviewer = mkAppAttrs { default = "zathura"; };
powermenu = mkAppAttrs {
default = "powermenu-bemenu";
bind = [ "$mod SHIFT, q, exec, ${powermenu}" ];
};
presentation-mode = mkAppAttrs {
default = "presentation-mode-bemenu";
bind = [ "$mod SHIFT, p, exec, ${presentation-mode}" ];
};
rssreader = mkAppAttrs {
default = "newsboat";
bind = [ "$mod, n, exec, ${terminal} -T ${rssreader} -e ${rssreader}" ];
};
screenshotter = mkAppAttrs {
default = "screenshot";
bind = [
"$mod, Print, exec, ${screenshotter} output" # select monitor
"$mod SHIFT, Print, exec, ${screenshotter} region" # select region
"$mod CTRL, Print, exec, ${screenshotter} window" # select window
];
};
terminal = mkAppAttrs {
default = "kitty";
bind = [ "$mod, Return, exec, ${terminal}" ];
};
torrent-client = mkAppAttrs { default = "qbittorrent"; };
videoplayer = mkAppAttrs { default = "mpv"; };
};
config = {
wayland.windowManager.hyprland.settings = {
bind = binds;
windowrule = windowrules;
};
};
}

View file

@ -0,0 +1,22 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.bluetoothsettings.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "dmenu-bluetooth") {
home.packages = with pkgs; [ dmenu-bluetooth ];
home.sessionVariables = {
DMENU_BLUETOOTH_LAUNCHER = cfg.applications.applauncher.default or "bemenu";
};
};
}

View file

@ -0,0 +1,25 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.matrix-client.default;
inherit (lib) mkDefault mkIf;
in
{
config = mkIf (cfg.enable && app == "element-desktop") {
# FIXME: screen sharing does not work
programs.element-desktop = {
enable = true;
settings = {
# Use Chromium for screen sharing
default_theme = mkDefault "dark";
};
};
};
}

View file

@ -0,0 +1,45 @@
{ config, lib, ... }:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.imageviewer.default;
desktop = "feh.desktop";
mimeTypes = [
"image/gif"
"image/heic"
"image/jpeg"
"image/jpg"
"image/pjpeg"
"image/png"
"image/tiff"
"image/webp"
"image/x-bmp"
"image/x-pcx"
"image/x-png"
"image/x-portable-anymap"
"image/x-portable-bitmap"
"image/x-portable-graymap"
"image/x-portable-pixmap"
"image/x-tga"
"image/x-xbitmap"
];
associations =
let
genMimeAssociations = import ../genMimeAssociations.nix;
in
genMimeAssociations desktop mimeTypes;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "feh") {
programs.feh = {
enable = true;
};
xdg.mimeApps = {
defaultApplications = associations;
associations.added = associations;
};
};
}

View file

@ -0,0 +1,8 @@
# Generate a list of mime associations for a desktop file
desktop: mimeTypes:
builtins.listToAttrs (
map (mimeType: {
name = mimeType;
value = desktop;
}) mimeTypes
)

View file

@ -0,0 +1,21 @@
{
config,
lib,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.terminal.default;
inherit (lib) mkIf;
in
{
imports = [ ../../../kitty ];
config = mkIf (cfg.enable && app == "kitty") {
programs.kitty = {
enable = true;
};
};
}

View file

@ -0,0 +1,20 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.office.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "libreoffice") {
home.packages = [ pkgs.libreoffice ];
# TODO: set Tools > Options > Application Colors > Automatic = Dark
};
}

View file

@ -0,0 +1,41 @@
{
config,
lib,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.browser.default;
desktop = "librewolf.desktop";
mimeTypes = [
"text/html"
"text/xml"
"application/xhtml+xml"
"application/vnd.mozilla.xul+xml"
"x-scheme-handler/http"
"x-scheme-handler/https"
];
associations =
let
genMimeAssociations = import ../genMimeAssociations.nix;
in
genMimeAssociations desktop mimeTypes;
inherit (lib) mkIf;
in
{
imports = [ ../../../librewolf ];
config = mkIf (cfg.enable && app == "librewolf") {
programs.librewolf = {
enable = true;
};
xdg.mimeApps = {
associations.added = associations;
defaultApplications = associations;
};
};
}

View file

@ -0,0 +1,15 @@
{ config, lib, ... }:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.videoplayer.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "mpv") {
programs.mpv = {
enable = true;
};
};
}

View file

@ -0,0 +1,22 @@
{ config, lib, ... }:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.musicplayer.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "ncmpcpp") {
programs = {
ncmpcpp = {
enable = true;
};
};
services = {
mpd = {
enable = true;
};
};
};
}

View file

@ -0,0 +1,22 @@
{
config,
lib,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.networksettings.default;
inherit (lib) mkIf;
in
{
imports = [ ../../../networkmanager-dmenu ];
config = mkIf (cfg.enable && app == "networkmanager_dmenu") {
programs.networkmanager-dmenu = {
enable = true;
config.dmenu.dmenu_command = "bemenu";
};
};
}

View file

@ -0,0 +1,47 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.rssreader.default;
reloadTime = "${toString config.programs.newsboat.reloadTime}";
newsboat-reload = (import ./newsboat-reload.nix { inherit config pkgs; });
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "newsboat") {
programs.newsboat = {
enable = true;
extraConfig = builtins.readFile ./extra-config;
};
home.packages = [ newsboat-reload ]; # newsboat's waybar module executes newsboat-reload on click
# Automatically reload newsboat on timer
systemd.user = {
timers.newsboat-reload = {
Unit.Description = "Reload newsboat every ${reloadTime} minutes";
Timer.OnBootSec = "10sec";
Timer.OnUnitActiveSec = "${reloadTime}min";
Timer.Unit = "newsboat-reload.service";
Install.WantedBy = [ "timers.target" ];
};
services.newsboat-reload = {
Unit.Description = "Reload newsboat";
Service.Type = "oneshot";
Service.ExecStart = "${newsboat-reload}/bin/newsboat-reload";
Install.WantedBy = [ "multi-user.target" ];
};
};
};
}

View file

@ -0,0 +1,35 @@
# Format
feedlist-title-format "Your feeds (%u unread, %t total)%?T? - tag %T&?"
articlelist-title-format "Articles in feed %T (%u unread, %t total) - %U"
searchresult-title-format "Search result (%u unread, %t total)"
filebrowser-title-format "%?O?Open File&Save File? - %f"
help-title-format "Help"
selecttag-title-format "Select Tag"
selectfilter-title-format "Select Filter"
itemview-title-format "%T (%u unread, %t total) "
urlview-title-format "URLs"
dialogs-title-format "Dialogs"
feedlist-format "%4i %n %11u %t"
articlelist-format "%4i %f %D %?T?|%-17T| ?%t"
notify-format "%d new articles (%n unread articles, %f unread feeds)"
# Colors
color background white default
color listnormal white default
color listfocus white black bold
color listnormal_unread magenta default
color listfocus_unread magenta black bold
color info blue black bold
color article white default
# Highlight
highlight article "(^Feed:.*|^Title:.*|^Author:.*)" blue default bold
highlight article "(^Link:.*|^Date:.*)" default default
highlight article "https?://[^ ]+" green default
highlight article "^(Title):.*$" blue default
highlight article "\\[[0-9][0-9]*\\]" magenta default bold
highlight article "\\[image\\ [0-9]+\\]" green default bold
highlight article "\\[embedded flash: [0-9][0-9]*\\]" green default bold
highlight article ":.*\\(link\\)$" cyan default
highlight article ":.*\\(image\\)$" blue default
highlight article ":.*\\(embedded flash\\)$" magenta default

View file

@ -0,0 +1,10 @@
{ config, pkgs, ... }:
let
newsboat = "${pkgs.newsboat}/bin/newsboat";
notify = "${pkgs.libnotify}/bin/notify-send";
signal = "${toString config.programs.waybar.settings.mainBar."custom/newsboat".signal}";
in
(pkgs.writeShellScriptBin "newsboat-reload" ''
${notify} -u low 'Newsboat' 'Reloading RSS feeds...' && ${newsboat} -x reload && ${notify} -u low 'Newsboat' 'RSS feeds reloaded.' && pkill -RTMIN+${signal} waybar
'')

View file

@ -0,0 +1,22 @@
{
config,
lib,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.password-manager.default;
inherit (lib) mkIf;
in
{
imports = [ ../../../password-manager ];
config = mkIf (cfg.enable && app == "passmenu-bemenu") {
programs.passwordManager = {
enable = true;
wayland = true;
};
};
}

View file

@ -0,0 +1,18 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.powermenu.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "powermenu-bemenu") {
home.packages = [ (import ./powermenu-bemenu.nix { inherit config pkgs; }) ];
};
}

View file

@ -0,0 +1,10 @@
{ config, pkgs, ... }:
(pkgs.writeShellScriptBin "powermenu-bemenu" ''
case $(echo -e "shutdown\nreboot\nlock\nkill" | bemenu -p "") in
shutdown) systemctl poweroff ;;
reboot) systemctl reboot ;;
lock) "${config.programs.hyprlock.package}/bin/hyprlock" ;;
kill) hyprctl dispatch exit ;;
esac
'')

View file

@ -0,0 +1,22 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.presentation-mode.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "presentation-mode-bemenu") {
home.packages = [
(pkgs.writeShellScriptBin "presentation-mode-bemenu" (
builtins.readFile ./presentation-mode-bemenu.sh
))
];
};
}

View file

@ -0,0 +1,32 @@
# Variables
DISPLAYS=( $(hyprctl monitors | grep -E '^Monitor' | awk '{print $2}') )
EXTEND_RIGHT="Extend to right of main"
EXTEND_LEFT="Extend to left of main"
MIRROR="Mirror main"
DISABLE="Disable main"
# Exit if only one display is available
[[ "${#DISPLAYS[@]}" -eq 1 ]] && echo "Only one display available." && exit 0
MAIN_DISPLAY=${DISPLAYS[0]}
SECOND_DISPLAY=${DISPLAYS[1]} # TODO: Add support for more than two displays
# Select action
ACTIONS="$EXTEND_RIGHT\n$EXTEND_LEFT\n$MIRROR\n$DISABLE"
ACTIONS_CHOICE=$(echo -e "$ACTIONS" | bemenu -p "Select action")
# Handle actions that do not need a mode
case "$ACTIONS_CHOICE" in
"$MIRROR") hyprctl keyword monitor "$SECOND_DISPLAY", preferred, auto, 1, mirror, "$MAIN_DISPLAY" && exit 0;;
"$DISABLE") hyprctl keyword monitor "$MAIN_DISPLAY", disable && exit 0;;
esac
# Select mode
MODES=$( hyprctl monitors | awk '/^Monitor/{flag=1; next} /^$/{flag=0} flag' | awk -F "availableModes: " '{print $2}' | sed 's/ /\\n/g' | awk NF )
MODES_CHOICE=$(echo -e "$MODES" | bemenu -p "Select mode")
# Handle actions that need a mode
case "$ACTIONS_CHOICE" in
"$EXTEND_RIGHT") hyprctl keyword monitor "$SECOND_DISPLAY", "$MODES_CHOICE", auto-right, 1 ;;
"$EXTEND_LEFT") hyprctl keyword monitor "$SECOND_DISPLAY", "$MODES_CHOICE", auto-left, 1 ;;
esac

View file

@ -0,0 +1,34 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.torrent-client.default;
desktop = "org.qbittorrent.qBittorrent.desktop";
mimeTypes = [
"application/x-bittorrent"
"x-scheme-handler/magnet"
];
associations =
let
genMimeAssociations = import ../genMimeAssociations.nix;
in
genMimeAssociations desktop mimeTypes;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "qbittorrent") {
home.packages = [ pkgs.qbittorrent ];
# TODO: automatically apply dark theme
xdg.mimeApps = {
defaultApplications = associations;
associations.added = associations;
};
};
}

View file

@ -0,0 +1,18 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.screenshotter.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "screenshot") {
home.packages = [ (import ./screenshot.nix { inherit config pkgs; }) ];
};
}

View file

@ -0,0 +1,11 @@
{ config, pkgs, ... }:
# pass the mode (output, window, region) as a command line argument
let
screenshotDir = "${config.xdg.userDirs.pictures}/screenshots";
in
(pkgs.writeShellScriptBin "screenshot" ''
mkdir -p ${screenshotDir}
${pkgs.hyprshot}/bin/hyprshot --mode $1 --output-folder ${screenshotDir} --filename screenshot_$(date +"%Y-%m-%d_%H-%M-%S").png
'')

View file

@ -0,0 +1,43 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.emailclient.default;
desktop = "thunderbird.desktop";
mimeTypes = [
"message/rfc822"
"x-scheme-handler/mailto"
"text/calendar"
"text/x-vcard"
];
associations =
let
genMimeAssociations = import ../genMimeAssociations.nix;
in
genMimeAssociations desktop mimeTypes;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "thunderbird") {
home.packages = [ pkgs.thunderbird ];
# programs.thunderbird = {
# enable = true;
# profiles.default = {
# isDefault = mkDefault true;
# withExternalGnupg = mkDefault true;
# };
# };
xdg.mimeApps = {
defaultApplications = associations;
associations.added = associations;
};
};
}

View file

@ -0,0 +1,20 @@
{
config,
lib,
...
}:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.filemanager.default;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "yazi") {
programs.yazi = {
enable = true;
enableZshIntegration = config.programs.zsh.enable;
};
};
}

View file

@ -0,0 +1,33 @@
{ config, lib, ... }:
let
cfg = config.wayland.windowManager.hyprland;
app = cfg.applications.pdfviewer.default;
desktop = "org.pwmt.zathura.desktop";
mimeTypes = [
"application/pdf"
];
associations =
let
genMimeAssociations = import ../genMimeAssociations.nix;
in
genMimeAssociations desktop mimeTypes;
inherit (lib) mkIf;
in
{
config = mkIf (cfg.enable && app == "zathura") {
programs.zathura = {
enable = true;
options = {
guiptions = "none";
selection-clipboard = "clipboard";
};
};
xdg.mimeApps = {
defaultApplications = associations;
associations.added = associations;
};
};
}