nixfiles/home-manager/modules/ezpcusr.nix
2025-02-27 16:37:14 -07:00

621 lines
21 KiB
Nix
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

inputs: {
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.ezpcusr;
# lockCommand = pkgs.writeScript "lock.sh" ''
# ${pkgs.swaylock-effects}/bin/swaylock -f --clock --indicator --screenshots --effect-scale 0.8 --effect-blur 8x3 --effect-vignette 0.2:0.5 --fade-in 0.5 --text-color ${config.ezcolors.base16.base08} --inside-color ${config.ezcolors.base16.base00} --ring-color ${config.ezcolors.base16.base01} --datestr "%Y-%m-%e" --timestr "%I:%M %p"
# '';
lockCommand = pkgs.writeShellScript "lock.sh" ''
exec ${pkgs.swaylock}/bin/swaylock -f --text-color ${config.ezcolors.base16.base08} --inside-color ${config.ezcolors.base16.base00} --ring-color ${config.ezcolors.base16.base01} -c ${config.ezcolors.base16.base00}
'';
in {
options.ezpcusr = {
enable = mkEnableOption "Enable simple PC user config";
uploadScript = mkOption {
type = types.nullOr types.package;
default = null;
description = "A path to a script that takes a path to a file and returns a URL";
};
screenshotsPath = mkOption {
description = "Path to save screenshots in";
default = "$HOME/Media/Screenshots";
type = types.str;
};
screensaver = mkOption {
description = "ezpcusr screensaver";
default = {};
type = types.submodule {
options = {
lockTime = mkOption {
type = types.int;
default = 600;
description = "Time until your screen locks";
};
offTime = mkOption {
type = types.int;
default = 900;
description = "Time until your screen turns off";
};
};
};
};
bluetooth = mkOption {
type = types.bool;
default = false;
description = "If this PC has bluetooth support";
};
battery = mkOption {
type = types.bool;
default = false;
description = "If this PC has a battery";
};
location = mkOption {
description = "Your location (used for weather)";
example = "US-12345";
default = "";
type = types.str;
};
};
config = lib.mkIf cfg.enable {
services.swayidle = {
enable = lib.mkDefault true;
events = [
{
event = "before-sleep";
command = "${pkgs.systemd}/bin/loginctl lock-session";
}
{
event = "lock";
command = "${pkgs.playerctl}/bin/playerctl -a pause; ${lockCommand}";
}
{
event = "unlock";
command = "${pkgs.procps}/bin/pkill -USR1 swaylock";
}
];
timeouts = [
{
timeout = cfg.screensaver.lockTime;
command = "${pkgs.systemd}/bin/loginctl lock-session";
}
{
timeout = cfg.screensaver.offTime;
command = "${pkgs.sway}/bin/swaymsg 'output * dpms off'";
resumeCommand = "${pkgs.sway}/bin/swaymsg 'output * dpms on'";
}
];
};
wayland.windowManager.hyprland = {
enable = false;
systemd.enable = true;
extraConfig = let
swayConfig = config.wayland.windowManager.sway.config;
swayBindings = swayConfig.keybindings;
swayToHyprlandBinding = key: binding: let
splitKey = lib.splitString "+" key;
isMod = m: m == "Mod4" || m == "Shift";
convertMod = m:
if m == "Mod4"
then "SUPER"
else lib.toUpper m;
mods = filter isMod splitKey;
modsStr = "${(lib.concatStringsSep "_" (map convertMod mods))},";
normalKeys = filter (m: isMod m == false) splitKey;
normalKey = lib.elemAt normalKeys 0;
convertedKey = "${modsStr}${normalKey}";
convertDir = dir: lib.elemAt (lib.stringToCharacters dir) 0;
splitBinding = lib.splitString " " binding;
bindingAction = lib.elemAt splitBinding 0;
newBinding =
if bindingAction == "exec"
then "exec, ${lib.concatStringsSep " " (lib.tail splitBinding)}"
else if bindingAction == "workspace"
then let n = lib.last splitBinding; in "workspace, ${n}"
else if bindingAction == "kill"
then "killactive,"
else if bindingAction == "focus"
then let
l = lib.last splitBinding;
in
if l == "mode_toggle"
then "togglefloating,"
else "movefocus,${convertDir l}"
else if bindingAction == "fullscreen"
then "fullscreen,0"
else if bindingAction == "floating"
then "togglefloating,"
else if bindingAction == "move"
then let
splitMove = lib.tail splitBinding;
moveThing = lib.elemAt splitMove 0;
toThing =
if lib.length splitMove >= 3
then lib.elemAt splitMove 2
else null;
in
if toThing == null
then "movewindow,${convertDir moveThing}"
else if moveThing == "container" && toThing == "workspace"
then "movetoworkspacesilent,${lib.last splitMove}"
else null
else null;
in
if newBinding == null
then "# ${key} - ${binding}"
else "bind=${convertedKey}, ${newBinding}";
convertedBindings = lib.concatStringsSep "\n" (lib.mapAttrsToList swayToHyprlandBinding swayBindings);
bindingsStr = "${convertedBindings}\n";
in ''
monitor=,preferred,auto,auto
gestures {
workspace_swipe = on
}
${convertedBindings}
'';
};
wayland.windowManager.sway = {
enable = lib.mkDefault true;
systemd.enable = lib.mkDefault true;
wrapperFeatures.gtk = lib.mkDefault true;
extraConfig = ''
exec keyctl link @u @s
workspace 1
'';
config = {
terminal = lib.mkDefault "${pkgs.foot}/bin/foot";
modifier = lib.mkDefault "Mod4";
keybindings = let
modifier = config.wayland.windowManager.sway.config.modifier;
alphabet = ["Ctrl" "Alt" "Ctrl+Alt"];
genKeyAttrs = move:
lib.listToAttrs (
map
(
n: {
name = "${modifier}${
if move
then "+Shift"
else ""
}+${builtins.elemAt alphabet ((n - 11) / 10)}+${toString (lib.mod n 10)}";
value = "${
if move
then "move container to "
else ""
}workspace number ${toString n}";
}
)
(lib.lists.range 11 (10 * (builtins.length alphabet) + 10))
);
in
lib.mkOptionDefault (
let
volumeUp = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ +5%";
volumeDown = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ -5%";
in
{
"${modifier}+q" = "kill";
"Print" = "exec ${config.services.flameshot.package}/bin/flameshot gui -p=\"${config.services.flameshot.settings.General.savePath}/$(date '+${config.services.flameshot.settings.General.filenamePattern}')\" --raw | ${pkgs.wl-clipboard}/bin/wl-copy -t image/png";
"Shift+Print" = "exec ${pkgs.wl-clipboard}/bin/wl-paste > /tmp/clipup && ${
if cfg.uploadScript != null
then cfg.uploadScript
else ":"
} /tmp/clipup | ${pkgs.wl-clipboard}/bin/wl-copy && ${pkgs.libnotify}/bin/notify-send 'Clipboard uploaded!'";
"${modifier}+c" = "exec ${config.services.clipman.package}/bin/clipman pick -t rofi";
"${modifier}+minus" = volumeDown;
"${modifier}+equal" = volumeUp;
"XF86AudioRaiseVolume" = volumeUp;
"XF86AudioLowerVolume" = volumeDown;
"XF86AudioMute" = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle";
"XF86AudioMicMute" = "exec ${pkgs.pulseaudio}/bin/pactl set-source-mute @DEFAULT_SOURCE@ toggle";
"XF86MonBrightnessDown" = "exec ${pkgs.light}/bin/light -U 10";
"XF86MonBrightnessUp" = "exec ${pkgs.light}/bin/light -A 10";
"${modifier}+semicolon" = "exec ${pkgs.light}/bin/light -U 10";
"${modifier}+apostrophe" = "exec ${pkgs.light}/bin/light -A 10";
# Previous/next but change the shuffle/random state before action (and change back afterwards)
"${modifier}+Shift+bracketright" = "exec ${pkgs.playerctl}/bin/playerctl shuffle Toggle && ${pkgs.playerctl}/bin/playerctl next && ${pkgs.playerctl}/bin/playerctl shuffle Toggle";
"${modifier}+Shift+bracketleft" = "exec ${pkgs.playerctl}/bin/playerctl shuffle Toggle && ${pkgs.playerctl}/bin/playerctl previous && ${pkgs.playerctl}/bin/playerctl shuffle Toggle";
"Shift+XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl shuffle Toggle && ${pkgs.playerctl}/bin/playerctl next && ${pkgs.playerctl}/bin/playerctl shuffle Toggle";
# Previous/next
"${modifier}+bracketright" = "exec ${pkgs.playerctl}/bin/playerctl next";
"${modifier}+bracketleft" = "exec ${pkgs.playerctl}/bin/playerctl previous";
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next";
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous";
# Seek forward/back
"${modifier}+Ctrl+bracketright" = "exec ${pkgs.playerctl}/bin/playerctl position 5+";
"${modifier}+Ctrl+bracketleft" = "exec ${pkgs.playerctl}/bin/playerctl position 5-";
"Ctrl+XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl position 5+";
"Ctrl+XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl position 5-";
# Toggle play/pause
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
"XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
"${modifier}+backslash" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
"${modifier}+p" = "exec bash ${inputs.bwmenu}/bwmenu";
"${modifier}+e" = "exec bash ${inputs.bemoji}/bemoji -t";
"${modifier}+0" = "workspace 10";
"${modifier}+Shift+0" = "move container to workspace 10";
"Ctrl+Alt+l" = "exec ${pkgs.systemd}/bin/loginctl lock-session";
"${modifier}+s" = "sticky toggle";
}
// genKeyAttrs true
// genKeyAttrs false
);
menu = "${config.programs.rofi.package}/bin/rofi -show drun -show-icons -run-command '${pkgs.sway}/bin/swaymsg exec -- {cmd}'";
bars = [];
gaps = {
smartGaps = lib.mkDefault true;
smartBorders = lib.mkDefault "on";
inner = lib.mkDefault 10;
outer = lib.mkDefault 0;
};
};
};
programs.firefox.enable = true;
programs.waybar = {
enable = lib.mkDefault true;
systemd = {
enable = lib.mkDefault true;
target = lib.mkDefault "sway-session.target";
};
settings.mainbar = let
# weatherCommand = f: "(${pkgs.curl}/bin/curl 'wttr.in/${cfg.location}?format=${f}' || echo 'ERR') | ${pkgs.gnused}/bin/sed 's/^Unknown.*/ERR/' | ${pkgs.coreutils}/bin/tr -s ' '";
weatherCommand = f: "(${pkgs.curl}/bin/curl 'wttr.in/${cfg.location}?u&format=${f}' || echo 'ERR') | ${pkgs.gnused}/bin/sed 's/^Unknown.*/ERR/' | ${pkgs.gnused}/bin/sed -e 's/[ +]//g' -e 's/0\\.0/0/g' -e 's/0\\./\\./g' -e 's/mph//g' -e 's/°F/°/g'";
in {
position = lib.mkDefault "left";
height = lib.mkDefault null;
modules-left = ["sway/workspaces" "custom/spacer" "custom/weather-temp" "custom/weather-precip" "custom/weather-wind"];
modules-center = ["clock#1" "clock#2" "custom/spacer" "custom/media" "custom/spacer" "clock#3" "clock#4" "custom/spacer" "clock#5"];
modules-right = ["pulseaudio" "custom/spacer" "memory" "custom/spacer" "cpu"] ++ lib.optionals cfg.battery ["custom/spacer" "battery"] ++ ["custom/spacer" "tray"];
"custom/spacer" = {
format = lib.mkDefault "";
rotate = lib.mkDefault 90;
tooltip = lib.mkDefault false;
};
"custom/weather-temp" = {
exec = lib.mkDefault (weatherCommand "%c+%t");
on-click = lib.mkDefault "${pkgs.xdg-utils}/bin/xdg-open 'https://weather.com/weather/today/l/85625'";
on-click-right = lib.mkDefault "${pkgs.xdg-utils}/bin/xdg-open 'https://wttr.in/${cfg.location}'";
interval = lib.mkDefault 300;
};
"custom/weather-precip" = {
exec = lib.mkDefault (weatherCommand "🌧+%p");
on-click = lib.mkDefault "${pkgs.xdg-utils}/bin/xdg-open 'https://www.lightningmaps.org/'";
on-click-right = lib.mkDefault "${pkgs.xdg-utils}/bin/xdg-open 'https://wttr.in/${cfg.location}'";
interval = lib.mkDefault 300;
};
"custom/weather-wind" = {
exec = lib.mkDefault (weatherCommand "🌬+%w");
on-click = lib.mkDefault "${pkgs.xdg-utils}/bin/xdg-open 'https://www.ventusky.com/";
on-click-right = lib.mkDefault "${pkgs.xdg-utils}/bin/xdg-open 'https://wttr.in/${cfg.location}'";
interval = lib.mkDefault 300;
};
"custom/media" = {
rotate = lib.mkDefault 90;
max-length = lib.mkDefault 60;
on-click = lib.mkDefault "${pkgs.playerctl}/bin/playerctl play-pause";
exec = lib.mkDefault "${pkgs.playerctl}/bin/playerctl metadata --format '{{ emoji(status) }} {{ artist }} - {{ title }}' --follow";
};
"sway/workspaces" = {
disable-scroll = lib.mkDefault true;
};
"clock#1" = {
tooltip = lib.mkDefault false;
format = lib.mkDefault "{:%a}";
};
"clock#2" = {
tooltip = lib.mkDefault false;
format = lib.mkDefault "{:%m-%d}";
};
"clock#3" = {
tooltip = lib.mkDefault false;
format = lib.mkDefault "{:%I:%M}";
};
"clock#4" = {
tooltip = lib.mkDefault false;
format = lib.mkDefault "{:%p}";
};
"clock#5" = {
tooltip = lib.mkDefault false;
timezone = lib.mkDefault "Etc/UTC";
format = lib.mkDefault "{:%H%M}";
};
pulseaudio = {
format = lib.mkDefault "{icon} {volume}%";
format-bluetooth = lib.mkDefault "{icon} {volume}%";
format-muted = lib.mkDefault "";
format-icons = ["" "" ""];
on-click = lib.mkDefault "${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle";
on-click-right = lib.mkDefault "${pkgs.pavucontrol}/bin/pavucontrol";
ignored-sinks = ["Easy Effects Sink"];
};
memory = {
interval = lib.mkDefault 20;
format = lib.mkDefault " {}%";
};
cpu = {
interval = lib.mkDefault 20;
format = lib.mkDefault " {usage}%";
};
battery = {
states = {
good = lib.mkDefault 90;
warning = lib.mkDefault 25;
critical = lib.mkDefault 10;
};
format = lib.mkDefault "{icon} {capacity}%";
format-icons = {
default = ["" "" "" "" "" "" "" "" "" ""];
charging = ["" "" "" "" "" "" ""];
};
};
tray = {
icon-size = lib.mkDefault 18;
spacing = lib.mkDefault 5;
};
};
style = ''
window#waybar {
background: #${config.ezcolors.base16.base01};
color: #${config.ezcolors.base16.base06};
}
#custom-spacer {
font-size: 15px;
color: #${config.ezcolors.base16.base00};
font-weight: bold;
}
#workspaces,
#clock.1,
#clock.2,
#clock.3,
#clock.4,
#clock.5,
#pulseaudio,
#memory,
#cpu,
#battery,
#disk,
#tray,
#mode,
#custom-weather-temp,
#custom-weather-precip,
#custom-weather-wind,
#custom-media {
color: #${config.ezcolors.base16.base06};
font-size: ${toString (config.ezfonts.font.size + 1)}px;
background: #${config.ezcolors.base16.base00};
padding: 5px 0;
}
#workspaces { padding: 0 }
#clock.1 { padding: 5px 0 0 0; }
#clock.2 { padding: 0 0 5px 0; }
#clock.3 { padding: 5px 0 0 0; }
#clock.4 { padding: 0 0 5px 0; }
#custom-weather-temp { padding: 5px 0 0 0; }
#custom-weather-precip { padding: 5px 0; }
#custom-weather-wind { padding: 0 0 5px 0; }
#custom-media.playing {
color: #${config.ezcolors.base16.base0A};
}
#workspaces button.focused {
color: #${config.ezcolors.base16.base0A};
}
#workspaces button:hover {
background: #${config.ezcolors.base16.base02};
}
#pulseaudio {
color: #${config.ezcolors.base16.base0B};
}
#memory {
color: #${config.ezcolors.base16.base0C};
}
#cpu {
color: #${config.ezcolors.base16.base0D};
}
#battery {
color: #${config.ezcolors.base16.base0E};
}
* {
font-family: "${config.ezfonts.font.name}";
border-radius: 0;
border-width: 0;
border-style: none;
margin: 0;
padding: 0;
}
'';
};
services.mako = {
enable = lib.mkDefault true;
maxVisible = lib.mkDefault 6;
extraConfig = lib.generators.toKeyValue {} {
on-button-middle = "dismiss-all";
};
};
systemd.user.services.mako = {
Service = {
ExecStart = "${pkgs.mako}/bin/mako";
};
Install = {
After = ["sway-session.target"];
WantedBy = ["sway-session.target"];
};
};
ezcolors.enable = lib.mkDefault true;
ezfonts.enable = lib.mkDefault true;
services.blueman-applet.enable = lib.mkDefault cfg.bluetooth;
services.mpris-proxy.enable = lib.mkDefault true;
services.playerctld.enable = lib.mkDefault true;
gtk = {
enable = lib.mkDefault true;
iconTheme = {
package = lib.mkDefault pkgs.papirus-icon-theme;
name = lib.mkDefault "Papirus-Dark";
};
};
home.pointerCursor = {
package = lib.mkDefault pkgs.adwaita-icon-theme;
name = lib.mkDefault "Adwaita";
size = lib.mkDefault 24;
x11.enable = lib.mkDefault true;
gtk.enable = lib.mkDefault true;
};
qt = {
enable = lib.mkDefault true;
platformTheme = lib.mkDefault "gtk";
};
# programs.kermit = {
# enable = lib.mkDefault true;
# settings = {
# opacity = lib.mkDefault "0.90";
# key = lib.mkDefault "shift";
# };
# };
programs.foot.enable = true;
xdg.enable = true;
xdg.userDirs.enable = true;
xdg.configFile."mimeapps.list".force = true;
xdg.mimeApps = let
applications = {
"inode/directory" = "pcmanfm-qt.desktop";
"text/html" = "librewolf.desktop";
"x-scheme-handler/http" = "librewolf.desktop";
"x-scheme-handler/https" = "librewolf.desktop";
"x-scheme-handler/about" = "librewolf.desktop";
"application/zip" = "ark.desktop";
"application/rar" = "ark.desktop";
"application/7z" = "ark.desktop";
"application/*tar" = "ark.desktop";
};
in {
enable = true;
associations.added = applications;
defaultApplications = applications;
};
programs.mpv.enable = lib.mkDefault true;
fonts.fontconfig.enable = lib.mkDefault true;
home.packages = with pkgs; [
wl-clipboard
wtype
ydotool
keyutils
# programs
pavucontrol
kdePackages.ark
pcmanfm-qt
# CLI tools
yt-dlp
maim
slop
xorg.xhost
];
programs.rofi = {
enable = lib.mkDefault true;
package = pkgs.rofi-wayland;
terminal = lib.mkDefault "${pkgs.foot}/bin/foot";
};
services.flameshot = {
enable = true;
package = pkgs.flameshot.override { enableWlrSupport = true; };
settings.General = {
filenamePattern = "%F_%T";
savePath = "Media/Screenshots";
saveAfterCopy = true;
uiColor = "#${config.ezcolors.base16.base04}";
contrastUiColor = "#${config.ezcolors.base16.base05}";
disabledGrimWarning = true;
};
};
services.clipman.enable = true;
};
}