{ config, lib, pkgs, ... }: let # Module host = config.host; # Resources palette = import ./resources/palette.nix; words = builtins.toFile "words" ( (builtins.readFile ./resources/words.txt) + (builtins.readFile (host.local + "/resources/words.txt")) ); # Packages add-words = pkgs.callPackage ../packages/add-words.nix { }; gh = pkgs.callPackage ../packages/gh.nix { }; git-diff-image = pkgs.callPackage ../packages/git-diff-image.nix { }; gopass-await = pkgs.callPackage ../packages/gopass-await.nix { inherit (pkgs.gnome) zenity; }; iosevka-custom = pkgs.callPackage ../packages/iosevka-custom.nix { }; mozjpeg-simple = pkgs.callPackage ../packages/mozjpeg-simple.nix { }; off = pkgs.callPackage ../packages/off.nix { }; zsh-abbr = pkgs.callPackage ../packages/zsh-abbr.nix { }; zsh-click = pkgs.callPackage ../packages/zsh-click.nix { }; in { imports = [ ../packages/organize-downloads.nix ./local/home.nix ]; options.host = { firefoxProfile = lib.mkOption { type = lib.types.str; }; local = lib.mkOption { type = lib.types.path; }; }; config = { nixpkgs.overlays = [ (import ./unstable.nix) (_: pkgs: { vscodium = pkgs.vscodium.overrideAttrs (a: { preFixup = a.preFixup + '' gappsWrapperArgs+=( --unset NIXOS_OZONE_WL ) ''; }); }) ]; # Home manager programs.home-manager.enable = true; nixpkgs.config.allowUnfree = true; manual.html.enable = true; home.username = "ak"; home.homeDirectory = "/home/ak"; # User home.file.".face".source = ./resources/andrew.jpg; xdg.configFile."Yubico/u2f_keys".source = host.local + "/resources/andrew.u2f"; # Keyboard home.file.".XCompose" = { onChange = "rm -rfv /home/ak/.cache/gtk-3.0/compose"; text = (builtins.readFile ./resources/Compose) + (builtins.readFile (host.local + "/resources/Compose")); }; # Services services.gpg-agent = { enable = true; enableSshSupport = true; }; systemd.user.services.yubikey-touch-detector = { Install.WantedBy = [ "graphical-session.target" ]; Unit.Description = "YubiKey touch detector"; Service.ExecStart = "${pkgs.yubikey-touch-detector}/bin/yubikey-touch-detector --libnotify"; }; # Applications home.packages = with pkgs; [ add-words corefonts darktable delta dnsutils exiftool fd file firefox-wayland gh gimp-with-plugins git-diff-image git-filter-repo gnome.gnome-tweaks gnomeExtensions.appindicator gnomeExtensions.system-monitor gnomeExtensions.tiling-assistant google-fonts # If removed, add `roboto` gopass htop httpie imagemagickBig inkscape iosevka-custom.mono iosevka-custom.proportional iosevka-custom.term killall libqalculate # Used by VS code extension theaflowers.qalc lsof magic-wormhole moreutils mozjpeg-simple mtr multitail ncdu nix-top nix-tree nixpkgs-fmt nixpkgs-review off pngtools pup pwgen qalculate-gtk ripgrep rsync shellcheck nodePackages.svgo sqlitebrowser tig trash-cli v4l-utils virt-manager visidata whois xorg.xev yaru-theme yq ]; fonts.fontconfig.enable = true; programs = { bat.enable = true; direnv = { enable = true; nix-direnv.enable = true; config.global.warn_timeout = "5m"; stdlib = '' use_gopass() { eval "$(${gopass-await}/bin/gopass-await "$@")" } ''; }; exa = { enable = true; enableAliases = true; }; fzf = rec { enable = true; enableZshIntegration = true; defaultOptions = [ "--height 33%" "--reverse" ]; defaultCommand = "fd --one-file-system --type file"; # --no-ignore-parent pending https://github.com/sharkdp/fd/pull/817 (fd v9) fileWidgetCommand = defaultCommand; changeDirWidgetCommand = "fd --one-file-system --type directory"; # --no-ignore-parent pending https://github.com/sharkdp/fd/pull/817 (fd v9) }; git = { enable = true; aliases = { ff = "merge --ff-only"; diff-image = "!f() { cd -- \"\${GIT_PREFIX:-.}\"; GIT_DIFF_IMAGE_ENABLED=1 git diff \"$@\"; }; f"; kitty = "difftool --tool=kitty --no-symlinks --dir-diff"; puff = "pull --ff-only"; recent = "!git --no-pager log --max-count 8 --pretty=tformat:\"%w($(tput cols),0,8)%C(cyan)%h%Creset %C(yellow)%cr:%C(magenta)%d%Creset %s\""; }; attributes = [ "*.gif diff=image" "*.jpg diff=image" "*.png diff=image" ]; delta = { enable = true; options = { file-renamed-label = "moved:"; line-numbers-left-format = "{nm:>1} "; line-numbers-left-style = "#444444"; line-numbers-minus-style = "#872843 bold"; line-numbers-plus-style = "#5c7b2a bold"; line-numbers-right-format = "{np:>1}▐"; line-numbers-right-style = "#444444"; line-numbers-zero-style = "#444444 bold"; minus-emph-style = "#827c7d #42282d"; minus-empty-line-marker-style = "normal #42282d"; minus-non-emph-style = "#444444"; minus-style = "#827c7d #42282d"; plus-emph-style = "syntax #343e28"; plus-empty-line-marker-style = "normal #343e28"; plus-non-emph-style = "syntax"; plus-style = "syntax #343e28"; syntax-theme = "Monokai Extended"; whitespace-error-style = "reverse white"; full = { file-style = "white bold"; file-decoration-style = "omit"; hunk-header-style = "omit"; line-numbers = true; }; }; }; signing.key = "0x9254D45940949194"; extraConfig = { core.autocrlf = "input"; diff.algorithm = "histogram"; init.defaultBranch = "main"; merge.commit = false; merge.conflictStyle = "zdiff3"; push.followTags = true; diff.image.command = "${git-diff-image}/bin/git_diff_image"; difftool = { prompt = false; trustExitCode = true; }; "difftool \"kitty\"".cmd = "kitty +kitten diff $LOCAL $REMOTE"; tig = { line-graphics = "utf-8"; main-view-date = "custom"; main-view-date-format = "%F %H:%M"; main-view-id-display = true; show-changes = false; tab-size = 4; truncation-delimiter = "utf-8"; vertical-split = false; color = (builtins.listToAttrs (map (n: lib.nameValuePair "palette-${toString n}" "color8 default") (lib.range 0 13))) // { author = "color8 default"; cursor = "black magenta bold"; graph-commit = "magenta default"; date = "yellow default"; id = "cyan default"; main-head = "magenta default bold"; main-local-tag = "green default"; main-ref = "magenta default"; main-remote = "blue default"; main-tag = "green default"; main-tracked = "blue default bold"; search-result = "black white bold"; title-blur = "white black"; title-focus = "white black bold"; }; }; }; ignores = [ ".direnv/" ".envrc" ".envrc.gemset.nix" ".envrc.nix" ".vscode/" ]; iniContent.core.pager = lib.mkForce "${pkgs.delta}/bin/delta --color-only --features full"; # Set feature userName = "Andrew Kvalheim"; userEmail = "Andrew@Kvalhe.im"; }; gpg = { enable = true; settings = { default-key = "0x9254D45940949194"; keyid-format = "0xlong"; no-greeting = true; no-symkey-cache = true; throw-keyids = true; }; }; jq.enable = true; kitty = { enable = true; font = { package = iosevka-custom.term; name = "Iosevka Custom Term"; size = 11; }; keybindings = { "shift+left" = "previous_tab"; "ctrl+shift+left" = "move_tab_backward"; "shift+right" = "next_tab"; "ctrl+shift+right" = "move_tab_forward"; "shift+down" = "previous_window"; "ctrl+shift+up" = "move_window_backward"; "shift+up" = "next_window"; "ctrl+shift+down" = "move_window_forward"; "alt+down" = "resize_window shorter"; "alt+up" = "resize_window taller"; }; settings = with palette; { # Mouse click_interval = "0.25"; focus_follows_mouse = "yes"; mouse_hide_wait = "0"; select_by_word_characters = "-_?&%+#"; # Windows hide_window_decorations = true; scrollback_lines = "16384"; enabled_layouts = "vertical, horizontal"; # Workaround for https://github.com/kovidgoyal/kitty/issues/3180 touch_scroll_multiplier = "10"; # Sounds enable_audio_bell = "no"; # Font bold_font = "Iosevka Custom Term Bold"; italic_font = "Iosevka Custom Term Italic"; bold_italic_font = "Iosevka Custom Term Bold Italic"; active_tab_font_style = "bold"; inactive_tab_font_style = "bold"; # Cursor cursor_shape = "beam"; # URLs url_style = "single"; # Colors wayland_titlebar_color = black; foreground = white; background = black; cursor = orange; url_color = white; active_border_color = dark-gray; inactive_border_color = dark-gray; bell_border_color = red; active_tab_foreground = white; active_tab_background = dark-gray; inactive_tab_foreground = gray; inactive_tab_background = dark-gray; selection_foreground = black; selection_background = orange; color0 = dark-gray; color1 = red; color2 = green; color3 = yellow; color4 = blue; color5 = orange; color6 = purple; color7 = white; color8 = gray; color9 = red; color10 = green; color11 = yellow; color12 = blue; color13 = orange; color14 = purple; color15 = white; }; }; ssh = { enable = true; includes = [ "config.d/*" ]; extraOptionOverrides = { GSSAPIAuthentication = "no"; PreferredAuthentications = "publickey"; }; }; vscode = { enable = true; package = pkgs.vscodium; userSettings = import ./resources/vscode.nix { inherit lib; inherit words; }; keybindings = [ { key = "ctrl+j"; command = "-workbench.action.togglePanel"; } { key = "ctrl+j"; command = "editor.action.joinLines"; } { key = "shift+alt+m"; command = "editor.emmet.action.wrapWithAbbreviation"; } { key = "shift+alt+down"; command = "-editor.action.insertCursorBelow"; } { key = "shift+alt+down"; command = "editor.action.copyLinesDownAction"; } { key = "shift+alt+up"; command = "-editor.action.insertCursorAbove"; } { key = "shift+alt+up"; command = "editor.action.copyLinesUpAction"; } { key = "ctrl+k i"; command = "editor.action.formatChanges"; } ]; }; zsh = { enable = true; autocd = false; history = { path = "$HOME/akorg/resource/zsh-history"; expireDuplicatesFirst = true; extended = true; ignoreDups = false; ignoreSpace = true; save = 100000000; size = 1000000000; }; sessionVariables = { HIST_STAMPS = "yyyy-mm-dd"; REPORTTIME = 10; WORDCHARS = "_.~;!#$%^"; }; initExtra = with pkgs; '' setopt HIST_FIND_NO_DUPS setopt NOCLOBBER setopt PUSHD_SILENT export DIRENV_LOG_FORMAT="$(print -P "%B%F{8}┃ %%s%f")" TIMEFMT="$(print -P "%B%F{8}┃ Duration: %%*Es, CPU: %%P, Memory: %%MkB%f")" ZSH_HIGHLIGHT_REGEXP+=('^[[:blank:][:space:]]*(''\'''${(j:|:)''${(k)ABBR_REGULAR_USER_ABBREVIATIONS}}')$' 'fg=blue,bold') git() { if [[ "$1" == 'checkout' ]]; then echo 'Reminder: Use `git switch` or `git restore` instead.' >&2 command git "$@" elif [[ "$1" == 'clone' && "$2" =~ '^https://(github\.com|gitlab\.com)/([^/]+)/[^/]+' ]]; then shift echo "Detected origin name ''\'''${match[2]}'" >&2 command git clone --origin "''${match[2]}" "$@" else command git "$@" fi } rd() { diff --recursive --unified "$@" | delta } rdw() { diff --ignore-all-space --recursive --unified "$@" | delta } [[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh ''; shellAliases = (builtins.listToAttrs (map (c: lib.nameValuePair c "noglob ${c}") [ "git" "http" "youtube-dl" ])) // { cat = "bat --plain"; cp = "cp --reflink=auto"; code = "codium"; e = "exa --all --group-directories-first --long --header --time-style long-iso"; icat = "kitty +kitten icat"; mv = "mv --no-clobber --verbose"; p = "gopass"; rm = "rm --one-file-system --verbose"; watch = "watch --color"; }; prezto = { enable = true; pmoduleDirs = [ "${zsh-abbr}/share/zsh/plugins" "${zsh-click}/share/zsh/plugins" ]; pmodules = [ "environment" "terminal" "spectrum" "completion" "syntax-highlighting" "history-substring-search" "prompt" "git" "zsh-abbr" "click" ]; prompt.theme = "powerlevel10k"; syntaxHighlighting.highlighters = [ "main" "regexp" ]; syntaxHighlighting.styles = { arg0 = "fg=white,bold"; precommand = "fg=white,italic"; reserved-word = "fg=blue"; }; terminal = { autoTitle = true; multiplexerTitleFormat = "%1~"; tabTitleFormat = "%1~"; windowTitleFormat = "%1~"; }; extraConfig = '' zstyle ':prezto:module:git:alias' skip 'yes' ''; }; }; }; home.file.".mozilla/firefox/${host.firefoxProfile}/chrome/userChrome.css".source = ./resources/userChrome.css; home.file.".mozilla/firefox/${host.firefoxProfile}/user.js".source = ./resources/user.js; home.file.".visidatarc".text = '' options.clipboard_copy_cmd = '${pkgs.wl-clipboard}/bin/wl-copy' options.clipboard_paste_cmd = '${pkgs.wl-clipboard}/bin/wl-paste --no-newline' ''; # File type associations xdg.mimeApps = { enable = true; associations.added = { # Pending https://github.com/darktable-org/darktable/pull/12218 "image/heif" = [ "darktable-heif.desktop" ]; }; defaultApplications = { # Archive "application/zip" = "org.gnome.FileRoller.desktop"; # Document "application/pdf" = "org.gnome.Evince.desktop"; "application/vnd.openxmlformats-officedocument.wordprocessingml.document" = "writer.desktop"; # Image "image/heif" = "org.gnome.eog.desktop"; "image/jpeg" = "org.gnome.eog.desktop"; "image/png" = "org.gnome.eog.desktop"; "image/svg+xml" = "org.gnome.eog.desktop"; "image/tiff" = "org.gnome.eog.desktop"; # Text "application/gpx+xml" = "codium.desktop"; "application/json" = "codium.desktop"; "application/xml" = "codium.desktop"; "text/markdown" = "codium.desktop"; "text/plain" = "codium.desktop"; # Web "application/xhtml+xml" = "firefox.desktop"; "text/html" = "firefox.desktop"; "x-scheme-handler/http" = "firefox.desktop"; "x-scheme-handler/https" = "firefox.desktop"; }; }; xdg.configFile."mimeapps.list".force = true; # Workaround for nix-community/home-manager#1213 # Spell check home.file.".hunspell_en_US".source = words; home.file.".mozilla/firefox/${host.firefoxProfile}/persdict.dat".source = words; home.file.".cspell.json".text = builtins.toJSON { dictionaries = [ "custom" ]; dictionaryDefinitions = [{ name = "custom"; path = words; }]; enableFiletypes = [ "haml" "nix" "ruby" "shellscript" ]; }; # Environment home.sessionVariables = rec { ANSIBLE_NOCOWS = true; EDITOR = "${pkgs.vscodium}/bin/codium --wait"; EXA_COLORS = lib.concatStringsSep ":" (lib.attrsets.mapAttrsToList (k: v: "${k}=${v}") { ur = "2;37"; # the user-read permission bit uw = "2;37"; # the user-write permission bit ux = "1;32"; # the user-execute permission bit for regular files ue = "1;32"; # the user-execute for other file kinds gr = "2;37"; # the group-read permission bit gw = "2;37"; # the group-write permission bit gx = "2;37"; # the group-execute permission bit tr = "1;35"; # the others-read permission bit tw = "1;31"; # the others-write permission bit tx = "2;37"; # the others-execute permission bit su = "1;33"; # setuid, setgid, and sticky permission bits for files sf = "1;33"; # setuid, setgid, and sticky for other file kinds xa = "1;33"; # the extended attribute indicator sn = "2;37"; # the numbers of a file’s size ub = "1;37"; # the units of a file’s size if it is lower than 1 KB/Kib uk = "1;34"; # the units of a file’s size if it is between 1 KB/KiB and 1 MB/MiB um = "1;33"; # the units of a file’s size if it is between 1 MB/MiB and 1 GB/GiB ug = "1;31"; # the units of a file’s size if it is between 1 GB/GiB and 1 TB/TiB ut = "1;31"; # the units of a file’s size if it is 1 TB/TiB or higher uu = "30"; # a user that’s you un = "31"; # a user that’s someone else gu = "30"; # a group that you belong to gn = "31"; # a group you aren’t a member of da = "2;3;37"; # a file’s date lp = "2;37"; # the path of a symlink cc = "1;33"; # an escaped character in a filename }); LS_COLORS = lib.concatStringsSep ":" (lib.attrsets.mapAttrsToList (k: v: "${k}=${v}") { di = "1;36"; # directories ex = "32"; # executable files fi = "37"; # regular files pi = "3;34"; # named pipes so = "3;34"; # sockets bd = "1;34"; # block devices cd = "1;34"; # character devices ln = "35"; # symlinks or = "31"; # symlinks with no target }); NIXOS_OZONE_WL = "1"; VISUAL = EDITOR; }; xdg.configFile."zsh/abbreviations".text = '' abbr a='git add --patch' abbr b="git switch --create" abbr c="git commit" abbr d="git diff ':!*.lock'" abbr ds="git diff --staged ':!*.lock'" abbr dsw="git diff --staged --ignore-all-space ':!*.lock'" abbr dw="git diff --ignore-all-space ':!*.lock'" abbr et="e --tree" abbr gf="git fetch --all --jobs 4 --prune" abbr gff="git fetch --all --jobs 4 --prune && git merge --ff-only" abbr h="tig --all" abbr rebase="git rebase --autostash --autosquash --interactive" abbr s="git status" abbr stash="git stash save --include-untracked" abbr undo="git restore --patch" ''; home.file.".npmrc".text = '' fund=false update-notifier=false ''; home.file.".p10k.zsh".source = ./resources/p10k.zsh; # Workaround for https://github.com/NixOS/nixpkgs/issues/101616 home.file."${config.xdg.configHome}/autostart/gnome-keyring-ssh.desktop".text = '' [Desktop Entry] Type=Application Name=SSH Key Agent Hidden=true ''; home.file."${config.xdg.configHome}/autostart/disabled-extensions-notification.desktop".text = '' [Desktop Entry] Type=Application Name=Disabled Extensions Notification NoDisplay=true Exec=${pkgs.writeShellScript "disabled-extensions-notification" '' [[ "$(gsettings get org.gnome.shell disable-user-extensions)" == 'true' ]] || exit case "$(${pkgs.libnotify}/bin/notify-send --urgency 'critical' --icon 'extensions' \ 'Extensions have been automatically disabled.' \ --action 'enable=Re-Enable' \ --action 'settings=Settings…')" \ in 'enable') gsettings set org.gnome.shell disable-user-extensions 'false';; 'settings') gnome-extensions-app & disown;; esac ''} ''; xdg.dataFile."nautilus/scripts/HEIF,PNG,TIFF → JPEG" = { executable = true; text = with pkgs; '' #!${bash}/bin/bash set -Eeuxo pipefail paths="$(sed /^$/d <<< "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS")" tr '\n' '\0' <<< "$paths" | xargs -0 -n 1 -P 8 nice ${mozjpeg-simple}/bin/mozjpeg ''; }; xdg.dataFile."nautilus/scripts/PNG: Optimize" = { executable = true; text = with pkgs; '' #!${bash}/bin/bash set -Eeuxo pipefail paths="$(sed /^$/d <<< "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS")" tr '\n' '\0' <<< "$paths" \ | xargs -0 nice ${efficient-compression-tool}/bin/ect -8 -keep -quiet --mt-file \ 2> >(${gnome.zenity}/bin/zenity --width 600 --progress --pulsate --auto-close --auto-kill) ''; }; xdg.dataFile."nautilus/scripts/PNG: Trim" = { executable = true; text = with pkgs; '' #!${bash}/bin/bash set -Eeuxo pipefail paths="$(sed /^$/d <<< "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS")" tr '\n' '\0' <<< "$paths" | xargs -0 -n 1 -P 8 nice ${imagemagick}/bin/mogrify -trim ''; }; }; }