diff options
author | Azat Bahawi <azat@bahawi.net> | 2023-02-19 17:50:35 +0300 |
---|---|---|
committer | Azat Bahawi <azat@bahawi.net> | 2023-02-19 17:50:35 +0300 |
commit | 91fb4f28ef5d87e8bcf7749928d30ba4a9cbbd34 (patch) | |
tree | e07291fcb1cf62a561ffe58d1fd8e2968ff6fcb3 /modules/common | |
parent | 2023-02-15 (diff) |
2023-02-19
Diffstat (limited to 'modules/common')
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; + }; + }; + }; +} |