{ config, pkgs, user, name, ... }: # https://nix-community.github.io/home-manager/options.html let my-deps = { notify-send = "${pkgs.libnotify}/bin/notify-send"; playerctl = "${pkgs.playerctl}/bin/playerctl"; grim = "${pkgs.grim}/bin/grim"; slurp = "${pkgs.slurp}/bin/slurp"; amixer = "${pkgs.alsa-utils}/bin/amixer"; swaybg = "${pkgs.swaybg}/bin/swaybg"; terminal = "${pkgs.foot}/bin/foot"; chafa = "${pkgs.chafa}/bin/chafa"; exiftool = "${pkgs.exiftool}/bin/exiftool"; wc = "${pkgs.coreutils}/bin/wc"; xargs = "${pkgs.findutils}/bin/xargs"; menu = "${pkgs.wofi}/bin/wofi --dmenu"; }; my-scripts = { play-pause = (pkgs.writeShellScriptBin "play-pause" '' if [ "$(${my-deps.playerctl} --list-all | ${ my-deps.wc } -l)" -lt 2 ] then ${my-deps.playerctl} play-pause else ${ my-deps.playerctl } --list-all | \ ${ my-deps.xargs } -I _ ${ my-deps.playerctl } --player _ metadata --format '_ - {{title}}' | \ ${ my-deps.menu } | ${pkgs.gawk}/bin/awk '{print $1}' | \ ${ my-deps.xargs } -I _ ${ my-deps.playerctl } --player _ play-pause fi ''); bwmenu = (pkgs.writeShellScriptBin "bwmenu" '' items="$(rbw list)" echo "$items" | ${ my-deps.menu } | xargs -I_ rbw get _ | wl-copy ''); screenshot = (pkgs.writeShellScriptBin "screenshot" '' OUT_DIR=~/Pictures/Screenshots mkdir -p "$OUT_DIR" FILE=$OUT_DIR/$(date +"%Y-%m-%dT%H:%M:%SZ").png ${ my-deps.grim } -g "$(${ my-deps.slurp } -o)" "$FILE" ${my-deps.notify-send} "Screenshot Taken" "$FILE" cat "$FILE" | wl-copy -t image/png ''); brightness-down = (pkgs.writeShellScriptBin "brightness-down" '' light -U 10 ${my-deps.notify-send} "Brightness" -h int:value:$(light) -a brightness-down -t 1000 ''); brightness-up = (pkgs.writeShellScriptBin "brightness-up" '' light -A 10 ${my-deps.notify-send} "Brightness" -h int:value:$(light) -a brightness-up -t 1000 ''); }; lf-sixel = pkgs.callPackage ../../custom/lf-sixel/. { }; in { programs.home-manager.enable = true; home.username = "tristan"; home.homeDirectory = "/home/tristan"; xdg.userDirs.enable = true; home.packages = (with pkgs; [ libnotify wl-clipboard wofi du-dust htop imv libsixel lf-sixel yt-dlp playerctl pavucontrol brave quickemu bitwarden libsForQt5.kasts ]) ++ (with my-scripts; [ play-pause bwmenu screenshot brightness-up brightness-down ]); programs.fish = { enable = true; }; programs.swaylock = { enable = true; package = pkgs.swaylock-effects; settings = { clock = true; screenshots = true; effect-scale = 0.5; effect-blur = "10x10"; }; }; services.swayidle.enable = true; services.swayidle.systemdTarget = "graphical-session.target"; services.swayidle.events = [ { event = "before-sleep"; command = "${pkgs.swaylock-effects}/bin/swaylock"; } { event = "lock"; command = "${pkgs.swaylock-effects}/bin/swaylock"; } ]; services.swayidle.timeouts = [ { timeout = 60; command = "${pkgs.swaylock-effects}/bin/swaylock -f"; } ]; wayland.windowManager.hyprland = { enable = true; systemdIntegration = true; # https://wiki.hyprland.org/Configuring/Variables/ extraConfig = '' ## global hyprland configuration env = GDK_BACKEND,wayland,x11 env = QT_QPA_PLATFORM,wayland;xcb env = SDL_VIDEODRIVER,wayland env = CLUTTER_BACKEND,wayland env = XDG_CURRENT_DESKTOP,Hyprland env = XDG_SESSION_TYPE,wayland env = XDG_SESSION_DESKTOP,Hyprland env = QT_AUTO_SCREEN_SCALE_FACTOR,1 env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1 env = NIXOS_OZONE_WL,1 input { kb_layout = gb kb_options = caps:escape touchpad { natural_scroll = yes scroll_factor = 0.5 } } bind = SUPER, RETURN, exec, ${ my-deps.terminal } bind = SUPER_SHIFT, Q, killactive, bind = SUPER_SHIFT, E, exit, bind = SUPER, d, exec, wofi --show drun bind = SUPER, Z, exec, "${pkgs.swaylock-effects}/bin/swaylock" -f bind = SUPER, M, exec, ${ my-deps.terminal } -e ncmpcpp bind = SUPER, E, exec, ${ my-deps.terminal } -e neomutt bind = SUPER, O, exec, pcmanfm bind = SUPER, h, movefocus,l bind = SUPER, l, movefocus,r bindm = SUPER, mouse:272, movewindow bindm = SUPER, mouse:273, resizewindow bind = SUPER, j, layoutmsg,cyclenext bind = SUPER, k, layoutmsg,cycleprev bind = SUPER, space, layoutmsg,swapwithmaster master bind = SUPER, F, fullscreen, bind = SUPER, V, togglefloating, bind = SUPER_SHIFT, V, togglegroup, bind = SUPER_SHIFT, space, changegroupactive,n bind = SUPER_SHIFT, P, exec,${ my-scripts.bwmenu }/bin/bwmenu bind = SUPER_SHIFT, S, exec,${ my-scripts.screenshot }/bin/screenshot bind =,XF86AudioRaiseVolume, exec,${ my-deps.amixer } sset Master 5%+ && ${ my-deps.amixer } sset Master unmute bind =,XF86AudioLowerVolume, exec,${ my-deps.amixer } sset Master 5%- bind =,XF86AudioPlay, exec,${ my-scripts.play-pause }/bin/play-pause bind =,XF86AudioNext, exec,${ my-deps.playerctl } next bind =,XF86AudioPrev, exec,${ my-deps.playerctl } previous bind =,XF86MonBrightnessUp, exec,${ my-scripts.brightness-up }/bin/brightness-up bind =,XF86MonBrightnessDown, exec,${ my-scripts.brightness-down }/bin/brightness-down bind = SUPER,1,workspace,1 bind = SUPER,2,workspace,2 bind = SUPER,3,workspace,3 bind = SUPER,4,workspace,4 bind = SUPER,5,workspace,5 bind = SUPER,6,workspace,6 bind = SUPER,7,workspace,7 bind = SUPER,8,workspace,8 bind = SUPER,9,workspace,9 bind = SUPER,0,workspace,10 bind = SUPER_SHIFT,1,movetoworkspace,1 bind = SUPER_SHIFT,2,movetoworkspace,2 bind = SUPER_SHIFT,3,movetoworkspace,3 bind = SUPER_SHIFT,4,movetoworkspace,4 bind = SUPER_SHIFT,5,movetoworkspace,5 bind = SUPER_SHIFT,6,movetoworkspace,6 bind = SUPER_SHIFT,7,movetoworkspace,7 bind = SUPER_SHIFT,8,movetoworkspace,8 bind = SUPER_SHIFT,9,movetoworkspace,9 bind = SUPER_SHIFT,0,movetoworkspace,10 gestures { workspace_swipe = yes } decoration { rounding = 5 blur = 0 } bezier=overshot, 0.05, 0.9, 0.1, 1.1 animations { enabled = 1 animation = windows, 1, 5, default animation = border, 1, 5, default animation = fade, 1, 10,default animation = workspaces, 1, 3, overshot } general { resize_on_border = yes layout = master } ''; }; programs.waybar.enable = true; programs.waybar.settings = { mainBar = { layer = "top"; position = "top"; height = 36; modules-left = [ "hyprland/window" ]; modules-right = [ "mpris" "pulseaudio" "clock" "tray" "battery" ]; clock = { format = "πŸ“… {:%a %b-%d %I:%M %p}"; }; pulseaudio = { format-muted = "πŸ”‡ {volume}%"; format = "{icon} {volume}"; format-icons.default = [ "πŸ”ˆ" "πŸ”‰" "πŸ”Š" ]; on-click = "${pkgs.pavucontrol}/bin/pavucontrol"; }; mpris = { format = "{player_icon} {title}"; format-paused = "{status_icon} {title}"; player-icons = { default = "▢️"; mpv = "🎡"; }; status-icons = { paused = "⏸️"; }; on-click = "${my-scripts.play-pause}/bin/play-pause"; }; battery = { format = "{icon} {capacity}%"; format-icons = [ "🀏" "πŸͺ«" "πŸ”‹" ]; states = { warning = 30; critical = 15; }; }; }; }; programs.waybar.systemd = { enable = true; target = "hyprland-session.target"; }; services.udiskie = { enable = true; notify = true; }; gtk = { enable = true; theme = { name = "Materia-dark"; package = pkgs.materia-theme; }; iconTheme = { name = "Vimix-Doder"; package = pkgs.vimix-icon-theme; }; cursorTheme = { name = "Vanilla-DMZ"; package = pkgs.vanilla-dmz; size = 24; }; gtk3.bookmarks = [ "file:///home/tristan/Documents" "file:///home/tristan/Pictures/Screenshots" ]; }; services.mako = { enable = true; }; programs.ncmpcpp = { enable = true; settings.mpd_host = "music.local"; bindings = [ { key = "j"; command = "scroll_down"; } { key = "k"; command = "scroll_up"; } { key = "l"; command = "next_column"; } { key = "h"; command = "previous_column"; } { key = "J"; command = [ "select_item" "scroll_down" ]; } { key = "K"; command = [ "select_item" "scroll_up" ]; } ]; }; services.mpd-mpris.enable = true; services.mpd-mpris.mpd = { host = "music.local"; }; programs.mpv.enable = true; programs.mpv.bindings = { l = "seek 5"; h = "seek -5"; e = "add chapter 1"; b = "add chapter -1"; ">" = "multiply speed 1.1"; "<" = "multiply speed 1/1.1"; "." = "frame-step"; "," = "frame-back-step"; "ctrl+n" = "playlist-next"; "ctrl+p" = "playlist-prev"; k = "add volume 2"; j = "add volume -2"; m = "cycle mute"; c = "cycle sub-visibility"; }; programs.mpv.scripts = [ pkgs.mpvScripts.mpris ]; programs.foot.enable = true; programs.foot.server.enable = true; programs.foot.settings = { main = { term = "xterm-256color"; font = "mono:size=12"; }; colors = { foreground = "abb2bf"; background = "282c34"; regular0 = "222222"; regular1 = "eb3a26"; regular2 = "7fbc59"; regular3 = "e9db65"; regular4 = "4781d1"; regular5 = "7d74bb"; regular6 = "50a2bd"; regular7 = "dcdccc"; bright0 = "666666"; bright1 = "e15d4e"; bright2 = "8fbd73"; bright3 = "e3d97e"; bright4 = "6791ce"; bright5 = "8f88be"; bright6 = "6caabf"; bright7 = "ffffff"; }; }; programs.vscode = { enable = true; package = pkgs.vscodium; extensions = with pkgs; [ vscode-extensions.asvetliakov.vscode-neovim vscode-extensions.jnoortheen.nix-ide ]; userSettings = { "vscode-neovim.neovimExecutablePaths.linux" = "/run/current-system/sw/bin/nvim"; "keyboard.dispatch" = "keyCode"; }; }; programs.rbw = { enable = true; settings = { email = "tristan@tristans.cloud"; base_url = "https://vault.tristans.cloud"; }; }; programs.ssh.enable = true; programs.ssh.matchBlocks = { "git.tristans.cloud" = { user = "git"; port = 2222; }; }; programs.neovim.defaultEditor = true; programs.lf.enable = true; programs.lf.package = lf-sixel; programs.lf.keybindings = { D = "trash"; "" = ":rename"; "" = "open-with"; }; programs.lf.commands = { trash = "%${pkgs.trash-cli}/bin/trash-put \"$fx\""; open-with = ''''${{ set -f ${pkgs.ranger}/bin/rifle -l $fx read -p "Open with: " method ${pkgs.ranger}/bin/rifle -p $method $fx }}''; bulk-rename = ''''${{ old="$(mktemp)" new="$(mktemp)" if [ -n "$fs" ]; then fs="$(basename -a $fs)" else fs="$(ls)" fi printf '%s\n' "$fs" >"$old" printf '%s\n' "$fs" >"$new" $EDITOR "$new" [ "$(wc -l < "$new")" -ne "$(wc -l < "$old")" ] && exit paste "$old" "$new" | while IFS= read -r names; do src="$(printf '%s' "$names" | cut -f1)" dst="$(printf '%s' "$names" | cut -f2)" if [ "$src" = "$dst" ] || [ -e "$dst" ]; then continue fi mv -- "$src" "$dst" done rm -- "$old" "$new" lf -remote "send $id unselect" }}''; }; programs.lf.previewer.source = pkgs.writeShellScript "preview" '' image () { ${my-deps.chafa} "$1" -f sixel -s "$(($2/2))x$3" | sed 's/#/\n#/g' ${ my-deps.exiftool } "$1" } batted () { cat "$@" } CACHE="$HOME/.cache/lf/thumbnail.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | awk '{print $1}'))" case "$(printf "%s\n" "$(readlink -f "$1")" | awk '{print tolower($0)}')" in *.tgz|*.tar.gz) tar tzf "$1" ;; *.tar.bz2|*.tbz2) tar tjf "$1" ;; *.tar.txz|*.txz) xz --list "$1" ;; *.tar) tar tf "$1" ;; *.zip|*.jar|*.war|*.ear|*.oxt) unzip -l "$1" ;; *.rar) unrar l "$1" ;; *.md) glow -s dark "$1" ;; *.7z) 7z l "$1" ;; *.[1-8]) man "$1" | col -b ;; *.o) nm "$1";; *.torrent) transmission-show "$1" ;; *.iso) iso-info --no-header -l "$1" ;; *.odt|*.ods|*.odp|*.sxw) odt2txt "$1" ;; *.doc) catdoc "$1" ;; *.docx) docx2txt "$1" - ;; *.xml|*.html) w3m -dump "$1";; *.xls|*.xlsx) ssconvert --export-type=Gnumeric_stf:stf_csv "$1" "fd://1" | batted --language=csv ;; *.wav|*.mp3|*.flac|*.m4a|*.wma|*.ape|*.ac3|*.og[agx]|*.spx|*.opus|*.as[fx]|*.mka) ${ my-deps.exiftool } "$1" ;; *.pdf) [ ! -f "$CACHE.jpg" ] && \ pdftoppm -jpeg -f 1 -singlefile "$1" "$CACHE" image "$CACHE.jpg" "$2" "$3" "$4" "$5" ;; *.epub) [ ! -f "$CACHE" ] && \ epub-thumbnailer "$1" "$CACHE" 1024 image "$CACHE" "$2" "$3" "$4" "$5" ;; *.cbz|*.cbr|*.cbt) [ ! -f "$CACHE" ] && \ comicthumb "$1" "$CACHE" 1024 image "$CACHE" "$2" "$3" "$4" "$5" ;; *.avi|*.mp4|*.wmv|*.dat|*.3gp|*.ogv|*.mkv|*.mpg|*.mpeg|*.vob|*.fl[icv]|*.m2v|*.mov|*.webm|*.ts|*.mts|*.m4v|*.r[am]|*.qt|*.divx) [ ! -f "$CACHE.jpg" ] && \ ffmpegthumbnailer -i "$1" -o "$CACHE.jpg" -s 0 -q 5 image "$CACHE.jpg" "$2" "$3" "$4" "$5" ;; *.bmp|*.jpg|*.jpeg|*.png|*.xpm|*.webp|*.gif|*.jfif) image "$1" "$2" "$3" "$4" "$5" ;; *.svg) [ ! -f "$CACHE.jpg" ] && \ convert "$1" "$CACHE.jpg" image "$CACHE.jpg" "$2" "$3" "$4" "$5" ;; *.ino) batted --language=cpp "$1" ;; *) batted "$1" ;; esac ''; home.file.".config/wofi/config".text = '' term=foot ''; home.file.".icons/default".source = "${pkgs.vanilla-dmz}/share/icons/Vanilla-DMZ"; programs.librewolf.enable = true; programs.git = { enable = true; aliases = { graph = "log --oneline --all --graph"; amend = "commit --amend --no-edit"; }; }; programs.helix = { enable = true; languages = [ { name = "nix"; auto-format = true; language-server = { command = "${pkgs.rnix-lsp}/bin/rnix-lsp"; }; } ]; }; programs.neomutt.extraConfig = '' # Default index colors: color index yellow default '.*' color index_author red default '.*' color index_number blue default color index_subject cyan default '.*' # New mail is boldened: color index brightyellow black "~N" color index_author brightred black "~N" color index_subject brightcyan black "~N" # Tagged mail is highlighted: color index brightyellow blue "~T" color index_author brightred blue "~T" color index_subject brightcyan blue "~T" # Other colors and aesthetic settings: mono bold bold mono underline underline mono indicator reverse mono error bold color normal default default color indicator brightblack white color sidebar_highlight red default color sidebar_divider brightblack black color sidebar_flagged red black color sidebar_new green black color normal brightyellow default color error red default color tilde black default color message cyan default color markers red white color attachment white default color search brightmagenta default color status brightyellow black color hdrdefault brightgreen default color quoted green default color quoted1 blue default color quoted2 cyan default color quoted3 yellow default color quoted4 red default color quoted5 brightred default color signature brightgreen default color bold black default color underline black default color normal default default # Regex highlighting: color header blue default ".*" color header brightmagenta default "^(From)" color header brightcyan default "^(Subject)" color header brightwhite default "^(CC|BCC)" color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL color body green default "\`[^\`]*\`" # Green text between ` and ` color body brightblue default "^# \.*" # Headings as bold blue color body brightcyan default "^## \.*" # Subheadings as bold cyan color body brightgreen default "^### \.*" # Subsubheadings as bold green color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow color body brightcyan default "[;:][-o][)/(|]" # emoticons color body brightcyan default "[;:][)(|]" # emoticons color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon? color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon? color body red default "(BAD signature)" color body cyan default "(Good signature)" color body brightblack default "^gpg: Good signature .*" color body brightyellow default "^gpg: " color body brightyellow red "^gpg: BAD signature from.*" mono body bold "^gpg: Good signature" mono body bold "^gpg: BAD signature from.*" color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]" ''; programs.aerc.extraBinds = '' # Binds are of the form = # To use '=' in a key sequence, substitute it with "Eq": "" # If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit = :prev-tab = :next-tab = :term [messages] Q = :quit T = :toggle-threads j = :next = :next = :next 50% = :next 100% = :next -s 100% k = :prev = :prev = :prev 50% = :prev = :prev -s 100% gg = :select 0 G = :select -1 J = :next-folder K = :prev-folder v = :mark -t V = :mark -v f = :flag F = :unflag t = :toggle-threads = :view D = :delete C = :compose Rr = :reply Rq = :reply -q rr = :reply -a rq = :reply -aq rt = :unflag:reply -a -Tthanks Rt = :unflag:reply -qa -Tquoted_thanks a = :mv Archive c = :cf $ = :term ! = :term | = :pipe ga = :flag:pipe -mb git am -3 gp = :term git push gl = :term git log / = :search \ = :filter n = :next-result N = :prev-result [view] / = :toggle-key-passthrough/ q = :close | = :pipe -m S = :save H = :toggle-headers D = :delete = :prev-part = :next-part J = :next K = :prev f = :forward Rr = :reply Rq = :reply -q rr = :reply -a rq = :reply -aq rt = :reply -Tthanks ga = :pipe -b git am -3 gp = :term git push gl = :term git log [view::passthrough] $noinherit = true $ex = = :toggle-key-passthrough [compose] $ex = = :prev-field = :next-field = :next-field [compose::editor] # Keybindings used when the embedded terminal is selected in the compose view $noinherit = true $ex = = :term = :prev-field = :next-field = :prev-tab = :next-tab [compose::review] # Keybindings used when reviewing a message to be sent y = :send n = :abort e = :edit a = :attach c = :encrypt s = :sign V = :header -f X-Sourcehut-Patchset-Update NEEDS_REVISION A = :header -f X-Sourcehut-Patchset-Update APPLIED R = :header -f X-Sourcehut-Patchset-Update REJECTED [terminal] $noinherit = true $ex = = :term = :prev-tab = :next-tab ''; programs.aerc.extraConfig = { general = { pgp-provider = "gpg"; unsafe-accounts-conf = true; }; ui = { }; viewer = { }; filters = { "text/plain" = "colorize"; "text/calendar" = "calendar"; "message/delivery-status" = "colorize"; "message/rfc822" = "colorize"; "image/*" = "img2sixel"; "text/html" = "html | colorize"; }; }; home.file.".config/pipewire/pipewire.conf.d/raop-discover.conf".text = '' context.modules = [ { name = libpipewire-module-raop-discover args = { } } ] ''; home.file.".config/pipewire/pipewire.conf.d/tunnel.conf".text = '' context.modules = [ { name = module-native-protocol-tcp }, { name = module-zeroconf-publish }, { name = module-zeroconf-discover } ] ''; systemd.user.services = { snapclient = { Unit = { Description = "Snapclient"; }; Service = { ExecStart = "${pkgs.snapcast}/bin/snapclient -h music.local"; }; }; }; services.kdeconnect = { enable = true; indicator = true; }; }