Restructure repo

This commit is contained in:
2025-11-29 20:18:45 +01:00
parent e1e2040deb
commit 1e89b45042
97 changed files with 114 additions and 139 deletions

View File

@@ -0,0 +1,80 @@
{ config, pkgs, ... }:
{
programs.pimsync.enable = true;
services.pimsync.enable = true;
accounts.calendar = {
basePath = "${config.xdg.dataHome}/calendars";
accounts = {
"radicale" = {
primary = true;
primaryCollection = "personal";
local = {
type = "filesystem";
fileExt = ".ics";
};
remote = {
url = "https://radicale.jelles.net/";
type = "caldav";
userName = "kiri";
# TODO: Bitwarden
passwordCommand = [
"${pkgs.coreutils}/bin/cat"
config.sops.secrets.radicale_pass.path
];
};
pimsync = {
enable = true;
extraPairDirectives = [
{
name = "collections";
params = [ "from b" ];
}
];
};
};
"university" = {
remote = {
type = "http";
};
local = {
type = "filesystem";
fileExt = ".ics";
};
pimsync = {
enable = true;
extraRemoteStorageDirectives = [
{
name = "collection_id";
params = [ "events" ];
}
{
name = "url";
children = [
{
name = "cmd";
params = [
"${pkgs.coreutils}/bin/cat"
config.sops.secrets.university_calendar_url.path
];
}
];
}
];
extraPairDirectives = [
{
name = "collection";
params = [ "events" ];
}
];
};
};
};
};
}

View File

@@ -0,0 +1,6 @@
{
imports = [
./email.nix
./calendar.nix
];
}

View File

@@ -0,0 +1,87 @@
{ config, ... }:
{
# Global enablement
programs.mbsync.enable = true;
programs.msmtp.enable = true;
programs.notmuch.enable = true;
services.mbsync.enable = true;
accounts.email.maildirBasePath = "${config.xdg.dataHome}/mail";
accounts.email.accounts = {
main = {
enable = true;
primary = true;
address = "mail@jelles.net";
imap = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 993;
tls.enable = true;
};
realName = "Jelle Spreeuwenberg";
smtp = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 465;
tls.enable = true;
};
userName = "mail@jelles.net";
passwordCommand = "rbw get \"Main E-Mail\"";
mbsync = {
enable = true;
create = "both";
expunge = "both";
patterns = [ "*" ];
};
msmtp.enable = true;
notmuch.enable = true;
};
old = {
enable = true;
address = "mail@jellespreeuwenberg.nl";
imap = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 993;
tls.enable = true;
};
realName = "Jelle Spreeuwenberg";
smtp = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 465;
tls.enable = true;
};
userName = "mail@jellespreeuwenberg.nl";
passwordCommand = "rbw get \"Old E-Mail\"";
mbsync = {
enable = true;
create = "both";
expunge = "both";
patterns = [ "*" ];
};
msmtp.enable = true;
notmuch.enable = true;
};
uni = {
enable = true;
flavor = "outlook.office365.com";
address = "j.spreeuwenberg@student.tue.nl";
realName = "Jelle Spreeuwenberg";
userName = "j.spreeuwenberg@student.tue.nl";
};
work = {
enable = true;
flavor = "outlook.office365.com";
address = "jelle.spreeuwenberg@yookr.org";
realName = "Jelle Spreeuwenberg";
userName = "jelle.spreeuwenberg@yookr.org";
};
};
}

View File

@@ -0,0 +1,23 @@
{ config, pkgs, ... }:
{
programs.aerc = {
enable = true;
extraConfig = {
general.unsafe-accounts-conf = true;
filters = {
"text/html" = "${pkgs.w3m}/bin/w3m -I UTF-8 -T text/html";
"text/ical" = "${pkgs.bat}/bin/bat -fP --style=plain --language=ical";
"text/*" = "${pkgs.bat}/bin/bat -fP --style=plain";
};
};
};
accounts.email.accounts = {
main = {
aerc.enable = true;
};
old = {
aerc.enable = true;
};
};
}

View File

@@ -0,0 +1,11 @@
{ pkgs, ... }:
{
programs.rbw = {
enable = true;
settings = {
base_url = "https://vault.jelles.net";
email = "mail@jelles.net";
pinentry = pkgs.pinentry-gnome3;
};
};
}

View File

@@ -0,0 +1,7 @@
{
programs.direnv = {
enable = true;
enableZshIntegration = true;
nix-direnv.enable = true;
};
}

View File

@@ -0,0 +1,7 @@
# Discord is a popular chat application.
{ inputs, ... }:
{
programs.discord = {
enable = true;
};
}

View File

@@ -0,0 +1,23 @@
{
programs.ghostty = {
enable = true;
installVimSyntax = true;
enableZshIntegration = true;
settings = {
font-feature = "-calt, -liga, -dlig";
window-padding-x = 10;
window-padding-y = 10;
keybind = [
"ctrl+j=goto_split:left"
"ctrl+i=goto_split:up"
"ctrl+k=goto_split:down"
"ctrl+l=goto_split:right"
"shift+ctrl+j=new_split:left"
"shift+ctrl+i=new_split:up"
"shift+ctrl+k=new_split:down"
"shift+ctrl+l=new_split:right"
"shift+ctrl+tab=new_tab"
];
};
};
}

View File

@@ -0,0 +1,55 @@
# Git configuration
{config, ...}: let
username = config.var.git.username;
email = config.var.git.email;
in {
programs.git = {
enable = true;
ignores = [
".cache/"
".DS_Store"
".idea/"
"*.swp"
"*.elc"
"auto-save-list"
".direnv/"
"node_modules"
"result"
"result-*"
];
settings = {
user.name = username;
user.email = email;
init.defaultBranch = "main";
pull.rebase = "false";
push.autoSetupRemote = true;
color.ui = "1";
alias = {
essa = "push --force";
co = "checkout";
fuck = "commit --amend -m";
c = "commit -m";
ca = "commit -am";
forgor = "commit --amend --no-edit";
graph = "log --all --decorate --graph --oneline";
oops = "checkout --";
l = "log";
r = "rebase";
s = "status --short";
ss = "status";
d = "diff";
ps = "!git push origin $(git rev-parse --abbrev-ref HEAD)";
pl = "!git pull origin $(git rev-parse --abbrev-ref HEAD)";
af = "!git add $(git ls-files -m -o --exclude-standard | sk -m)";
st = "status";
br = "branch";
df = "!git hist | peco | awk '{print $2}' | xargs -I {} git diff {}^ {}";
hist = ''
log --pretty=format:"%Cgreen%h %Creset%cd %Cblue[%cn] %Creset%s%C(yellow)%d%C(reset)" --graph --date=relative --decorate --all'';
llog = ''
log --graph --name-status --pretty=format:"%C(red)%h %C(reset)(%cd) %C(green)%an %Creset%s %C(yellow)%d%Creset" --date=relative'';
edit-unmerged = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; hx `f`";
};
};
};
}

View File

@@ -0,0 +1,20 @@
{
config,
pkgs,
...
}: {
programs.gpg = {
enable = true;
homedir = "${config.xdg.dataHome}/gnupg";
};
services.gpg-agent = {
enable = true;
enableSshSupport = true;
enableZshIntegration = true;
pinentry = {
package = pkgs.pinentry-gnome3;
};
sshKeys = ["CD848796822630B280FC6DFA55F24A20040F22B5"];
};
}

View File

@@ -0,0 +1,52 @@
{config, ...}: let
animationSpeed = config.theme.animation-speed;
animationDuration =
if animationSpeed == "slow"
then "4"
else if animationSpeed == "medium"
then "2.5"
else "1.5";
borderDuration =
if animationSpeed == "slow"
then "10"
else if animationSpeed == "medium"
then "6"
else "3";
in {
wayland.windowManager.hyprland.settings = {
animations = {
enabled = true;
bezier = [
"linear, 0, 0, 1, 1"
"md3_standard, 0.2, 0, 0, 1"
"md3_decel, 0.05, 0.7, 0.1, 1"
"md3_accel, 0.3, 0, 0.8, 0.15"
"overshot, 0.05, 0.9, 0.1, 1.1"
"crazyshot, 0.1, 1.5, 0.76, 0.92"
"hyprnostretch, 0.05, 0.9, 0.1, 1.0"
"menu_decel, 0.1, 1, 0, 1"
"menu_accel, 0.38, 0.04, 1, 0.07"
"easeInOutCirc, 0.85, 0, 0.15, 1"
"easeOutCirc, 0, 0.55, 0.45, 1"
"easeOutExpo, 0.16, 1, 0.3, 1"
"softAcDecel, 0.26, 0.26, 0.15, 1"
"md2, 0.4, 0, 0.2, 1"
];
animation = [
"windows, 1, ${animationDuration}, md3_decel, popin 60%"
"windowsIn, 1, ${animationDuration}, md3_decel, popin 60%"
"windowsOut, 1, ${animationDuration}, md3_accel, popin 60%"
"border, 1, ${borderDuration}, default"
"fade, 1, ${animationDuration}, md3_decel"
"layersIn, 1, ${animationDuration}, menu_decel, slide"
"layersOut, 1, ${animationDuration}, menu_accel"
"fadeLayersIn, 1, ${animationDuration}, menu_decel"
"fadeLayersOut, 1, ${animationDuration}, menu_accel"
"workspaces, 1, ${animationDuration}, menu_decel, slide"
"specialWorkspace, 1, ${animationDuration}, md3_decel, slidevert"
];
};
};
}

View File

@@ -0,0 +1,75 @@
{ pkgs, ... }:
{
wayland.windowManager.hyprland.settings = {
bind = [
"$mod, return, exec, uwsm app -- ${pkgs.kitty}/bin/kitty" # Ghostty (terminal)
#"$mod,E, exec, uwsm app -- ${pkgs.xfce.thunar}/bin/thunar" # Thunar
"$mod, b, exec, uwsm app -- ${pkgs.brave}/bin/brave" # Brave Browser
"$mod, m, exec, uwsm app -- ${pkgs.thunderbird}/bin/thunderbird" # Proton Mail
#"$mod,L, exec, uwsm app -- ${pkgs.hyprlock}/bin/hyprlock" # Lock
"$mod, space, exec, vicinae toggle" # Launcher FIXME: broken
#"$mod,X, exec, powermenu" # Powermenu
#"$mod, space, exec, menu" # Launcher
"$shiftMod, space, exec, hyprfocus-toggle" # Toggle HyprFocus
"$mod, q, killactive," # Close window
"$mod, t, togglefloating," # Toggle Floating
"$mod, f, fullscreen" # Toggle Fullscreen
"$mod, j, layoutmsg, cyclenext" # Move focus Down
"$mod, k, layoutmsg, cycleprev" # Move focus Up
"$altMod, j, layoutmsg, swapnext" # Move focus Down
"$altMod, k, layoutmsg, swapprev" # Move focus Up
"$mod, x, focusmonitor, +1" # Focus next monitor
"$altMod, x, movewindow, mon:+1"
"$altMod, h, layoutmsg, addmaster" # Add to master
"$altMod, l, layoutmsg, removemaster" # Remove from master
"$mod, print, exec, screenshot region" # Screenshot region
", PRINT, exec, screenshot monitor" # Screenshot monitor
"$mod, w, workspace, 1"
"$mod, e, workspace, 2"
"$mod, r, workspace, 3"
"$mod, i, workspace, 11"
"$mod, o, workspace, 12"
"$mod, p, workspace, 13"
"$altMod, w, movetoworkspace, 1"
"$altMod, e, movetoworkspace, 2"
"$altMod, r, movetoworkspace, 3"
"$altMod, i, movetoworkspace, 11"
"$altMod, o, movetoworkspace, 12"
"$altMod, p, movetoworkspace, 13"
"$mod, z, togglespecialworkspace, scratchpad"
];
bindm = [
"$mod, mouse:272, movewindow" # Move Window (mouse)
"$mod, mouse:274, resizewindow" # Resize Window (mouse)
];
binde = [
"$mod, h, layoutmsg, mfact -0.01" # Move focus left
"$mod, l, layoutmsg, mfact +0.01" # Move focus Right
];
bindl = [
",XF86AudioMute, exec, sound-toggle" # Toggle Mute
",XF86AudioPlay, exec, ${pkgs.playerctl}/bin/playerctl play-pause" # Play/Pause Song
",XF86AudioNext, exec, ${pkgs.playerctl}/bin/playerctl next" # Next Song
",XF86AudioPrev, exec, ${pkgs.playerctl}/bin/playerctl previous" # Previous Song
",switch:Lid Switch, exec, ${pkgs.hyprlock}/bin/hyprlock" # Lock when closing Lid
];
bindle = [
",XF86AudioRaiseVolume, exec, sound-up" # Sound Up
",XF86AudioLowerVolume, exec, sound-down" # Sound Down
",XF86MonBrightnessUp, exec, brightness-up" # Brightness Up
",XF86MonBrightnessDown, exec, brightness-down" # Brightness Down
];
};
}

View File

@@ -0,0 +1,184 @@
# Hyprland is a dynamic tiling Wayland compositor that is highly customizable and performant.
{
pkgs,
config,
lib,
...
}:
let
border-size = config.theme.border-size;
gaps-in = config.theme.gaps-in;
gaps-out = config.theme.gaps-out;
active-opacity = config.theme.active-opacity;
inactive-opacity = config.theme.inactive-opacity;
rounding = config.theme.rounding;
blur = config.theme.blur;
keyboardLayout = config.var.keyboardLayout;
background = "rgb(" + config.lib.stylix.colors.base00 + ")";
in
{
imports = [
./animations.nix
./bindings.nix
./polkitagent.nix
];
home.packages = with pkgs; [
qt5.qtwayland
qt6.qtwayland
libsForQt5.qt5ct
qt6Packages.qt6ct
hyprshot
hyprpicker
swappy
imv
wf-recorder
wlr-randr
wl-clipboard
brightnessctl
gnome-themes-extra
libva
dconf
wayland-utils
wayland-protocols
glib
direnv
meson
];
wayland.windowManager.hyprland = {
enable = true;
xwayland.enable = true;
systemd = {
enable = false;
variables = [
"--all"
]; # https://wiki.hyprland.org/Nix/Hyprland-on-Home-Manager/#programs-dont-work-in-systemd-services-but-do-on-the-terminal
};
package = null;
portalPackage = null;
settings = {
"$mod" = "SUPER";
"$shiftMod" = "SUPER_SHIFT";
"$altMod" = "SUPER_ALT";
exec-once = [
"systemctl --user enable --now hyprpaper.service &"
];
monitor = config.var.hyprland.monitor;
env = [
"XDG_CURRENT_DESKTOP,Hyprland"
"MOZ_ENABLE_WAYLAND,1"
"ANKI_WAYLAND,1"
"DISABLE_QT5_COMPAT,0"
"NIXOS_OZONE_WL,1"
"XDG_SESSION_TYPE,wayland"
"XDG_SESSION_DESKTOP,Hyprland"
"QT_AUTO_SCREEN_SCALE_FACTOR,1"
"QT_QPA_PLATFORM=wayland,xcb"
"QT_WAYLAND_DISABLE_WINDOWDECORATION,1"
"ELECTRON_OZONE_PLATFORM_HINT,auto"
"__GL_GSYNC_ALLOWED,0"
"__GL_VRR_ALLOWED,0"
"DISABLE_QT5_COMPAT,0"
"DIRENV_LOG_FORMAT,"
"WLR_DRM_NO_ATOMIC,1"
"WLR_BACKEND,vulkan"
"WLR_RENDERER,vulkan"
"WLR_NO_HARDWARE_CURSORS,1"
"SDL_VIDEODRIVER,wayland"
"CLUTTER_BACKEND,wayland"
];
workspace = config.var.hyprland.workspace ++ [
"special:scratchpad, on-created-empty:[float; size monitor_w/1.5 monitor_h/1.5; center] $TERMINAL"
];
cursor = {
no_hardware_cursors = true;
default_monitor = "0";
};
general = {
resize_on_border = true;
gaps_in = gaps-in;
gaps_out = gaps-out;
border_size = border-size;
layout = "master";
"col.inactive_border" = lib.mkForce background;
};
decoration = {
dim_special = 0.3;
active_opacity = active-opacity;
inactive_opacity = inactive-opacity;
rounding = rounding;
shadow = {
enabled = true;
range = 20;
render_power = 3;
};
blur = {
enabled = if blur then "true" else "false";
size = 18;
};
};
master = {
new_status = true;
allow_small_split = true;
mfact = 0.65;
};
misc = {
vfr = true;
disable_hyprland_logo = true;
disable_splash_rendering = true;
disable_autoreload = false;
focus_on_activate = true;
on_focus_under_fullscreen = 2;
};
windowrule = [
"match:title hyprpanel-settings, float on"
"match:class xdg-desktop-portal-gtk, float on, center on, size monitor_w/2 monitor_h/2"
# Bitwarden extension
# idle inhibit while watching videos
#"idleinhibit focus, class:^(mpv|.+exe|celluloid)$"
#"idleinhibit focus, class:^(zen)$, title:^(.*YouTube.*)$"
#"idleinhibit fullscreen, class:^(zen)$"
#"dimaround, class:^(gcr-prompter)$"
#"dimaround, class:^(xdg-desktop-portal-gtk)$"
#"dimaround, class:^(polkit-gnome-authentication-agent-1)$"
#"dimaround, class:^(zen)$, title:^(File Upload)$"
];
layerrule = [
"match:namespace vicinae, no_anim on, blur on, ignore_alpha 0"
#"no_anim, launcher"
#"no_anim, ^ags-.*"
];
input = {
kb_layout = keyboardLayout;
kb_options = "caps:escape";
follow_mouse = 1;
sensitivity = 0.5;
repeat_delay = 300;
repeat_rate = 50;
numlock_by_default = true;
touchpad = {
natural_scroll = true;
clickfinger_behavior = true;
};
};
};
};
}

View File

@@ -0,0 +1,6 @@
# HyprPolkitAgent is a simple polkit agent for wayland compositors
{pkgs, ...}: {
home.packages = with pkgs; [hyprpolkitagent];
wayland.windowManager.hyprland.settings.exec-once = ["systemctl --user start hyprpolkitagent"];
}

View File

@@ -0,0 +1,249 @@
# Hyprpanel is the bar on top of the screen
# Display information like workspaces, battery, wifi, ...
{ config, ... }:
let
transparentButtons = config.theme.bar.transparentButtons;
accent = "#${config.lib.stylix.colors.base0D}";
accent-alt = "#${config.lib.stylix.colors.base03}";
background = "#${config.lib.stylix.colors.base00}";
background-alt = "#${config.lib.stylix.colors.base01}";
foreground = "#${config.lib.stylix.colors.base05}";
foregroundOnWallpaper = "#${config.theme.textColorOnWallpaper}";
font = "${config.stylix.fonts.serif.name}";
fontSizeForHyprpanel = "${toString config.stylix.fonts.sizes.desktop}px";
rounding = config.theme.rounding;
border-size = config.theme.border-size;
gaps-out = config.theme.gaps-out;
gaps-in = config.theme.gaps-in;
floating = config.theme.bar.floating;
transparent = config.theme.bar.transparent;
position = config.theme.bar.position; # "top" ou "bottom"
notificationOpacity = 90;
location = config.var.location;
homeDir = "/home/${config.var.username}";
in
{
wayland.windowManager.hyprland.settings.exec-once = [ "hyprpanel" ];
programs.hyprpanel = {
enable = true;
settings = {
bar.layouts = {
"*" = {
left = [
"dashboard"
"workspaces"
"windowtitle"
];
middle = [
"media"
];
right = [
"systray"
"volume"
"bluetooth"
"battery"
"network"
"clock"
"notifications"
];
};
};
theme.font.name = font;
theme.font.size = fontSizeForHyprpanel;
theme.bar.outer_spacing = if floating && transparent then "0px" else "8px";
theme.bar.buttons.y_margins = if floating && transparent then "0px" else "8px";
theme.bar.buttons.spacing = "0.3em";
theme.bar.buttons.radius =
(if transparent then toString rounding else toString (rounding - 8)) + "px";
theme.bar.floating = floating;
theme.bar.buttons.padding_x = "0.8rem";
theme.bar.buttons.padding_y = "0.4rem";
theme.bar.margin_top = (if position == "top" then toString (gaps-in * 2) else "0") + "px";
theme.bar.margin_bottom = (if position == "top" then "0" else toString (gaps-in * 2)) + "px";
theme.bar.margin_sides = toString gaps-out + "px";
theme.bar.border_radius = toString rounding + "px";
theme.bar.transparent = transparent;
theme.bar.location = position;
theme.bar.dropdownGap = "4.5em";
theme.bar.menus.shadow = if transparent then "0 0 0 0" else "0px 0px 3px 1px #16161e";
theme.bar.buttons.style = "default";
theme.bar.buttons.monochrome = true;
theme.bar.menus.monochrome = true;
theme.bar.menus.card_radius = toString rounding + "px";
theme.bar.menus.border.size = toString border-size + "px";
theme.bar.menus.border.radius = toString rounding + "px";
theme.bar.menus.menu.media.card.tint = 90;
bar.launcher.icon = "";
bar.workspaces.show_numbered = false;
bar.workspaces.workspaces = 3;
bar.workspaces.numbered_active_indicator = "color";
bar.workspaces.monitorSpecific = true;
bar.workspaces.applicationIconEmptyWorkspace = "";
bar.workspaces.showApplicationIcons = true;
bar.workspaces.showWsIcons = true;
bar.workspaces.ignored = "-98"; # NOTE: Ignore special:scratchpad workspace. Hyprpanel only supports workspace numbers
#bar.workspaces.ignoredWorkspaces = "/scratchpad/i";
#bar.workspaces.ignored_workspaces = "/scratchpad/i";
bar.windowtitle.label = true;
bar.volume.label = false;
bar.network.truncation_size = 12;
bar.bluetooth.label = false;
bar.clock.format = "%a %b %d %H:%M";
bar.notifications.show_total = true;
bar.media.show_active_only = true;
bar.customModules.updates.pollingInterval = 1440000;
notifications.position = "top right";
notifications.showActionsOnHover = true;
theme.notification.opacity = notificationOpacity;
theme.notification.enableShadow = true;
theme.notification.border_radius = toString rounding + "px";
theme.osd.enable = true;
theme.osd.orientation = "vertical";
theme.osd.location = "left";
theme.osd.radius = toString rounding + "px";
theme.osd.margins = "0px 0px 0px 10px";
theme.osd.muted_zero = true;
menus.clock.weather.location = location;
menus.clock.weather.unit = "metric";
menus.dashboard.powermenu.confirmation = false;
menus.dashboard.powermenu.avatar.image = "~/.face.icon";
menus.dashboard.shortcuts.left.shortcut1.icon = "";
menus.dashboard.shortcuts.left.shortcut1.command = "zen";
menus.dashboard.shortcuts.left.shortcut1.tooltip = "Zen";
menus.dashboard.shortcuts.left.shortcut2.icon = "󰅶";
menus.dashboard.shortcuts.left.shortcut2.command = "caffeine";
menus.dashboard.shortcuts.left.shortcut2.tooltip = "Caffeine";
menus.dashboard.shortcuts.left.shortcut3.icon = "󰖔";
menus.dashboard.shortcuts.left.shortcut3.command = "night-shift";
menus.dashboard.shortcuts.left.shortcut3.tooltip = "Night-shift";
menus.dashboard.shortcuts.left.shortcut4.icon = "";
menus.dashboard.shortcuts.left.shortcut4.command = "menu";
menus.dashboard.shortcuts.left.shortcut4.tooltip = "Search Apps";
menus.dashboard.shortcuts.right.shortcut1.icon = "";
menus.dashboard.shortcuts.right.shortcut1.command = "hyprpicker -a";
menus.dashboard.shortcuts.right.shortcut1.tooltip = "Color Picker";
menus.dashboard.shortcuts.right.shortcut3.icon = "󰄀";
menus.dashboard.shortcuts.right.shortcut3.command = "screenshot region swappy";
menus.dashboard.shortcuts.right.shortcut3.tooltip = "Screenshot";
menus.dashboard.directories.left.directory1.label = " Home";
menus.dashboard.directories.left.directory1.command = "xdg-open ${homeDir}";
menus.dashboard.directories.left.directory2.label = "󰲂 Documents";
menus.dashboard.directories.left.directory2.command = "xdg-open ${homeDir}/Documents";
menus.dashboard.directories.left.directory3.label = "󰉍 Downloads";
menus.dashboard.directories.left.directory3.command = "xdg-open ${homeDir}/Downloads";
menus.dashboard.directories.right.directory1.label = " Desktop";
menus.dashboard.directories.right.directory1.command = "xdg-open ${homeDir}/Desktop";
menus.dashboard.directories.right.directory2.label = " Videos";
menus.dashboard.directories.right.directory2.command = "xdg-open ${homeDir}/Videos";
menus.dashboard.directories.right.directory3.label = "󰉏 Pictures";
menus.dashboard.directories.right.directory3.command = "xdg-open ${homeDir}/Pictures";
menus.power.lowBatteryNotification = true;
wallpaper.enable = false;
# theme.bar.buttons.workspaces.hover = accent-alt;
# theme.bar.buttons.workspaces.active = accent;
# theme.bar.buttons.workspaces.available = accent-alt;
# theme.bar.buttons.workspaces.occupied = accent-alt;
#
# theme.bar.menus.background = background;
# theme.bar.menus.cards = background-alt;
# theme.bar.menus.label = foreground;
# theme.bar.menus.text = foreground;
# theme.bar.menus.border.color = accent;
# theme.bar.menus.popover.text = foreground;
# theme.bar.menus.popover.background = background-alt;
# theme.bar.menus.listitems.active = accent;
# theme.bar.menus.icons.active = accent;
# theme.bar.menus.switch.enabled = accent;
# theme.bar.menus.check_radio_button.active = accent;
# theme.bar.menus.buttons.default = accent;
# theme.bar.menus.buttons.active = accent;
# theme.bar.menus.iconbuttons.active = accent;
# theme.bar.menus.progressbar.foreground = accent;
# theme.bar.menus.slider.primary = accent;
# theme.bar.menus.tooltip.background = background-alt;
# theme.bar.menus.tooltip.text = foreground;
# theme.bar.menus.dropdownmenu.background = background-alt;
# theme.bar.menus.dropdownmenu.text = foreground;
# theme.bar.background =
# background
# + (
# if transparentButtons && transparent
# then "00"
# else ""
# );
# theme.bar.buttons.text =
# if transparent && transparentButtons
# then foregroundOnWallpaper
# else foreground;
# theme.bar.buttons.background =
# (
# if transparent
# then background
# else background-alt
# )
# + (
# if transparentButtons
# then "00"
# else ""
# );
# theme.bar.buttons.icon = accent;
#
# theme.bar.buttons.notifications.background = background-alt;
# theme.bar.buttons.hover = background;
# theme.bar.buttons.notifications.hover = background;
# theme.bar.buttons.notifications.total = accent;
# theme.bar.buttons.notifications.icon = accent;
#
# theme.osd.bar_color = accent;
# theme.osd.bar_overflow_color = accent-alt;
# theme.osd.icon = background;
# theme.osd.icon_container = accent;
# theme.osd.label = accent;
# theme.osd.bar_container = background-alt;
#
# theme.bar.menus.menu.media.background.color = background-alt;
# theme.bar.menus.menu.media.card.color = background-alt;
#
# theme.notification.background = background-alt;
# theme.notification.actions.background = accent;
# theme.notification.actions.text = foreground;
# theme.notification.label = accent;
# theme.notification.border = background-alt;
# theme.notification.text = foreground;
# theme.notification.labelicon = accent;
# theme.notification.close_button.background = background-alt;
# theme.notification.close_button.label = "#f38ba8";
};
};
}

View File

@@ -0,0 +1,14 @@
# Hyprpaper is used to set the wallpaper on the system
{lib, ...}: {
# The wallpaper is set by stylix
services.hyprpaper = {
enable = true;
settings = {
ipc = "on";
splash = false;
splash_offset = 2.0;
};
};
systemd.user.services.hyprpaper.Unit.After =
lib.mkForce "graphical-session.target";
}

View File

@@ -0,0 +1,22 @@
{
services = {
hyprsunset = {
enable = true;
settings = {
max-gamma = 150;
profile = [
{
time = "7:30";
identity = true;
}
{
time = "23:00";
temperature = 2000;
gamma = 0.8;
}
];
};
};
};
}

View File

@@ -0,0 +1,26 @@
{ config, ... }:
{
programs.khal = {
enable = true;
locale = {
timeformat = "%H:%M";
dateformat = "%m-%d";
};
};
accounts.calendar.accounts = {
"radicale" = {
khal = {
enable = true;
type = "discover";
color = "light blue";
};
};
"university" = {
khal = {
enable = true;
color = "#c72125";
};
};
};
}

View File

@@ -0,0 +1,24 @@
# Kitty is a fast, featureful, GPU based terminal emulator
{
programs.kitty = {
enable = true;
settings = {
scrollback_lines = 10000;
initial_window_width = 1200;
initial_window_height = 600;
update_check_interval = 0;
enable_audio_bell = false;
confirm_os_window_close = "0";
remember_window_size = "no";
disable_ligatures = "always";
url_style = "curly";
copy_on_select = "clipboard";
cursor_shape = "Underline";
cursor_underline_thickness = 3;
window_padding_width = 10;
open_url_with = "default";
allow_remote_control = "yes";
listen_on = "unix:/tmp/mykitty";
};
};
}

View File

@@ -0,0 +1,38 @@
# Lazygit is a simple terminal UI for git commands.
{
config,
lib,
...
}:
let
accent = "#${config.lib.stylix.colors.base0D}";
muted = "#${config.lib.stylix.colors.base03}";
in
{
programs.lazygit = {
enable = true;
settings = lib.mkForce {
disableStartupPopups = true;
notARepository = "skip";
promptToReturnFromSubprocess = false;
update.method = "never";
git = {
parseEmoji = true;
};
gui = {
theme = {
activeBorderColor = [
accent
"bold"
];
inactiveBorderColor = [ muted ];
};
showListFooter = false;
showRandomTip = false;
showCommandLog = false;
showBottomLine = false;
nerdFontsVersion = "3";
};
};
};
}

View File

@@ -0,0 +1,98 @@
# Mime type associations for the system.
{ lib, ... }:
with lib;
let
defaultApps = {
# check desktop files here: `ls $(echo $XDG_DATA_DIRS| sed "s/:/ /g")`
browser = [ "brave-browser.desktop" ];
text = [ "nixCats.desktop" ];
image = [ "imv-dir.desktop" ];
audio = [ "mpv.desktop" ];
video = [ "mpv.desktop" ];
directory = [ "thunar.desktop" ];
office = [ "libreoffice.desktop" ];
pdf = [ "org.pwmt.zathura.desktop" ];
terminal = [ "kitty.desktop" ];
discord = [ "discord.desktop" ];
archive = [ "xarchiver.desktop" ];
};
mimeMap = {
text = [ "text/plain" ];
image = [
"image/bmp"
"image/gif"
"image/jpeg"
"image/jpg"
"image/png"
"image/svg+xml"
"image/tiff"
"image/vnd.microsoft.icon"
"image/webp"
];
audio = [
"audio/aac"
"audio/mpeg"
"audio/ogg"
"audio/opus"
"audio/wav"
"audio/webm"
"audio/x-matroska"
];
video = [
"video/mp2t"
"video/mp4"
"video/mpeg"
"video/ogg"
"video/webm"
"video/x-flv"
"video/x-matroska"
"video/x-msvideo"
];
directory = [ "inode/directory" ];
browser = [
"text/html"
"x-scheme-handler/about"
"x-scheme-handler/http"
"x-scheme-handler/https"
"x-scheme-handler/unknown"
];
office = [
"application/vnd.oasis.opendocument.text"
"application/vnd.oasis.opendocument.spreadsheet"
"application/vnd.oasis.opendocument.presentation"
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
"application/msword"
"application/vnd.ms-excel"
"application/vnd.ms-powerpoint"
"application/rtf"
];
pdf = [ "application/pdf" ];
terminal = [ "terminal" ];
archive = [
"application/zip"
"application/rar"
"application/7z"
"application/*tar"
];
discord = [ "x-scheme-handler/discord" ];
};
associations =
with lists;
listToAttrs (
flatten (mapAttrsToList (key: map (type: attrsets.nameValuePair type defaultApps."${key}")) mimeMap)
);
in
{
xdg = {
configFile."mimeapps.list".force = true;
mimeApps = {
enable = true;
associations.added = associations;
defaultApplications = associations;
};
};
}

View File

@@ -0,0 +1,6 @@
{config, ...}: {
programs.nh = {
enable = true;
flake = "/home/kiri/.config/nixos"; # Assuming this is the flake root
};
}

View File

@@ -0,0 +1,2 @@
indent_type = "Spaces"
indent_width = 2

View File

@@ -0,0 +1,157 @@
{ inputs, config, ... }:
let
inherit (inputs.nixCats) utils;
luaPath = ./.;
categoryDefinitions =
{ pkgs, ... }:
{
# to define and use a new category, simply add a new list to a set here,
# and later, you will include categoryname = true; in the set you
# provide when you build the package using this builder function.
# see :help nixCats.flake.outputs.packageDefinitions for info on that section.
# lspsAndRuntimeDeps:
# this section is for dependencies that should be available
# at RUN TIME for plugins. Will be available to PATH within neovim terminal
# this includes LSPs
lspsAndRuntimeDeps = {
general = with pkgs; [
universal-ctags
stdenv.cc.cc
ripgrep
fd
stylua
lua-language-server
nixd
nix-doc
nixfmt
dafny
typescript
typescript-language-server
rust-analyzer
rustfmt
markdownlint-cli2
basedpyright
black
isort
astro-language-server
];
};
startupPlugins = {
general = with pkgs.vimPlugins; [
lz-n
plenary-nvim
catppuccin-nvim
];
};
optionalPlugins = {
general = with pkgs.vimPlugins; [
nvim-treesitter.withAllGrammars
nvim-treesitter-textobjects
nvim-treesitter-context
trouble-nvim
guess-indent-nvim
gitsigns-nvim
which-key-nvim
telescope-nvim
telescope-fzf-native-nvim
telescope-ui-select-nvim
conform-nvim
blink-cmp
luasnip
friendly-snippets
todo-comments-nvim
mini-nvim
nvim-lspconfig
lazydev-nvim
nvim-autopairs
indent-blankline-nvim
nvim-lint
render-markdown-nvim
colorful-menu-nvim
];
};
sharedLibraries = {
general = with pkgs; [ ];
};
environmentVariables = { };
extraWrapperArgs = { };
python3.libraries = {
test = (_: [ ]);
};
extraLuaPackages = {
general = [ (_: [ ]) ];
};
extraCats = { };
};
packageDefinitions = {
nixCats =
{ pkgs, ... }:
{
settings = {
suffix-path = true;
suffix-LD = true;
aliases = [
"nvim"
"vim"
"vi"
];
wrapRc = true;
configDirName = "nixCats";
hosts.python3.enable = true;
hosts.node.enable = true;
};
categories = {
general = true;
};
extra = {
nixdExtras = {
nixpkgs = ''import ${pkgs.path} {}'';
nixos_options = ''(builtins.getFlake "path:///home/kiri/.config/nixos").nixosConfigurations.${toString config.var.hostname}.options'';
home_manager_options = ''(builtins.getFlake "path:///home/kiri/.config/nixos").nixosConfigurations.${toString config.var.hostname}.options.home-manager.users.type.getSubOptions []'';
};
};
};
};
defaultPackageName = "nixCats";
in
{
imports = [
(utils.mkHomeModules {
inherit
defaultPackageName
luaPath
categoryDefinitions
packageDefinitions
;
inherit (inputs) nixpkgs;
dependencyOverlays = [ (utils.standardPluginOverlay inputs) ];
})
];
nixCats.enable = true;
}

View File

@@ -0,0 +1,5 @@
require("options")
require("plugins.ui")
require("plugins.editor")
require("plugins.coding")
require("plugins.lsp")

View File

@@ -0,0 +1,133 @@
-- Set <space> as the leader key
-- See `:help mapleader`
-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used)
vim.g.mapleader = " "
vim.g.maplocalleader = " "
-- [[ Setting options ]]
-- See `:help vim.o`
-- NOTE: You can change these options as you wish!
-- For more options, you can see `:help option-list`
-- Make line numbers default
vim.o.number = true
-- You can also add relative line numbers, to help with jumping.
-- Experiment for yourself to see if you like it!
-- vim.o.relativenumber = true
-- Enable mouse mode, can be useful for resizing splits for example!
vim.o.mouse = "a"
-- Don't show the mode, since it's already in the status line
vim.o.showmode = false
vim.opt.shortmess:append("Wc")
-- Sync clipboard between OS and Neovim.
-- Schedule the setting after `UiEnter` because it can increase startup-time.
-- Remove this option if you want your OS clipboard to remain independent.
-- See `:help 'clipboard'`
vim.schedule(function()
vim.o.clipboard = "unnamedplus"
end)
-- Enable break indent
vim.o.breakindent = true
-- Save undo history
vim.o.undofile = true
-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term
vim.o.ignorecase = true
vim.o.smartcase = true
-- Keep signcolumn on by default
vim.o.signcolumn = "yes"
-- Decrease update time
vim.o.updatetime = 250
-- Decrease mapped sequence wait time
vim.o.timeoutlen = 300
-- Configure how new splits should be opened
vim.o.splitright = true
vim.o.splitbelow = true
-- Sets how neovim will display certain whitespace characters in the editor.
-- See `:help 'list'`
-- and `:help 'listchars'`
--
-- Notice listchars is set using `vim.opt` instead of `vim.o`.
-- It is very similar to `vim.o` but offers an interface for conveniently interacting with tables.
-- See `:help lua-options`
-- and `:help lua-options-guide`
vim.o.list = true
vim.opt.listchars = { tab = "» ", trail = "·", nbsp = "" }
-- Preview substitutions live, as you type!
vim.o.inccommand = "split"
-- Show which line your cursor is on
vim.o.cursorline = true
-- Minimal number of screen lines to keep above and below the cursor.
vim.o.scrolloff = 10
-- if performing an operation that would fail due to unsaved changes in the buffer (like `:q`),
-- instead raise a dialog asking if you wish to save the current file(s)
-- See `:help 'confirm'`
vim.o.confirm = true
-- [[ Basic Keymaps ]]
-- See `:help vim.keymap.set()`
-- Clear highlights on search when pressing <Esc> in normal mode
-- See `:help hlsearch`
vim.keymap.set("n", "<Esc>", "<cmd>nohlsearch<CR>")
-- Diagnostic keymaps
vim.keymap.set("n", "<leader>q", vim.diagnostic.setloclist, { desc = "Open diagnostic [Q]uickfix list" })
-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier
-- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which
-- is not what someone will guess without a bit more experience.
--
-- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping
-- or just use <C-\><C-n> to exit terminal mode
vim.keymap.set("t", "<Esc><Esc>", "<C-\\><C-n>", { desc = "Exit terminal mode" })
-- TIP: Disable arrow keys in normal mode
-- vim.keymap.set('n', '<left>', '<cmd>echo "Use h to move!!"<CR>')
-- vim.keymap.set('n', '<right>', '<cmd>echo "Use l to move!!"<CR>')
-- vim.keymap.set('n', '<up>', '<cmd>echo "Use k to move!!"<CR>')
-- vim.keymap.set('n', '<down>', '<cmd>echo "Use j to move!!"<CR>')
-- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows
--
-- See `:help wincmd` for a list of all window commands
vim.keymap.set("n", "<C-h>", "<C-w><C-h>", { desc = "Move focus to the left window" })
vim.keymap.set("n", "<C-l>", "<C-w><C-l>", { desc = "Move focus to the right window" })
vim.keymap.set("n", "<C-j>", "<C-w><C-j>", { desc = "Move focus to the lower window" })
vim.keymap.set("n", "<C-k>", "<C-w><C-k>", { desc = "Move focus to the upper window" })
-- NOTE: Some terminals have colliding keymaps or are not able to send distinct keycodes
-- vim.keymap.set("n", "<C-S-h>", "<C-w>H", { desc = "Move window to the left" })
-- vim.keymap.set("n", "<C-S-l>", "<C-w>L", { desc = "Move window to the right" })
-- vim.keymap.set("n", "<C-S-j>", "<C-w>J", { desc = "Move window to the lower" })
-- vim.keymap.set("n", "<C-S-k>", "<C-w>K", { desc = "Move window to the upper" })
-- [[ Basic Autocommands ]]
-- See `:help lua-guide-autocommands`
-- Highlight when yanking (copying) text
-- Try it with `yap` in normal mode
-- See `:help vim.hl.on_yank()`
vim.api.nvim_create_autocmd("TextYankPost", {
desc = "Highlight when yanking (copying) text",
group = vim.api.nvim_create_augroup("kickstart-highlight-yank", { clear = true }),
callback = function()
vim.hl.on_yank()
end,
})

View File

@@ -0,0 +1,263 @@
require("lz.n").load({
-- {
-- "nvim-treesitter-context",
-- event = "BufReadPost",
-- after = function()
-- require("treesitter-context").setup({
-- enable = true,
-- max_lines = 3, -- How many lines the window should span
-- })
-- end,
-- },
{
"nvim-lint",
event = { "BufReadPre", "BufNewFile" },
after = function()
local lint = require("lint")
lint.linters_by_ft = {
markdown = { "markdownlint-cli2" },
}
-- Create autocommand which carries out the actual linting
-- on the specified events.
local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true })
vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave" }, {
group = lint_augroup,
callback = function()
-- Only run the linter in buffers that you can modify in order to
-- avoid superfluous noise, notably within the handy LSP pop-ups that
-- describe the hovered symbol using Markdown.
if vim.bo.modifiable then
lint.try_lint()
end
end,
})
end,
},
{
"nvim-autopairs",
event = "InsertEnter",
after = function()
require("nvim-autopairs").setup({
check_ts = true,
})
end,
},
{
"nvim-treesitter",
dep_of = "render-markdown.nvim",
-- cmd = { "" },
event = "DeferredUIEnter",
-- ft = "",
-- keys = "",
-- colorscheme = "",
load = function(name)
vim.cmd.packadd(name)
vim.cmd.packadd("nvim-treesitter-textobjects")
end,
after = function()
-- [[ Configure Treesitter ]]
-- See `:help nvim-treesitter`
require("nvim-treesitter.configs").setup({
highlight = { enable = true },
indent = { enable = true },
incremental_selection = {
enable = true,
keymaps = {
init_selection = "<c-space>",
node_incremental = "<c-space>",
scope_incremental = "<c-s>",
node_decremental = "<M-space>",
},
},
textobjects = {
select = {
enable = true,
lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim
keymaps = {
-- You can use the capture groups defined in textobjects.scm
["aa"] = "@parameter.outer",
["ia"] = "@parameter.inner",
["af"] = "@function.outer",
["if"] = "@function.inner",
["ac"] = "@class.outer",
["ic"] = "@class.inner",
},
},
move = {
enable = true,
set_jumps = true, -- whether to set jumps in the jumplist
goto_next_start = {
["]m"] = "@function.outer",
["]]"] = "@class.outer",
},
goto_next_end = {
["]M"] = "@function.outer",
["]["] = "@class.outer",
},
goto_previous_start = {
["[m"] = "@function.outer",
["[["] = "@class.outer",
},
goto_previous_end = {
["[M"] = "@function.outer",
["[]"] = "@class.outer",
},
},
swap = {
enable = true,
swap_next = {
["<leader>a"] = "@parameter.inner",
},
swap_previous = {
["<leader>A"] = "@parameter.inner",
},
},
},
})
end,
},
{
"conform.nvim",
event = "BufWritePre",
cmd = "ConformInfo",
keys = {
{
"<leader>f",
function()
require("conform").format({ async = true, lsp_format = "fallback" })
end,
mode = "",
desc = "[F]ormat buffer",
},
},
after = function()
require("conform").setup({
notify_on_error = true,
format_on_save = function(bufnr)
-- Disable "format_on_save lsp_fallback" for languages that don't
-- have a well standardized coding style. You can add additional
-- languages here or re-enable it for the disabled ones.
local disable_filetypes = { c = true, cpp = true }
if disable_filetypes[vim.bo[bufnr].filetype] then
return nil
else
return {
timeout_ms = 500,
lsp_format = "fallback",
}
end
end,
formatters_by_ft = {
lua = { "stylua" },
-- Conform can also run multiple formatters sequentially
python = { "isort", "black" },
--
-- You can use 'stop_after_first' to run the first available formatter from the list
-- javascript = { "prettierd", "prettier", stop_after_first = true },
},
})
end,
},
{
"friendly-snippets",
},
{
"luasnip",
before = function()
require("lz.n").trigger_load("friendly-snippets")
end,
after = function()
require("luasnip.loaders.from_vscode").lazy_load()
end,
},
{
"blink.cmp",
before = function()
-- Trigger lazydev so it's ready for blink source
require("lz.n").trigger_load({ "lazydev.nvim", "luasnip" })
end,
event = "VimEnter",
after = function()
require("blink.cmp").setup({
keymap = {
preset = "default",
-- [Up/Down]
["<C-j>"] = { "select_next", "fallback" },
["<C-k>"] = { "select_prev", "fallback" }, -- Overrides Signature Help
-- [Insert Suggestion]
["<C-l>"] = { "select_and_accept", "fallback" },
-- [Remap Signature Help]
-- Since we took <C-k>, let's move signature help to <C-g> (optional)
["<C-g>"] = { "show_signature", "hide_signature", "fallback" },
},
appearance = {
nerd_font_variant = "mono",
},
completion = {
-- By default, you may press `<c-space>` to show the documentation.
-- Optionally, set `auto_show = true` to show the documentation after a delay.
documentation = {
auto_show = true,
auto_show_delay_ms = 500,
window = {
border = "rounded",
},
},
menu = {
border = "rounded",
draw = {
columns = { { "kind_icon" }, { "label", gap = 1 } },
components = {
label = {
text = function(ctx)
return require("colorful-menu").blink_components_text(ctx)
end,
highlight = function(ctx)
return require("colorful-menu").blink_components_highlight(ctx)
end,
},
},
},
},
},
cmdline = {
completion = {
menu = {
auto_show = true,
},
},
keymap = { preset = "inherit" },
},
sources = {
default = {
"lsp",
"path",
"snippets",
"lazydev",
},
providers = {
lazydev = { module = "lazydev.integrations.blink", score_offset = 100 },
},
},
snippets = { preset = "luasnip" },
fuzzy = { implementation = "prefer_rust_with_warning" },
-- Shows a signature help window while you type arguments for a function
signature = {
window = { border = "rounded" },
enabled = true,
},
})
end,
},
})

View File

@@ -0,0 +1,170 @@
require("lz.n").load({
{
"guess-indent.nvim",
event = "BufReadPre",
after = function()
require("guess-indent").setup({})
end,
},
{
"gitsigns.nvim",
event = { "BufReadPre", "BufNewFile" },
after = function()
require("gitsigns").setup({
signs = {
add = { text = "" },
change = { text = "" },
delete = { text = "" },
topdelete = { text = "" },
changedelete = { text = "" },
},
on_attach = function(bufnr)
local gitsigns = require("gitsigns")
local function map(mode, l, r, opts)
opts = opts or {}
opts.buffer = bufnr
vim.keymap.set(mode, l, r, opts)
end
-- Navigation
map("n", "]c", function()
if vim.wo.diff then
vim.cmd.normal({ "]c", bang = true })
else
gitsigns.nav_hunk("next")
end
end, { desc = "Jump to next git [c]hange" })
map("n", "[c", function()
if vim.wo.diff then
vim.cmd.normal({ "[c", bang = true })
else
gitsigns.nav_hunk("prev")
end
end, { desc = "Jump to previous git [c]hange" })
-- Actions
-- visual mode
map("v", "<leader>hs", function()
gitsigns.stage_hunk({ vim.fn.line("."), vim.fn.line("v") })
end, { desc = "git [s]tage hunk" })
map("v", "<leader>hr", function()
gitsigns.reset_hunk({ vim.fn.line("."), vim.fn.line("v") })
end, { desc = "git [r]eset hunk" })
-- normal mode
map("n", "<leader>hs", gitsigns.stage_hunk, { desc = "git [s]tage hunk" })
map("n", "<leader>hr", gitsigns.reset_hunk, { desc = "git [r]eset hunk" })
map("n", "<leader>hS", gitsigns.stage_buffer, { desc = "git [S]tage buffer" })
map("n", "<leader>hu", gitsigns.stage_hunk, { desc = "git [u]ndo stage hunk" })
map("n", "<leader>hR", gitsigns.reset_buffer, { desc = "git [R]eset buffer" })
map("n", "<leader>hp", gitsigns.preview_hunk, { desc = "git [p]review hunk" })
map("n", "<leader>hb", gitsigns.blame_line, { desc = "git [b]lame line" })
map("n", "<leader>hd", gitsigns.diffthis, { desc = "git [d]iff against index" })
map("n", "<leader>hD", function()
gitsigns.diffthis("@")
end, { desc = "git [D]iff against last commit" })
-- Toggles
map("n", "<leader>tb", gitsigns.toggle_current_line_blame, { desc = "[T]oggle git show [b]lame line" })
map("n", "<leader>tD", gitsigns.preview_hunk_inline, { desc = "[T]oggle git show [D]eleted" })
end,
})
end,
},
{
"telescope.nvim",
event = "VimEnter",
after = function()
local actions = require("telescope.actions")
require("telescope").setup({
defaults = {
path_display = { "truncate" },
layout_strategy = "horizontal",
layout_config = {
prompt_position = "top",
},
sorting_strategy = "ascending",
mappings = {
i = {
["<C-k>"] = actions.move_selection_previous, -- Move up with Ctrl-k
["<C-j>"] = actions.move_selection_next, -- Move down with Ctrl-j
["<C-q>"] = actions.send_selected_to_qflist + actions.open_qflist, -- Send to quickfix
},
},
},
extensions = {
["ui-select"] = {
require("telescope.themes").get_dropdown(),
},
},
})
-- Enable Telescope extensions if they are installed
pcall(require("telescope").load_extension, "fzf")
pcall(require("telescope").load_extension, "ui-select")
-- See `:help telescope.builtin`
local builtin = require("telescope.builtin")
vim.keymap.set("n", "<leader>sh", builtin.help_tags, { desc = "[S]earch [H]elp" })
vim.keymap.set("n", "<leader>sk", builtin.keymaps, { desc = "[S]earch [K]eymaps" })
vim.keymap.set("n", "<leader>sf", builtin.find_files, { desc = "[S]earch [F]iles" })
vim.keymap.set("n", "<leader>ss", builtin.builtin, { desc = "[S]earch [S]elect Telescope" })
vim.keymap.set("n", "<leader>sw", builtin.grep_string, { desc = "[S]earch current [W]ord" })
vim.keymap.set("n", "<leader>sg", builtin.live_grep, { desc = "[S]earch by [G]rep" })
vim.keymap.set("n", "<leader>sd", builtin.diagnostics, { desc = "[S]earch [D]iagnostics" })
vim.keymap.set("n", "<leader>sr", builtin.resume, { desc = "[S]earch [R]esume" })
vim.keymap.set("n", "<leader>s.", builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' })
vim.keymap.set("n", "<leader><leader>", builtin.buffers, { desc = "[ ] Find existing buffers" })
-- Slightly advanced example of overriding default behavior and theme
vim.keymap.set("n", "<leader>/", function()
-- You can pass additional configuration to Telescope to change the theme, layout, etc.
builtin.current_buffer_fuzzy_find(require("telescope.themes").get_dropdown({
winblend = 10,
previewer = false,
}))
end, { desc = "[/] Fuzzily search in current buffer" })
-- It's also possible to pass additional configuration options.
-- See `:help telescope.builtin.live_grep()` for information about particular keys
vim.keymap.set("n", "<leader>s/", function()
builtin.live_grep({
grep_open_files = true,
prompt_title = "Live Grep in Open Files",
})
end, { desc = "[S]earch [/] in Open Files" })
-- Shortcut for searching your Neovim configuration files
vim.keymap.set("n", "<leader>sn", function()
builtin.find_files({ cwd = vim.fn.stdpath("config") })
end, { desc = "[S]earch [N]eovim files" })
end,
},
{
"trouble.nvim",
cmd = "Trouble",
keys = {
{ "<leader>xx", "<cmd>Trouble diagnostics toggle<cr>", desc = "Diagnostics (Trouble)" },
{ "<leader>xX", "<cmd>Trouble diagnostics toggle filter.buf=0<cr>", desc = "Buffer Diagnostics (Trouble)" },
},
after = function()
require("trouble").setup({
focus = true,
})
end,
},
{
"todo-comments.nvim",
event = { "BufReadPre", "BufNewFile" },
keys = {
{ "<leader>st", "<cmd>TodoTelescope<cr>", desc = "[S]earch [T]odos" },
{ "<leader>xt", "<cmd>TodoTrouble<cr>", desc = "Todo (Trouble)" },
},
after = function()
require("todo-comments").setup({
signs = false,
})
end,
},
})

View File

@@ -0,0 +1,168 @@
require("lz.n").load({
{
{
-- lazydev makes your lsp way better in your config without needing extra lsp configuration.
"lazydev.nvim",
cmd = "LazyDev",
ft = "lua",
after = function()
require("lazydev").setup({
library = {
{ words = { "nixCats" }, path = (nixCats.nixCatsPath or "") .. "/lua" },
},
})
end,
},
{
"nvim-lspconfig",
event = { "BufReadPre", "BufNewFile" },
after = function()
vim.api.nvim_create_autocmd("LspAttach", {
group = vim.api.nvim_create_augroup("kickstart-lsp-attach", { clear = true }),
callback = function(args)
-- Get the client and buffer from the event arguments [cite: 119]
local client = vim.lsp.get_client_by_id(args.data.client_id)
local bufnr = args.buf
local map = function(keys, func, desc, mode)
mode = mode or "n"
vim.keymap.set(mode, keys, func, { buffer = bufnr, desc = "LSP: " .. desc })
end
-- Mappings (Standard LSP functions from lsp-defaults) [cite: 20-23]
map("grn", vim.lsp.buf.rename, "[R]e[n]ame")
map("gra", vim.lsp.buf.code_action, "[G]oto Code [A]ction", { "n", "x" })
map("grD", vim.lsp.buf.declaration, "[G]oto [D]eclaration")
-- Telescope Mappings
map("grr", require("telescope.builtin").lsp_references, "[G]oto [R]eferences")
map("gri", require("telescope.builtin").lsp_implementations, "[G]oto [I]mplementation")
map("grd", require("telescope.builtin").lsp_definitions, "[G]oto [D]efinition")
map("gO", require("telescope.builtin").lsp_document_symbols, "Open Document Symbols")
map("gW", require("telescope.builtin").lsp_dynamic_workspace_symbols, "Open Workspace Symbols")
map("grt", require("telescope.builtin").lsp_type_definitions, "[G]oto [T]ype Definition")
-- Highlight references (Document Highlight)
if client and client:supports_method("textDocument/documentHighlight", bufnr) then
local highlight_augroup = vim.api.nvim_create_augroup("kickstart-lsp-highlight", { clear = false })
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
buffer = bufnr,
group = highlight_augroup,
callback = vim.lsp.buf.document_highlight,
})
vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
buffer = bufnr,
group = highlight_augroup,
callback = vim.lsp.buf.clear_references,
})
vim.api.nvim_create_autocmd("LspDetach", {
group = vim.api.nvim_create_augroup("kickstart-lsp-detach", { clear = true }),
callback = function(event)
vim.lsp.buf.clear_references()
vim.api.nvim_clear_autocmds({ group = "kickstart-lsp-highlight", buffer = event.buf })
end,
})
end
-- Inlay Hints
if client and client:supports_method("textDocument/inlayHint", bufnr) then
map("<leader>th", function()
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = bufnr }))
end, "[T]oggle Inlay [H]ints")
end
end,
})
-- 1. Setup Diagnostics (Visuals)
vim.diagnostic.config({
severity_sort = true,
float = { border = "rounded", source = "if_many" },
underline = { severity = vim.diagnostic.severity.ERROR },
signs = {
text = {
[vim.diagnostic.severity.ERROR] = "",
[vim.diagnostic.severity.WARN] = "",
[vim.diagnostic.severity.INFO] = "",
[vim.diagnostic.severity.HINT] = "󰠠 ",
},
},
virtual_text = {
source = "if_many",
spacing = 4,
prefix = "",
format = function(diagnostic)
local diagnostic_message = {
[vim.diagnostic.severity.ERROR] = diagnostic.message,
[vim.diagnostic.severity.WARN] = diagnostic.message,
[vim.diagnostic.severity.INFO] = diagnostic.message,
[vim.diagnostic.severity.HINT] = diagnostic.message,
}
return diagnostic_message[diagnostic.severity]
end,
},
})
vim.lsp.config("lua_ls", {
settings = {
Lua = {
runtime = { version = "LuaJIT" },
signatureHelp = { enabled = true },
diagnostics = { globals = { "nixCats", "vim" } },
telemetry = { enabled = false },
completion = { callSnippet = "Replace" },
},
},
})
vim.lsp.enable("lua_ls")
-- Nix
vim.lsp.config("nixd", {
settings = {
nixd = {
nixpkgs = { expr = nixCats.extra("nixdExtras.nixpkgs") },
options = {
nixos = { expr = nixCats.extra("nixdExtras.nixos_options") },
["home-manager"] = { expr = nixCats.extra("nixdExtras.home_manager_options") },
},
formatting = { command = { "nixfmt" } },
},
},
})
vim.lsp.enable("nixd")
-- Dafny
vim.lsp.enable("dafny")
-- TypeScript/JS
vim.lsp.enable("ts_ls")
-- Rust
vim.lsp.enable("rust_analyzer")
-- Python
vim.lsp.config("basedpyright", {
settings = {
basedpyright = {
analysis = {
autoSearchPaths = true,
useLibraryCodeForTypes = true,
diagnosticMode = "openFilesOnly",
typeCheckingMode = "standard",
inlayHints = {
variableTypes = true,
callArgumentNames = true,
functionReturnTypes = true,
},
},
},
},
})
vim.lsp.enable("basedpyright")
vim.lsp.enable("astro")
end,
},
},
})

View File

@@ -0,0 +1,158 @@
require("lz.n").load({
{
"catppuccin-nvim",
event = "VimEnter",
after = function()
require("catppuccin").setup({
flavour = "mocha",
term_colors = true,
dim_inactive = {
enabled = true,
shade = "dark",
percentage = 0.15,
},
integrations = {
gitsigns = true,
telescope = true,
treesitter = true,
treesitter_context = true,
markdown = true,
which_key = true,
blink_cmp = {
style = "bordered",
},
},
native_lsp = {
enabled = true,
virtual_text = {
errors = { "italic" },
hints = { "italic" },
warnings = { "italic" },
information = { "italic" },
},
underlines = {
errors = { "underline" },
hints = { "underline" },
warnings = { "underline" },
information = { "underline" },
},
inlay_hints = {
background = true,
},
},
})
vim.cmd.colorscheme("catppuccin")
end,
},
{
"colorful-menu.nvim",
after = function()
require("colorful-menu").setup({})
end,
},
{
"indent-blankline.nvim",
event = "User FileOpened",
after = function()
require("ibl").setup({
indent = { char = "|" },
scope = {
enabled = false,
show_start = false,
show_end = false,
},
})
end,
},
{
"render-markdown.nvim",
before = function()
require("lz.n").trigger_load({ "nvim-treesitter", "mini.nvim" })
end,
after = function()
require("render-markdown").setup({})
end,
},
{
"which-key.nvim",
event = "VimEnter",
before = function()
require("lz.n").trigger_load("nvim-web-devicons")
end,
after = function()
require("which-key").setup({
preset = "modern",
delay = 200,
win = {
border = "rounded",
},
icons = {
-- set icon mappings to true if you have a Nerd Font
mappings = true,
-- If you are using a Nerd Font: set icons.keys to an empty table which will use the
-- default which-key.nvim defined Nerd Font icons, otherwise define a string table
keys = {},
},
-- Document existing key chains
spec = {
{ "<leader>s", group = "[S]earch" },
{ "<leader>t", group = "[T]oggle" },
{ "<leader>h", group = "Git [H]unk", mode = { "n", "v" } },
},
})
end,
},
{
"mini.nvim",
after = function()
-- Better Around/Inside textobjects
require("mini.ai").setup({ n_lines = 500 })
-- Add/delete/replace surroundings (brackets, quotes, etc.)
require("mini.surround").setup()
-- Simple and easy statusline.
local statusline = require("mini.statusline")
statusline.setup({ use_icons = true })
statusline.section_location = function()
return "%2l:%-2v"
end
local files = require("mini.files")
files.setup()
vim.keymap.set("n", "<leader>e", function()
if not files.close() then
files.open(vim.api.nvim_buf_get_name(0))
end
end, { desc = "File [E]xplorer" })
local icons = require("mini.icons")
icons.setup()
icons.mock_nvim_web_devicons()
local hipatterns = require("mini.hipatterns")
hipatterns.setup({
highlighters = {
-- Highlight hex color strings (#rrggbb) using that color
hex_color = hipatterns.gen_highlighter.hex_color(),
},
})
local indentscope = require("mini.indentscope")
indentscope.setup({
symbol = "",
-- draw = { animation = indentscope.gen_animation.linear({}) },
})
vim.api.nvim_create_autocmd("FileType", {
pattern = { "help", "alpha", "dashboard", "neo-tree", "Trouble", "lazy", "mason" },
callback = function()
vim.b.miniindentscope_disable = true
end,
})
end,
},
})

View File

@@ -0,0 +1,35 @@
{
programs.rclone = {
enable = true;
remotes = {
gdrive = {
config = {
type = "drive";
scope = "drive";
root_folder_id = "";
};
secrets = {
token = "/home/kiri/.config/rclone/gdrive_token";
client_id = "/home/kiri/.config/rclone/gdrive_client_id";
client_secret = "/home/kiri/.config/rclone/gdrive_client_secret"; #TODO: sops?
};
mounts = {
"/" = {
enable = true;
mountPoint = "/home/kiri/gdrive";
options = {
dir-cache-time = "5000h";
poll-interval = "10s";
vfs-cache-mode = "full";
};
};
};
};
};
};
}

View File

@@ -0,0 +1,36 @@
# - ## Brightness
#-
#- This module provides a set of scripts to control the brightness of the screen.
#-
#- - `brightness-up` increases the brightness by 5%.
#- - `brightness-down` decreases the brightness by 5%.
#- - `brightness-set [value]` sets the brightness to the given value.
#- - `brightness-change [up|down] [value]` increases or decreases the brightness by the given value.
{pkgs, ...}: let
increments = "5";
brightness-change = pkgs.writeShellScriptBin "brightness-change" ''
[[ $1 == "up" ]] && ${pkgs.brightnessctl}/bin/brightnessctl set ''${2-${increments}}%+
[[ $1 == "down" ]] && ${pkgs.brightnessctl}/bin/brightnessctl set ''${2-${increments}}%-
'';
brightness-set = pkgs.writeShellScriptBin "brightness-set" ''
${pkgs.brightnessctl}/bin/brightnessctl set ''${1-100}%
'';
brightness-up = pkgs.writeShellScriptBin "brightness-up" ''
brightness-change up ${increments}
'';
brightness-down = pkgs.writeShellScriptBin "brightness-down" ''
brightness-change down ${increments}
'';
in {
home.packages = [
pkgs.brightnessctl
brightness-change
brightness-up
brightness-down
brightness-set
];
}

View File

@@ -0,0 +1,26 @@
# - ## Caffeine
#-
#- Caffeine is a simple script that toggles hypridle (disable suspend & screenlock).
#-
#- - `caffeine-status` - Check if hypridle is running. (0/1)
#- - `caffeine-status-icon` - Check if hypridle is running. (icon)
#- - `caffeine` - Toggle hypridle.
{pkgs, ...}: let
caffeine-status = pkgs.writeShellScriptBin "caffeine-status" ''
[[ $(pidof "hypridle") ]] && echo "0" || echo "1"
'';
caffeine-status-icon = pkgs.writeShellScriptBin "caffeine-status-icon" ''
[[ $(pidof "hypridle") ]] && echo "󰾪" || echo "󰅶"
'';
caffeine = pkgs.writeShellScriptBin "caffeine" ''
if [[ $(pidof "hypridle") ]]; then
systemctl --user stop hypridle.service
${pkgs.swayosd}/bin/swayosd-client --custom-message="Caffeine On" --custom-icon="emblem-default"
else
systemctl --user start hypridle.service
${pkgs.swayosd}/bin/swayosd-client --custom-message="Caffeine Off" --custom-icon="emblem-default"
fi
'';
in {home.packages = [caffeine-status caffeine caffeine-status-icon];}

View File

@@ -0,0 +1,15 @@
{
imports = [
./nixy.nix
./sounds.nix
./brightness.nix
./caffeine.nix
./hyprpanel.nix
./hyprfocus.nix
./night-shift.nix
./screenshot.nix
./nerdfont-fzf.nix
./notification.nix
./system.nix
];
}

View File

@@ -0,0 +1,52 @@
# - ## Hyprfocus
#-
#- A simple script to toggle focus on few windows in Hyprland.
#- (disable gaps, border, shadow, opacity, etc.)
#-
#- - `hyprfocus-on` - Enable hyprfocus.
#- - `hyprfocus-off` - Disable hyprfocus.
#- - `hyprfocus-toggle` - Toggle hyprfocus.
{pkgs, ...}: let
hyprfocus-on =
pkgs.writeShellScriptBin "hyprfocus-on"
# bash
''
hyprpanel-hide
hyprctl --batch "\
keyword animations:enabled 0;\
keyword decoration:shadow:enabled 0;\
keyword decoration:blur:enabled 0;\
keyword general:gaps_in 0;\
keyword general:gaps_out 0;\
keyword general:border_size 1;\
keyword decoration:rounding 0;\
keyword decoration:inactive_opacity 1;\
keyword decoration:active_opacity 1"
echo "1" > /tmp/hyprfocus
${pkgs.swayosd}/bin/swayosd-client --custom-message="Hyprfocus On" --custom-icon="emblem-default"
'';
hyprfocus-off =
pkgs.writeShellScriptBin "hyprfocus-off"
# bash
''
hyprctl reload
hyprpanel-show
rm /tmp/hyprfocus
${pkgs.swayosd}/bin/swayosd-client --custom-message="Hyprfocus Off" --custom-icon="emblem-default"
'';
hyprfocus-toggle =
pkgs.writeShellScriptBin "hyprfocus-toggle"
# bash
''
if [ -f /tmp/hyprfocus ]; then
hyprfocus-off
else
hyprfocus-on
fi
'';
in {home.packages = [hyprfocus-on hyprfocus-off hyprfocus-toggle];}

View File

@@ -0,0 +1,45 @@
# - ## Hyprpanel
#-
#- Quick scripts to toggle, reload, hide & show hyprpanel.
#-
#- - `hyprpanel-toggle` - Toggle hyprpanel (hide/show).
#- - `hyprpanel-show` - Show hyprpanel.
#- - `hyprpanel-hide` - Hide hyprpanel.
#- - `hyprpanel-reload` - Reload hyprpanel.
{pkgs, ...}: let
hyprpanel-toggle = pkgs.writeShellScriptBin "hyprpanel-toggle" ''
hyprpanel toggleWindow bar-0
hyprpanel toggleWindow bar-1
hyprpanel toggleWindow bar-2
hyprpanel toggleWindow bar-3
'';
hyprpanel-hide = pkgs.writeShellScriptBin "hyprpanel-hide" ''
status=$(hyprpanel isWindowVisible bar-0)
if [[ $status == "true" ]]; then
hyprpanel toggleWindow bar-0
fi
status=$(hyprpanel isWindowVisible bar-1)
if [[ $status == "true" ]]; then
hyprpanel toggleWindow bar-1
fi
'';
hyprpanel-show = pkgs.writeShellScriptBin "hyprpanel-show" ''
status=$(hyprpanel isWindowVisible bar-0)
if [[ $status == "false" ]]; then
hyprpanel toggleWindow bar-0
fi
status=$(hyprpanel isWindowVisible bar-1)
if [[ $status == "false" ]]; then
hyprpanel toggleWindow bar-1
fi
'';
hyprpanel-reload = pkgs.writeShellScriptBin "hyprpanel-reload" ''
[ $(pgrep "hyprpanel") ] && pkill hyprpanel
hyprctl dispatch exec hyprpanel
'';
in {
home.packages = [hyprpanel-toggle hyprpanel-reload hyprpanel-hide hyprpanel-show];
}

View File

@@ -0,0 +1,31 @@
# - ## Nerdfont FZF
#-
#- This module provides a script to search for Nerd Fonts icons using fzf.
#-
#- - `nerdfont-fzf` - Search for Nerd Fonts icons using fzf.
{
pkgs,
config,
...
}: let
nerdfont-fzf = pkgs.writeShellScriptBin "nerdfont-fzf" ''
icons=$(${pkgs.jq}/bin/jq -r 'to_entries[] | "\(.key):\(.value.char)"' "/home/${config.var.username}/.config/nerdfont_glyphnames.json" | awk -F: '{print "\033[95m "$2" \033[0m "$1}')
fzf_result=$(echo "$icons" | ${pkgs.fzf}/bin/fzf --ansi --border none | awk '{print $1}')
if [ -z "$fzf_result" ]; then
echo "No icon selected"
exit 1
fi
echo "Copied to clipboard: $fzf_result"
${pkgs.wl-clipboard}/bin/wl-copy "$fzf_result"
'';
in {
home.packages = [nerdfont-fzf];
xdg.configFile."nerdfont_glyphnames.json" = {
source = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/ryanoasis/nerd-fonts/384b1825ea0037b0314f7f9c660a80c1ecdb219a/glyphnames.json";
hash = "sha256-Ps0dyFcMs51RMTthBOVSOf/lafPV/53JxuNSKlmZ7cc=";
};
};
}

View File

@@ -0,0 +1,71 @@
# - ## Night-Shift
#-
#- Night-Shift is a feature that reduces the amount of blue light emitted by your screen, which can help reduce eye strain and improve sleep quality. This module provides a set of scripts to control Night-Shift on your system.
#- It use hyprsunset to control the screen temperature.
#-
#- - `night-shift-on` activates Night-Shift.
#- - `night-shift-off` deactivates Night-Shift.
#- - `night-shift` toggles Night-Shift.
#- - `night-shift-status` checks if Night-Shift is active. (0/1)
#- - `night-shift-status-icon` checks if Night-Shift is active. (icon)
{pkgs, ...}: let
value = "4500"; # Default value for night-shift temperature
night-shift-on =
pkgs.writeShellScriptBin "night-shift-on"
# bash
''
${pkgs.hyprsunset}/bin/hyprsunset -t ${value} &
${pkgs.swayosd}/bin/swayosd-client --custom-message="Night-Shift On" --custom-icon="emblem-default"
'';
night-shift-off =
pkgs.writeShellScriptBin "night-shift-off"
# bash
''
pkill hyprsunset
${pkgs.swayosd}/bin/swayosd-client --custom-message="Night-Shift Off" --custom-icon="emblem-default"
'';
night-shift =
pkgs.writeShellScriptBin "night-shift"
# bash
''
if pidof "hyprsunset"; then
night-shift-off
else
night-shift-on
fi
'';
night-shift-status =
pkgs.writeShellScriptBin "night-shift-status"
# bash
''
if pidof "hyprsunset"; then
echo "1"
else
echo "0"
fi
'';
night-shift-status-icon =
pkgs.writeShellScriptBin "night-shift-status-icon"
# bash
''
if pidof "hyprsunset"; then
echo "󰖔"
else
echo "󰖕"
fi
'';
in {
home.packages = [
pkgs.hyprsunset
night-shift-on
night-shift-off
night-shift
night-shift-status
night-shift-status-icon
];
}

View File

@@ -0,0 +1,77 @@
# - ## Nixy
#-
#- Nixy is a simple script that I use to manage my NixOS system. It's a simple script that provides a menu to rebuild, test, update, collect garbage, clean boot menu, etc.
#-
#- - `nixy` - UI wizard to manage the system.
#- - `nixy rebuild` - Rebuild the system.
#- - `nixy ...` - ... see the script for more commands.
{ pkgs, config, ... }:
let
configDirectory = config.var.configDirectory;
nixy = pkgs.writeShellScriptBin "nixy"
# bash
''
function exec() {
$@
}
function ui(){
DEFAULT_ICON="󰘳"
# "icon;name;command"[]
apps=(
"󰑓;Rebuild;nixy rebuild"
"󰐊;Test;nixy test"
"󰚰;Update;nixy update"
";Collect Garbage;nixy gc"
"󰍜;Clean Boot Menu;nixy cb"
";List generation;nixy listgen"
"󰌌;Hyprland Keybindings;nvim ${configDirectory}/docs/KEYBINDINGS-HYPRLAND.md"
"󰋩;Wallpapers;zen https://github.com/anotherhadi/nixy-wallpapers"
)
# Apply default icons if empty:
for i in "''${!apps[@]}"; do
apps[i]=$(echo "''${apps[i]}" | sed 's/^;/'$DEFAULT_ICON';/')
done
fzf_result=$(printf "%s\n" "''${apps[@]}" | awk -F ';' '{print $1" "$2}' | fzf)
[[ -z $fzf_result ]] && exit 0
fzf_result=''${fzf_result/ /;}
line=$(printf "%s\n" "''${apps[@]}" | grep "$fzf_result")
command=$(echo "$line" | sed 's/^[^;]*;//;s/^[^;]*;//')
exec "$command"
exit $?
}
[[ $1 == "" ]] && ui
if [[ $1 == "rebuild" ]];then
cd ${configDirectory} && git add . && sudo nixos-rebuild switch --flake
elif [[ $1 == "test" ]];then
cd ${configDirectory} && git add . && sudo nixos-rebuild test --flake
elif [[ $1 == "update" ]];then
cd ${configDirectory} && nix flake update
elif [[ $1 == "gc" ]];then
echo "Starting Nix garbage collection..."
cd ${configDirectory} && \
echo "Cleaning up system garbage..." && \
sudo nix-collect-garbage -d && \
echo "Cleaning up user garbage..." && \
nix-collect-garbage -d && \
echo "Collecting garbage from Nix store..." && \
nix-store --gc && \
echo "Optimizing Nix store..." && \
nix-store --optimise
echo "Nix garbage collection complete."
elif [[ $1 == "cb" ]];then
sudo /run/current-system/bin/switch-to-configuration boot
elif [[ $1 == "listgen" ]];then
sudo nix-env -p /nix/var/nix/profiles/system --list-generations
else
echo "Unknown argument"
fi
'';
in { home.packages = [ nixy ]; }

View File

@@ -0,0 +1,31 @@
# - ## Notif
#-
# This file provides a script to send custom notifications using `notify-send`.
#-
#- - `notif {id} {title} {description}` - Sends a notification
{pkgs, ...}: let
notif =
pkgs.writeShellScriptBin "notif" # bash
''
# Shell script to send custom notifications
# Usage: notif "sender_id" "message" ["description"]
NOTIF_FOLDER="/tmp/notif"
sender_id=$1 # To overwrite existing notifications
title=$2
description=$3
[[ -d "$NOTIF_FOLDER" ]] || mkdir $NOTIF_FOLDER
[[ -f "$NOTIF_FOLDER/$sender_id" ]] || (echo "0" > "$NOTIF_FOLDER/$sender_id")
old_notification_id=$(cat "$NOTIF_FOLDER/$sender_id")
[[ -z "$old_notification_id" ]] && old_notification_id=0
${pkgs.libnotify}/bin/notify-send \
--replace-id="$old_notification_id" --print-id \
--app-name="$sender_id" \
"$title" \
"$description" \
> "$NOTIF_FOLDER/$sender_id"
'';
in {home.packages = [pkgs.libnotify notif];}

View File

@@ -0,0 +1,32 @@
# - ## Screenshot
#-
#- This module provides a script to take screenshots using `grimblast` and `swappy`.
#-
#- - `screenshot [region|window|monitor] [swappy]` - Take a screenshot of the region, window, or monitor. Optionally, use `swappy` to copy the screenshot to the clipboard.
{pkgs, ...}: let
screenshot = pkgs.writeShellScriptBin "screenshot" ''
if [[ $2 == "swappy" ]];then
folder="/tmp"
else
folder="$HOME/Pictures"
fi
filename="$(date +%Y-%m-%d_%H:%M:%S).png"
if [[ $1 == "window" ]];then
mode="active"
elif [[ $1 == "region" ]];then
mode="area"
elif [[ $1 == "monitor" ]];then
mode="output"
fi
${pkgs.grimblast}/bin/grimblast --notify --freeze copysave $mode "$folder/$filename" || exit 1
if [[ $2 == "swappy" ]];then
${pkgs.swappy}/bin/swappy -f "$folder/$filename" -o "$HOME/Pictures/$filename"
exit 0
fi
'';
in {
home.packages = [ screenshot pkgs.grim pkgs.grimblast ];
}

View File

@@ -0,0 +1,36 @@
# - ## Sound
#-
#- This module provides a set of scripts to control the volume of the default audio sink using `wpctl`.
#-
#- - `sound-up` increases the volume by 5%.
#- - `sound-down` decreases the volume by 5%.
#- - `sound-set [value]` sets the volume to the given value.
#- - `sound-toggle` toggles the mute state of the default audio sink.
{pkgs, ...}: let
increments = "5";
sound-change = pkgs.writeShellScriptBin "sound-change" ''
[[ $1 == "mute" ]] && wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
[[ $1 == "up" ]] && wpctl set-volume @DEFAULT_AUDIO_SINK@ ''${2-${increments}}%+
[[ $1 == "down" ]] && wpctl set-volume @DEFAULT_AUDIO_SINK@ ''${2-${increments}}%-
[[ $1 == "set" ]] && wpctl set-volume @DEFAULT_AUDIO_SINK@ ''${2-100}%
'';
sound-up = pkgs.writeShellScriptBin "sound-up" ''
sound-change up ${increments}
'';
sound-set = pkgs.writeShellScriptBin "sound-set" ''
sound-change set ''${1-100}
'';
sound-down = pkgs.writeShellScriptBin "sound-down" ''
sound-change down ${increments}
'';
sound-toggle = pkgs.writeShellScriptBin "sound-toggle" ''
sound-change mute
'';
in {
home.packages = [sound-change sound-up sound-down sound-toggle sound-set];
}

View File

@@ -0,0 +1,69 @@
# - ## System
#-
#- Usefull quick scripts
#-
#- - `lock` - Lock the screen. (hyprlock)
#- - `powermode-toggle` - Toggle between performance and balanced power mode. (powerprofilesctl)
{pkgs, ...}: let
menu =
pkgs.writeShellScriptBin "menu"
# bash
''
if pgrep wofi; then
pkill wofi
else
wofi -p "Apps" --show drun
fi
'';
powermenu =
pkgs.writeShellScriptBin "powermenu"
# bash
''
if pgrep wofi >/dev/null; then
pkill wofi
exit 0
fi
declare -A actions=(
["󰌾 Lock"]="hyprlock"
["󰍃 Logout"]="hyprctl dispatch exit"
[" Suspend"]="systemctl suspend"
["󰑐 Reboot"]="systemctl reboot"
["󰿅 Shutdown"]="systemctl poweroff"
)
selected_option=$(
printf '%s\n' "''${!actions[@]}" | wofi -p "Powermenu" --dmenu
)
if [[ -n "$selected_option" ]]; then
action_command=''${actions["''$selected_option"]}
if [[ -n "$action_command" ]]; then
eval "$action_command"
fi
fi
'';
lock =
pkgs.writeShellScriptBin "lock"
# bash
''
${pkgs.hyprlock}/bin/hyprlock
'';
powermode-toggle =
pkgs.writeShellScriptBin "powermode-toggle"
# bash
''
current_profile=$(powerprofilesctl get)
if [ "$current_profile" = "performance" ]; then
powerprofilesctl set balanced
${pkgs.swayosd}/bin/swayosd-client --custom-message="Powermode set to balanced" --custom-icon="emblem-default"
else
powerprofilesctl set performance
${pkgs.swayosd}/bin/swayosd-client --custom-message="Powermode set to performance" --custom-icon="emblem-default"
fi
'';
in {home.packages = [lock powermode-toggle menu powermenu];}

View File

@@ -0,0 +1,4 @@
# Import all shell configurations
{
imports = [./fzf.nix ./zsh.nix ./starship.nix ./zoxide.nix ./eza.nix];
}

View File

@@ -0,0 +1,13 @@
# Eza is a ls replacement
{
programs.eza = {
enable = true;
icons = "auto";
extraOptions = [
"--group-directories-first"
"--no-quotes"
"--icons=always"
];
};
}

View File

@@ -0,0 +1,33 @@
# Fzf is a general-purpose command-line fuzzy finder.
{
config,
lib,
...
}: let
accent = "#" + config.lib.stylix.colors.base0D;
foreground = "#" + config.lib.stylix.colors.base05;
muted = "#" + config.lib.stylix.colors.base03;
in {
programs.fzf = {
enable = true;
enableZshIntegration = true;
colors = lib.mkForce {
"fg+" = accent;
"bg+" = "-1";
"fg" = foreground;
"bg" = "-1";
"prompt" = muted;
"pointer" = accent;
};
defaultOptions = [
"--margin=1"
"--layout=reverse"
"--border=none"
"--info='hidden'"
"--header=''"
"--prompt='/ '"
"-i"
"--no-bold"
];
};
}

View File

@@ -0,0 +1,72 @@
# starship is a minimal, fast, and extremely customizable prompt for any shell!
{
config,
lib,
...
}:
let
accent = "#${config.lib.stylix.colors.base0D}";
background-alt = "#${config.lib.stylix.colors.base01}";
in
{
programs.starship = {
enable = true;
enableZshIntegration = true;
settings = {
add_newline = true;
format = lib.concatStrings [
"$nix_shell"
"$hostname"
"$directory"
"$git_branch"
"$git_state"
"$git_status"
"$line_break"
"$character"
];
directory = {
style = accent;
truncation_length = 99;
truncate_to_repo = false;
};
character = {
success_symbol = "[](${accent})";
error_symbol = "[](red)";
vimcmd_symbol = "[](${accent})";
};
nix_shell = {
format = "[$symbol]($style) ";
symbol = "🐚";
style = "";
};
git_branch = {
symbol = "[](${background-alt}) ";
style = "fg:${accent} bg:${background-alt}";
format = "on [$symbol$branch]($style)[](${background-alt}) ";
};
git_status = {
format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](218)($ahead_behind$stashed)]($style)";
style = "cyan";
conflicted = "";
renamed = "";
deleted = "";
stashed = "";
};
git_state = {
format = "([$state( $progress_current/$progress_total)]($style)) ";
style = "bright-black";
};
line_break = {
disabled = false;
};
};
};
}

View File

@@ -0,0 +1,7 @@
# Zoxide is a cd replacement
{
programs.zoxide = {
enable = true;
enableZshIntegration = true;
};
}

View File

@@ -0,0 +1,214 @@
# My shell configuration
{
pkgs,
lib,
config,
...
}:
let
fetch = config.theme.fetch; # neofetch, nerdfetch, pfetch
in
{
home.packages = with pkgs; [
bat
ripgrep
tldr
sesh
];
# Add go binaries to the PATH
home.sessionPath = [ "$HOME/go/bin" ];
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting = {
enable = true;
highlighters = [
"main"
"brackets"
"pattern"
"regexp"
"root"
"line"
];
};
historySubstringSearch.enable = true;
history = {
ignoreDups = true;
save = 10000;
size = 10000;
};
profileExtra = lib.optionalString (config.home.sessionPath != [ ]) ''
export PATH="$PATH''${PATH:+:}${lib.concatStringsSep ":" config.home.sessionPath}"
'';
shellAliases = {
c = "clear";
clera = "clear";
celar = "clear";
e = "exit";
cd = "z";
ls = "eza --icons=always --no-quotes";
tree = "eza --icons=always --tree --no-quotes";
sl = "ls";
open = "${pkgs.xdg-utils}/bin/xdg-open";
cat = "bat --theme=base16 --color=always --paging=never --tabs=2 --wrap=never --plain";
mkdir = "mkdir -p";
obsidian-no-gpu = "env ELECTRON_OZONE_PLATFORM_HINT=auto obsidian --ozone-platform=x11";
wireguard-import = "nmcli connection import type wireguard file";
notes = "nvim ~/notes/index.md --cmd 'cd ~/notes' -c ':lua Snacks.picker.smart()'";
note = "notes";
tmp = "nvim /tmp/$(date | sed 's/ //g;s/\\.//g').md";
nix-shell = "nix-shell --command zsh";
# git
g = "lazygit";
ga = "git add";
gc = "git commit";
gcu = "git add . && git commit -m 'Update'";
gp = "git push";
gpl = "git pull";
gs = "git status";
gd = "git diff";
gco = "git checkout";
gcb = "git checkout -b";
gbr = "git branch";
grs = "git reset HEAD~1";
grh = "git reset --hard HEAD~1";
gaa = "git add .";
gcm = "git commit -m";
};
initContent =
# bash
''
bindkey -v
export KEYTIMEOUT=1
${
if fetch == "neofetch" then
pkgs.neofetch + "/bin/neofetch"
else if fetch == "nerdfetch" then
"nerdfetch"
else if fetch == "pfetch" then
"echo; ${pkgs.pfetch}/bin/pfetch"
else
""
}
function sesh-sessions() {
session=$(sesh list -t -c | fzf --height 70% --reverse)
[[ -z "$session" ]] && return
sesh connect $session
}
function chatgptfolder(){
echo "################################"
echo "### TREE ###"
echo "################################"
${pkgs.eza}/bin/eza --tree -aF --icons never
echo -e "\n\n"
echo "##############################"
echo "### CONTENT ###"
echo "##############################"
find . -type f -not -path '*/.git/*' -print0 | while IFS= read -r -d "" file; do
echo -e "\n--- DEBUT: $file ---\n"
cat "$file"
echo -e "\n--- FIN: $file ---\n"
done
}
function n4c() {
category=''${1:-all}
shift
args=''${*}
nix develop "github:nix4cyber/n4c#''${category}" ''${args} -c zsh
}
zle -N sesh-sessions
bindkey -M emacs '\es' sesh-sessions
bindkey -M vicmd '\es' sesh-sessions
bindkey -M viins '\es' sesh-sessions
# search history based on what's typed in the prompt
autoload -U history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[OA" history-beginning-search-backward-end
bindkey "^[OB" history-beginning-search-forward-end
# General completion behavior
zstyle ':completion:*' completer _extensions _complete _approximate
# Use cache
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path "$XDG_CACHE_HOME/zsh/.zcompcache"
# Complete the alias
zstyle ':completion:*' complete true
# Autocomplete options
zstyle ':completion:*' complete-options true
# Completion matching control
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' keep-prefix true
# Group matches and describe
zstyle ':completion:*' menu select
zstyle ':completion:*' list-grouped false
zstyle ':completion:*' list-separator '''
zstyle ':completion:*' group-name '''
zstyle ':completion:*' verbose yes
zstyle ':completion:*:matches' group 'yes'
zstyle ':completion:*:warnings' format '%F{red}%B-- No match for: %d --%b%f'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*:descriptions' format '[%d]'
# Colors
zstyle ':completion:*' list-colors ''${(s.:.)LS_COLORS}
# case insensitive tab completion
zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories
zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
zstyle ':completion:*:*:-command-:*:*' group-order aliases builtins functions commands
zstyle ':completion:*' special-dirs true
zstyle ':completion:*' squeeze-slashes true
# Sort
zstyle ':completion:*' sort false
zstyle ":completion:*:git-checkout:*" sort false
zstyle ':completion:*' file-sort modification
zstyle ':completion:*:eza' sort false
zstyle ':completion:complete:*:options' sort false
zstyle ':completion:files' sort false
${lib.optionalString config.services.gpg-agent.enable ''
gnupg_path=$(ls $XDG_RUNTIME_DIR/gnupg)
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/gnupg/$gnupg_path/S.gpg-agent.ssh"
''}
# Allow foot to pipe command output
function precmd {
if ! builtin zle; then
print -n "\e]133;D\e\\"
fi
}
function preexec {
print -n "\e]133;C\e\\"
}
'';
};
}

View File

@@ -0,0 +1,44 @@
# Spicetify is a spotify client customizer
{
pkgs,
config,
lib,
inputs,
...
}:
let
spicePkgs = inputs.spicetify-nix.legacyPackages.${pkgs.stdenv.hostPlatform.system};
accent = "${config.lib.stylix.colors.base0D}";
background = "${config.lib.stylix.colors.base00}";
in
{
imports = [ inputs.spicetify-nix.homeManagerModules.default ];
stylix.targets.spicetify.enable = false;
programs.spicetify = {
enable = true;
theme = lib.mkForce spicePkgs.themes.dribbblish;
colorScheme = "custom";
customColorScheme = {
button = accent;
button-active = accent;
tab-active = accent;
player = background;
main = background;
sidebar = background;
};
enabledExtensions = with spicePkgs.extensions; [
playlistIcons
lastfm
historyShortcut
hidePodcasts
adblock
fullAppDisplay
keyboardShortcut
];
};
}

View File

@@ -0,0 +1,9 @@
{ config, ... }:
{
programs.ssh = {
enable = true;
includes = [
config.sops.secrets.ssh_config_orion.path
];
};
}

View File

@@ -0,0 +1,137 @@
# Thunar is a file explorer
{
pkgs,
config,
...
}: let
user = config.var.username;
in {
# ctrl + m to toggle the menubar
home.packages = with pkgs; [
xfce.thunar
xfce.xfconf
xfce.tumbler
xfce.thunar-archive-plugin
xfce.thunar-volman
xfce.thunar-media-tags-plugin
p7zip
xarchiver
];
gtk = {
iconTheme = {
name = "WhiteSur";
package = pkgs.whitesur-icon-theme.override {
boldPanelIcons = true;
alternativeIcons = true;
};
};
};
home.sessionVariables = {
XDG_ICON_DIR = "${pkgs.whitesur-icon-theme}/share/icons/WhiteSur";
};
# bookmarks for the side pane
gtk.gtk3.bookmarks = [
"file:///home/${user}/Downloads Downloads"
"file:///home/${user}/Pictures Pictures"
"file:///home/${user}/.config/nixos NixOS"
"file:///home/${user}/dev Development"
];
home.file.".config/xarchiver/xarchiverrc".text = ''
[xarchiver]
preferred_format=0
prefer_unzip=true
confirm_deletion=true
sort_filename_content=false
advanced_isearch=true
auto_expand=true
store_output=false
icon_size=2
show_archive_comment=false
show_sidebar=true
show_location_bar=true
show_toolbar=true
preferred_custom_cmd=
preferred_temp_dir=/tmp
preferred_extract_dir=/home/${user}/Downloads
allow_sub_dir=0
ensure_directory=true
overwrite=false
full_path=2
touch=false
fresh=false
update=false
store_path=false
updadd=true
freshen=false
recurse=true
solid_archive=false
remove_files=false
'';
home.file.".config/xfce4/xfconf/xfce-perchannel-xml/thunar.xml".text = ''
<?xml version="1.0" encoding="UTF-8"?>
<channel name="thunar" version="1.0">
<property name="last-view" type="string" value="ThunarIconView"/>
<property name="last-icon-view-zoom-level" type="string" value="THUNAR_ZOOM_LEVEL_100_PERCENT"/>
<property name="last-window-maximized" type="bool" value="true"/>
<property name="last-separator-position" type="int" value="170"/>
<property name="last-statusbar-visible" type="bool" value="false"/>
<property name="last-menubar-visible" type="bool" value="false"/>
<property name="misc-single-click" type="bool" value="false"/>
<property name="shortcuts-icon-emblems" type="bool" value="true"/>
<property name="tree-icon-emblems" type="bool" value="true"/>
<property name="misc-file-size-binary" type="bool" value="true"/>
<property name="misc-thumbnail-draw-frames" type="bool" value="false"/>
<property name="misc-text-beside-icons" type="bool" value="true"/>
<property name="misc-change-window-icon" type="bool" value="true"/>
<property name="hidden-bookmarks" type="array">
<value type="string" value="computer:///"/>
<value type="string" value="recent:///"/>
<value type="string" value="file:///"/>
<value type="string" value="network:///"/>
</property>
<property name="hidden-devices" type="array">
<value type="string" value="52FEA905FEA8E309"/>
</property>
<property name="last-toolbar-item-order" type="string" value="0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17"/>
<property name="last-toolbar-visible-buttons" type="string" value="0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0"/>
<property name="last-location-bar" type="string" value="ThunarLocationButtons"/>
<property name="last-show-hidden" type="bool" value="false"/>
<property name="last-details-view-zoom-level" type="string" value="THUNAR_ZOOM_LEVEL_38_PERCENT"/>
<property name="last-details-view-column-widths" type="string" value="50,50,127,50,50,50,50,50,751,50,50,75,50,145"/>
<property name="last-toolbar-items" type="string" value="menu:1,back:1,forward:0,open-parent:0,open-home:0,undo:0,redo:0,zoom-in:0,zoom-out:0,zoom-reset:0,view-as-icons:0,view-as-detailed-list:0,view-as-compact-list:0,toggle-split-view:0,location-bar:1,reload:0,search:1,uca-action-1710183590071525-1:0,new-tab:0,new-window:0,view-switcher:0"/>
</channel>
'';
xdg.configFile."Thunar/uca.xml".text = ''
<?xml version="1.0" encoding="UTF-8"?>
<actions>
<action>
<icon>utilities-terminal</icon>
<name>Open Terminal Here</name>
<unique-id>1700000000000001</unique-id>
<command>kitty -d %f</command>
<description>Opens Kitty terminal in the selected folder</description>
<patterns>*</patterns>
<startup-notify/>
<directories/>
</action>
<action>
<icon></icon>
<name>Extract here</name>
<submenu></submenu>
<unique-id>1689618425925956-3</unique-id>
<command>xarchiver -x . %f</command>
<description>Extracts the archive into the directory it is located in.</description>
<range>*</range>
<patterns>*.tar.bz2;*.tar.gz;*.tar.xz;*.tar.Z;*.tar;*.taz;*.tb2;*.tbz;*.tbz2;*.tgz;*.txz;*.zip;*.bz2;*.docx;*.apk;*.gz;*.odt;</patterns>
<other-files/>
</action>
</actions>
'';
}

View File

@@ -0,0 +1,59 @@
{ config, ... }:
{
programs.thunderbird = {
enable = true;
profiles.kiri = {
isDefault = true;
withExternalGnupg = true;
settings = {
# LAYOUT: Force 3-Pane Vertical View (Folders | List | Message)
"mail.ui.display.message_pane_vertical" = true;
# APPEARANCE: Enable "Cards View" (modern multi-line list)
# Note: 'cards' is the value for the new view
"mail.ui.display.thread_pane_view_type" = "cards";
# DENSITY: "Compact" is usually cleaner for tech-savvy users
"mail.uidensity" = 1; # 0=Default, 1=Compact, 2=Touch
# PRIVACY & CLEANUP
"privacy.donottrackheader.enabled" = true;
"mail.server.server2.hidden" = true; # Hide "Local Folders"
# Start page disable for faster boot
"mailnews.start_page.enabled" = false;
# Disable the "Get a new email address" feature in account manager
"mail.provider.enabled" = false;
};
};
};
# Enable Thunderbird for specific accounts
accounts.email.accounts = {
main = {
thunderbird.enable = true;
};
old = {
thunderbird.enable = true;
};
uni = {
thunderbird = {
enable = true;
settings = id: {
"mail.smtpserver.smtp_${id}.authMethod" = 10;
"mail.server.server_${id}.authMethod" = 10;
};
};
};
work = {
thunderbird = {
enable = true;
settings = id: {
"mail.smtpserver.smtp_${id}.authMethod" = 10;
"mail.server.server_${id}.authMethod" = 10;
};
};
};
};
}

View File

@@ -0,0 +1,12 @@
{ config, pkgs, ... }:
{
home.packages = [ pkgs.todoman ];
xdg.configFile."todoman/config.py".text = ''
path = "${config.xdg.dataHome}/calendars/*/*"
date_format = "%d-%m-%Y"
time_format = "%H:%M"
default_list = "personal"
default_due = 48
'';
}

View File

@@ -0,0 +1,8 @@
# Udiskie is a simple daemon that uses udisks to automatically mount removable storage devices.
{
services.udiskie = {
enable = true;
notify = true;
automount = true;
};
}

View File

@@ -0,0 +1,13 @@
{ inputs, ... }:
{
imports = [ inputs.vicinae.homeManagerModules.default ];
services.vicinae = {
enable = true;
autoStart = true;
};
wayland.windowManager.hyprland.settings.exec-once = [
"systemctl enable --now --user vicinae.service"
];
}

View File

@@ -0,0 +1,102 @@
# Wofi is a launcher for Wayland, inspired by rofi.
{
config,
pkgs,
lib,
...
}:
let
accent = "#${config.lib.stylix.colors.base0D}";
background = "#${config.lib.stylix.colors.base00}";
background-alt = "#${config.lib.stylix.colors.base01}";
foreground = "#${config.lib.stylix.colors.base05}";
font = config.stylix.fonts.serif.name;
rounding = config.theme.rounding;
font-size = config.stylix.fonts.sizes.popups;
in
{
home.packages = with pkgs; [ wofi-emoji ];
programs.wofi = {
enable = true;
settings = {
allow_markup = true;
width = 450;
show = "drun";
prompt = "Apps";
normal_window = true;
height = 305;
allow_images = true;
image_size = 24;
insensitive = true;
hide_scroll = true;
no_actions = true;
gtk_dark = true;
};
style =
lib.mkForce
# css
''
* {
font-family: "${font}";
font-weight: 500;
font-size: ${toString font-size}px;
}
#window {
background-color: ${background};
color: ${foreground};
border-radius: ${toString rounding}px;
}
#outer-box {
padding: 20px;
}
#input {
background-color: ${background-alt};
border: 0px solid ${accent};
color: ${foreground};
padding: 8px 12px;
}
#scroll {
margin-top: 20px;
}
#inner-box {}
#img {
padding-right: 8px;
}
#text {
color: ${foreground};
}
#text:selected {
color: ${foreground};
}
#entry {
padding: 6px;
}
#entry:selected {
background-color: ${accent};
color: ${foreground};
}
#unselected {}
#selected {}
#input,
#entry:selected {
border-radius: ${toString rounding}px;
}
'';
};
}

View File

@@ -0,0 +1,14 @@
# Zathura is a PDF viewer
{
programs.zathura = {
enable = true;
options = {
guioptions = "v";
adjust-open = "width";
statusbar-basename = true;
render-loading = false;
scroll-step = 120;
};
};
}

View File

@@ -0,0 +1,14 @@
{ config, pkgs, ... }:
{
services.actual = {
enable = true;
openFirewall = false;
settings = {
port = 3000;
hostname = "127.0.0.1"; # Listen on all IPv4 addresses
};
};
services.caddy.virtualHosts."finance.jelles.net".extraConfig = "reverse_proxy :3000";
}

View File

@@ -0,0 +1,20 @@
# Adguard is a network-wide ad blocker
# When installed, open localhost:3000 to setup
{config, ...}: let
domain = "adguard.hadi.diy";
in {
services = {
adguardhome = {
enable = true;
port = 3000;
};
nginx.virtualHosts."${domain}" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.adguardhome.port}";
};
};
};
}

65
modules/nixos/arr.nix Normal file
View File

@@ -0,0 +1,65 @@
# *arr is a collection of media management applications.
# See https://github.com/rasmus-kirk/nixarr
# Setup guide: https://nixarr.com/wiki/setup/
{config, ...}: let
domain = "hadi.diy";
mkVirtualHost = port: {
useACMEHost = domain;
forceSSL = true;
locations."/" = {proxyPass = "http://127.0.0.1:${toString port}";};
};
username = config.var.username;
in {
# Add my secrets
sops.secrets = {
recyclarr = {
owner = "recyclarr";
mode = "0777";
};
wireguard-pia = {
group = "media";
mode = "0600";
};
};
nixarr = {
enable = true;
mediaUsers = [username];
mediaDir = "/mnt/data/media";
stateDir = "/mnt/data/.state/nixarr";
vpn = {
enable = true;
wgConf = config.sops.secrets.wireguard-pia.path;
};
jellyfin.enable = true;
jellyseerr.enable = true;
prowlarr.enable = true;
radarr.enable = true;
sonarr.enable = true;
bazarr.enable = true;
readarr.enable = true;
transmission = {
enable = true;
extraSettings = {trash-original-torrent-files = true;};
vpn.enable = true;
};
recyclarr = {
enable = true;
configFile = config.sops.secrets.recyclarr.path;
};
};
services.nginx.virtualHosts = {
"jellyfin.${domain}" = mkVirtualHost 8096;
"jellyseerr.${domain}" = mkVirtualHost 5055;
"bazarr.${domain}" = mkVirtualHost 6767;
"prowlarr.${domain}" = mkVirtualHost 9696;
"radarr.${domain}" = mkVirtualHost 7878;
"sonarr.${domain}" = mkVirtualHost 8989;
"transmission.${domain}" = mkVirtualHost 9091;
"readarr.${domain}" = mkVirtualHost 8787;
};
}

21
modules/nixos/audio.nix Normal file
View File

@@ -0,0 +1,21 @@
# Audio configuration for NixOS using PipeWire
{
security.rtkit.enable = true;
services.pulseaudio.enable = false;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
wireplumber = {
enable = true;
extraConfig = {
"10-disable-camera" = {
"wireplumber.profiles" = {main."monitor.libcamera" = "disabled";};
};
};
};
};
}

View File

@@ -0,0 +1,23 @@
# Bitwarden (or vaultwarden) is a self-hosted password manager.
{ config, ... }:
let
domain = "vault.jelles.net";
in
{
services = {
vaultwarden = {
enable = true;
backupDir = "/var/backup/vaultwarden";
config = {
DOMAIN = "https://" + domain;
SIGNUPS_ALLOWED = true;
ROCKET_PORT = 8100;
ROCKET_LOG = "critical";
};
};
caddy.virtualHosts."vault.jelles.net".extraConfig =
"reverse_proxy :${toString config.services.vaultwarden.config.ROCKET_PORT}";
};
}

View File

@@ -0,0 +1,9 @@
# Bluetooth configuration for NixOS
{pkgs, ...}: {
environment.systemPackages = with pkgs; [blueman];
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
};
services.blueman.enable = true;
}

22
modules/nixos/caddy.nix Normal file
View File

@@ -0,0 +1,22 @@
{ inputs, pkgs, ... }:
{
services.caddy = {
enable = true;
virtualHosts."community.jelles.net".extraConfig = ''
root * ${inputs.community-website.packages.${pkgs.stdenv.hostPlatform.system}.default}
file_server
'';
virtualHosts."zentire.jelles.net".extraConfig = ''
root * ${inputs.zentire-website.packages.${pkgs.stdenv.hostPlatform.system}.default}
file_server
'';
email = "mail@jelles.net";
};
networking.firewall = {
allowedTCPPorts = [
80
443
];
};
}

View File

@@ -0,0 +1,14 @@
{
services = {
copyparty = {
enable = true;
settings = {
e2dsa = true;
no-cfg = true;
};
};
caddy.virtualHosts."files.jelles.net".extraConfig = "reverse_proxy :3923";
};
}

6
modules/nixos/docker.nix Normal file
View File

@@ -0,0 +1,6 @@
# Docker is a containerization platform that allows you to run applications in isolated environments called containers.
{ config, ... }:
{
virtualisation.docker.enable = true;
users.users."${config.var.username}".extraGroups = [ "docker" ];
}

View File

@@ -0,0 +1,35 @@
{
config,
inputs,
pkgs,
...
}:
{
users.groups.eleakxir = { };
users.users.hadi.extraGroups = [ "eleakxir" ];
services.eleakxir = {
enable = true;
port = 9198;
user = "eleakxir";
group = "eleakxir";
limit = 1000;
folders = [
"/var/lib/eleakxir/leaks/"
"/mnt/data/clean-leak/"
];
debug = true;
};
environment.systemPackages = [
inputs.eleakxir.packages.${pkgs.stdenv.hostPlatform.system}.leak-utils
];
services.nginx.virtualHosts."eleakxir-back.hadi.diy" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.eleakxir.port}";
};
};
}

View File

@@ -0,0 +1,9 @@
# Firewall configuration for NixOS
{
networking.firewall = {
enable = true;
allowPing = false;
};
networking.nftables.enable = true;
}

27
modules/nixos/fonts.nix Normal file
View File

@@ -0,0 +1,27 @@
# Fonts configuration for NixOS
{ pkgs, ... }:
{
fonts = {
packages = with pkgs; [
roboto
work-sans
comic-neue
source-sans
comfortaa
inter
lato
lexend
jost
dejavu_fonts
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
nerd-fonts.fira-code
nerd-fonts.meslo-lg
openmoji-color
twemoji-color-font
];
enableDefaultPackages = false;
};
}

46
modules/nixos/gitea.nix Normal file
View File

@@ -0,0 +1,46 @@
{ config, pkgs, ... }:
{
services.gitea = {
enable = true;
appName = "Git Server"; # A name for your Gitea instance
user = "git";
group = "git";
settings = {
server = {
PROTOCOL = "http"; # Use http for now, caddy will handle https
DOMAIN = "git.jelles.net";
ROOT_URL = "https://git.jelles.net/";
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 3001;
START_SSH_SERVER = false;
DISABLE_SSH = false; # Disable the built-in SSH server, use HTTPS for cloning
SSH_PORT = 22;
};
service = {
DISABLE_REGISTRATION = true; # Consider enabling for public instances
};
};
};
services.caddy.virtualHosts."git.jelles.net".extraConfig = "reverse_proxy :3001";
users.users.git = {
isSystemUser = true;
description = "Gitea Service User";
home = config.services.gitea.stateDir;
createHome = true;
homeMode = "750";
useDefaultShell = true;
group = "git";
};
users.groups.git = { };
systemd.tmpfiles.rules = [
"Z /var/lib/gitea 0750 git git - -"
];
}

View File

@@ -0,0 +1,353 @@
# Glance is a self-hosted homepage/dashboard service.
{
config,
lib,
...
}: let
domain = "start.hadi.diy";
rgb-to-hsl = color: let
r = ((lib.toInt config.lib.stylix.colors."${color}-rgb-r") * 100.0) / 255;
g = ((lib.toInt config.lib.stylix.colors."${color}-rgb-g") * 100.0) / 255;
b = ((lib.toInt config.lib.stylix.colors."${color}-rgb-b") * 100.0) / 255;
max = lib.max r (lib.max g b);
min = lib.min r (lib.min g b);
delta = max - min;
fmod = base: int: base - (int * builtins.floor (base / int));
h =
if delta == 0
then 0
else if max == r
then 60 * (fmod ((g - b) / delta) 6)
else if max == g
then 60 * (((b - r) / delta) + 2)
else if max == b
then 60 * (((r - g) / delta) + 4)
else 0;
l = (max + min) / 2;
s =
if delta == 0
then 0
else 100 * delta / (100 - lib.max (2 * l - 100) (100 - (2 * l)));
roundToString = value: toString (builtins.floor (value + 0.5));
in
lib.concatMapStringsSep " " roundToString [h s l];
in {
# TODO: Add tailscale custom widget
services = {
glance = {
enable = true;
settings = {
theme = {
contrast-multiplier = lib.mkForce 1.4;
};
pages = [
{
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{
type = "clock";
hour-format = "24h";
}
{
type = "weather";
location = "Paris, France";
}
{
type = "markets";
markets = [
{
symbol = "BTC-USD";
name = "Bitcoin";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:BTCUSD";
}
{
symbol = "SOL-USD";
name = "Solana";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:SOLUSD";
}
{
symbol = "ETH-USD";
name = "Ethereum";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:ETHUSD";
}
];
}
{
type = "dns-stats";
service = "adguard";
url = "https://adguard.hadi.diy";
username = "hadi";
password = "\${secret:adguard-pwd}";
}
];
}
{
size = "full";
widgets = [
{
type = "search";
search-engine = "duckduckgo";
}
{
type = "bookmarks";
groups = [
{
title = "";
same-tab = true;
color = "200 50 50";
links = [
{
title = "ProtonMail";
url = "https://proton.me/mail";
}
{
title = "Github";
url = "https://github.com";
}
{
title = "Youtube";
url = "https://youtube.com";
}
{
title = "Figma";
url = "https://figma.com";
}
];
}
{
title = "Docs";
same-tab = true;
color = "200 50 50";
links = [
{
title = "Nixpkgs repo";
url = "https://github.com/NixOS/nixpkgs";
}
{
title = "Nixvim";
url = "https://nix-community.github.io/nixvim/";
}
{
title = "Hyprland wiki";
url = "https://wiki.hyprland.org/";
}
{
title = "Search NixOS";
url = "https://search-nixos.hadi.diy";
}
];
}
{
title = "Homelab";
same-tab = true;
color = "100 50 50";
links = [
{
title = "Router";
url = "http://192.168.1.254/";
}
{
title = "Cloudflare";
url = "https://dash.cloudflare.com/";
}
];
}
{
title = "Work";
same-tab = true;
color = "50 50 50";
links = [
{
title = "Outlook";
url = "https://outlook.office.com/";
}
{
title = "Teams";
url = "https://teams.microsoft.com/";
}
{
title = "Office";
url = "https://www.office.com/";
}
];
}
{
title = "Cyber";
same-tab = true;
color = rgb-to-hsl "base09";
links = [
{
title = "CyberChef";
url = "https://cyberchef.org/";
}
{
title = "TryHackMe";
url = "https://tryhackme.com/";
}
{
title = "RootMe";
url = "https://www.root-me.org/";
}
{
title = "Exploit-DB";
url = "https://www.exploit-db.com/";
}
{
title = "CrackStation";
url = "https://crackstation.net/";
}
];
}
{
title = "Misc";
same-tab = true;
color = rgb-to-hsl "base01";
links = [
{
title = "Svgl";
url = "https://svgl.app/";
}
{
title = "Excalidraw";
url = "https://excalidraw.com/";
}
{
title = "Cobalt (Downloader)";
url = "https://cobalt.tools/";
}
{
title = "Mazanoke (Image optimizer)";
url = "https://mazanoke.com/";
}
{
title = "Vert (File converter)";
url = "https://vert.sh/";
}
];
}
];
}
{
type = "server-stats";
servers = [
{
type = "local";
name = "Jack";
}
];
}
{
type = "group";
widgets = [
{
type = "monitor";
title = "Services";
cache = "1m";
sites = [
{
title = "Vaultwarden";
url = "https://vault.hadi.diy";
icon = "si:bitwarden";
}
{
title = "Nextcloud";
url = "https://cloud.hadi.diy";
icon = "si:nextcloud";
}
{
title = "Adguard";
url = "https://adguard.hadi.diy";
icon = "si:adguard";
}
{
title = "Mealie";
url = "https://mealie.hadi.diy";
icon = "si:mealie";
}
];
}
{
type = "monitor";
title = "*arr";
cache = "1m";
sites = [
{
title = "Jellyfin";
url = "https://jellyfin.hadi.diy";
icon = "si:jellyfin";
}
{
title = "Jellyseerr";
url = "https://jellyseerr.hadi.diy";
icon = "si:odysee";
}
{
title = "Radarr";
url = "https://radarr.hadi.diy";
icon = "si:radarr";
}
{
title = "Sonarr";
url = "https://sonarr.hadi.diy";
icon = "si:sonarr";
}
{
title = "Prowlarr";
url = "https://prowlarr.hadi.diy";
icon = "si:podcastindex";
}
{
title = "Transmission";
url = "https://transmission.hadi.diy";
icon = "si:transmission";
}
];
}
];
}
];
}
];
name = "Home";
}
];
server = {port = 5678;};
};
};
nginx.virtualHosts."${domain}" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${
toString config.services.glance.settings.server.port
}";
};
};
};
systemd.services.glance = {
serviceConfig = {
DynamicUser = lib.mkForce false;
User = "glance";
Group = "glance";
};
};
users = {
groups.glance = {};
users.glance = {
isSystemUser = true;
description = "Glance user";
group = "glance";
};
};
sops.secrets.adguard-pwd = {
owner = "glance";
mode = "0600";
};
}

300
modules/nixos/glance.nix Normal file
View File

@@ -0,0 +1,300 @@
{ config, lib, ... }:
let
rgb-to-hsl =
color:
let
r = ((lib.toInt config.lib.stylix.colors."${color}-rgb-r") * 100.0) / 255;
g = ((lib.toInt config.lib.stylix.colors."${color}-rgb-g") * 100.0) / 255;
b = ((lib.toInt config.lib.stylix.colors."${color}-rgb-b") * 100.0) / 255;
max = lib.max r (lib.max g b);
min = lib.min r (lib.min g b);
delta = max - min;
fmod = base: int: base - (int * builtins.floor (base / int));
h =
if delta == 0 then
0
else if max == r then
60 * (fmod ((g - b) / delta) 6)
else if max == g then
60 * (((b - r) / delta) + 2)
else if max == b then
60 * (((r - g) / delta) + 4)
else
0;
l = (max + min) / 2;
s = if delta == 0 then 0 else 100 * delta / (100 - lib.max (2 * l - 100) (100 - (2 * l)));
roundToString = value: toString (builtins.floor (value + 0.5));
in
lib.concatMapStringsSep " " roundToString [
h
s
l
];
in
{
services = {
glance = {
enable = true;
settings = {
server.port = 8101;
pages = [
{
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{
type = "clock";
hour-format = "24h";
}
{
type = "weather";
location = "Paris, France";
}
{
type = "markets";
markets = [
{
symbol = "BTC-USD";
name = "Bitcoin";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:BTCUSD";
}
{
symbol = "SOL-USD";
name = "Solana";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:SOLUSD";
}
{
symbol = "ETH-USD";
name = "Ethereum";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:ETHUSD";
}
];
}
];
}
{
size = "full";
widgets = [
{
type = "search";
search-engine = "google";
}
{
type = "bookmarks";
groups = [
{
title = "";
same-tab = true;
color = "200 50 50";
links = [
{
title = "Github";
url = "https://github.com";
}
{
title = "Youtube";
url = "https://youtube.com";
}
{
title = "Figma";
url = "https://figma.com";
}
];
}
{
title = "Docs";
same-tab = true;
color = "200 50 50";
links = [
{
title = "Nixpkgs repo";
url = "https://github.com/NixOS/nixpkgs";
}
{
title = "Nixvim";
url = "https://nix-community.github.io/nixvim/";
}
{
title = "Hyprland wiki";
url = "https://wiki.hyprland.org/";
}
{
title = "Search NixOS";
url = "https://search-nixos.hadi.diy";
}
];
}
{
title = "Homelab";
same-tab = true;
color = "100 50 50";
links = [
{
title = "Router";
url = "http://192.168.1.254/";
}
{
title = "Cloudflare";
url = "https://dash.cloudflare.com/";
}
];
}
{
title = "Work";
same-tab = true;
color = "50 50 50";
links = [
{
title = "Outlook";
url = "https://outlook.office.com/";
}
{
title = "Teams";
url = "https://teams.microsoft.com/";
}
{
title = "Office";
url = "https://www.office.com/";
}
];
}
{
title = "Cyber";
same-tab = true;
color = rgb-to-hsl "base09";
links = [
{
title = "CyberChef";
url = "https://cyberchef.org/";
}
{
title = "TryHackMe";
url = "https://tryhackme.com/";
}
{
title = "RootMe";
url = "https://www.root-me.org/";
}
{
title = "Exploit-DB";
url = "https://www.exploit-db.com/";
}
{
title = "CrackStation";
url = "https://crackstation.net/";
}
];
}
{
title = "Misc";
same-tab = true;
color = rgb-to-hsl "base01";
links = [
{
title = "Svgl";
url = "https://svgl.app/";
}
{
title = "Excalidraw";
url = "https://excalidraw.com/";
}
{
title = "Cobalt (Downloader)";
url = "https://cobalt.tools/";
}
{
title = "Mazanoke (Image optimizer)";
url = "https://mazanoke.com/";
}
{
title = "Vert (File converter)";
url = "https://vert.sh/";
}
];
}
];
}
{
type = "server-stats";
servers = [
{
type = "local";
name = "orion";
}
];
}
{
type = "group";
widgets = [
{
type = "monitor";
title = "Services";
cache = "1m";
sites = [
{
title = "Vaultwarden";
url = "https://vault.jelles.net";
icon = "si:bitwarden";
}
{
title = "Files";
url = "https://fiels.jelles.net";
icon = "si:nextcloud";
}
];
}
{
type = "monitor";
title = "*arr";
cache = "1m";
sites = [
{
title = "Jellyfin";
url = "https://jellyfin.hadi.diy";
icon = "si:jellyfin";
}
{
title = "Jellyseerr";
url = "https://jellyseerr.hadi.diy";
icon = "si:odysee";
}
{
title = "Radarr";
url = "https://radarr.hadi.diy";
icon = "si:radarr";
}
{
title = "Sonarr";
url = "https://sonarr.hadi.diy";
icon = "si:sonarr";
}
{
title = "Prowlarr";
url = "https://prowlarr.hadi.diy";
icon = "si:podcastindex";
}
{
title = "Transmission";
url = "https://transmission.hadi.diy";
icon = "si:transmission";
}
];
}
];
}
];
}
];
name = "Home";
}
];
};
};
caddy.virtualHosts."jelles.net".extraConfig =
"reverse_proxy :${toString config.services.glance.settings.server.port}";
};
}

View File

@@ -0,0 +1,48 @@
{ config, ... }:
{
services = {
home-assistant = {
enable = true;
openFirewall = false;
extraComponents = [
"evohome" # The Honeywell TCC (Europe) component
"met" # Default weather
"radio_browser" # Default radio
];
# Configuration for components that support YAML (like Evohome)
config = {
homeassistant = {
name = "My Home";
latitude = 51.5; # Update with your actual location
longitude = 5.9; # Update with your actual location
unit_system = "metric";
time_zone = config.var.timeZone;
};
# Honeywell TCC (Europe) / Evohome configuration
# https://www.home-assistant.io/integrations/evohome/
evohome = {
username = "!secret honeywell_username";
password = "!secret honeywell_password";
};
# Basic default setup
default_config = { };
http = {
server_port = 8123;
server_host = "127.0.0.1";
use_x_forwarded_for = true;
trusted_proxies = [
"127.0.0.1"
"::1"
];
};
};
};
caddy.virtualHosts."home.jelles.net".extraConfig =
"reverse_proxy :${toString config.services.home-assistant.config.http.server_port}";
};
}

View File

@@ -0,0 +1,9 @@
# Home-manager configuration for NixOS
{inputs, ...}: {
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
backupFileExtension = "hm-backup";
extraSpecialArgs = {inherit inputs;};
};
}

View File

@@ -0,0 +1,15 @@
# Hyprland is a dynamic tiling Wayland compositor.
{
inputs,
pkgs,
...
}:
{
programs.hyprland = {
enable = true;
withUWSM = true;
package = inputs.hyprland.packages."${pkgs.stdenv.hostPlatform.system}".hyprland;
portalPackage =
inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland;
};
}

19
modules/nixos/mealie.nix Normal file
View File

@@ -0,0 +1,19 @@
# Mealie is a recipe management and meal planning application.
{config, ...}: let
domain = "mealie.hadi.diy";
in {
services = {
mealie = {
enable = true;
port = 8092;
};
nginx.virtualHosts."${domain}" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.mealie.port}";
};
};
};
}

45
modules/nixos/nginx.nix Normal file
View File

@@ -0,0 +1,45 @@
# Nginx is a web server that can also be used as a reverse proxy, load balancer, and HTTP cache.
{config, ...}: let
domain = "hadi.diy";
in {
security.acme = {
acceptTerms = true;
defaults.email = config.var.git.email;
certs."${domain}" = {
domain = "${domain}";
extraDomainNames = ["*.${domain}"];
group = "nginx";
dnsProvider = "cloudflare";
dnsPropagationCheck = true;
credentialsFile = config.sops.secrets.cloudflare-dns-token.path;
};
};
# Return 444 for all requests not matching a used subdomain.
services.nginx = {
enable = true;
virtualHosts = {
"default" = {
default = true;
locations."/" = {return = 444;};
};
"*.${domain}" = {
useACMEHost = domain;
forceSSL = true;
locations."/" = {return = 444;};
};
"aaaaaa.${domain}" = {
useACMEHost = domain;
forceSSL = true;
locations."/" = {return = 444;};
};
};
};
networking.firewall = {
allowedTCPPorts = [80 443];
allowedUDPPorts = [80 443];
};
sops.secrets.cloudflare-dns-token = {path = "/etc/cloudflare/dnskey.txt";};
}

58
modules/nixos/nix.nix Normal file
View File

@@ -0,0 +1,58 @@
# Nix configuration for NixOS
{
config,
inputs,
...
}:
let
autoGarbageCollector = config.var.autoGarbageCollector;
in
{
security.sudo.extraRules = [
{
users = [ config.var.username ];
commands = [
{
command = "/run/current-system/sw/bin/nixos-rebuild";
options = [ "NOPASSWD" ];
}
];
}
];
nixpkgs.config.allowUnfree = true;
nix = {
nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
channel.enable = false;
extraOptions = ''
warn-dirty = false
'';
settings = {
download-buffer-size = 262144000; # 250 MB (250 * 1024 * 1024)
auto-optimise-store = true;
trusted-users = [ config.var.username ]; # Allows remote nixos-rebuild to vps
experimental-features = [
"nix-command"
"flakes"
];
substituters = [
# high priority since it's almost always used
"https://cache.nixos.org?priority=10"
"https://hyprland.cachix.org"
"https://nix-community.cachix.org"
"https://numtide.cachix.org"
];
trusted-public-keys = [
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE="
];
};
gc = {
automatic = autoGarbageCollector;
persistent = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
};
}

63
modules/nixos/omen.nix Normal file
View File

@@ -0,0 +1,63 @@
# Omen laptop configuration for NixOS
# Import this only if you have an HP Omen laptop
{
config,
pkgs,
...
}: let
hp-omen-linux-module =
pkgs.callPackage
({
kernel ? config.boot.kernelPackages.kernel,
stdenv,
fetchFromGitHub,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "hp-omen-linux-module";
version = "rebase-6.14";
src = fetchFromGitHub {
owner = "ranisalt";
repo = "hp-omen-linux-module";
rev = finalAttrs.version;
sha256 = "sha256-2zCm29bdboSjRm/caMjBPGNc0tZXPUnIIYlHxxfhAok=";
};
setSourceRoot = ''
export sourceRoot=$(pwd)/${finalAttrs.src.name}/src
'';
nativeBuildInputs = kernel.moduleBuildDependencies;
makeFlags = [
"KERNELDIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
];
installPhase = ''
runHook preInstall
install hp-wmi.ko -Dm444 -t $out/lib/modules/${kernel.modDirVersion}/kernel/drivers/platform/x86/hp/
runHook postInstall
'';
})) {kernel = config.boot.kernelPackages.kernel;};
in {
boot.extraModulePackages = [hp-omen-linux-module];
boot.kernelModules = ["hp-wmi"];
users.groups.omen-rgb = {};
users.users.${config.var.username}.extraGroups = ["omen-rgb"];
systemd.tmpfiles.rules = [
"w /sys/devices/platform/hp-wmi/rgb_zones/zone00 0660 root omen-rgb -"
"w /sys/devices/platform/hp-wmi/rgb_zones/zone01 0660 root omen-rgb -"
"w /sys/devices/platform/hp-wmi/rgb_zones/zone02 0660 root omen-rgb -"
"w /sys/devices/platform/hp-wmi/rgb_zones/zone03 0660 root omen-rgb -"
];
services.udev.extraRules = ''
SUBSYSTEM=="platform", KERNEL=="hp-wmi", ACTION=="add", \
RUN+="${pkgs.coreutils-full}/bin/sleep 2", \
RUN+="${pkgs.coreutils}/bin/chgrp omen-rgb /sys/devices/platform/hp-wmi/rgb_zones/zone00", \
RUN+="${pkgs.coreutils}/bin/chmod 0660 /sys/devices/platform/hp-wmi/rgb_zones/zone00", \
RUN+="${pkgs.coreutils}/bin/chgrp omen-rgb /sys/devices/platform/hp-wmi/rgb_zones/zone01", \
RUN+="${pkgs.coreutils}/bin/chmod 0660 /sys/devices/platform/hp-wmi/rgb_zones/zone01", \
RUN+="${pkgs.coreutils}/bin/chgrp omen-rgb /sys/devices/platform/hp-wmi/rgb_zones/zone02", \
RUN+="${pkgs.coreutils}/bin/chmod 0660 /sys/devices/platform/hp-wmi/rgb_zones/zone02", \
RUN+="${pkgs.coreutils}/bin/chgrp omen-rgb /sys/devices/platform/hp-wmi/rgb_zones/zone03", \
RUN+="${pkgs.coreutils}/bin/chmod 0660 /sys/devices/platform/hp-wmi/rgb_zones/zone03"
'';
}

View File

@@ -0,0 +1,25 @@
{
services.radicale = {
enable = true;
settings = {
server = {
hosts = [ "127.0.0.1:5232" ];
};
auth = {
type = "htpasswd";
htpasswd_filename = "/var/lib/radicale/users";
htpasswd_encryption = "bcrypt";
};
storage = {
filesystem_folder = "/var/lib/radicale/collections";
};
};
};
services.caddy.virtualHosts."radicale.jelles.net".extraConfig = ''
reverse_proxy :5232 {
header_up X-Script-Name /
header_up X-Forwarded-For {remote}
header_up X-Remote-User {http.auth.user.id}
}'';
}

47
modules/nixos/sddm.nix Normal file
View File

@@ -0,0 +1,47 @@
# SDDM is a display manager for X11 and Wayland
{
pkgs,
inputs,
config,
...
}:
let
foreground = config.theme.textColorOnWallpaper;
sddm-astronaut = pkgs.sddm-astronaut.override {
embeddedTheme = "purple_leaves";
themeConfig = {
HeaderTextColor = "#${foreground}";
DateTextColor = "#${foreground}";
TimeTextColor = "#${foreground}";
LoginFieldTextColor = "#${foreground}";
PasswordFieldTextColor = "#${foreground}";
UserIconColor = "#${foreground}";
PasswordIconColor = "#${foreground}";
WarningColor = "#${foreground}";
LoginButtonBackgroundColor = "#${foreground}";
SystemButtonsIconsColor = "#${foreground}";
SessionButtonTextColor = "#${foreground}";
VirtualKeyboardButtonTextColor = "#${foreground}";
DropdownBackgroundColor = "#${foreground}";
HighlightBackgroundColor = "#${foreground}";
};
};
in
{
services.displayManager = {
sddm = {
package = pkgs.kdePackages.sddm;
extraPackages = [ sddm-astronaut ];
enable = true;
wayland.enable = true;
theme = "sddm-astronaut-theme";
settings = {
Wayland.SessionDir = "${
inputs.hyprland.packages."${pkgs.stdenv.hostPlatform.system}".hyprland
}/share/wayland-sessions";
};
};
};
environment.systemPackages = [ sddm-astronaut ];
}

26
modules/nixos/ssh.nix Normal file
View File

@@ -0,0 +1,26 @@
# SSH configuration
{ config, ... }:
let
username = config.var.username;
in
{
services.openssh = {
enable = true;
ports = [ 22 ];
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
AllowUsers = [
username
"git"
];
};
};
# Add my public SSH key to my user
users.users."${username}" = {
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAU2LydkXRTtNFY7oyX8JQURwXLVhB71DeK8XzrXeFX1 openpgp:0xA490D93A"
];
};
}

View File

@@ -0,0 +1,50 @@
# Systemd-boot configuration for NixOS
{ pkgs, config, ... }:
{
boot = {
bootspec.enable = true;
loader = {
efi.canTouchEfiVariables = true;
systemd-boot = {
enable = true;
consoleMode = "auto";
configurationLimit = 5;
extraInstallCommands = ''
ENTRIES="${config.boot.loader.efi.efiSysMountPoint}/loader/entries"
PROFILES="/nix/var/nix/profiles"
for file in "$ENTRIES"/nixos-generation-*.conf; do
generation=$(${pkgs.coreutils}/bin/basename "$file" | ${pkgs.gnugrep}/bin/grep -o -E '[0-9]+')
timestamp=$(${pkgs.coreutils}/bin/stat -c %y "$PROFILES/system-$generation-link" 2>/dev/null | ${pkgs.coreutils}/bin/cut -d. -f1)
if [ -z "$timestamp" ]; then
timestamp="Unknown Date"
fi
${pkgs.gnused}/bin/sed -i "s/^version .*/version Generation $generation - $timestamp/" "$file"
done
'';
};
};
tmp.cleanOnBoot = true;
kernelPackages = pkgs.linuxPackages_latest; # _zen, _hardened, _rt, _rt_latest, etc.
# Silent boot
kernelParams = [
"quiet"
"splash"
"rd.systemd.show_status=false"
"rd.udev.log_level=3"
"udev.log_priority=3"
"boot.shell_on_fail"
];
consoleLogLevel = 0;
initrd.verbose = false;
};
# To avoid systemd services hanging on shutdown
systemd.settings.Manager = {
DefaultTimeoutStopSec = "10s";
};
}

19
modules/nixos/users.nix Normal file
View File

@@ -0,0 +1,19 @@
# Users configuration for NixOS
{
config,
pkgs,
...
}: let
username = config.var.username;
in {
programs.zsh.enable = true;
users = {
defaultUserShell = pkgs.zsh;
users.${username} = {
isNormalUser = true;
description = "${username} account";
extraGroups = ["networkmanager" "wheel"];
};
};
}

137
modules/nixos/utils.nix Normal file
View File

@@ -0,0 +1,137 @@
# Misc
{
pkgs,
config,
...
}:
let
hostname = config.var.hostname;
keyboardLayout = config.var.keyboardLayout;
configDir = config.var.configDirectory;
timeZone = config.var.timeZone;
defaultLocale = config.var.defaultLocale;
otherLocale = config.var.otherLocale;
numericLocale = config.var.numericLocale;
timeLocale = config.var.timeLocale;
autoUpgrade = config.var.autoUpgrade;
editor = config.var.preferred.editor;
terminal = config.var.preferred.terminal;
browser = config.var.preferred.browser;
in
{
networking.hostName = hostname;
networking.networkmanager.enable = true;
systemd.services.NetworkManager-wait-online.enable = false;
# system.autoUpgrade = {
# enable = autoUpgrade;
# dates = "04:00";
# flake = "${configDir}";
# flags = [
# "--update-input"
# "nixpkgs"
# "--commit-lock-file"
# ];
# allowReboot = false;
# };
time = {
timeZone = timeZone;
};
i18n.defaultLocale = defaultLocale;
i18n.extraLocaleSettings = {
LC_ADDRESS = otherLocale;
LC_IDENTIFICATION = otherLocale;
LC_MEASUREMENT = otherLocale;
LC_MONETARY = numericLocale;
LC_NAME = otherLocale;
LC_NUMERIC = numericLocale;
LC_PAPER = otherLocale;
LC_TELEPHONE = otherLocale;
LC_TIME = timeLocale;
};
services = {
xserver = {
enable = true;
xkb.layout = keyboardLayout;
xkb.variant = "";
};
# gnome.gnome-keyring.enable = true;
# psd = {
# enable = true;
# resyncTimer = "10m";
# };
};
console.keyMap = keyboardLayout;
environment.variables = {
XDG_DATA_HOME = "$HOME/.local/share";
PASSWORD_STORE_DIR = "$HOME/.local/share/password-store";
EDITOR = editor;
TERMINAL = terminal;
TERM = terminal;
BROWSER = browser;
};
services.libinput.enable = true;
programs.dconf.enable = true;
services = {
dbus = {
enable = true;
implementation = "broker";
packages = with pkgs; [
gcr
gnome-settings-daemon
];
};
gvfs.enable = true;
upower.enable = true;
power-profiles-daemon.enable = true;
udisks2.enable = true;
};
# enable zsh autocompletion for system packages (systemd, etc)
environment.pathsToLink = [ "/share/zsh" ];
# Faster rebuilding
documentation = {
enable = true;
doc.enable = true;
man.enable = true;
dev.enable = true;
info.enable = true;
nixos.enable = true;
};
environment.systemPackages = with pkgs; [
hyprland-qtutils
xdg-utils
];
xdg.portal = {
enable = true;
xdgOpenUsePortal = true;
config = {
common.default = [ "gtk" ];
hyprland.default = [
"gtk"
"hyprland"
];
};
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
};
security = {
# allow wayland lockers to unlock the screen
pam.services.hyprlock.text = "auth include login";
# userland niceness
rtkit.enable = true;
# don't ask for password for wheel group
sudo.wheelNeedsPassword = false;
};
}

View File

@@ -0,0 +1,91 @@
{
lib,
pkgs,
config,
...
}:
{
options.theme = lib.mkOption {
type = lib.types.attrs;
default = {
rounding = 17;
gaps-in = 5;
gaps-out = 10;
active-opacity = 1;
inactive-opacity = 1;
blur = true;
border-size = 3;
animation-speed = "fast"; # "fast" | "medium" | "slow"
fetch = "none"; # "nerdfetch" | "neofetch" | "pfetch" | "none"
textColorOnWallpaper = config.lib.stylix.colors.base01; # Color of the text displayed on the wallpaper (Lockscreen, display manager, ...)
bar = {
# Hyprpanel
position = "top"; # "top" | "bottom"
transparent = true;
transparentButtons = false;
floating = true;
};
};
description = "Theme configuration options";
};
config.stylix = {
enable = true;
# Mocha
# See https://tinted-theming.github.io/tinted-gallery/ for more schemes
base16Scheme = {
base00 = "0F0F15"; # Default Background
base01 = "15151A"; # Lighter Background (Used for status bars, line number and folding marks)
base02 = "313244"; # Selection Background
base03 = "45475a"; # Comments, Invisibles, Line Highlighting
base04 = "585b70"; # Dark Foreground (Used for status bars)
base05 = "cdd6f4"; # Default Foreground, Caret, Delimiters, Operators
base06 = "f5e0dc"; # Light Foreground (Not often used)
base07 = "b4befe"; # Light Background (Not often used)
base08 = "f38ba8"; # Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted
base09 = "fab387"; # Integers, Boolean, Constants, XML Attributes, Markup Link Url
base0A = "f9e2af"; # Classes, Markup Bold, Search Text Background
base0B = "a6e3a1"; # Strings, Inherited Class, Markup Code, Diff Inserted
base0C = "94e2d5"; # Support, Regular Expressions, Escape Characters, Markup Quotes
base0D = "89b4fa"; # Functions, Methods, Attribute IDs, Headings, Accent color
base0E = "cba6f7"; # Keywords, Storage, Selector, Markup Italic, Diff Changed
base0F = "f2cdcd"; # Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?>
};
cursor = {
name = "phinger-cursors-light";
package = pkgs.phinger-cursors;
size = 28;
};
fonts = {
monospace = {
package = pkgs.nerd-fonts.jetbrains-mono;
name = "JetBrains Mono Nerd Font";
};
sansSerif = {
package = pkgs.source-sans-pro;
name = "Source Sans Pro";
};
serif = config.stylix.fonts.sansSerif;
emoji = {
package = pkgs.noto-fonts-color-emoji;
name = "Noto Color Emoji";
};
sizes = {
applications = 13;
desktop = 13;
popups = 15;
terminal = 11.5;
};
};
polarity = "dark";
image = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/anotherhadi/awesome-wallpapers/refs/heads/main/app/static/wallpapers/leef_dark_purple_minimalist.png";
sha256 = "sha256-q6ufFdC/tMSb+mllw7XhilkAObemXXyps2SBlnMt7mY=";
};
};
}