summaryrefslogtreecommitdiff
path: root/modules/common
diff options
context:
space:
mode:
Diffstat (limited to 'modules/common')
-rw-r--r--modules/common/alacritty.nix116
-rw-r--r--modules/common/aria2.nix36
-rw-r--r--modules/common/bat.nix40
-rw-r--r--modules/common/beets.nix73
-rw-r--r--modules/common/chromium.nix27
-rw-r--r--modules/common/common/default.nix11
-rw-r--r--modules/common/common/documentation.nix28
-rw-r--r--modules/common/common/home-manager.nix24
-rw-r--r--modules/common/common/locale.nix6
-rw-r--r--modules/common/common/networking.nix3
-rw-r--r--modules/common/common/nix/default.nix163
-rw-r--r--modules/common/common/nix/patches/alejandra-no-ads.patch33
-rw-r--r--modules/common/common/shell/default.nix139
-rw-r--r--modules/common/common/shell/functions.bash73
-rw-r--r--modules/common/common/users.nix8
-rw-r--r--modules/common/curl.nix38
-rw-r--r--modules/common/default.nix29
-rw-r--r--modules/common/direnv.nix22
-rw-r--r--modules/common/emacs/default.nix163
-rw-r--r--modules/common/emacs/doom/config.el223
-rw-r--r--modules/common/emacs/doom/init.el119
-rw-r--r--modules/common/emacs/doom/packages.el17
-rw-r--r--modules/common/fonts.nix91
-rw-r--r--modules/common/git.nix117
-rw-r--r--modules/common/gnupg.nix58
-rw-r--r--modules/common/htop.nix57
-rw-r--r--modules/common/mpv.nix135
-rw-r--r--modules/common/nmap.nix84
-rw-r--r--modules/common/openconnect.nix83
-rw-r--r--modules/common/openssh.nix58
-rw-r--r--modules/common/password-store.nix33
-rw-r--r--modules/common/profiles/default.nix90
-rw-r--r--modules/common/profiles/dev/containers.nix76
-rw-r--r--modules/common/profiles/dev/default.nix89
-rw-r--r--modules/common/profiles/dev/editorconfig.ini83
-rw-r--r--modules/common/profiles/dev/gdbinit41
-rw-r--r--modules/common/profiles/dev/ghci.conf35
-rw-r--r--modules/common/profiles/dev/pystartup.py121
-rw-r--r--modules/common/profiles/dev/sql.nix101
-rw-r--r--modules/common/profiles/headful.nix107
-rw-r--r--modules/common/profiles/headless.nix23
-rw-r--r--modules/common/qutebrowser.nix536
-rw-r--r--modules/common/subversion.nix52
-rw-r--r--modules/common/tmux.nix60
-rw-r--r--modules/common/vim/default.nix50
-rw-r--r--modules/common/vim/rc.vim253
-rw-r--r--modules/common/vscode.nix167
-rw-r--r--modules/common/wget.nix35
-rw-r--r--modules/common/zathura.nix120
49 files changed, 4146 insertions, 0 deletions
diff --git a/modules/common/alacritty.nix b/modules/common/alacritty.nix
new file mode 100644
index 0000000..142f6c5
--- /dev/null
+++ b/modules/common/alacritty.nix
@@ -0,0 +1,116 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.alacritty;
+in {
+ options.nixfiles.modules.alacritty.enable =
+ mkEnableOption "Alacritty terminal emulator";
+
+ config = mkIf cfg.enable {
+ hm.programs.alacritty = {
+ enable = true;
+ settings = with config.nixfiles.modules; {
+ window = {
+ padding = with config.fontScheme.monospaceFont; {
+ x = size;
+ y = size;
+ };
+ dynamic_padding = false;
+ decorations = "full";
+ };
+ font = with config.fontScheme.monospaceFont; {
+ normal = {
+ inherit family;
+ style = "Regular";
+ };
+ bold = {
+ inherit family;
+ style = "Bold";
+ };
+ italic = {
+ inherit family;
+ style = "Italic";
+ };
+ bold_italic = {
+ inherit family;
+ style = "Bold Italic";
+ };
+ inherit size;
+ };
+ colors = with config.colourScheme; {
+ primary = {inherit background foreground;};
+ cursor = {
+ text = "CellBackground";
+ cursor = "CellForeground";
+ };
+ vi_mode_cursor = {
+ text = "CellBackground";
+ cursor = "CellForeground";
+ };
+ search = {
+ matches = {
+ foreground = white;
+ background = red;
+ };
+ focused_match = {
+ foreground = red;
+ background = black;
+ };
+ footer_bar = {
+ foreground = black;
+ background = white;
+ };
+ };
+ hints = {
+ start = {
+ foreground = black;
+ background = yellow;
+ };
+ end = {
+ foreground = yellow;
+ background = black;
+ };
+ line_indicator = {
+ foreground = null;
+ background = null;
+ };
+ selection = {
+ text = "CellBackground";
+ background = "CellForeground";
+ };
+ normal = {
+ inherit black red green yellow blue magenta cyan white;
+ };
+ bright = {
+ inherit
+ brightBlack
+ brightRed
+ brightGreen
+ brightYellow
+ brightBlue
+ brightMagenta
+ brightCyan
+ brightWhite
+ ;
+ };
+ };
+ };
+ bell = {
+ duration = 0;
+ command = null; # TODO notify-send?
+ };
+ cursor = {
+ style = {
+ shape = "Block";
+ blinking = "Off";
+ };
+ vi_mode_style = "Block";
+ };
+ selection.save_to_clipboard = true; # TODO autocutsel?
+ };
+ };
+ };
+}
diff --git a/modules/common/aria2.nix b/modules/common/aria2.nix
new file mode 100644
index 0000000..f33acb9
--- /dev/null
+++ b/modules/common/aria2.nix
@@ -0,0 +1,36 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.aria2;
+in {
+ options.nixfiles.modules.aria2.enable = mkEnableOption "aria2";
+
+ config = mkIf cfg.enable {
+ hm.programs.aria2 = {
+ enable = true;
+
+ settings = {
+ bt-max-peers = 128;
+ bt-save-metadata = true;
+ continue = true;
+ enable-dht = true;
+ enable-peer-exchange = true;
+ enable-rpc = false;
+ follow-torrent = true;
+ log-level = "info";
+ max-connection-per-server = 16;
+ max-overall-upload-limit = "1K";
+ max-tries = 5;
+ max-upload-limit = "1K";
+ seed-ratio = 0.1;
+ seed-time = 0.1;
+ stream-piece-selector = "default";
+ timeout = 60;
+ };
+ };
+ };
+}
diff --git a/modules/common/bat.nix b/modules/common/bat.nix
new file mode 100644
index 0000000..2b31d16
--- /dev/null
+++ b/modules/common/bat.nix
@@ -0,0 +1,40 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.bat;
+in {
+ options.nixfiles.modules.bat.enable =
+ mkEnableOption "bat, an alternative to cat";
+
+ config = mkIf cfg.enable {
+ hm.programs = {
+ bat = {
+ enable = true;
+ config = {
+ style = "plain";
+ tabs = "4";
+ theme = "base16";
+ wrap = "never";
+ };
+ };
+
+ bash = {
+ shellAliases = let
+ bat = "${pkgs.bat}/bin/bat";
+ in {
+ bay = "${bat} --language=yaml --tabs 2";
+ baj = "${bat} --language=json --tabs 2";
+ };
+
+ initExtra = mkAfter ''
+ _complete_alias bay _bat bat
+ _complete_alias baj _bat bat
+ '';
+ };
+ };
+ };
+}
diff --git a/modules/common/beets.nix b/modules/common/beets.nix
new file mode 100644
index 0000000..83cbff1
--- /dev/null
+++ b/modules/common/beets.nix
@@ -0,0 +1,73 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.beets;
+in {
+ options.nixfiles.modules.beets.enable =
+ mkEnableOption "beets";
+
+ config = mkIf cfg.enable {
+ hm = let
+ beetsdir = "${config.dirs.data}/beets";
+ in {
+ home.sessionVariables.BEETSDIR = beetsdir;
+
+ programs = {
+ beets = {
+ enable = true;
+
+ settings = {
+ library = "${beetsdir}/library.db";
+ directory = config.userDirs.music;
+ plugins = "badfiles edit fetchart info mbsync scrub";
+ original_date = true;
+ import = {
+ write = true;
+ copy = true;
+ move = false;
+ bell = true;
+ from_scratch = true;
+ };
+ match = {
+ preferred = {
+ countries = [
+ "JP"
+ "KR"
+ "TW"
+ "HK"
+ "CN"
+ "RU"
+ "NL"
+ "DE"
+ "AT"
+ "GB|UK"
+ "CA"
+ "AU"
+ "NZ"
+ "US"
+ ];
+ original_year = true;
+ };
+ };
+ edit = {
+ albumfields = "album artist albumartist";
+ itemfields = "track title album artist albumartist day month year genre";
+ };
+ fetchart = {
+ auto = true;
+ cautious = true;
+ cover_names = "cover Cover folder Folder art Art album Album front Front";
+ sources = "filesystem coverart itunes amazon albumart wikipedia";
+ };
+ scrub.auto = true;
+ };
+ };
+
+ bash.shellAliases.beet = "${config.hm.programs.beets.package}/bin/beet --config ${config.dirs.config}/beets/config.yaml";
+ };
+ };
+ };
+}
diff --git a/modules/common/chromium.nix b/modules/common/chromium.nix
new file mode 100644
index 0000000..4f0ae12
--- /dev/null
+++ b/modules/common/chromium.nix
@@ -0,0 +1,27 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.chromium;
+in {
+ options.nixfiles.modules.chromium.enable = mkEnableOption "Chromium";
+
+ config = mkIf cfg.enable {
+ hm = {
+ home.packages = with pkgs; [profile-cleaner];
+
+ programs.chromium = {
+ enable = true;
+
+ package = pkgs.chromium;
+
+ extensions = [
+ {id = "cjpalhdlnbpafiamejdnhcphjbkeiagm";} # uBlock Origin
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/common/common/default.nix b/modules/common/common/default.nix
new file mode 100644
index 0000000..2bfe7e8
--- /dev/null
+++ b/modules/common/common/default.nix
@@ -0,0 +1,11 @@
+_: {
+ imports = [
+ ./documentation.nix
+ ./home-manager.nix
+ ./locale.nix
+ ./networking.nix
+ ./nix
+ ./shell
+ ./users.nix
+ ];
+}
diff --git a/modules/common/common/documentation.nix b/modules/common/common/documentation.nix
new file mode 100644
index 0000000..55f6138
--- /dev/null
+++ b/modules/common/common/documentation.nix
@@ -0,0 +1,28 @@
+{
+ config,
+ lib,
+ pkgs,
+ this,
+ ...
+}:
+with lib; {
+ config = mkMerge [
+ (mkIf this.isHeadful {
+ hm.manual = {
+ html.enable = false;
+ json.enable = false;
+ manpages.enable = true;
+ };
+
+ documentation = {
+ enable = true;
+ doc.enable = false;
+ info.enable = false;
+ };
+ })
+ (mkIf this.isHeadless {
+ hm.manual.manpages.enable = false;
+ documentation.enable = false;
+ })
+ ];
+}
diff --git a/modules/common/common/home-manager.nix b/modules/common/common/home-manager.nix
new file mode 100644
index 0000000..b28260a
--- /dev/null
+++ b/modules/common/common/home-manager.nix
@@ -0,0 +1,24 @@
+{
+ inputs,
+ lib,
+ localUsername ? lib.my.username,
+ ...
+}:
+with lib; {
+ imports = [
+ (mkAliasOptionModule ["hm"] ["home-manager" "users" localUsername])
+ ];
+
+ hm = {
+ news.display = "silent";
+ home.stateVersion = with builtins;
+ head (split "\n" (readFile "${inputs.nixpkgs}/.version"));
+ };
+
+ home-manager = {
+ backupFileExtension = "bak";
+ useUserPackages = true;
+ useGlobalPkgs = true;
+ verbose = true;
+ };
+}
diff --git a/modules/common/common/locale.nix b/modules/common/common/locale.nix
new file mode 100644
index 0000000..bcb577a
--- /dev/null
+++ b/modules/common/common/locale.nix
@@ -0,0 +1,6 @@
+_: {
+ hm.home.language = {
+ collate = "C";
+ messages = "C";
+ };
+}
diff --git a/modules/common/common/networking.nix b/modules/common/common/networking.nix
new file mode 100644
index 0000000..e5d27d8
--- /dev/null
+++ b/modules/common/common/networking.nix
@@ -0,0 +1,3 @@
+{pkgs, ...}: {
+ environment.systemPackages = with pkgs; [myip];
+}
diff --git a/modules/common/common/nix/default.nix b/modules/common/common/nix/default.nix
new file mode 100644
index 0000000..0898457
--- /dev/null
+++ b/modules/common/common/nix/default.nix
@@ -0,0 +1,163 @@
+{
+ config,
+ inputs,
+ lib,
+ localUsername ? lib.my.username,
+ pkgs,
+ pkgsPR,
+ this,
+ ...
+}:
+with lib; {
+ _module.args = let
+ importNixpkgs = nixpkgs:
+ import nixpkgs {inherit (config.nixpkgs) config localSystem;};
+ in rec {
+ pkgsLocal = importNixpkgs "${config.my.home}/src/nixpkgs"; # Impure!
+ pkgsMaster = importNixpkgs inputs.nixpkgs-master;
+ pkgsStable = importNixpkgs inputs.nixpkgs-stable;
+ pkgsRev = rev: hash:
+ importNixpkgs (pkgs.fetchFromGitHub {
+ owner = "NixOS";
+ repo = "nixpkgs";
+ inherit rev hash;
+ });
+ pkgsPR = pr: pkgsRev "refs/pull/${toString pr}/head";
+ };
+
+ nix = let
+ filteredInputs = filterAttrs (n: _: n != "self") inputs;
+ in {
+ settings = {
+ # https://github.com/NixOS/nix/blob/master/src/libutil/experimental-features.cc
+ experimental-features = concatStringsSep " " [
+ "ca-derivations"
+ "flakes"
+ "nix-command"
+ "recursive-nix"
+ ];
+ keep-derivations =
+ if this.isHeadful
+ then "true"
+ else "false";
+ keep-outputs =
+ if this.isHeadful
+ then "true"
+ else "false";
+ flake-registry = "${inputs.flake-registry}/flake-registry.json";
+ warn-dirty = false;
+ };
+
+ nixPath =
+ mapAttrsToList (n: v: "${n}=${v}") filteredInputs
+ ++ ["nixfiles=${config.my.home}/src/nixfiles"];
+
+ registry =
+ mapAttrs (_: flake: {inherit flake;}) filteredInputs
+ // {nixfiles.flake = inputs.self;};
+
+ settings = {
+ trusted-users = ["root" localUsername];
+
+ substituters = [
+ "https://azahi.cachix.org"
+ "https://cache.iog.io"
+ "https://cachix.cachix.org"
+ "https://nix-community.cachix.org"
+ "https://pre-commit-hooks.cachix.org"
+ ];
+ trusted-public-keys = [
+ "azahi.cachix.org-1:2bayb+iWYMAVw3ZdEpVg+NPOHCXncw7WMQ0ElX1GO3s="
+ "cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM="
+ "hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
+ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
+ "pre-commit-hooks.cachix.org-1:Pkk3Panw5AW24TOv6kz3PvLhlH8puAsJTBbOPmBo7Rc="
+ ];
+ };
+ };
+
+ nixpkgs.overlays = with inputs; [
+ self.overlays.default
+ (_: super:
+ {
+ nix-bash-completions = super.nix-bash-completions.overrideAttrs (_: _: {
+ postPatch = ''
+ substituteInPlace _nix \
+ --replace 'nix nixos-option' 'nixos-option'
+ '';
+ });
+
+ helm = with super;
+ kubernetes-helm-wrapped.override {
+ plugins = with kubernetes-helmPlugins; [helm-secrets];
+ };
+
+ alejandra = super.alejandra.overrideAttrs (_: _: {
+ patches = [./patches/alejandra-no-ads.patch];
+ });
+
+ logcli = super.grafana-loki.overrideAttrs (_: _: {
+ subPackages = ["cmd/logcli"];
+ });
+
+ inherit (pkgsPR "215704" "sha256-o2F/ZAugljJKlVIAHMTBK6+Lj6BiBwteA5OuaWPKXm0=") dendrite;
+
+ inherit (pkgsPR "216465" "sha256-ik3e+KM27hGkKWTOOUWj1YtiqHTJvl04dx0/X08P1A0=") amdvlk;
+ }
+ // (with super; let
+ np = nodePackages;
+ in {
+ # Normalises package names. This is done purely for aesthetics.
+ css-language-server = np.vscode-css-languageserver-bin;
+ dhall-language-server = dhall-lsp-server;
+ dockerfile-language-server = np.dockerfile-language-server-nodejs;
+ editorconfig = editorconfig-core-c;
+ go-language-server = gopls;
+ html-language-server = np.vscode-html-languageserver-bin;
+ inherit (np) bash-language-server;
+ inherit (np) vim-language-server;
+ inherit (np) yaml-language-server;
+ json-language-server = np.vscode-json-languageserver-bin;
+ k3d = kube3d;
+ kubelogin = kubelogin-oidc;
+ lua-language-server = sumneko-lua-language-server;
+ nix-language-server = rnix-lsp;
+ omnisharp = omnisharp-roslyn;
+ telepresence = telepresence2;
+ tor-browser = tor-browser-bundle-bin;
+ }))
+ emacs-overlay.overlay
+ nur.overlay
+ ];
+
+ environment.systemPackages = with pkgs;
+ optionals this.isHeadful [
+ nix-top
+ nix-tree
+ ];
+
+ hm.home = {
+ packages = with pkgs; [nix-index];
+
+ file.".nix-defexpr/default.nix".text =
+ optionalString this.isHeadful
+ (
+ let
+ hostname = strings.escapeNixIdentifier this.hostname;
+ in ''
+ let
+ self = builtins.getFlake "nixfiles";
+ configurations = self.nixosConfigurations;
+ local = configurations.${hostname};
+ in rec {
+ inherit self;
+ inherit (self) inputs lib;
+ inherit (lib) my;
+ this = my.configurations.${hostname};
+ inherit (local) config;
+ inherit (local.config.system.build) toplevel vm vmWithBootLoader manual;
+ } // configurations // local._module.args
+ ''
+ );
+ };
+}
diff --git a/modules/common/common/nix/patches/alejandra-no-ads.patch b/modules/common/common/nix/patches/alejandra-no-ads.patch
new file mode 100644
index 0000000..6eaac66
--- /dev/null
+++ b/modules/common/common/nix/patches/alejandra-no-ads.patch
@@ -0,0 +1,33 @@
+diff --git i/src/alejandra_cli/src/cli.rs w/src/alejandra_cli/src/cli.rs
+index bab102c..b90bf1d 100644
+--- i/src/alejandra_cli/src/cli.rs
++++ w/src/alejandra_cli/src/cli.rs
+@@ -7,7 +7,6 @@ use futures::future::RemoteHandle;
+ use futures::stream::FuturesUnordered;
+ use futures::task::SpawnExt;
+
+-use crate::ads::random_ad;
+ use crate::verbosity::Verbosity;
+
+ /// The Uncompromising Nix Code Formatter.
+@@ -203,11 +202,6 @@ pub fn main() -> std::io::Result<()> {
+ (true, false) => "requires formatting",
+ }
+ );
+-
+- if in_place {
+- eprintln!();
+- eprint!("{}", random_ad());
+- }
+ }
+
+ std::process::exit(if in_place { 0 } else { 2 });
+@@ -218,8 +212,6 @@ pub fn main() -> std::io::Result<()> {
+ eprintln!(
+ "Congratulations! Your code complies with the Alejandra style."
+ );
+- eprintln!();
+- eprint!("{}", random_ad());
+ }
+
+ std::process::exit(0);
diff --git a/modules/common/common/shell/default.nix b/modules/common/common/shell/default.nix
new file mode 100644
index 0000000..1eebfa2
--- /dev/null
+++ b/modules/common/common/shell/default.nix
@@ -0,0 +1,139 @@
+{
+ lib,
+ pkgs,
+ this,
+ ...
+}:
+with lib; {
+ hm = {
+ programs = {
+ bash = {
+ enable = true;
+
+ shellOptions = [
+ "autocd"
+ "cdspell"
+ "checkjobs"
+ "checkwinsize"
+ "dirspell"
+ "extglob"
+ "globstar"
+ "histappend"
+ "histreedit"
+ "histverify"
+ ];
+
+ profileExtra = ''
+ export _PROFILE_SOURCED=1
+ '';
+
+ initExtra = ''
+ set -o notify
+
+ if [ "$TERM" != "dumb" ] || [ -n "$INSIDE_EMACS" ]; then
+ PROMPT_COLOR="1;31m"
+ ((UID)) && PROMPT_COLOR="1;32m"
+ if [ -n "$INSIDE_EMACS" ] || [ "$TERM" = "eterm" ] || [ "$TERM" = "eterm-color" ]; then
+ PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
+ else
+ PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\\$\[\033[0m\] "
+ fi
+ if test "$TERM" = "xterm"; then
+ PS1="\[\033]2;\h:\u:\w\007\]$PS1"
+ fi
+ fi
+
+ ${readFile ./functions.bash}
+
+ GRC_ALIASES=true
+ source ${pkgs.grc}/etc/profile.d/grc.sh
+
+ if [ -z "$_PROFILE_SOURCED" ] && [ -f "$HOME/.profile" ]; then
+ source "$HOME/.profile"
+ fi
+ '';
+
+ shellAliases =
+ listToAttrs
+ (map
+ ({
+ name,
+ value,
+ }:
+ nameValuePair name (with pkgs; let
+ pkg =
+ if this.isHeadful
+ then
+ (coreutils.overrideAttrs (_: super: {
+ patches =
+ super.patches
+ ++ [
+ (fetchpatch {
+ url = "https://raw.githubusercontent.com/jarun/advcpmv/ea268d870b475edd5960dcd55d5378abc9705958/advcpmv-0.9-9.1.patch";
+ hash = "sha256-d+SRT/R4xmfHLAdOr7m4R3WFiW64P5ZH6iqDvErYCyg=";
+ })
+ ];
+ }))
+ else coreutils;
+ in "${pkg}/bin/coreutils --coreutils-prog=${value}"))
+ (
+ let
+ mkAlias = {
+ name ? head command,
+ command,
+ }: {
+ inherit name;
+ value = concatStringsSep " " command;
+ };
+
+ progressBar = optionalString this.isHeadful "--progress-bar";
+ in [
+ (mkAlias {command = ["cp" "--interactive" "--recursive" progressBar];})
+ (mkAlias {command = ["mv" "--interactive" progressBar];})
+ (mkAlias {command = ["rm" "--interactive=once"];})
+ (mkAlias {command = ["ln" "--interactive"];})
+ (mkAlias {command = ["mkdir" "--parents"];})
+ (mkAlias {command = ["rmdir" "--parents"];})
+ (mkAlias {
+ name = "lower";
+ command = ["tr" "'[:upper:]'" "'[:lower:]'"];
+ })
+ (mkAlias {
+ name = "upper";
+ command = ["tr" "'[:lower:]'" "'[:upper:]'"];
+ })
+ (mkAlias {
+ name = "disk";
+ command = [
+ "df"
+ "--human-readable"
+ "--exclude-type=tmpfs"
+ "--exclude-type=devtmpfs"
+ "2>/dev/null"
+ ];
+ })
+ ]
+ ))
+ // genAttrs ["grep" "egrep" "fgrep"]
+ (name: "${pkgs.gnugrep}/bin/${name} --color=always");
+
+ historyControl = ["ignoredups" "ignorespace"];
+ };
+
+ command-not-found.enable = false;
+
+ dircolors.enable = true;
+ };
+
+ home.packages = with pkgs; [grc];
+ };
+
+ environment.systemPackages = with pkgs; [
+ bash-completion
+ bc
+ gawk
+ hr
+ moreutils
+ pv
+ ];
+}
diff --git a/modules/common/common/shell/functions.bash b/modules/common/common/shell/functions.bash
new file mode 100644
index 0000000..c18104f
--- /dev/null
+++ b/modules/common/common/shell/functions.bash
@@ -0,0 +1,73 @@
+_complete_alias() {
+ local alias_name=$1
+ local base_function=$2
+ local function_name=_alias_$alias_name
+ shift 2
+ eval "$function_name() {
+ COMP_WORDS=( ${*@Q} \"\${COMP_WORDS[@]:1}\" )
+ (( COMP_CWORD += $# - 1 ))
+ _completion_loader $1
+ $base_function
+ }"
+ complete -F "$function_name" "$alias_name"
+}
+
+function where() {
+ local s
+ s="$(type -P "$1")"
+ realpath "$s"
+}
+_complete_alias where _complete complete
+
+function what() {
+ local s
+ s="$(where "$1")"
+ printf "%s\n" "${s%/*/*}"
+}
+_complete_alias what _complete complete
+
+function cat() {
+ if (($# == 1)) && [[ -d $1 ]]; then
+ ll "$1"
+ else
+ command cat "$@"
+ fi
+}
+
+function cd() {
+ builtin cd "$@" &&
+ if ((${#FUNCNAME[@]} == 1)); then
+ ls
+ fi
+}
+
+function mkcd() {
+ mkdir -p "$1" && builtin cd "$1"
+}
+
+function mvcd() {
+ mv -i -- "$PWD" "$1" && builtin cd .
+}
+
+function bak() {
+ local f
+ for f; do
+ cp -ai -- "$f" "$f.bak"
+ done
+}
+
+function ubak() {
+ local f
+ for f; do
+ [[ $f == *.bak ]] || f="$f.bak"
+ mv -i -- "$f" "${f%.bak}"
+ done
+}
+
+function dec2hex() {
+ printf "0x%X\n" "$1"
+}
+
+function hex2dec() {
+ printf "%d\n" "0x$1"
+}
diff --git a/modules/common/common/users.nix b/modules/common/common/users.nix
new file mode 100644
index 0000000..aee0e38
--- /dev/null
+++ b/modules/common/common/users.nix
@@ -0,0 +1,8 @@
+{
+ lib,
+ localUsername ? lib.my.username,
+ ...
+}:
+with lib; {
+ imports = [(mkAliasOptionModule ["my"] ["users" "users" localUsername])];
+}
diff --git a/modules/common/curl.nix b/modules/common/curl.nix
new file mode 100644
index 0000000..e7bee31
--- /dev/null
+++ b/modules/common/curl.nix
@@ -0,0 +1,38 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.curl;
+in {
+ options.nixfiles.modules.curl.enable =
+ mkEnableOption "Wether to enable cURL.";
+
+ config = mkIf cfg.enable {
+ hm.home.file.".curlrc".text = ''
+ connect-timeout = 60
+ progress-bar
+ referer = ";auto"
+ remote-time
+ show-error
+ '';
+
+ environment.systemPackages = with pkgs; [
+ curl
+ (writeShellScriptBin "0x0" ''
+ url="https://0x0.st"
+ form="file=@"
+
+ if [ -t 0 ] && [ -n "$1" ]; then
+ form="$form$1"
+ else
+ form="$form-"
+ fi
+
+ ${curl}/bin/curl --form "$form" "$url"
+ '')
+ ];
+ };
+}
diff --git a/modules/common/default.nix b/modules/common/default.nix
new file mode 100644
index 0000000..e6040cd
--- /dev/null
+++ b/modules/common/default.nix
@@ -0,0 +1,29 @@
+_: {
+ imports = [
+ ./alacritty.nix
+ ./aria2.nix
+ ./bat.nix
+ ./beets.nix
+ ./chromium.nix
+ ./common
+ ./curl.nix
+ ./direnv.nix
+ ./emacs
+ ./fonts.nix
+ ./git.nix
+ ./gnupg.nix
+ ./htop.nix
+ ./mpv.nix
+ ./nmap.nix
+ ./openssh.nix
+ ./password-store.nix
+ ./profiles
+ ./qutebrowser.nix
+ ./subversion.nix
+ ./tmux.nix
+ ./vim
+ ./vscode.nix
+ ./wget.nix
+ ./zathura.nix
+ ];
+}
diff --git a/modules/common/direnv.nix b/modules/common/direnv.nix
new file mode 100644
index 0000000..b235cee
--- /dev/null
+++ b/modules/common/direnv.nix
@@ -0,0 +1,22 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.direnv;
+in {
+ options.nixfiles.modules.direnv.enable =
+ mkEnableOption "direnv";
+
+ config = mkIf cfg.enable {
+ hm = {
+ programs.direnv = {
+ enable = true;
+ nix-direnv.enable = true;
+ };
+
+ home.sessionVariables.DIRENV_LOG_FORMAT = "";
+ };
+ };
+}
diff --git a/modules/common/emacs/default.nix b/modules/common/emacs/default.nix
new file mode 100644
index 0000000..7395c51
--- /dev/null
+++ b/modules/common/emacs/default.nix
@@ -0,0 +1,163 @@
+{
+ config,
+ inputs,
+ lib,
+ pkgs,
+ pkgsStable,
+ this,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.emacs;
+in {
+ options.nixfiles.modules.emacs.enable = mkEnableOption "GNU Emacs";
+
+ config = mkIf cfg.enable {
+ nixfiles.modules = {
+ fonts.enable = true;
+ git.client.enable = true;
+ gnupg.enable = true;
+ };
+
+ hm = {
+ xdg.configFile = {
+ "doom/init.el".source = ./doom/init.el;
+ "doom/packages.el".source = ./doom/packages.el;
+ "doom/config.el" = {
+ text = concatStringsSep "\n" [
+ (let
+ # NOTE gopls will require the "go" executable which must be provided
+ # by the project's flake/shell.
+ extraBins = with pkgs;
+ [
+ enchant # :checkers (spell +enchant)
+ (python3.withPackages (p:
+ with p; [
+ black # :lang python :editor format
+ isort # :lang python
+ pyflakes # :lang python
+ python-lsp-server # :lang (python +lsp)
+ ]))
+ asmfmt # :editor format
+ bash-language-server # :lang (sh +lsp)
+ clang-tools # :lang (cc +lsp) :editor format
+ cmake-format # :lang cc :editor format
+ cmigemo # :lang japanese
+ css-language-server # :lang (web +lsp)
+ dhall-language-server # :lang (dhall +lsp)
+ dockerfile-language-server # :tools (docker +lsp)
+ editorconfig # :tools editorconfig
+ fd # doom!
+ gnuplot # :lang (org +gnuplot)
+ gnutls # doom!
+ go-language-server # :lang (go +lsp)
+ gomodifytags # :lang go
+ gore # :lang go
+ gotests # :lang go
+ gotools # :lang go
+ graphviz # :lang (org +roam2) :lang plantuml
+ html-language-server # :lang (web +lsp)
+ html-tidy # :lang web
+ jre # :lang plantuml
+ json-language-server # :lang (json +lsp)
+ nix-language-server # :lang (nix +lsp)
+ nixfmt # :lang nix :editor format
+ nodePackages.js-beautify # :lang web
+ nodePackages.prettier # :editor format
+ nodePackages.stylelint # :lang web
+ nodejs # :tools debugger
+ pandoc # :lang org markdown latex
+ pinentry-emacs # doom!
+ pre-commit # :tools magit
+ ripgrep # doom!
+ rust-analyzer # :lang (rust +lsp)
+ rustfmt # :lang rust
+ shellcheck # :lang sh
+ shfmt # :lang sh :editor format
+ sqlite # :lang (org +roam2) :tools lookup
+ texlab # lang (tex +lsp)
+ texlive.combined.scheme-full # :lang org tex
+ unzip # :tools debugger
+ wordnet # :tools (lookup +dictionary +offline)
+ yaml-language-server # :lang (yaml +lsp)
+ zls # :lang (zig +lsp)
+ zstd # :emacs undo
+ ]
+ ++ (
+ #
+ # GDB doesn't support[1] Apple Silicon on MacOS.
+ #
+ # [1]: https://inbox.sourceware.org/gdb/6b48224b-9e2e-518d-793b-df4fc5514884@arm.com/
+ if (this.system != "aarch64-darwin")
+ then [gdb] # :tools debugger
+ else [lldb] # :tools debugger
+ )
+ ++ optionals (!pkgs.stdenv.isDarwin)
+ [
+ # NOTE Haskell is pretty much broken every couple of days on
+ # MacOS and I usually don't write anything in Haskell while
+ # I'm on my work laptop, so... ShellCheck seems to be working,
+ # though.
+ haskellPackages.ormolu # :lang haskell :editor format
+ haskellPackages.haskell-language-server # :lang (haskell +lsp)
+ haskellPackages.cabal-fmt # :lang haskell :editor format
+ haskellPackages.cabal-install # :lang haskell
+ haskellPackages.hoogle # :lang haskell
+ ];
+ in ''
+ ;; This will integrate packages which are required by various
+ ;; modules without polluting the user's profile.
+ (setq exec-path (append exec-path '(${
+ concatMapStringsSep " " (x: ''"${x}/bin"'') extraBins
+ })))
+ (setenv "PATH" (concat (getenv "PATH") ":${
+ concatMapStringsSep ":" (x: "${x}/bin") extraBins
+ }"))
+
+ ;; Font must be set to N+2 because otherwise it looks too small.
+ (setq doom-font (font-spec :family "${config.fontScheme.monospaceFont.family}"
+ :size ${toString (config.fontScheme.monospaceFont.size + 2)})
+ doom-unicode-font doom-font)
+
+ (setq user-full-name "${my.fullname}"
+ user-mail-address "${my.email}")
+
+ ;; :app irc
+ (setq circe-default-nick "${my.username}"
+ circe-default-realname "${my.email}"
+ circe-default-user circe-default-nick)
+
+ ;; :lang plantuml
+ (setq org-plantuml-jar-path "${pkgs.plantuml}/lib/plantuml.jar")
+
+ ;; :input japanese
+ (setq migemo-dictionary "${pkgs.cmigemo}/share/migemo/utf-8/migemo-dict")
+
+ ;; :input japanese
+ (setq skk-large-jisyo "${pkgs.skk-dicts}/share/skk/SKK-JISYO.L")
+ '')
+ (builtins.readFile ./doom/config.el)
+ ];
+ onChange = with config.hm.programs; ''
+ if [[ -x "''${XDG_CONFIG_HOME:~/.config}/emacs/bin/doom" ]]; then
+ oldpath="$PATH"
+ export PATH="''${PATH:-/bin}:${emacs.package}/bin:${git.package}/bin"
+
+ "''${XDG_CONFIG_HOME:~/.config}/emacs/bin/doom" sync
+
+ export PATH="$oldpath"
+ unset oldpath
+ fi
+ '';
+ };
+ };
+
+ programs.emacs = {
+ enable = true;
+ package = pkgs.emacs28; # Pin to avoid surprises.
+ # For some reason latest libvterm is not picked up by Emacs.
+ extraPackages = _: with pkgsStable.emacsPackages; [vterm];
+ };
+ };
+ };
+}
diff --git a/modules/common/emacs/doom/config.el b/modules/common/emacs/doom/config.el
new file mode 100644
index 0000000..9284e0b
--- /dev/null
+++ b/modules/common/emacs/doom/config.el
@@ -0,0 +1,223 @@
+;;
+;;; Misc
+;;
+
+(setq display-line-numbers-type t)
+
+(setq scroll-margin 10
+ hscroll-margin 10)
+
+(setq browse-url-generic-program (executable-find "firefox")
+ browse-url-browser-function 'browse-url-generic)
+
+;;
+;;; Doom-specific
+;;
+
+;; Make it more default-ey.
+(setq frame-title-format '("Emacs")
+ icon-title-format frame-title-format)
+
+(setq doom-theme 'doom-tomorrow-night)
+
+(setq +format-on-save-enabled-modes '(not nix-mode json-mode yaml-mode))
+
+;;
+;;; LSP
+;;
+
+(setq lsp-enable-suggest-server-download nil)
+
+;;
+;;; Org
+;;
+
+(setq org-directory "~/doc/org/")
+(after! org
+ (setq org-todo-keywords '((sequence
+ "PROJ(p)" ; A master task.
+ "TODO(t)" ; A task that needs to be done with statues:
+ "STRT(s@)" ; - In progress.
+ "HOLD(l@/!)" ; - Paused because of me.
+ "WAIT(w@/!)" ; - Paused because of not me.
+ "|"
+ "DONE(d@/!)" ; Complete state.
+ "KILL(k@/!)")) ; Incomplete state.
+ org-todo-keyword-faces '(("PROJ" . +org-todo-project)
+ ("TODO" . +org-todo-active)
+ ("STRT" . +org-todo-active)
+ ("HOLD" . +org-todo-onhold)
+ ("WAIT" . +org-todo-onhold)
+ ("DONE" . +org-todo-cancel)
+ ("KILL" . +org-todo-cancel))))
+
+(add-hook! 'org-mode-hook 'auto-fill-mode)
+
+(add-hook! 'org-mode-hook (lambda (&rest _)
+ (setq fill-column 80)))
+
+(setq org-roam-directory "~/doc/roam/"
+ org-roam-db-location (concat org-roam-directory ".db"))
+
+(use-package! org-roam-ui
+ :requires websocket
+ :after org-roam
+ :config
+ (setq org-roam-ui-sync-theme t
+ org-roam-ui-follow t
+ org-roam-ui-update-on-save t
+ org-roam-ui-open-on-start t))
+
+;;
+;;; Elisp
+;;
+
+(setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc))
+
+;;
+;;; Haskell
+;;
+
+(setq lsp-haskell-formatting-provider "ormolu")
+
+;;
+;;; Nix
+;;
+
+(after! lsp-mode
+ (add-to-list 'lsp-language-id-configuration '(nix-mode . "nix"))
+ (lsp-register-client
+ (make-lsp-client :new-connection (lsp-stdio-connection '("rnix-lsp"))
+ :major-modes '(nix-mode)
+ :server-id 'nix)))
+
+;;
+;;; YAML
+;;
+
+(add-hook! 'yaml-mode-hook
+ (defun +disable-flycheck-for-yaml-helm-templates ()
+ (when (and buffer-file-name
+ (string-match-p "/templates/" buffer-file-name)
+ (or (string-suffix-p ".yaml" buffer-file-name)
+ (string-suffix-p ".yml" buffer-file-name)))
+ (remove-hook! 'yaml-mode-local-vars-hook #'lsp!)
+ (pushnew! flycheck-disabled-checkers 'yaml-jsyaml 'yaml-ruby 'yaml-yamllint))))
+
+(setq-hook! 'yaml-mode-hook +format-with-lsp nil)
+
+;;
+;;; Elfeed
+;;
+
+(setq elfeed-db-directory "~/.elfeed"
+ elfeed-enclosure-default-dir (concat elfeed-db-directory "/enclosures")
+ rmh-elfeed-org-files (list (concat elfeed-db-directory "/index.org"))
+ elfeed-goodies/powerline-default-separator nil
+ elfeed-goodies/entry-pane-size 0.75
+ elfeed-goodies/entry-pane-position 'bottom)
+
+;;
+;;; mu4e
+;;
+
+(setq mu4e-root-maildir "~/mail"
+ mu4e-context-policy 'ask-if-none
+ mu4e-compose-context-policy 'always-ask
+ mu4e-compose--org-msg-toggle-next nil
+ mu4e-update-interval 60
+ sendmail-program (executable-find "msmtp")
+ send-mail-function #'smtpmail-send-it
+ message-sendmail-f-is-evil t
+ message-sendmail-extra-arguments '("--read-envelope-from")
+ message-send-mail-function #'message-send-mail-with-sendmail
+ +mu4e-personal-addresses (list "frodo@gondor.net"
+ "frodo@rohan.net"
+ "azahi@shire.me"
+ "admin@shire.me"
+ "ceo@shire.me"
+ "a.gondor@yahoo.com"
+ "a.gondor@yahoo.com"))
+
+(set-email-account! "shire"
+ '((mu4e-drafts-folder . "/shire/Drafts")
+ (mu4e-refile-folder . "/shire/Archive")
+ (mu4e-sent-folder . "/shire/Sent")
+ (mu4e-trash-folder . "/shire/Trash")
+ (smtpmail-smtp-user . "azahi"))
+ t)
+
+(set-email-account! "yahoo"
+ '((mu4e-sent-folder . "/yahoo/Sent")
+ (mu4e-drafts-folder . "/yahoo/Drafts")
+ (mu4e-trash-folder . "/yahoo/Trash")
+ (mu4e-refile-folder . "/yahoo/Archive")
+ (smtpmail-smtp-user . "a.gondor"))
+ t)
+
+(setq +mu4e-compose-org-msg-toggle-next nil)
+
+;;
+;;; Circe
+;;
+
+(defun nixfiles/irc-bouncer-password-f (&rest _)
+ (+pass-get-secret "server/soju.manwe.shire.me/azahi"))
+
+(set-irc-server! "libera"
+ `(:host "shire.me"
+ :port 6667
+ :user "azahi/libera"
+ :pass nixfiles/irc-bouncer-password-f))
+
+(set-irc-server! "oftc"
+ `(:host "shire.me"
+ :port 6667
+ :user "azahi/oftc"
+ :pass nixfiles/irc-bouncer-password-f))
+
+(set-irc-server! "hackint"
+ `(:host "shire.me"
+ :port 6667
+ :user "azahi/hackint"
+ :pass nixfiles/irc-bouncer-password-f))
+
+(set-irc-server! "rizon"
+ `(:host "shire.me"
+ :port 6667
+ :user "azahi/rizon"
+ :pass nixfiles/irc-bouncer-password-f))
+
+;; (use-package! hledger-mode
+;; :mode ("\\.journal\\'")
+;; :hook ((hledger-view-mode . hl-line-mode)
+;; (hledger-view-mode . center-text-for-reading))
+;; :init
+;; (setq hledger-jfile "~/doc/accounting/current.journal")
+;; :config
+;; (set-company-backend! 'hledger-mode 'hledger-company)
+;; (add-hook! 'hledger-mode-hook
+;; (lambda (&rest _)
+;; (make-local-variable 'company-backends)
+;; (add-to-list 'company-backends 'hledger-company))))
+
+;; (use-package! hledger-input
+;; :hook ((hledger-input-post-commit . hledger-show-new-balances)
+;; (hledger-input-mode . auto-fill-mode)
+;; (hledger-input-mode . (lambda (&rest _)
+;; (make-local-variable 'compay-idle-delay)
+;; (setq-local company-idle-delay 0.1))))
+;; :init
+;; (setq hledger-input-buffer-height 20))
+
+;; (use-package! kubernetes
+;; :defer t
+;; :commands (kubernetes-overview)
+;; :init (setq kubernetes-poll-frequency 3600
+;; kubernetes-redraw-frequency 3600))
+
+;; (use-package! kubernetes-evil
+;; :after kubernetes-overview)
+
+;; (use-package! kubernetes-tramp
+;; :defer t)
diff --git a/modules/common/emacs/doom/init.el b/modules/common/emacs/doom/init.el
new file mode 100644
index 0000000..cdab069
--- /dev/null
+++ b/modules/common/emacs/doom/init.el
@@ -0,0 +1,119 @@
+(doom! :input
+ ;; japanese
+
+ :completion
+ company
+ vertico
+
+ :ui
+ ;; deft
+ doom
+ ;; doom-dashboard
+ ;; doom-quit
+ ;; emoji
+ hl-todo
+ indent-guides
+ ;; ligatures
+ ;; modeline
+ ;; nav-flash
+ ophints
+ (popup +defaults)
+ ;; tabs
+ ;; unicode
+ (vc-gutter +diff-hl +pretty)
+ window-select
+ workspaces
+
+ :editor
+ (evil +everywhere)
+ file-templates
+ fold
+ format
+ ;; lispy
+ ;; multiple-cursors
+ parinfer
+ ;; rotate-text
+ snippets
+ word-wrap
+
+ :emacs
+ dired
+ ;; electric
+ ibuffer
+ undo
+ vc
+
+ :term
+ eshell
+ vterm
+
+ :checkers
+ syntax
+ (spell +enchant
+ +everywhere
+ +flyspell)
+ grammar
+
+ :tools
+ ansible
+ (debugger +lsp)
+ direnv
+ (docker +lsp)
+ editorconfig
+ (eval +overlay)
+ gist
+ (lookup +dictionary +offline)
+ (lsp +peek)
+ (magit +forge)
+ make
+ (pass +auth)
+ ;; pdf
+ terraform
+ tree-sitter
+ upload
+
+ :os
+ (:if IS-MAC macos)
+ ;; (tty +osc)
+
+ :lang
+ (cc +lsp +tree-sitter)
+ (common-lisp +lsp +tree-sitter)
+ (csharp +lsp +tree-sitter)
+ data
+ (dhall +lsp +tree-sitter)
+ (emacs-lisp +lsp +tree-sitter)
+ (go +lsp +tree-sitter)
+ ;; graphql
+ (:if IS-LINUX (haskell +lsp +tree-sitter))
+ (java +lsp +tree-sitter)
+ (javascript +lsp +tree-sitter)
+ (json +lsp +tree-sitter)
+ (kotlin +lsp +tree-sitter)
+ (latex +lsp +tree-sittter)
+ (markdown +lsp +tree-sitter)
+ (nix +lsp)
+ (org +pandoc +roam2)
+ plantuml
+ (python +lsp +tree-sitter)
+ (:if IS-LINUX (racket +lsp +tree-sitter))
+ ;; rst
+ (rust +lsp +tree-sitter)
+ (:if IS-LINUX (scheme +lsp +tree-sitter +racket))
+ (sh +lsp +tree-sitter)
+ web
+ (yaml +lsp +tree-sitter)
+ (zig +lsp +tree-sitter)
+
+ :email
+ mu4e
+
+ :app
+ calendar
+ ;; emms
+ ;; everywhere
+ irc
+ (rss +org)
+
+ :config
+ (default +bindings +smartparens))
diff --git a/modules/common/emacs/doom/packages.el b/modules/common/emacs/doom/packages.el
new file mode 100644
index 0000000..298a203
--- /dev/null
+++ b/modules/common/emacs/doom/packages.el
@@ -0,0 +1,17 @@
+(disable-packages! writegood-mode)
+
+(unpin! org-roam)
+(package! org-roam
+ :recipe (:host github
+ :repo "org-roam/org-roam"
+ :branch "main"))
+(package! org-roam-ui
+ :recipe (:host github
+ :repo "org-roam/org-roam-ui"
+ :branch "main"))
+
+;; (package! hledger-mode)
+
+;; (package! kubernetes)
+;; (package! kubernetes-evil)
+;; (package! kubernetes-tramp)
diff --git a/modules/common/fonts.nix b/modules/common/fonts.nix
new file mode 100644
index 0000000..483de0d
--- /dev/null
+++ b/modules/common/fonts.nix
@@ -0,0 +1,91 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.fonts;
+in {
+ imports = [
+ (mkAliasOptionModule ["fontScheme"] [
+ "nixfiles"
+ "modules"
+ "fonts"
+ "fontScheme"
+ ])
+ ];
+
+ options.nixfiles.modules.fonts = {
+ enable = mkEnableOption "fonts and their configurations";
+
+ fontScheme = let
+ mkFont = {
+ family,
+ style,
+ size,
+ }: {
+ family = mkOption {
+ description = "Family of the font.";
+ type = types.str;
+ default = family;
+ };
+ style = mkOption {
+ description = "Style of the font.";
+ type = types.str;
+ default = style;
+ };
+ size = mkOption {
+ description = "Size of the font.";
+ type = types.int;
+ default = size;
+ };
+ };
+ in {
+ serifFont = mkFont {
+ family = "Iosevka Etoile";
+ style = "Regular";
+ size = 14;
+ };
+
+ serifFontFallback = mkFont {
+ family = "Sarasa Gothic J";
+ style = "Regular";
+ size = 14;
+ };
+
+ sansSerifFont = mkFont {
+ family = "Iosevka Aile";
+ style = "Regular";
+ size = 14;
+ };
+
+ sansSerifFontFallback = mkFont {
+ family = "Sarasa Gothic J";
+ style = "Regular";
+ size = 14;
+ };
+
+ monospaceFont = mkFont {
+ family = "Iosevka";
+ style = "Regular";
+ size = 14;
+ };
+
+ monospaceFontFallback = mkFont {
+ family = "Sarasa Mono J";
+ style = "Regular";
+ size = 14;
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ fonts.fonts = with pkgs; [
+ iosevka-bin
+ (iosevka-bin.override {variant = "aile";})
+ (iosevka-bin.override {variant = "etoile";})
+ sarasa-gothic
+ ];
+ };
+}
diff --git a/modules/common/git.nix b/modules/common/git.nix
new file mode 100644
index 0000000..2c1dd1f
--- /dev/null
+++ b/modules/common/git.nix
@@ -0,0 +1,117 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.git;
+in {
+ options.nixfiles.modules.git.client.enable =
+ mkEnableOption "Git client";
+
+ config = mkIf cfg.client.enable {
+ hm = {
+ home.packages = with pkgs; [glab hut];
+
+ programs = {
+ git = {
+ enable = true;
+
+ package = pkgs.git.override {
+ doInstallCheck = false;
+ pythonSupport = false;
+ sendEmailSupport = true;
+ withLibsecret = false;
+ withSsh = true;
+ };
+
+ userName = my.fullname;
+ userEmail = my.email;
+ signing = {
+ inherit (my.pgp) key;
+ signByDefault = true;
+ };
+
+ extraConfig =
+ {
+ advice.detachedHead = false;
+ color.ui = true;
+ core.whitespace = "trailing-space";
+ diff = {
+ mnemonicPrefix = true;
+ renames = "copies";
+ submodule = "log";
+ };
+ init.defaultBranch = "master";
+ status.submoduleSummary = true;
+ }
+ // mapAttrs'
+ (n: v: nameValuePair ''url "git@${v}:"'' {insteadOf = "${n}:";}) {
+ "alpine" = "gitlab.alpinelinux.org";
+ "bitbucket" = "bitbucket.com";
+ "codeberg" = "codeberg.org";
+ "freedesktop" = "gitlab.freedesktop.org";
+ "github" = "github.com";
+ "gitlab" = "gitlab.com";
+ "gnome" = "gitlab.gnome.org";
+ "haskell" = "gitlab.haskell.org";
+ "kde" = "invent.kde.org";
+ "notabug" = "notabug.org";
+ "opencode" = "opencode.net";
+ "sourcehut" = "git.sr.ht";
+ "videolan" = "code.videolan.org";
+ };
+
+ aliases = let
+ git = "${config.hm.programs.git.package}/bin/git";
+ curl = "${pkgs.curl}/bin/curl";
+ in {
+ fuck = "!${git} reset --hard && ${git} clean -fdx";
+ gud = ''commit -m "git gud"'';
+ wtc = "!${curl} -sq whatthecommit.com/index.txt | ${git} commit -F -";
+ };
+
+ # All helper tools/editor generated files should go here. This must
+ # be kept relatively clean and void of any project-specific residual
+ # files.
+ ignores = [
+ "*~"
+ ".DS_Store"
+ ".cache/clangd/"
+ ".ccls-cache/"
+ ".dir-locals.el"
+ ".gdb_history"
+ ".netrwhist"
+ ".projectile"
+ "[._]*.s[a-v][a-z]"
+ "[._]*.sw[a-p]"
+ "[._]s[a-rt-v][a-z]"
+ "[._]ss[a-gi-z]"
+ "[._]sw[a-p]"
+ "\#*\#"
+ "compile_commands*.json"
+ "cscope.*"
+ "vgcore.*"
+ ];
+ };
+
+ gh = {
+ enable = true;
+ settings.git_protocol = "ssh";
+ };
+
+ bash = {
+ shellAliases = {
+ gl = "${pkgs.glab}/bin/glab";
+ ht = "${pkgs.hut}/bin/hut";
+ };
+ initExtra = mkAfter ''
+ _complete_alias gl __start_glab glab
+ _complete_alias ht __start_hut hut
+ '';
+ };
+ };
+ };
+ };
+}
diff --git a/modules/common/gnupg.nix b/modules/common/gnupg.nix
new file mode 100644
index 0000000..c0f10f9
--- /dev/null
+++ b/modules/common/gnupg.nix
@@ -0,0 +1,58 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.gnupg;
+in {
+ options.nixfiles.modules.gnupg.enable = mkEnableOption "GnuPG";
+
+ config = mkIf cfg.enable {
+ hm.programs.gpg = {
+ enable = true;
+
+ settings =
+ {
+ display-charset = "utf-8";
+ enable-progress-filter = true;
+ fixed-list-mode = true;
+ keyid-format = "0xlong";
+ no-comments = true;
+ no-emit-version = true;
+ no-greeting = true;
+ with-fingerprint = true;
+ throw-keyids = false;
+
+ use-agent = true;
+
+ armor = true;
+
+ no-random-seed-file = true;
+
+ list-options = "show-uid-validity";
+ verify-options = "show-uid-validity";
+ }
+ // (let
+ cipherAlgos = ["AES256" "AES192" "AES"];
+ digestAlgos = ["SHA512" "SHA384" "SHA256" "SHA224"];
+ compressionAlgos = ["ZLIB" "BZIP2" "ZIP" "Uncompressed"];
+
+ cs = concatStringsSep " ";
+ in {
+ default-preference-list =
+ cs (cipherAlgos ++ digestAlgos ++ compressionAlgos);
+
+ personal-cipher-preferences = cs cipherAlgos;
+ personal-digest-preferences = cs digestAlgos;
+ personal-compress-preferences = cs compressionAlgos;
+
+ s2k-cipher-algo = head cipherAlgos;
+ s2k-digest-algo = head digestAlgos;
+
+ digest-algo = head digestAlgos;
+ cert-digest-algo = head digestAlgos;
+ });
+ };
+ };
+}
diff --git a/modules/common/htop.nix b/modules/common/htop.nix
new file mode 100644
index 0000000..bf3f1e4
--- /dev/null
+++ b/modules/common/htop.nix
@@ -0,0 +1,57 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.htop;
+in {
+ options.nixfiles.modules.htop.enable =
+ mkEnableOption "htop";
+
+ config = mkIf cfg.enable {
+ hm.programs.htop = {
+ enable = true;
+
+ settings = with config.hm.lib.htop; {
+ fields = with fields; [
+ PID
+ USER
+ PRIORITY
+ NICE
+ M_SIZE
+ M_RESIDENT
+ M_SHARE
+ STATE
+ PERCENT_CPU
+ PERCENT_MEM
+ TIME
+ COMM
+ ];
+ account_guest_in_cpu_meter = 1;
+ detailed_cpu_time = 0;
+ enable_mouse = 0;
+ find_comm_in_cmdline = 1;
+ header_margin = 1;
+ hide_function_bar = 1;
+ hide_kernel_threads = 1;
+ hide_userland_threads = 1;
+ highlight_base_name = 1;
+ highlight_changes = 0;
+ highlight_changes_delay_secs = 1;
+ highlight_deleted_exe = 1;
+ highlight_megabytes = 1;
+ highlight_threads = 1;
+ shadow_other_users = 1;
+ show_cpu_frequency = 1;
+ show_cpu_usage = 1;
+ show_program_path = 0;
+ show_thread_names = 0;
+ strip_exe_from_cmdline = 1;
+ tree_view = 1;
+ tree_view_always_by_pid = 1;
+ update_process_names = 1;
+ };
+ };
+ };
+}
diff --git a/modules/common/mpv.nix b/modules/common/mpv.nix
new file mode 100644
index 0000000..afab1dd
--- /dev/null
+++ b/modules/common/mpv.nix
@@ -0,0 +1,135 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.mpv;
+in {
+ options.nixfiles.modules.mpv.enable = mkEnableOption "mpv";
+
+ config = mkIf cfg.enable {
+ hm.programs = {
+ mpv = {
+ enable = true;
+
+ package = with pkgs;
+ wrapMpv mpv-unwrapped {
+ scripts = with mpvScripts; [
+ autoload
+ mpv-autosub
+ sponsorblock
+ ];
+ };
+
+ bindings = {
+ "RIGHT" = "seek 10";
+ "LEFT" = "seek -10";
+ "UP" = "seek 60";
+ "DOWN" = "seek -60";
+
+ "Shift+RIGHT" = "no-osd seek 1 exact";
+ "Shift+LEFT" = "no-osd seek -1 exact";
+ "Shift+UP" = "no-osd seek 5 exact";
+ "Shift+DOWN" = "no-osd seek -5 exact";
+
+ "Alt+k" = "add sub-scale +0.1";
+ "Alt+j" = "add sub-scale -0.1";
+
+ "B" = ''cycle-values background "#000000" "#ffffff"'';
+ };
+
+ profiles = {
+ "protocol.http".force-window = "immediate";
+ "protocol.https".profile = "protocol.http";
+ };
+
+ config = let
+ lang = comcat [
+ "Japanese"
+ "japanese"
+ "jp"
+ "jpn"
+ "jaJP"
+ "ja-JP"
+ "English"
+ "english"
+ "en"
+ "eng"
+ "enUS"
+ "en-US"
+ "Russian"
+ "russian"
+ "ru"
+ "rus"
+ "ruRU"
+ "ru-RU"
+ ];
+ in {
+ audio-display = "no";
+ autofit-larger = "100%x95%";
+ cursor-autohide = 1000;
+ force-seekable = "no";
+ fullscreen = true;
+ msg-color = true;
+ msg-module = true;
+ prefetch-playlist = true;
+ save-position-on-quit = false;
+ screenshot-format = "png";
+ screenshot-template = "%F [%p]";
+ stop-screensaver = true;
+ term-osd-bar = true;
+ use-filedir-conf = true;
+
+ osd-bar-align-y = 0;
+ osd-bar-h = 2;
+ osd-bar-w = 60;
+ osd-border-color = "#FF262626";
+ osd-border-size = 2.5;
+ osd-color = "#FFFFFFFF";
+ osd-duration = 2500;
+ osd-font-size = 40;
+ osd-fractions = true;
+ osd-level = 1;
+ osd-shadow-color = "#33000000";
+
+ osc = false;
+
+ sub-auto = "fuzzy";
+ sub-file-paths-append = "srt";
+ sub-ass-force-margins = true;
+ sub-ass-force-style = "kerning=yes";
+ sub-fix-timing = true;
+ sub-use-margins = true;
+ sub-font-size = 40;
+ sub-color = "#FFFFFFFF";
+ sub-border-color = "#FF262626";
+ sub-border-size = 2.5;
+ sub-shadow-offset = 1;
+ sub-shadow-color = "#33000000";
+ sub-spacing = 0.5;
+ blend-subtitles = true;
+
+ audio-file-auto = "fuzzy";
+ volume = 100;
+ volume-max = 200;
+
+ alang = lang;
+ slang = lang;
+
+ ytdl = true;
+ ytdl-raw-options = ''sub-lang="${lang}",write-sub='';
+ };
+ };
+
+ bash = {
+ shellAliases.cam = "${config.hm.programs.mpv.package}/bin/mpv av://v4l2:/dev/video0";
+
+ initExtra = mkAfter ''
+ _complete_alias cam _mpv mpv
+ '';
+ };
+ };
+ };
+}
diff --git a/modules/common/nmap.nix b/modules/common/nmap.nix
new file mode 100644
index 0000000..73f948c
--- /dev/null
+++ b/modules/common/nmap.nix
@@ -0,0 +1,84 @@
+{
+ config,
+ lib,
+ pkgs,
+ inputs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.nmap;
+in {
+ options.nixfiles.modules.nmap.enable = mkEnableOption "Nmap";
+
+ config = mkIf cfg.enable {
+ hm = {
+ home = {
+ file = {
+ ".nmap/scripts/vulners/vulners.nse".source = "${inputs.nmap-vulners}/vulners.nse";
+ ".nmap/scripts/vulscan/vulscan.nse".source = "${inputs.nmap-vulscan}/vulscan.nse";
+ };
+
+ packages = with pkgs; [nmap nmap-formatter];
+
+ activation.regenerateNmapScripts = with pkgs; ''
+ ${nmap}/bin/nmap --script-updatedb
+ '';
+ };
+
+ programs.bash = {
+ shellAliases = let
+ base = "${pkgs.nmap}/bin/nmap -sV";
+ in {
+ nmap-vulners = "${base} --script=vulners/vulners.nse";
+ nmap-vulscan = "${base} --script=vulscan/vulscan.nse";
+ };
+ initExtra = mkAfter ''
+ _complete_alias nmap-vulners _nmap nmap
+ _complete_alias nmap-vulscan _nmap nmap
+ '';
+ };
+
+ systemd.user = {
+ services.update-nmap-vulscan-lists = {
+ Service = {
+ ExecStart = let
+ pkg = with pkgs;
+ writeShellApplication {
+ name = "update-nmap-vulscan-lists";
+ runtimeInputs = [curl];
+ text = ''
+ declare -a vulscandbs=(
+ "cve"
+ "exploitdb"
+ "openvas"
+ "osvdb"
+ "scipvuldb"
+ "securityfocus"
+ "securitytracker"
+ "xforce"
+ )
+ for i in "''${vulscandbs[@]}"; do
+ ${curl}/bin/curl \
+ -o "${config.my.home}/.nmap/scripts/vulscan/$i.csv" \
+ "https://www.computec.ch/projekte/vulscan/download/$i.csv"
+ done
+ '';
+ };
+ in "${pkg}/bin/update-nmap-vulscan-lists";
+ };
+ };
+
+ timers.update-nmap-vulscan-lists = {
+ # TODO Figure out how to check for network-online.target for user
+ # timers.
+ Timer = {
+ OnCalendar = "daily";
+ Persistent = true;
+ Unit = "update-nmap-vulscan-lists.service";
+ };
+ Install.WantedBy = ["timers.target"];
+ };
+ };
+ };
+ };
+}
diff --git a/modules/common/openconnect.nix b/modules/common/openconnect.nix
new file mode 100644
index 0000000..780f93f
--- /dev/null
+++ b/modules/common/openconnect.nix
@@ -0,0 +1,83 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.openconnect;
+in {
+ options.nixfiles.modules.openconnect.enable =
+ mkEnableOption "OpenConnect VPN";
+
+ config = mkIf.enable {
+ assertions = [
+ {
+ assertion = config.networking.networkmanager.enable;
+ message = "NetworkManager is required";
+ }
+ ];
+
+ # Spent three days trying to make this work but still getting "No SSO
+ # handler" even on the HEAD version that 100% has SSO support baked in.
+ # It's all so tiresome[1]... aaand KDE is not supported[2].
+ #
+ # I fucking hate AnyConnect, truly an example of how shit is is non-free
+ # software. SAML also sucks balls. I also hate my company for using this
+ # shit, guess I have no other choice but to use the absolute dogshit laptop
+ # they gave me.
+ #
+ # [1]: https://gitlab.gnome.org/GNOME/NetworkManager-openconnect
+ # [1]: https://gitlab.com/openconnect/openconnect/-/issues/424
+ # [2]: https://groups.google.com/g/linux.debian.bugs.dist/c/lK8u-LMY7n4
+ # [2]: https://bugs.kde.org/show_bug.cgi?id=448153
+
+ networking.networkmanager.plugins = with pkgs; [
+ ((networkmanager-openconnect.override {
+ withGnome = false;
+ openconnect = openconnect.overrideAttrs (_: super: {
+ version = "unstable-2022-10-23";
+ src = fetchFromGitLab {
+ owner = "openconnect";
+ repo = "openconnect";
+ rev = "acdfc753f7885b2a539f99036ac41ba1b78cc7ae";
+ hash = "sha256-ub+Z4WFD77h5YMQTb+TLc7EyY2KjBWglF1QVTirCHJM=";
+ };
+ });
+ })
+ .overrideAttrs (_: super: {
+ version = "unstable-2022-09-10";
+ src = fetchFromGitLab {
+ domain = "gitlab.gnome.org";
+ owner = "GNOME";
+ repo = "NetworkManager-openconnect";
+ rev = "3c1590786518e9acca33c250660ad21cae565acd";
+ hash = "sha256-YTUN46QHsHkXPAhImPG/MMLMqjlSRknapVO8u43nnWk=";
+ };
+ buildInputs =
+ super.buildInputs
+ ++ [
+ (webkitgtk_4_1.override {
+ inherit (gnome) libsoup;
+ })
+ ];
+ nativeBuildInputs =
+ super.nativeBuildInputs
+ ++ [
+ autoreconfHook
+ ];
+ postPatch = ''
+ substituteInPlace configure.ac \
+ --replace "PKG_CHECK_MODULES(LIBSECRET, libsecret-1 >= 0.18)" ""
+ '';
+ preAutoreconf = ''
+ autoupdate
+ '';
+ preConfigure = ''
+ NOCONFIGURE=x ./autogen.sh
+ touch gtk4/nm-openconnect-dialog.ui
+ '';
+ }))
+ ];
+ };
+}
diff --git a/modules/common/openssh.nix b/modules/common/openssh.nix
new file mode 100644
index 0000000..4b80809
--- /dev/null
+++ b/modules/common/openssh.nix
@@ -0,0 +1,58 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.openssh;
+in {
+ options.nixfiles.modules.openssh.client.enable =
+ mkEnableOption "OpenSSH client";
+
+ config = mkIf cfg.client.enable {
+ hm = {
+ home.packages = with pkgs; [mosh sshfs];
+
+ programs.ssh = {
+ enable = true;
+
+ hashKnownHosts = true;
+
+ controlMaster = "auto";
+ controlPersist = "24H";
+
+ serverAliveCountMax = 30;
+ serverAliveInterval = 60;
+
+ matchBlocks = let
+ mkBlock = name: {
+ hostname ? name,
+ port ? 22022, # NOTE This is not the default OpenSSH port.
+ user ? my.username,
+ identityFile ? "${config.my.home}/.ssh/${my.username}_${my.ssh.type}",
+ extraAttrs ? {},
+ }:
+ nameValuePair name ({inherit hostname port user identityFile;}
+ // extraAttrs);
+
+ internalServers =
+ mapAttrs' mkBlock
+ (mapAttrs (name: _: {
+ hostname = "${name}.${my.domain.shire}";
+ }) (filterAttrs (_: attr:
+ hasAttr "wireguard" attr
+ && attr.isHeadless)
+ my.configurations));
+ in
+ internalServers
+ // (mapAttrs' mkBlock {
+ gitolite = {
+ user = "git";
+ hostname = "git.${my.domain.shire}";
+ };
+ });
+ };
+ };
+ };
+}
diff --git a/modules/common/password-store.nix b/modules/common/password-store.nix
new file mode 100644
index 0000000..1de8a55
--- /dev/null
+++ b/modules/common/password-store.nix
@@ -0,0 +1,33 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.password-store;
+in {
+ options.nixfiles.modules.password-store.enable =
+ mkEnableOption "the standard UNIX password manager";
+
+ config = mkIf cfg.enable {
+ hm.programs = {
+ password-store = {
+ enable = true;
+
+ package = pkgs.pass.withExtensions (p: with p; [pass-otp]);
+
+ settings.PASSWORD_STORE_DIR = "${config.my.home}/.password-store";
+ };
+
+ # https://github.com/NixOS/nixpkgs/issues/183604
+ bash.initExtra = let
+ completions = "${config.hm.programs.password-store.package}/share/bash-completion/completions";
+ in
+ mkAfter ''
+ source ${completions}/pass-otp
+ source ${completions}/pass
+ '';
+ };
+ };
+}
diff --git a/modules/common/profiles/default.nix b/modules/common/profiles/default.nix
new file mode 100644
index 0000000..06ddaf4
--- /dev/null
+++ b/modules/common/profiles/default.nix
@@ -0,0 +1,90 @@
+{
+ config,
+ lib,
+ pkgs,
+ this,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.profiles.default;
+in {
+ imports = [
+ ./dev
+ ./headful.nix
+ ./headless.nix
+ (mkAliasOptionModule ["colourScheme"] [
+ "nixfiles"
+ "modules"
+ "profiles"
+ "default"
+ "colourScheme"
+ ])
+ ];
+
+ options.nixfiles.modules.profiles.default = {
+ enable =
+ mkEnableOption "The most default profile of them all."
+ // {
+ default = true;
+ };
+
+ colourScheme = let
+ mkColour = default:
+ mkOption {
+ type = types.str;
+ inherit default;
+ description = "Colour in a standard hexadecimal notation.";
+ example = "#000000";
+ };
+ in rec {
+ black = mkColour "#161719";
+ red = mkColour "#cc6666";
+ green = mkColour "#b5bd68";
+ yellow = mkColour "#f0c674";
+ blue = mkColour "#81a2be";
+ magenta = mkColour "#b294bb";
+ cyan = mkColour "#8abeb7";
+ white = mkColour "#c5c8c6";
+
+ brightBlack = mkColour "#969896";
+ brightRed = mkColour "#cc6666";
+ brightGreen = mkColour "#b5bd68";
+ brightYellow = mkColour "#f0c674";
+ brightBlue = mkColour "#81a2be";
+ brightMagenta = mkColour "#b294bb";
+ brightCyan = mkColour "#8abeb7";
+ brightWhite = mkColour "#ffffff";
+
+ background = black;
+ foreground = white;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = !(with this; isHeadless && isHeadful);
+ message = ''
+ The configuration cannot be both "headful" and "headless" at the same
+ time.
+ '';
+ }
+ ];
+
+ nixfiles.modules = {
+ htop.enable = true;
+ tmux.enable = true;
+ vim.enable = true;
+ };
+
+ time.timeZone = "Europe/Moscow";
+
+ environment.systemPackages = with pkgs; [
+ ddrescue
+ file
+ git
+ gnupg
+ tree
+ ];
+ };
+}
diff --git a/modules/common/profiles/dev/containers.nix b/modules/common/profiles/dev/containers.nix
new file mode 100644
index 0000000..cc24ab3
--- /dev/null
+++ b/modules/common/profiles/dev/containers.nix
@@ -0,0 +1,76 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.profiles.dev.containers;
+in {
+ options.nixfiles.modules.profiles.dev.containers.enable =
+ mkEnableOption "Tools for working with containers and container orchestration"
+ // {
+ default = config.nixfiles.modules.profiles.dev.default.enable;
+ };
+
+ config = mkIf cfg.enable {
+ hm = {
+ home = {
+ sessionVariables = {
+ MINIKUBE_IN_STYLE = "false";
+ WERF_DEV = "true";
+ WERF_INSECURE_REGISTRY = "true";
+ WERF_LOG_DEBUG = "true";
+ WERF_LOG_PRETTY = "false";
+ WERF_LOG_VERBOSE = "true";
+ WERF_SYNCHRONIZATION = ":local";
+ WERF_TELEMETRY = "false";
+ };
+
+ packages = with pkgs; [
+ argocd
+ chart-testing
+ clusterctl
+ cmctl
+ datree
+ helm
+ istioctl
+ kubeconform
+ kubectl
+ kubectl-doctor
+ kubectl-images
+ kubectl-tree
+ kubectx
+ kubelogin
+ kubent
+ kubescape
+ kubeseal
+ kubespy
+ minikube
+ skaffold
+ skopeo
+ stern
+ telepresence
+ werf
+ ];
+ };
+
+ programs.bash = {
+ shellAliases = with pkgs; {
+ b = "${buildah}/bin/buildah";
+ h = "${helm}/bin/helm";
+ k = "${kubectl}/bin/kubectl";
+ kns = "${kubectx}/bin/kubens";
+ ktx = "${kubectx}/bin/kubectx";
+ };
+ initExtra = mkAfter ''
+ _complete_alias b _buildah buildah
+ _complete_alias h __start_helm helm
+ _complete_alias k __start_kubectl kubectl
+ _complete_alias kns _kube_namespaces kubens
+ _complete_alias ktx _kube_contexts kubectx
+ '';
+ };
+ };
+ };
+}
diff --git a/modules/common/profiles/dev/default.nix b/modules/common/profiles/dev/default.nix
new file mode 100644
index 0000000..b05aeac
--- /dev/null
+++ b/modules/common/profiles/dev/default.nix
@@ -0,0 +1,89 @@
+{
+ config,
+ lib,
+ pkgs,
+ this,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.profiles.dev.default;
+in {
+ imports = [
+ ./containers.nix
+ ./sql.nix
+ ];
+
+ options.nixfiles.modules.profiles.dev.default.enable =
+ mkEnableOption "Catch-all profile for stuff related to software development and etc.";
+
+ config = mkIf cfg.enable {
+ nixfiles.modules = {
+ bat.enable = true;
+ curl.enable = true;
+ direnv.enable = true;
+ git.client.enable = true;
+ gnupg.enable = true;
+ nmap.enable = true;
+ wget.enable = true;
+ };
+
+ hm.home = {
+ file = {
+ ".editorconfig".source = ./editorconfig.ini;
+
+ ".gdbinit".source = ./gdbinit;
+
+ ".ghc/ghci.conf".source = ./ghci.conf;
+
+ ".stack/config.yaml".text = generators.toYAML {} {
+ templates.params = rec {
+ author-name = my.fullname;
+ author-email = my.email;
+ copyright = "Copyright (c) ${author-name} <${author-email}>";
+ github-username = my.username;
+ };
+ };
+
+ ".stack/global-project/stack.yaml".text = generators.toYAML {} {
+ packages = [];
+ resolver = "lts-20.3";
+ };
+ };
+
+ sessionVariables = with config.dirs; rec {
+ CABAL_DIR = "${config.my.home}/.cabal";
+ CABAL_CONFIG = pkgs.writeText "cabal-config" ''
+ repository hackage.haskell.org
+ url: https://hackage.haskell.org/
+ secure: True
+
+ jobs: $ncpus
+
+ remote-repo-cache: ${CABAL_DIR}/packages
+
+ world-file: ${CABAL_DIR}/world
+
+ logs-dir: ${CABAL_DIR}/logs
+ build-summary: ${CABAL_DIR}/logs/build.log
+
+ installdir: ${CABAL_DIR}/bin
+ extra-prog-path: ${CABAL_DIR}/bin
+ '';
+
+ STACK_ROOT = "${config.my.home}/.stack";
+
+ CARGO_HOME = "${config.my.home}/.cargo";
+
+ GOPATH = "${config.my.home}/.go";
+
+ PYTHONSTARTUP = ./pystartup.py;
+ };
+
+ packages = with pkgs; [
+ htmlq
+ jq
+ yq
+ ];
+ };
+ };
+}
diff --git a/modules/common/profiles/dev/editorconfig.ini b/modules/common/profiles/dev/editorconfig.ini
new file mode 100644
index 0000000..17b0317
--- /dev/null
+++ b/modules/common/profiles/dev/editorconfig.ini
@@ -0,0 +1,83 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+max_line_length = 80
+trim_trailing_whitespace = true
+
+[*.nix]
+indent_size = 2
+indent_style = space
+
+[*.{S,s,asm}]
+indent_size = 4
+indent_style = tab
+
+[*.{C,H,c,c++,cc,cpp,cxx,h,h++,hh,hpp,hxx}]
+indent_size = 4
+indent_style = tab
+
+[*.{cl,clj,el,l,lisp,lsp,rkt,scm,ss}]
+indent_size = 2
+indent_style = space
+
+[*.go]
+indent_size = 4
+indent_style = tab
+
+[*.{py,pyx}]
+indent_size = 4
+indent_style = space
+
+[*.{hs,lhs}]
+indent_size = 2
+indent_style = space
+
+[*.{html,xhtml,xml}]
+indent_size = 4
+indent_style = tab
+
+[*.json]
+indent_size = 2
+indent_style = space
+
+[*.{yaml,yml}]
+indent_size = 2
+indent_style = space
+
+[*.{toml,tml}]
+indent_size = 4
+indent_style = space
+
+[*.{py,pyx}]
+indent_size = 4
+indent_style = space
+max_line_length = 72
+
+[*.zig]
+indent_size = 4
+indent_style = tab
+
+[configure.ac]
+indent_size = 4
+indent_style = tab
+
+[{Makefile*,*.mk}]
+indent_size = 4
+indent_style = tab
+
+[{CMakeLists.txt,*.cmake}]
+indent_size = 8
+indent_style = tab
+
+[*.tex]
+indent_size = 4
+indent_style = tab
+
+[*.{md,adoc,rtf,txt}]
+indent_size = 4
+indent_style = tab
diff --git a/modules/common/profiles/dev/gdbinit b/modules/common/profiles/dev/gdbinit
new file mode 100644
index 0000000..e266236
--- /dev/null
+++ b/modules/common/profiles/dev/gdbinit
@@ -0,0 +1,41 @@
+set confirm off
+set verbose off
+set editing off
+
+set history expansion on
+
+set height 0
+set width 0
+
+handle SIGALRM nostop print nopass
+handle SIGBUS stop print nopass
+handle SIGPIPE nostop print nopass
+handle SIGSEGV stop print nopass
+
+set print address on
+set print elements 0
+set print object on
+set print pretty on
+set print repeats 0
+set print static-members on
+set print vtbl on
+
+set output-radix 10
+
+set demangle-style gnu-v3
+
+set disassembly-flavor intel
+
+alias iv=info variables
+
+alias da=disassemble
+
+define fs
+ finish
+ step
+end
+
+define btc
+ backtrace
+ continue
+end
diff --git a/modules/common/profiles/dev/ghci.conf b/modules/common/profiles/dev/ghci.conf
new file mode 100644
index 0000000..d672167
--- /dev/null
+++ b/modules/common/profiles/dev/ghci.conf
@@ -0,0 +1,35 @@
+:set -XBinaryLiterals
+:set -XFlexibleContexts
+:set -XNoMonomorphismRestriction
+
+:seti -XConstraintKinds
+:seti -XDataKinds
+:seti -XDeriveFunctor
+:seti -XFlexibleInstances
+:seti -XFunctionalDependencies
+:seti -XGADTs
+:seti -XLambdaCase
+:seti -XMagicHash
+:seti -XMultiParamTypeClasses
+:seti -XMultiWayIf
+:seti -XOverloadedLabels
+:seti -XPackageImports
+:seti -XPolyKinds
+:seti -XRankNTypes
+:seti -XScopedTypeVariables
+:seti -XStandaloneDeriving
+:seti -XTupleSections
+:seti -XTypeFamilies
+:seti -XTypeOperators
+:seti -XUndecidableInstances
+
+:set +c
+:set +m
+:set +r
+:set +s
+:set +t
+
+:set prompt "\ESC[1;34m>\ESC[m\STX "
+:set prompt-cont "\ESC[1;94m|\ESC[m\STX "
+
+:def hoogle \x -> pure (":!hoogle --color --count=10 \"" ++ x ++ "\"")
diff --git a/modules/common/profiles/dev/pystartup.py b/modules/common/profiles/dev/pystartup.py
new file mode 100644
index 0000000..adde66c
--- /dev/null
+++ b/modules/common/profiles/dev/pystartup.py
@@ -0,0 +1,121 @@
+import atexit
+import os
+import readline
+import rlcompleter
+import sys
+from code import InteractiveConsole
+from tempfile import mkstemp
+
+readline.parse_and_bind("tab: complete")
+
+
+class TermColors(dict):
+ color_templates = (
+ ("Normal", "0"),
+ ("Black", "0;30"),
+ ("Red", "0;31"),
+ ("Green", "0;32"),
+ ("Brown", "0;33"),
+ ("Blue", "0;34"),
+ ("Purple", "0;35"),
+ ("Cyan", "0;36"),
+ ("LightGray", "0;37"),
+ ("DarkGray", "1;30"),
+ ("LightRed", "1;31"),
+ ("LightGreen", "1;32"),
+ ("Yellow", "1;33"),
+ ("LightBlue", "1;34"),
+ ("LightPurple", "1;35"),
+ ("LightCyan", "1;36"),
+ ("White", "1;37"),
+ )
+ color_base = "\001\033[%sm\002"
+
+ def __init__(self):
+ self.update(dict([(k, self.color_base % v) for k, v in self.color_templates]))
+
+
+class Completer(object):
+ def save_history(self):
+ import readline
+
+ readline.write_history_file(self.python_histfile)
+
+ def __init__(self):
+ self.python_dir = os.path.expanduser("%s/python" % os.environ["XDG_DATA_HOME"])
+
+ if not os.path.exists(self.python_dir):
+ os.mkdir(self.python_dir)
+
+ self.python_histfile = os.path.expanduser("%s/history" % self.python_dir)
+
+ if os.path.exists(self.python_histfile):
+ readline.read_history_file(self.python_histfile)
+
+ readline.set_history_length(1000)
+ atexit.register(self.save_history)
+
+
+def DisplayHook(value):
+ if value is not None:
+ try:
+ import __builtin__
+
+ __builtin__._ = value
+ except ImportError:
+ __builtins__._ = value
+
+ import pprint
+
+ pprint.pprint(value)
+ del pprint
+
+
+class EditableBufferInteractiveConsole(InteractiveConsole):
+ def __init__(self, *args, **kwargs):
+ self.last_buffer = []
+ InteractiveConsole.__init__(self, *args, **kwargs)
+
+ def runsource(self, source, *args):
+ self.last_buffer = [source.encode("utf-8")]
+ return InteractiveConsole.runsource(self, source, *args)
+
+ def raw_input(self, *args):
+ line = InteractiveConsole.raw_input(self, *args)
+
+ if line == EDIT_CMD:
+ tmp_fd, tmp_file = mkstemp(".py")
+
+ os.write(tmp_fd, b"\n".join(self.last_buffer))
+ os.close(tmp_fd)
+
+ os.system("%s %s" % (EDITOR, tmp_file))
+
+ line = open(tmp_file).read()
+
+ os.unlink(tmp_file)
+ tmp_file = ""
+
+ lines = line.split("\n")
+
+ for i in range(len(lines) - 1):
+ self.push(lines[i])
+
+ line = lines[-1]
+ return line
+
+
+TC = TermColors()
+ps1 = "%sλ%s %s>%s "
+sys.ps1 = ps1 % (TC["Blue"], TC["Normal"], TC["White"], TC["Normal"])
+ps2 = " %s…%s %s>%s "
+sys.ps2 = ps2 % (TC["Blue"], TC["Normal"], TC["White"], TC["Normal"])
+sys.displayhook = DisplayHook
+
+C = Completer()
+EDITOR = os.environ.get("EDITOR", "vim")
+EDIT_CMD = ":e"
+C = EditableBufferInteractiveConsole(locals=locals())
+C.interact(banner="")
+
+sys.exit()
diff --git a/modules/common/profiles/dev/sql.nix b/modules/common/profiles/dev/sql.nix
new file mode 100644
index 0000000..7a2a09c
--- /dev/null
+++ b/modules/common/profiles/dev/sql.nix
@@ -0,0 +1,101 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.profiles.dev.sql;
+in {
+ options.nixfiles.modules.profiles.dev.sql.enable =
+ mkEnableOption "SQL stuff and database management tools"
+ // {
+ default = config.nixfiles.modules.profiles.dev.default.enable;
+ };
+
+ config = mkIf cfg.enable {
+ hm = {
+ home.packages = with pkgs; [
+ dbeaver
+ pgcli
+ litecli
+ ];
+
+ xdg = let
+ mainSection = {
+ destructive_warning = "True";
+ enable_pager = "True";
+ keyword_casing = "auto";
+ less_chatty = "True";
+ log_file = "/dev/null";
+ log_level = "CRITICAL";
+ multi_line = "False";
+ syntax_style = "default";
+ table_format = "fancy_grid";
+ };
+
+ colorsSection = with config.colourScheme; {
+ "arg-toolbar" = "noinherit bold";
+ "arg-toolbar.text" = "nobold";
+ "bottom-toolbar" = "bg:${black} ${white}";
+ "bottom-toolbar.off" = "bg:${black} ${brightBlack}";
+ "bottom-toolbar.on" = "bg:${black} ${brightWhite}";
+ "bottom-toolbar.transaction.failed" = "bg:${black} ${red} bold";
+ "bottom-toolbar.transaction.valid" = "bg:${black} ${green} bold";
+ "completion-menu.completion" = "bg:${black} ${white}";
+ "completion-menu.completion.current" = "bg:${white} ${black}";
+ "completion-menu.meta.completion" = "bg:${black} ${yellow}";
+ "completion-menu.meta.completion.current" = "bg:${yellow} ${black}";
+ "completion-menu.multi-column-meta" = "bg:${yellow} ${black}";
+ "scrollbar" = "bg:${black}";
+ "scrollbar.arrow" = "bg:${black}";
+ "search" = "bg:${magenta} ${brightWhite}";
+ "search-toolbar" = "noinherit bold";
+ "search-toolbar.text" = "nobold";
+ "search.current" = "bg:${green} ${brightWhite}";
+ "selected" = "bg:${blue} ${brightWhite}";
+ "system-toolbar" = "noinherit bold";
+ };
+
+ mkCliConfig = {
+ name,
+ custom,
+ }: {
+ "${name}/config" = {
+ text = generators.toINI {} {
+ main = mainSection // custom;
+ colors = mapAttrs (_: v: "'${v}'") colorsSection;
+ };
+ };
+ };
+ in {
+ configFile = mkMerge (map mkCliConfig [
+ {
+ name = "pgcli";
+ custom = {
+ auto_expand = "True";
+ casing_file = "/dev/null";
+ expand = "True";
+ history_file = "/dev/null";
+ keyring = "False";
+ multi_line_mode = "psql";
+ on_error = "STOP";
+ prompt = "'\\u@\\h:\\d> '";
+ vi = "True";
+ };
+ }
+ {
+ name = "litecli";
+ custom = {
+ audit_log = "/dev/null";
+ key_bindings = "vi";
+ prompt = "'\\d> '";
+ prompt_continuation = "'-> '";
+ auto_vertical_output = "True";
+ };
+ }
+ ]);
+ };
+ };
+ };
+}
diff --git a/modules/common/profiles/headful.nix b/modules/common/profiles/headful.nix
new file mode 100644
index 0000000..eec14c5
--- /dev/null
+++ b/modules/common/profiles/headful.nix
@@ -0,0 +1,107 @@
+{
+ config,
+ lib,
+ pkgs,
+ this,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.profiles.headful;
+in {
+ options.nixfiles.modules.profiles.headful.enable =
+ mkEnableOption "headful profile" // {default = this.isHeadful;};
+
+ config = mkIf cfg.enable {
+ nixfiles.modules = {
+ profiles.dev.default.enable = true;
+
+ alacritty.enable = true;
+ aria2.enable = true;
+ emacs.enable = true;
+ mpv.enable = true;
+ openssh.client.enable = true;
+ password-store.enable = true;
+ };
+
+ hm = {
+ home = {
+ file.".digrc".text = ''
+ +answer
+ +multiline
+ +recurse
+ '';
+
+ packages = with pkgs; [
+ fd
+ ripgrep
+ ripgrep-all
+ sd
+ ];
+ };
+
+ accounts.email = {
+ maildirBasePath = "${config.my.home}/mail";
+
+ accounts = let
+ mkAccount = attrs:
+ mkMerge [
+ {
+ mbsync = {
+ enable = true;
+ create = "both";
+ expunge = "both";
+ patterns = ["*"];
+ };
+ msmtp.enable = true;
+ mu.enable = true;
+ }
+ attrs
+ ];
+
+ pass = path: "${pkgs.pass}/bin/pass show ${path}";
+ in {
+ shire = mkAccount {
+ address = my.email;
+ gpg = {
+ inherit (my.pgp) key;
+ signByDefault = true;
+ encryptByDefault = false;
+ };
+
+ primary = true;
+
+ imap.host = "shire.me";
+ smtp.host = "shire.me";
+ userName = "azahi@shire.me";
+ passwordCommand = pass "email/shire.me/azahi";
+ };
+
+ yahoo = mkAccount {
+ address = "a.gondor@yahoo.com";
+
+ imap.host = "imap.yahoo.com";
+ smtp.host = "smtp.yahoo.com";
+ userName = "a.gondor@yahoo.com";
+ passwordCommand = pass "email/yahoo.com/a.gondor";
+ };
+ };
+ };
+
+ programs = {
+ mbsync.enable = true;
+ msmtp.enable = true;
+ mu.enable = true;
+ };
+ };
+
+ environment.systemPackages = with pkgs; [
+ (aspellWithDicts (p: with p; [en ru]))
+ arping
+ dnsutils
+ inetutils
+ ldns
+ socat
+ tcpdump
+ ];
+ };
+}
diff --git a/modules/common/profiles/headless.nix b/modules/common/profiles/headless.nix
new file mode 100644
index 0000000..cc7c326
--- /dev/null
+++ b/modules/common/profiles/headless.nix
@@ -0,0 +1,23 @@
+{
+ config,
+ lib,
+ pkgs,
+ this,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.profiles.headless;
+in {
+ options.nixfiles.modules.profiles.headless.enable =
+ mkEnableOption "headless profile" // {default = this.isHeadless;};
+
+ config = mkIf cfg.enable {
+ hm.home.file = {
+ ".hushlogin".text = "";
+ ".bash_history".source =
+ config.hm.lib.file.mkOutOfStoreSymlink "/dev/null";
+ };
+
+ environment.systemPackages = with pkgs; [alacritty.terminfo];
+ };
+}
diff --git a/modules/common/qutebrowser.nix b/modules/common/qutebrowser.nix
new file mode 100644
index 0000000..68a41a5
--- /dev/null
+++ b/modules/common/qutebrowser.nix
@@ -0,0 +1,536 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.qutebrowser;
+in {
+ options.nixfiles.modules.qutebrowser.enable = mkEnableOption "Qutebrowser";
+
+ config = mkIf cfg.enable {
+ hm.programs.qutebrowser = with config.nixfiles.modules; {
+ enable = true;
+
+ package = pkgs.qutebrowser.override {
+ withMediaPlayback = false;
+ withPdfReader = false;
+ };
+
+ keyBindings.normal = mkIf mpv.enable {
+ "z" = let
+ mpv = "${config.hm.programs.mpv.package}/bin/mpv";
+ in "hint links spawn --detach ${mpv} {hint-url}";
+ };
+
+ searchEngines = rec {
+ aliexpress = "https://www.aliexpress.com/wholesale?SearchText={}";
+ ansible = "https://galaxy.ansible.com/search?keywords={}";
+ arch = "https://wiki.archlinux.org/?search={}";
+ crates = "https://crates.io/search?q={}";
+ crawl = "http://crawl.chaosforge.org/index.php?search={}";
+ discogs = "https://www.discogs.com/search/?q={}";
+ dockerdocs = "https://docs.docker.com/search/?q={}";
+ dockerhub = "https://hub.docker.com/search?q={}";
+ doublegis = "https://2gis.ru/search/{}";
+ duckduckgo = "https://duckduckgo.com/?q={}'";
+ dwarffortress = "https://dwarffortresswiki.org/index.php?search={}";
+ ebay = "https://www.ebay.com/sch/i.html?_nkw={}";
+ ecosia = "https://www.ecosia.org/search?q={}";
+ factorio = "https://wiki.factorio.com/index.php?search={}";
+ genius = "https://genius.com/search?q={}";
+ github = "https://github.com/search?q={}";
+ godocs = "https://godocs.io/?q={}";
+ gogdb = "https://www.gogdb.org/products?search={}";
+ google = "https://www.google.com/search?q={}";
+ google-images = "https://www.google.com/search?q={}&tbm=isch";
+ gopkgs = "https://pkg.go.dev/search?q={}";
+ habr = "https://habr.com/ru/search/?q={}";
+ hackage = "https://hackage.haskell.org/packages/search?terms={}";
+ hackernews = "https://hn.algolia.com/?q={}";
+ headhunter = "https://hh.ru/search/vacancy?st=searchVacancy&text={}";
+ hoogle = "https://hoogle.haskell.org/?hoogle={}";
+ jisho = "https://jisho.org/search/{}";
+ kotobank = "https://kotobank.jp/gs/?q={}";
+ kubernetes = "https://kubernetes.io/search/?q={}";
+ lastfm = "https://www.last.fm/search?q={}";
+ lobsters = "https://lobste.rs/search?q=test{}";
+ mdn = "https://developer.mozilla.org/en-US/search?q={}";
+ melpa = "https://melpa.org/#/?q={}";
+ moddb = "https://www.moddb.com/search?q={}";
+ musicbrainz = "https://musicbrainz.org/search?query={}";
+ nix-issues = "https://github.com/NixOS/nix/issues?q={}";
+ nix-prs = "https://github.com/NixOS/nix/pulls?q={}";
+ nixos-flakes = "https://search.nixos.org/flakes?query={}";
+ nixos-options = "https://search.nixos.org/options?query={}";
+ nixos-packages = "https://search.nixos.org/packages?query={}";
+ nixos-wiki = "https://nixos.wiki/index.php?search={}";
+ nixpkgs-issues = "https://github.com/NixOS/nixpkgs/issues?q={}";
+ nixpkgs-prs = "https://github.com/NixOS/nixpkgs/pulls?q={}";
+ openstreetmap = "https://www.openstreetmap.org/search?query={}";
+ ozon = "https://www.ozon.ru/search/?text={}";
+ protondb = "https://www.protondb.com/search?q={}";
+ pypi = "https://pypi.org/search/?q={}";
+ pythondocs = "https://docs.python.org/3/search.html?q={}";
+ rateyourmusic = "https://rateyourmusic.com/search?searchterm={}";
+ riichi = "https://riichi.wiki/index.php?search={}";
+ rustdoc = "https://doc.rust-lang.org/std/?search={}";
+ searx = "https://searx.tiekoetter.com/search?q={}";
+ slashdot = "https://slashdot.org/index2.pl?fhfilter={}";
+ sourcehut = "https://sr.ht/projects?search={}";
+ steam = "https://store.steampowered.com/search/?term={}";
+ steamdb = "https://steamdb.info/search/?a=app&q={}";
+ ubuntu = "https://wiki.ubuntu.com/Home?action=fullsearch&value={}";
+ wikipedia-en = "https://en.wikipedia.org/w/index.php?search={}";
+ wikipedia-ru = "https://ru.wikipedia.org/w/index.php?search={}";
+ wikipedia-ja = "https://ja.wikipedia.org/w/index.php?search={}";
+ wolphramalpha = "https://www.wolframalpha.com/input/?i={}";
+ yahoo = "https://yahoo.com/search/?text={}";
+ yahoo-images = "https://yahoo.com/images/search?text={}";
+ yahoo-market = "https://market.yahoo.com/search?text={}";
+ youtube = "https://yewtu.be/search?q={}";
+
+ aw = arch;
+ d = duckduckgo;
+ do = dockerhub;
+ docker = dockerhub;
+ dod = dockerdocs;
+ g = google;
+ gh = github;
+ h = hoogle;
+ k = kubernetes;
+ mb = musicbrainz;
+ n = nixos-options;
+ nw = nixos-wiki;
+ py = pypi;
+ pyd = pythondocs;
+ rym = rateyourmusic;
+ s = searx;
+ sh = sourcehut;
+ sr = sourcehut;
+ w = wikipedia-en;
+ wen = wikipedia-en;
+ wja = wikipedia-ja;
+ wru = wikipedia-ru;
+ y = yahoo;
+ yt = youtube;
+ };
+
+ settings = {
+ changelog_after_upgrade = "never";
+
+ content = {
+ autoplay = false;
+ cookies.accept = "all";
+ default_encoding = "utf-8";
+ desktop_capture = "ask";
+ dns_prefetch = false;
+ geolocation = false;
+ headers.do_not_track = true;
+ javascript.enabled = true;
+ prefers_reduced_motion = true;
+ webgl = true;
+
+ blocking = {
+ enabled = true;
+ method = "adblock";
+ adblock.lists = [
+ "https://easylist.to/easylist/easylist.txt"
+ "https://easylist.to/easylist/easyprivacy.txt"
+ "https://easylist.to/easylist/fanboy-social.txt"
+ "https://secure.fanboy.co.nz/fanboy-annoyance.txt"
+ "https://secure.fanboy.co.nz/fanboy-cookiemonster.txt"
+ ];
+ };
+ };
+
+ completion = {
+ height = "50%";
+ show = "auto";
+ shrink = true;
+ timestamp_format = "%y-%m-%d";
+ min_chars = 3;
+ open_categories = ["bookmarks" "quickmarks" "history"];
+
+ scrollbar = {
+ width = 0;
+ padding = 0;
+ };
+ };
+
+ downloads = {
+ location = {
+ directory = config.userDirs.download;
+ prompt = true;
+ };
+ remove_finished = 0;
+ };
+
+ editor.command = [
+ (
+ if alacritty.enable
+ then "${pkgs.alacritty}/bin/alacritty"
+ else "${pkgs.xterm}/bin/xterm"
+ )
+ "-e"
+ "${config.programs.vim.package}/bin/vim"
+ "-f"
+ "{}"
+ ];
+
+ hints = {
+ auto_follow = "unique-match";
+ auto_follow_timeout = 0;
+ border = "0px";
+ min_chars = 1;
+ scatter = false;
+ uppercase = false;
+ };
+
+ hints.radius = 0;
+ keyhint.radius = 0;
+ prompt.radius = 0;
+
+ scrolling = {
+ bar = "never";
+ smooth = false;
+ };
+
+ spellcheck.languages = ["en-US" "en-GB" "ru-RU"];
+
+ statusbar.position = "bottom";
+
+ tabs = {
+ position = "top";
+
+ title = {
+ alignment = "left";
+ format = "{audio}{index} : {current_title}";
+ format_pinned = "{audio}{index}";
+ };
+
+ min_width = -1;
+ max_width = -1;
+
+ indicator.width = 0;
+
+ pinned = {
+ shrink = true;
+ frozen = false;
+ };
+
+ close_mouse_button = "middle";
+ mousewheel_switching = false;
+
+ background = true;
+ select_on_remove = "next";
+ new_position = {
+ related = "next";
+ unrelated = "last";
+ };
+
+ favicons = {
+ show = "pinned";
+ scale = 0.75;
+ };
+ };
+
+ url = rec {
+ default_page = "about:blank";
+ start_pages = [default_page];
+ };
+
+ window = {
+ hide_decoration = false;
+ title_format = "{perc}{current_title}{title_sep}qutebrowser";
+ };
+
+ colors = with config.colourScheme; {
+ completion = rec {
+ fg = white;
+ match.fg = red;
+ odd.bg = black;
+ even.bg = odd.bg;
+ category = {
+ fg = white;
+ bg = black;
+ border = {
+ top = black;
+ bottom = black;
+ };
+ };
+ item.selected = {
+ fg = black;
+ bg = white;
+ border = {
+ top = white;
+ bottom = white;
+ };
+ };
+ scrollbar = {
+ fg = white;
+ bg = black;
+ };
+ };
+ contextmenu = {
+ menu = {
+ fg = white;
+ bg = black;
+ };
+ selected = {
+ fg = black;
+ bg = white;
+ };
+ disabled = {
+ fg = brightBlack;
+ bg = black;
+ };
+ };
+ downloads = {
+ bar.bg = black;
+ start = {
+ fg = green;
+ bg = black;
+ };
+ stop = {
+ fg = yellow;
+ bg = black;
+ };
+ error = {
+ fg = red;
+ bg = black;
+ };
+ system = {
+ fg = "none";
+ bg = "none";
+ };
+ };
+ hints = {
+ fg = white;
+ match.fg = red;
+ bg = black;
+ };
+ keyhint = {
+ fg = white;
+ suffix.fg = red;
+ bg = black;
+ };
+ messages = {
+ error = rec {
+ bg = black;
+ fg = red;
+ border = bg;
+ };
+ info = rec {
+ fg = blue;
+ bg = black;
+ border = bg;
+ };
+ warning = rec {
+ fg = yellow;
+ bg = black;
+ border = bg;
+ };
+ };
+ prompts = rec {
+ fg = white;
+ bg = black;
+ selected = {
+ fg = black;
+ bg = white;
+ };
+ border = bg;
+ };
+ statusbar = {
+ normal = {
+ bg = black;
+ fg = white;
+ };
+ command = {
+ bg = black;
+ fg = white;
+ };
+ insert = {
+ bg = green;
+ fg = black;
+ };
+ passthrough = {
+ bg = blue;
+ fg = black;
+ };
+ private = {
+ bg = magenta;
+ fg = black;
+ };
+ url = {
+ fg = blue;
+ hover.fg = brightBlue;
+ success = {
+ http.fg = brightGreen;
+ https.fg = brightGreen;
+ };
+ warn.fg = brightYellow;
+ error.fg = brightRed;
+ };
+ };
+ tabs = rec {
+ bar.bg = black;
+ even = {
+ bg = black;
+ fg = white;
+ };
+ odd = with even; {inherit bg fg;};
+ selected = rec {
+ even = {
+ bg = white;
+ fg = black;
+ };
+ odd = with even; {inherit bg fg;};
+ };
+ pinned = rec {
+ even = {
+ bg = brightBlack;
+ fg = brightWhite;
+ };
+ odd = with even; {inherit bg fg;};
+ };
+ indicator = {
+ start = green;
+ stop = yellow;
+ error = red;
+ system = "none";
+ };
+ };
+ webpage = {
+ bg = "white";
+ darkmode = {
+ enabled = false;
+ algorithm = "lightness-cielab";
+ contrast = 0.0;
+ grayscale = {
+ all = false;
+ images = 0.0;
+ };
+ policy = {
+ images = "smart";
+ page = "smart";
+ };
+ threshold = {
+ background = 0;
+ text = 256;
+ };
+ };
+ preferred_color_scheme = "auto";
+ };
+ };
+
+ fonts =
+ (with config.fontScheme.monospaceFont; {
+ default_family = family;
+ default_size = (toString size) + "pt";
+ })
+ // {
+ web = with config.fontScheme; {
+ family = rec {
+ standard = sans_serif;
+ fixed = monospaceFont.family;
+ serif = serifFont.family;
+ sans_serif = sansSerifFont.family;
+ cursive = null;
+ fantasy = null;
+ };
+ size = rec {
+ default = sansSerifFont.size;
+ default_fixed = monospaceFont.size;
+ minimum = 0;
+ minimum_logical = default / 2;
+ };
+ };
+ }
+ // mapListToAttrs (_: "default_size default_family") [
+ "completion.category"
+ "completion.entry"
+ "contextmenu"
+ "debug_console"
+ "downloads"
+ "hints"
+ "keyhint"
+ "messages.error"
+ "messages.info"
+ "messages.warning"
+ "prompts"
+ "statusbar"
+ ];
+
+ qt = mkIf kde.enable {
+ force_platform = null;
+ force_platformtheme = "KDE";
+ };
+ };
+
+ extraConfig =
+ (let
+ mkPaddingDictionary = {
+ name,
+ bottom,
+ left,
+ right,
+ top,
+ }: let
+ n = "c.${name}.padding";
+ b = "'bottom': ${toString bottom}";
+ l = "'left': ${toString left}";
+ r = "'right': ${toString right}";
+ t = "'top': ${toString top}";
+ in "${n} = {${b}, ${l}, ${r}, ${t}}";
+
+ final = map mkPaddingDictionary [
+ {
+ name = "hints";
+ bottom = 3;
+ left = 3;
+ right = 3;
+ top = 3;
+ }
+ {
+ name = "statusbar";
+ bottom = 1;
+ left = 0;
+ right = 3;
+ top = 1;
+ }
+ {
+ name = "tabs";
+ bottom = 1;
+ left = 6;
+ right = 6;
+ top = 1;
+ }
+ ];
+ in
+ concatStringsSep "\n" final + "\n")
+ + (let
+ allowSetting = setting: url: "config.set('content.${setting}', True, '${url}')";
+
+ allowMediaCaptureSetting = url: [
+ (allowSetting "desktop_capture" url)
+ (allowSetting "media.audio_video_capture" url)
+ ];
+ allowedMediaCapture = flatten (map allowMediaCaptureSetting [
+ "https://discord.com"
+ "https://web.telegram.org"
+ ]);
+
+ allowNotificationsSetting = allowSetting "notifications.enabled";
+ allowedNotifications = map allowNotificationsSetting [
+ "https://discord.com"
+ "https://web.telegram.org"
+ ];
+
+ final = allowedMediaCapture ++ allowedNotifications;
+ in
+ concatStringsSep "\n" final + "\n");
+ };
+ };
+}
diff --git a/modules/common/subversion.nix b/modules/common/subversion.nix
new file mode 100644
index 0000000..077f449
--- /dev/null
+++ b/modules/common/subversion.nix
@@ -0,0 +1,52 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.subversion;
+in {
+ options.nixfiles.modules.subversion.enable = mkEnableOption "Subversion";
+
+ config = mkIf cfg.enable {
+ nixfiles.modules.gnupg.enable = true;
+
+ hm.home = {
+ file = {
+ ".subversion/config".text = generators.toINI {} {
+ auth = {
+ password-stores = "gpg-agent";
+ ssl-client-cert-file-prompt = "no";
+ store-passwords = "yes";
+ store-auth-creds = "yes";
+ };
+ helpers = {
+ editor-cmd = "${config.programs.vim.package}/bin/vim";
+ diff-cmd = "${pkgs.colordiff}/bin/colordiff";
+ };
+ miscellany = {
+ global-ignores = with config.hm.programs.git;
+ optionalString (ignores != []) (concatStringsSep " " ignores);
+ diff-ignore-content-type = "no";
+ };
+ working-copy = {
+ exclusive-locking-clients = "svn";
+ exclusive-locking = true;
+ busy-timeout = 10000;
+ };
+ };
+
+ ".subversion/servers".text = generators.toINI {} {
+ global = {
+ store-auth-creds = "yes";
+ store-passwords = "yes";
+ store-plaintext-passwords = "yes";
+ };
+ };
+ };
+
+ packages = with pkgs; [(subversionClient.override {saslSupport = true;})];
+ };
+ };
+}
diff --git a/modules/common/tmux.nix b/modules/common/tmux.nix
new file mode 100644
index 0000000..e978f72
--- /dev/null
+++ b/modules/common/tmux.nix
@@ -0,0 +1,60 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.tmux;
+in {
+ options.nixfiles.modules.tmux.enable =
+ mkEnableOption "tmux";
+
+ config = mkIf cfg.enable {
+ hm.programs.tmux = {
+ enable = true;
+
+ aggressiveResize = true;
+ baseIndex = 1;
+ clock24 = true;
+ disableConfirmationPrompt = true;
+ escapeTime = 0;
+ historyLimit = 50000;
+ newSession = true;
+ resizeAmount = 10;
+ terminal = "screen-256color";
+
+ extraConfig = ''
+ set -g set-titles on
+
+ set -g status-left ""
+ set -g status-right ""
+
+ set -g detach-on-destroy off
+
+ set -g status-keys emacs
+ set -g mode-keys vi
+
+ bind h select-pane -L
+ bind j select-pane -D
+ bind k select-pane -U
+ bind l select-pane -R
+
+ bind -r H resize-pane -L 10
+ bind -r J resize-pane -D 10
+ bind -r K resize-pane -U 10
+ bind -r L resize-pane -R 10
+
+ bind < swap-pane -D
+ bind > swap-pane -U
+
+ bind , swap-window -t -1
+ bind . swap-window -t +1
+
+ bind Tab last-window
+
+ bind _ split-window -v
+ bind | split-window -h
+ '';
+ };
+ };
+}
diff --git a/modules/common/vim/default.nix b/modules/common/vim/default.nix
new file mode 100644
index 0000000..0328e10
--- /dev/null
+++ b/modules/common/vim/default.nix
@@ -0,0 +1,50 @@
+{
+ config,
+ lib,
+ pkgs,
+ this,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.vim;
+in {
+ options.nixfiles.modules.vim.enable = mkEnableOption "Vim";
+
+ config = mkIf cfg.enable {
+ programs.vim.package = with pkgs;
+ (vim_configurable.override {
+ features = "normal";
+ cscopeSupport = false;
+ darwinSupport = pkgs.stdenv.isDarwin;
+ guiSupport = false;
+ luaSupport = false;
+ multibyteSupport = false;
+ netbeansSupport = false;
+ nlsSupport = false;
+ perlSupport = false;
+ pythonSupport = false;
+ rubySupport = false;
+ tclSupport = false;
+ ximSupport = false;
+ })
+ .customize {
+ name = "vim";
+ vimrcConfig = {
+ customRC = readFile ./rc.vim;
+ packages.myVimPackage.start = with vimPlugins; [
+ editorconfig-vim
+ vim-eunuch
+ vim-nix
+ vim-sleuth
+ vim-surround
+ vim-unimpaired
+ ];
+ };
+ };
+
+ environment = {
+ systemPackages = [config.programs.vim.package];
+ variables.EDITOR = mkOverride 100 "vim";
+ };
+ };
+}
diff --git a/modules/common/vim/rc.vim b/modules/common/vim/rc.vim
new file mode 100644
index 0000000..945643a
--- /dev/null
+++ b/modules/common/vim/rc.vim
@@ -0,0 +1,253 @@
+set nocompatible
+
+let $VIMFILES = expand('<sfile>:p:h')
+
+let g:skip_defaults_vim = 1
+
+let g:netrw_dirhistmax = 0
+
+set autoread
+set backspace=indent,eol,start
+
+set clipboard=unnamedplus
+set diffopt+=iwhite
+set hidden
+set history=256
+set lazyredraw
+set mouse=
+set path+=**
+set tabpagemax=50
+set viminfo=
+
+set cmdheight=1
+set display+=lastline
+set fillchars=vert:\ "
+set laststatus=2
+set modeline
+set noshowmode
+set ruler
+set shortmess+=I
+set textwidth=0
+set title
+
+set sessionoptions-=options
+set viewoptions-=options
+
+set noerrorbells
+set novisualbell
+
+set splitbelow
+set splitright
+
+set complete=
+set complete+=.
+set complete+=b
+set complete+=t
+set completeopt=
+set completeopt+=menu
+set completeopt+=longest
+
+set gdefault
+set hlsearch
+set incsearch
+set iskeyword+=-
+set magic
+
+set foldmethod=marker
+set nofoldenable
+
+set shortmess=
+set shortmess+=I
+set shortmess+=T
+set shortmess+=a
+set shortmess+=c
+set shortmess+=t
+
+set nolist
+set nowrap
+
+set scrolloff=10
+set sidescrolloff=10
+
+set number
+if v:version >= 700
+ set numberwidth=3
+endif
+
+set wildignorecase
+set wildmenu
+set wildignore=
+
+set nobackup
+set noswapfile
+set noundofile
+set nowritebackup
+
+set smartcase
+set ignorecase
+
+set autoindent
+set breakindent
+set smartindent
+
+set expandtab
+set shiftround
+set shiftwidth=4
+set smarttab
+set softtabstop=4
+set tabstop=4
+
+autocmd BufEnter *.* :set colorcolumn=
+
+if &t_Co == 8 && $TERM !~# '^Eterm'
+ set t_Co=16
+endif
+
+if &listchars ==# 'eol:$'
+ set listchars=tab:>\ ,trail:-,extends:>,precedes:<,nbsp:+
+endif
+
+if v:version > 703 || v:version == 703 && has("patch541")
+ set formatoptions+=j
+endif
+
+if has('path_extra')
+ setglobal tags-=./tags tags-=./tags; tags^=./tags;
+endif
+
+if !has('nvim') && &ttimeoutlen == -1
+ set ttimeout
+ set ttimeoutlen=100
+endif
+
+try
+ set encoding=utf-8
+ scriptencoding utf-8
+catch
+endtry
+
+try
+ if &fileencodings !~? "utf-8"
+ let g:added_fenc_utf8 = 1
+ set fileencodings+=utf-8
+ endif
+catch
+endtry
+
+if has('autocmd')
+ filetype plugin indent on
+
+ if exists("+omnifunc")
+ autocmd Filetype *
+ \ if &omnifunc == "" |
+ \ setlocal omnifunc=syntaxcomplete#Complete |
+ \ endif
+ endif
+
+ autocmd BufEnter * set noreadonly
+endif
+
+if has('syntax') && !exists('g:syntax_on')
+ syntax enable
+endif
+
+if !exists('g:loaded_matchit') && findfile('plugin/matchit.vim', &rtp) ==# ''
+ runtime! macros/matchit.vim
+endif
+
+nnoremap <SPACE> <nop>
+let mapleader=" "
+
+nnoremap :W :w
+nnoremap :W! :w!
+nnoremap :Q :q
+nnoremap :Q! :q!
+
+nnoremap <Expr> j v:count ? 'j' : 'gj'
+nnoremap <Expr> k v:count ? 'k' : 'gk'
+
+nnoremap J gt
+nnoremap K gT
+
+nnoremap <C-a> ^h
+vnoremap <C-a> ^h
+nnoremap H ^h
+vnoremap H ^h
+
+nnoremap <C-e> $
+vnoremap <C-e> $
+nnoremap L $
+vnoremap L $
+
+nnoremap N Nzzzv
+nnoremap n nzzzv
+
+inoremap <C-u> <C-g>u<C-u>
+inoremap <C-w> <C-g>u<C-w>
+
+vnoremap < <gv
+vnoremap > >gv
+vnoremap <Tab> >gv
+vnoremap <S-Tab> <gv
+nnoremap <Tab> >>_
+nnoremap <S-Tab> <<_
+
+nnoremap ]b :<C-u>bnext<CR>
+nnoremap [b :<C-u>bprevious<CR>
+
+nnoremap <C-h> <C-w>h
+nnoremap <C-j> <C-w>j
+nnoremap <C-k> <C-w>k
+nnoremap <C-l> <C-w>l
+
+nnoremap * /\<<C-r>=expand('<cword>')<CR>\><CR>
+nnoremap # ?\<<C-r>=expand('<cword>')<CR>\><CR>
+
+nnoremap <C-L> :<C-u>nohlsearch<C-r>=has('diff')?'<Bar>diffupdate':''<CR><CR><C-l>
+
+cnoremap ;/ <C-r>=expand('%:p:h').'/'<CR>
+cnoremap ;; <C-r>=expand('%:t')<CR>
+cnoremap ;. <C-r>=expand('%:p:r')<CR>
+
+nnoremap <Leader>. :<C-u>lcd %:p:h<CR>
+
+nnoremap Q @q
+
+nnoremap <Leader>c ^v$h
+nnoremap <Leader>v ggVG
+
+nnoremap <Leader>y "+y
+nnoremap <Leader>Y "+Y
+
+nnoremap <Leader>p "+p
+nnoremap <Leader>P "+P
+
+inoremap <C-v> <C-c>"+pi
+cnoremap <C-v> <C-r>+
+
+nmap <Leader>w :<C-u>w!<CR>
+nmap <Leader>wq :<C-u>wq!<CR>
+
+nnoremap ZX :<C-u>qa!<CR>
+
+nnoremap <Leader>q :<C-u>q<CR>
+
+command WS w !sudo tee "%" >/dev/null
+
+function! SwitchCase()
+ normal! ~
+ if strlen(getline('.')) != virtcol('.')
+ normal! h
+ endif
+endfunction
+nnoremap ~ :<C-u>call SwitchCase()<CR>
+
+function! s:GM()
+ execute 'normal! ^'
+ let first_col = virtcol('.')
+ execute 'normal! g_'
+ let last_col = virtcol('.')
+ execute 'normal! ' . (first_col + last_col) / 2 . '|'
+endfunction
+nnoremap gm :<C-u>call <SID>GM()<CR>
+onoremap gm :<C-u>call <SID>GM()<CR>
diff --git a/modules/common/vscode.nix b/modules/common/vscode.nix
new file mode 100644
index 0000000..6671973
--- /dev/null
+++ b/modules/common/vscode.nix
@@ -0,0 +1,167 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.vscode;
+in {
+ options.nixfiles.modules.vscode = {
+ enable = mkEnableOption "VSCode";
+
+ package = with pkgs;
+ mkOption {
+ type = types.enum [vscodium vscode vscode-fhs];
+ default = vscodium;
+ description = "Which package to use as a VSCode implementation.";
+ };
+
+ vim.enable = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Whether to enable Vim emulation.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ hm.programs.vscode = with config.nixfiles;
+ with modules;
+ with profiles; {
+ enable = true;
+
+ inherit (cfg) package;
+
+ extensions = with pkgs;
+ with vscode-extensions;
+ [
+ editorconfig.editorconfig
+ file-icons.file-icons
+ gitlab.gitlab-workflow
+ ms-kubernetes-tools.vscode-kubernetes-tools
+ redhat.vscode-xml
+ redhat.vscode-yaml
+ streetsidesoftware.code-spell-checker
+ ]
+ ++ optional cfg.vim.enable vscodevim.vim;
+
+ userSettings = let
+ font = config.fontScheme.monospaceFont;
+ fontFamily = font.family;
+ fontSize = font.size;
+ in {
+ editor =
+ {
+ inherit fontFamily fontSize;
+ inlayHints = {inherit fontFamily fontSize;};
+ codeLens = false;
+ cursorStyle = "block";
+ detectIndentation = true;
+ minimap.enabled = false;
+ renderWhitespace = "trailing";
+ rulers = [80 120];
+ smoothScrolling = false;
+ tabCompletion = "on";
+ }
+ // (let
+ surround = 10;
+ in {
+ cursorSurroundingLines = surround;
+ scrollBeyondLastColumn = surround;
+ });
+
+ keyboard.dispatch = "keyCode";
+
+ diffEditor.codeLens = false;
+
+ files = {
+ autoSave = "off";
+ enableTrash = false;
+ };
+
+ workbench = {
+ activityBar.visible = false;
+ editor.highlightModifiedTabs = true;
+ enableExperiments = false;
+ settings.enableNaturalLanguageSearch = false;
+ startupEditor = "none";
+ tips.enabled = false;
+ tree.indent = 4;
+ welcomePage = {
+ walkthroughs.openOnInstall = false;
+ preferReducedMotion = true;
+ };
+ };
+
+ debug.console = {inherit fontFamily fontSize;};
+
+ scm = {
+ inputFontFamily = fontFamily;
+ inputFontSize = fontSize;
+ };
+
+ extensions = {
+ autoCheckUpdates = false;
+ autoUpdate = false;
+ ignoreRecommendations = true;
+ };
+
+ terminal = {
+ external.linuxExec =
+ if alacritty.enable
+ then "${pkgs.alacritty}/bin/alacritty"
+ else "${pkgs.xterm}/bin/xterm}";
+
+ integrated = {
+ inherit fontFamily fontSize;
+ enableBell = true;
+ };
+ };
+
+ update = {
+ mode = "none";
+ showReleaseNotes = false;
+ };
+
+ telemetry = {
+ enableCrashReporter = false;
+ enableTelemetry = false;
+ };
+
+ security.workspace.trust.enabled = false;
+
+ git.allowForcePush = true;
+
+ vim = let
+ applyInputMethod = {
+ "ibus" = let
+ bin = "${pkgs.ibus}/bin/ibus";
+ in {
+ enable = true;
+ defaultIM = "xkb:us::eng";
+ obtainIMCmd = "${bin} engine";
+ switchIMCmd = "${bin} engine {im}";
+ };
+ "fcitx" = let
+ bin = "${pkgs.fcitx}/bin/fcitx-remote";
+ in {
+ enable = true;
+ defaultIM = "1";
+ obtainIMCmd = bin;
+ switchIMCmd = "${bin} -t {im}";
+ };
+ };
+ in
+ mkIf cfg.vim.enable rec {
+ easymotion = true;
+ easymotionMarkerFontFamily = fontFamily;
+ easymotionMarkerFontSize = fontSize;
+
+ leader = " ";
+
+ useSystemClipboard = true;
+ };
+ };
+ };
+ };
+}
diff --git a/modules/common/wget.nix b/modules/common/wget.nix
new file mode 100644
index 0000000..9a16fcc
--- /dev/null
+++ b/modules/common/wget.nix
@@ -0,0 +1,35 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.wget;
+in {
+ options.nixfiles.modules.wget.enable = mkEnableOption "wget";
+
+ config = mkIf cfg.enable {
+ hm = {
+ programs.bash.shellAliases.wget = "${pkgs.wget}/bin/wget --hsts-file=/tmp/wget-hsts";
+
+ home.sessionVariables.WGETRC = pkgs.writeText "wgetrc" ''
+ adjust_extension = on
+ dirstruct = off
+ follow_ftp = on
+ passive_ftp = off
+ progress = bar
+ quota = inf
+ reclevel = 5
+ recursive = off
+ robots = off
+ timestamping = off
+ tries = 5
+ wait = 0
+ waitretry = 10
+ '';
+ };
+
+ environment.systemPackages = with pkgs; [wget];
+ };
+}
diff --git a/modules/common/zathura.nix b/modules/common/zathura.nix
new file mode 100644
index 0000000..f78a9e9
--- /dev/null
+++ b/modules/common/zathura.nix
@@ -0,0 +1,120 @@
+{
+ config,
+ lib,
+ ...
+}:
+with lib; let
+ cfg = config.nixfiles.modules.zathura;
+in {
+ options.nixfiles.modules.zathura.enable =
+ mkEnableOption "Zathura PDF reader";
+
+ config = mkIf cfg.enable {
+ hm.programs.zathura = with config.nixfiles.modules; {
+ enable = true;
+
+ options =
+ (with config.colourScheme; {
+ default-fg = white;
+ default-bg = black;
+
+ statusbar-fg = black;
+ statusbar-bg = white;
+
+ inputbar-fg = black;
+ inputbar-bg = brightGreen;
+
+ notification-fg = black;
+ notification-bg = brightBlue;
+
+ notification-warning-fg = black;
+ notification-warning-bg = brightYellow;
+
+ notification-error-fg = black;
+ notification-error-bg = brightRed;
+
+ highlight-color = brightYellow;
+ highlight-active-color = yellow;
+
+ completion-fg = brightWhite;
+ completion-bg = brightBlack;
+
+ completion-highlight-fg = black;
+ completion-highlight-bg = brightRed;
+
+ completion-group-fg = black;
+ completion-group-bg = brightRed;
+
+ recolor-darkcolor = black;
+ recolor-lightcolor = white;
+ })
+ // {
+ recolor = true;
+ recolor-keephue = false;
+ recolor-reverse-video = false;
+
+ highlight-transparency = "0.3";
+
+ font = config.fontScheme.monospaceFont.family;
+
+ n-completion-items = 10;
+
+ guioptions = "";
+
+ statusbar-basename = true;
+ statusbar-home-tilde = true;
+
+ statusbar-h-padding = 0;
+ statusbar-v-padding = 0;
+
+ window-height = 800;
+ window-width = 600;
+
+ window-icon = "";
+
+ abort-clear-search = true;
+
+ incremental-search = true;
+
+ adjust-open = "best-fit";
+
+ advance-pages-per-row = false;
+
+ database = "sqlite";
+
+ dbus-service = false;
+
+ page-padding = 0;
+
+ pages-per-row = 1;
+
+ render-loading = false;
+
+ show-directories = true;
+ show-hidden = true;
+ show-recent = 10;
+
+ link-zoom = true;
+ link-hadjust = true;
+
+ window-title-basename = true;
+ window-title-home-tilde = true;
+ window-title-page = true;
+
+ zoom-center = false;
+ zoom-max = 1000;
+ zoom-min = 10;
+ zoom-step = 10;
+
+ scroll-hstep = -1;
+ scroll-step = 40;
+ scroll-full-overlap = 0;
+ scroll-wrap = true;
+ scroll-page-aware = false;
+
+ selection-clipboard = "clipboard";
+ selection-notification = false;
+ };
+ };
+ };
+}