diff --git a/home/home.nix b/home/home.nix index 2013152..99107fe 100644 --- a/home/home.nix +++ b/home/home.nix @@ -5,7 +5,7 @@ in { inherit machineVars; imports = [ - ./shellOptions.nix + ./shell.nix ./packages.nix ./config/ssh/hosts/pvv.nix @@ -26,6 +26,7 @@ in { ../modules/machineVars.nix ./modules/colors.nix + ./modules/shellAliases.nix inputs.secrets.outputs.home-config ] ++ optionals graphics [ diff --git a/home/modules/shellAliases.nix b/home/modules/shellAliases.nix new file mode 100644 index 0000000..76d8acf --- /dev/null +++ b/home/modules/shellAliases.nix @@ -0,0 +1,259 @@ +{ pkgs, lib, extendedLib, inputs, config, ... }: let + inherit (lib) types mkEnableOption mkOption mdDoc; + cfg = config.local.shell; + +# NOTE: +# This module is an over-engineered solution to a non-problem. +# It is a fun experiment in using the Nix language to create a +# shell alias system that organizes aliases into a tree structure, +# with categories and subcategories and subsubcategories and so on. +# +# It also has a lazy join function that will join a list of commands +# with a separator, but render it in a prettier way in a documentation +# file that you can print out and read. + + isAlias = v: builtins.isAttrs v && v ? "alias" && v ? "type"; +in { + options.local.shell = { + aliases = let + + coerceStrToAlias = str: { + type = " "; + alias = [ str ]; + }; + + aliasType = (types.coercedTo types.str coerceStrToAlias (types.submodule { + options = { + type = mkOption { + type = types.enum [ "|" "&&" ";" " " ]; + default = ";"; + description = '' + If the alias is a list of commands, this is the kind of separator that will be used. + ''; + }; + alias = mkOption { + type = types.listOf types.str; + }; + }; + })) // { + # NOTE: this check is necessary, because nix will recurse on types.either, + # and report that the option does not exist. + # See https://discourse.nixos.org/t/problems-with-types-oneof-and-submodules/15197 + check = v: builtins.isString v || isAlias v; + }; + + recursingAliasTreeType = types.attrsOf (types.either aliasType recursingAliasTreeType); + in mkOption { + type = recursingAliasTreeType; + description = "A tree of aliases"; + default = { }; + example = { + "My first alias category" = { + cmd1 = ''echo "hello world"''; + cmd2 = { + type = "|"; + alias = [ + "ls -la" + "grep -i hello" + ]; + }; + }; + + "My second alias category" = { + cmd1 = { + type = "&&"; + alias = [ + ''echo "hello world"'' + ''echo "goodbye world"'' + ]; + }; + }; + }; + }; + + variables = mkOption { + type = types.attrsOf types.str; + description = "Environment variables"; + default = { }; + }; + + # TODO: I want a similar system for functions at some point. + # functions = { + + # }; + + enablePackageManagerLecture = mkEnableOption "distro reminder messages, aliased to common package manager commands"; + enableAliasOverview = mkEnableOption "`aliases` command that prints out a list of all aliases" // { + default = true; + example = false; + }; + }; + + config = let + sedColor = + color: + inputPattern: + outputPattern: + "-e \"s|${inputPattern}|${outputPattern.before or ""}$(tput setaf ${toString color})${outputPattern.middle}$(tput op)${outputPattern.after or ""}|g\""; + + colorRed = sedColor 1; + + colorSlashes = colorRed "/" {middle = "/";}; + + # Alias type functors + # These will help pretty print the commands + functors = let + inherit (lib.strings) concatStringsSep; + inherit (extendedLib.termColors.front) blue; + in + { + "|" = { + apply = f: concatStringsSep " | " f.alias; + stringify = f: concatStringsSep (blue "\n| ") f.alias; + }; + "&&" = { + apply = f: concatStringsSep " && " f.alias; + stringify = f: concatStringsSep (blue "\n&& ") f.alias; + }; + ";" = { + apply = f: concatStringsSep "; " f.alias; + stringify = f: concatStringsSep (blue ";\n ") f.alias; + }; + " " = { + apply = f: concatStringsSep " " f.alias; + stringify = f: concatStringsSep " \\\n " f.alias; + }; + }; + + aliasTextOverview = let + inherit (lib) stringLength length concatStringsSep replaceStrings + attrValues mapAttrs isAttrs remove replicate mapNullable; + + inherit (extendedLib.termColors.front) red green blue; + + # String -> String -> String + wrap' = wrapper: str: wrapper + str + wrapper; + + # [String] -> String -> String -> String + replaceStrings' = from: to: replaceStrings from (replicate (length from) to); + + # String -> Int -> String + repeatString = string: times: concatStringsSep "" (replicate times string); + + # int -> String -> AttrSet -> String + stringifyCategory = level: name: category: let + title = "${repeatString " " level}[${green name}]"; + + commands = attrValues ((lib.flip mapAttrs) category (n: v: let + # String + indent = repeatString " " level; + + # String -> String + removeNixLinks = text: let + maybeMatches = builtins.match "(|.*[^)])(/nix/store/.*/bin/).*" text; + matches = mapNullable (remove "") maybeMatches; + in + if (maybeMatches == null) + then text + else replaceStrings' matches "" text; + + applyFunctor = attrset: let + applied = functors.${attrset.type}.stringify attrset; + indent' = indent + (repeatString " " ((stringLength " -> \"") + (stringLength n))) + " "; + in + replaceStrings' ["\n"] ("\n" + indent') applied; + + recurse = stringifyCategory (level + 1) n v; + in if isAlias v + then "${indent} ${red n} -> ${wrap' (blue "\"") (removeNixLinks (applyFunctor v))}" + else recurse + )); + in concatStringsSep "\n" ([title] ++ commands) + "\n"; + in (stringifyCategory 0 "Aliases" cfg.aliases) + "\n"; + + flattenedAliases = let + inherit (lib) mapAttrs attrValues filterAttrs isAttrs + isString concatStringsSep foldr; + + applyFunctor = attrset: functors.${attrset.type}.apply attrset; + + # TODO: better naming + allAttrValuesAreStrings = attrset: let + + # [ {String} ] + filteredAliases = [(filterAttrs (n: v: isString v) attrset)]; + + # [ {String} ] + remainingFunctors = let + functorSet = filterAttrs (_: v: isAlias v) attrset; + appliedFunctorSet = mapAttrs (n: v: applyFunctor v) functorSet; + in [ appliedFunctorSet ]; + + # [ {AttrSet} ] + remainingAliasSets = attrValues (filterAttrs (_: v: isAttrs v && !isAlias v) attrset); + + # [ {String} ] + recursedAliasSets = filteredAliases + ++ (remainingFunctors) + ++ (map allAttrValuesAreStrings remainingAliasSets); + in foldr (a: b: a // b) {} recursedAliasSets; + + in + allAttrValuesAreStrings cfg.aliases; + + in { + xdg.dataFile = { + aliases.text = aliasTextOverview; + packageManagerLecture = lib.mkIf cfg.enablePackageManagerLecture { + target = "package-manager.lecture"; + text = let + inherit (extendedLib.termColors.front) red blue; + in lib.concatStringsSep "\n" [ + ((red "This package manager is not installed on ") + (blue "NixOS") + (red ".")) + ((red "Either use ") + ("\"nix-env -i\"") + (red " or install it through a configuration file.")) + "" + ]; + }; + }; + + local.shell.aliases."Package Managers" = lib.mkIf cfg.enablePackageManagerLecture (let + inherit (lib.attrsets) nameValuePair listToAttrs; + + packageManagers = [ + "apt" + "dpkg" + "flatpak" + "pacman" + "pamac" + "paru" + "rpm" + "snap" + "xbps" + "yay" + "yum" + ]; + + command = "${pkgs.coreutils}/bin/cat $HOME/${config.xdg.dataFile.packageManagerLecture.target}"; + nameValuePairs = map (pm: nameValuePair pm command) packageManagers; + in listToAttrs nameValuePairs); + + local.shell.aliases.aliases = lib.mkIf cfg.enableAliasOverview + "${pkgs.coreutils}/bin/cat $HOME/${config.xdg.dataFile.aliases.target}"; + + programs = { + zsh = { + shellAliases = flattenedAliases; + sessionVariables = cfg.variables; + }; + bash = { + shellAliases = flattenedAliases; + sessionVariables = cfg.variables; + }; + fish = { + shellAliases = flattenedAliases; + # TODO: fish does not support session variables? + # localVariables = cfg.variables; + }; + }; + }; +} diff --git a/home/programs/zsh/default.nix b/home/programs/zsh/default.nix index e07ed60..d65c2ec 100644 --- a/home/programs/zsh/default.nix +++ b/home/programs/zsh/default.nix @@ -1,4 +1,4 @@ -{ pkgs, lib, config, shellOptions, ... }: +{ pkgs, lib, config, ... }: { programs.zsh = { @@ -58,13 +58,9 @@ } ]; - localVariables = shellOptions.variables; - - shellAliases = shellOptions.flattened.aliases; - initExtra = '' source ${./p10k.zsh} - + enable-fzf-tab zstyle ':fzf-tab:complete:cd:*' fzf-preview '${pkgs.exa}/bin/exa -1 --color=always $realpath' diff --git a/home/shell.nix b/home/shell.nix new file mode 100644 index 0000000..76601da --- /dev/null +++ b/home/shell.nix @@ -0,0 +1,303 @@ +{ config, pkgs, lib, extendedLib, inputs, ... }: let + sedColor = + color: + inputPattern: # sed regex. + outputPattern@{ before ? "" , middle ? "", after ? ""}: + "-e \"s|${inputPattern}|${before}$(tput setaf ${toString color})${middle}$(tput op)${after}|g\""; + + colorRed = sedColor 1; + + colorSlashes = colorRed "/" { middle = "/"; }; +in { + local.shell.aliases = let + p = pkg: "${pkgs.${pkg}}/bin/${pkg}"; + in { + # ░█▀▄░█▀▀░█▀█░█░░░█▀█░█▀▀░█▀▀░█▄█░█▀▀░█▀█░▀█▀░█▀▀ + # ░█▀▄░█▀▀░█▀▀░█░░░█▀█░█░░░█▀▀░█░█░█▀▀░█░█░░█░░▀▀█ + # ░▀░▀░▀▀▀░▀░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░▀░░▀░░▀▀▀ + + # Replacing all of coreutils with rust, lol + + "System Tool Replacements" = { + + # Convention: if replaced tool is useful in some situations, let it be available + # as its own command with its first character doubled. + # + # Example: cp -> ccp + + cd = "z"; + + ccp = "${pkgs.coreutils}/bin/cp"; + cp = "${p "rsync"} --progress --human-readable"; + cpr = "${p "rsync"} --progress --human-readable --recursive"; + + ccat = "${pkgs.coreutils}/bin/cat"; + cat = p "bat"; + + htop = "${pkgs.bottom}/bin/btm"; + hhtop = p "htop"; + + dig = p "dog"; + + # Flags are incompatible, so they are suffixed by -x + psx = p "procs"; + findx = p "fd"; + + ag = "${pkgs.ripgrep}/bin/rg"; + + lls = "${pkgs.coreutils}/bin/ls --color=always"; + ls = p "exa"; + la = "${p "exa"} -lah --changed --time-style long-iso --git --group"; + lsa = "la"; + + killall = "echo \"killall is dangerous on non-gnu platforms. Using 'pkill -x'\"; pkill -x"; + }; + + # ░█▀▀░█▀█░█░░░█▀█░█▀▄░▀█▀░▀▀█░█▀▀░█▀▄ + # ░█░░░█░█░█░░░█░█░█▀▄░░█░░▄▀░░█▀▀░█░█ + # ░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀░ + + # Normal commands, just with colors. + + "Colorized" = { + ip = "ip --color=always"; + diff = "diff --color=auto"; + grep = "grep --color=always"; + # TODO: doesn't work + # make = "${colormake}/bin/colormake"; + }; + + # ░█▀▄░█▀▀░█▄█░▀█▀░█▀█░█▀▄░█▀▀░█▀▄░█▀▀ + # ░█▀▄░█▀▀░█░█░░█░░█░█░█░█░█▀▀░█▀▄░▀▀█ + # ░▀░▀░▀▀▀░▀░▀░▀▀▀░▀░▀░▀▀░░▀▀▀░▀░▀░▀▀▀ + + # Stuff that I constantly forget... + + "Reminders" = { + regex-escapechars = "echo \"[\\^$.|?*+()\""; + }; + + # ░█▀█░▀█▀░█░█ + # ░█░█░░█░░▄▀▄ + # ░▀░▀░▀▀▀░▀░▀ + + # Nix related aliases + + "Nix Stuff" = { + nxr = "sudo nixos-rebuild switch"; + + nix-check-syntax = "nix-instantiate --parse-only"; + + nxr-hm = "sudo nixos-rebuild switch --flake ~/nix#home-manager-tester"; + nxr-ks = "sudo nixos-rebuild switch --flake ~/nix#kasei"; + + hms = toString inputs.nix-attr-search.packages.${pkgs.system}.home-manager-search; + nxo = toString inputs.nix-attr-search.packages.${pkgs.system}.nix-option-search; + }; + + # ░█▀▀░█░█░█▀▀░▀█▀░█▀▀░█▄█░█▀▄ + # ░▀▀█░░█░░▀▀█░░█░░█▀▀░█░█░█░█ + # ░▀▀▀░░▀░░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀░ + + # Systemd related aliases + + "Systemd Stuff" = { + scr = "sudo systemctl restart"; + scs = "systemctl status"; + scc = "systemctl cat"; + scf = "systemctl list-units --failed"; + jx = "journalctl -xeu"; + }; + + # ░█▀▀░█▀█░█▀▀░▀█▀░█░█░█▀█░█▀▄░█▀▀ + # ░▀▀█░█░█░█▀▀░░█░░█▄█░█▀█░█▀▄░█▀▀ + # ░▀▀▀░▀▀▀░▀░░░░▀░░▀░▀░▀░▀░▀░▀░▀▀▀ + + # Aliases that are so long/piped that they could be considered new software. + + "Software" = { + skusho = "${p "maim"} --hidecursor --nokeyboard $(echo $SCREENSHOT_DIR)/$(date_%s).png"; + skushoclip = { + type = "|"; + alias = [ + "${p "maim"} --hidecursor --nokeyboard --select" + "${p "xclip"} -selection clipboard -target image/png -in" + ]; + }; + + dp-check = { + type = "|"; + alias = [ + "ls -l /proc/$(pidof dropbox)/fd" + "egrep -v 'pipe:|socket:|/dev'" + "grep \"${config.services.dropbox.path}/[^.]\"" + ]; + }; + + subdirs-to-cbz = { + type = " "; + alias = [ + ''for dir in "./*";'' + '' ${p "zip"} -r "$dir.cbz" "$d";'' + ''done'' + ]; + }; + + connectedIps = { + type = "|"; + alias = [ + "netstat -tn 2>/dev/null" + "grep :$1" + "awk '{print $5}'" + "cut -d: -f1" + "sort" + "uniq -c" + "sort -nr" + "head" + ]; + }; + + path = ''echo $PATH | sed -e 's/:/\n/g' ${colorSlashes} | sort''; + + wowify = "${p "toilet"} -f pagga | ${p "lolcat"}"; + + aliasc = let + colorAliasNames = colorRed "\\(^[^=]*\\)=" { middle = "\\1"; after = "\\t"; }; + # The '[^]]' (character before /nix should not be ']') is there so that this + # alias definition won't be removed. + removeNixLinks = "-e 's|\\([^]]\\)/nix/store/.*/bin/|\\1|'"; + in { + type = "|"; + alias = [ + "alias" + "sed ${colorAliasNames} ${removeNixLinks}" + "column -ts $'\\t'" + ]; + }; + + ports = let + colorFirstColumn = colorRed "(^[^ ]+)" {middle = "\\1";}; + in { + type = "|"; + alias = [ + "sudo netstat -tulpn" + "grep LISTEN" + "sed -r 's/\\s+/ /g'" + "cut -d' ' -f 4,7" + "column -t" + "sed -r ${colorFirstColumn} ${colorSlashes}" + ]; + }; + }; + + # ░█▀█░█░░░▀█▀░█▀█░█▀▀░█▀▀░█▀▀ + # ░█▀█░█░░░░█░░█▀█░▀▀█░█▀▀░▀▀█ + # ░▀░▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀ + + # Normal commands that are just shortened. What would normally be considered + # the "technically correct definition" of an alias + + "Actual Aliases" = { + # dp = "${dropbox-cli}/bin/dropbox"; + + # Having 'watch' with a space after as an alias, enables it to expand other aliases + watch = "${pkgs.procps}/bin/watch "; + + concatPdfs = { + type = ";"; + alias = [ + ''echo "${extendedLib.termColors.front.red "Concatenating all pdfs in current directory to 'out.pdf'"}"'' + "${pkgs.poppler_utils}/bin/pdfunite *.pdf out.pdf" + ]; + }; + + m = p "ncmpcpp"; + p = "${pkgs.python39Packages.ipython}/bin/ipython"; + s = p "sxiv"; + v = p "mpv"; + zt = p "zathura"; + }; + + # ░█▄█░▀█▀░█▀▀░█▀▀ + # ░█░█░░█░░▀▀█░█░░ + # ░▀░▀░▀▀▀░▀▀▀░▀▀▀ + + # I didn't know where else to put these ¯\_(ツ)_/¯ + + "Misc" = { + youtube-dl-list = { + type = " "; + alias = [ + (p "yt-dlp") + "-f \"bestvideo[ext=mp4]+bestaudio[e=m4a]/bestvideo+bestaudio\"" + "-o \"%(playlist_index)s-%(title)s.%(ext)s\"" + ]; + }; + + music-dl = "${p "yt-dlp"} --extract-audio -f \"bestaudio[ext=m4a]/best\""; + music-dl-list = { + type = " "; + alias = [ + (p "yt-dlp") + "--extract-audio" + "-f \"bestaudio[ext=m4a]/best\"" + "-o \"%(playlist_index)s-%(title)s.%(ext)s\"" + ]; + }; + + view-latex = "${pkgs.texlive.combined.scheme-full}/bin/latexmk -pdf -pvc main.tex"; + + reload-tmux = "${p "tmux"} source $HOME/.config/tmux/tmux.conf"; + }; + + # ░█▀▀░█▀▀░█▀█░█▀▀░█▀▄░█▀█░▀█▀░█▀▀░█▀▄ + # ░█░█░█▀▀░█░█░█▀▀░█▀▄░█▀█░░█░░█▀▀░█░█ + # ░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░▀░▀░▀░░▀░░▀▀▀░▀▀░ + + # Code generated commands + + "Generated" = { + "cds" = let + inherit (lib.strings) concatStringsSep; + inherit (extendedLib.strings) repeatString; + + inherit (lib.lists) range flatten replicate; + inherit (lib.attrsets) nameValuePair listToAttrs; + + nthCds = n: [ + ("cd" + (repeatString "." (n + 1))) + ("cd." + toString n) + (repeatString "." (n + 1)) + ("." + toString n) + (".." + toString n) + ]; + realCommand = n: "cd " + (concatStringsSep "/" (replicate n "..")); + + nthCdsAsNameValuePairs = n: map (cmd: nameValuePair cmd (realCommand n)) (nthCds n); + allCdNameValuePairs = flatten (map nthCdsAsNameValuePairs (range 1 9)); + in + listToAttrs allCdNameValuePairs; + }; + }; + + # TODO: flatten functions + # local.shell.functions = { + # all = { + # md-to-pdf = functors.shellJoin.wrap [ + # "pandoc \"$1\"" + # "-f gfm" + # "-V linkcolor:blue" + # "-V geometry:a4paper" + # "-V geometry:margin=2cm" + # "-V mainfont=\"Droid Sans\"" + # "--pdf-engine=xelatex" + # "-o \"$2\"" + # ]; + # }; + # }; + + # local.shell.variables = { + # POWERLEVEL9K_LEFT_PROMPT_ELEMENTS = ["dir" "vcs"]; + # NIX_PATH = ''$HOME/.nix-defexpr/channels$\{NIX_PATH:+:}$NIX_PATH''; + # }; +} \ No newline at end of file diff --git a/home/shellOptions.nix b/home/shellOptions.nix deleted file mode 100644 index 935b2d5..0000000 --- a/home/shellOptions.nix +++ /dev/null @@ -1,433 +0,0 @@ -{ pkgs, lib, extendedLib, inputs, config, ... }: let - - sedColor = - color: - inputPattern: - outputPattern: - "-e \"s|${inputPattern}|${outputPattern.before or ""}$(tput setaf ${toString color})${outputPattern.middle}$(tput op)${outputPattern.after or ""}|g\""; - - colorRed = sedColor 1; - - colorSlashes = colorRed "/" {middle = "/";}; - - # Context Functors - functors = let - inherit (lib.strings) concatStringsSep; - inherit (extendedLib.termColors.front) blue; - genWrapper = type: value: { inherit type; inherit value; }; - in - { - shellPipe = { - wrap = genWrapper "shellPipe"; - apply = f: concatStringsSep " | " f.value; - stringify = f: concatStringsSep (blue "\n| ") f.value; - }; - shellAnd = { - wrap = genWrapper "shellAnd"; - apply = f: concatStringsSep " && " f.value; - stringify = f: concatStringsSep (blue "\n&& ") f.value; - }; - shellThen = { - wrap = genWrapper "shellThen"; - apply = f: concatStringsSep "; " f.value; - stringify = f: concatStringsSep (blue ";\n ") f.value; - }; - shellJoin = { - wrap = genWrapper "shellJoin"; - apply = f: concatStringsSep " " f.value; - stringify = f: concatStringsSep " \\\n " f.value; - }; - }; - - # AttrSet -> Bool - isFunctor = let - inherit (lib.lists) any; - inherit (lib.attrsets) attrValues; - in - attrset: - if !(attrset ? "type") - then false - else any (f: (f.wrap "").type == attrset.type) (attrValues functors); - -in rec { - _module.args.shellOptions = { - aliases = let - shellPipe = functors.shellPipe.wrap; - shellJoin = functors.shellJoin.wrap; - shellAnd = functors.shellAnd.wrap; - shellThen = functors.shellThen.wrap; - in with pkgs; { - - # ░█▀▄░█▀▀░█▀█░█░░░█▀█░█▀▀░█▀▀░█▄█░█▀▀░█▀█░▀█▀░█▀▀ - # ░█▀▄░█▀▀░█▀▀░█░░░█▀█░█░░░█▀▀░█░█░█▀▀░█░█░░█░░▀▀█ - # ░▀░▀░▀▀▀░▀░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░▀░░▀░░▀▀▀ - - # Replacing all of coreutils with rust, lol - - "System Tool Replacements" = { - - # Convention: if replaced tool is useful in some situations, let it be available - # as its own command with its first character doubled. - # - # Example: cp -> ccp - - cd = "z"; - - ccp = "${coreutils}/bin/cp"; - cp = "${rsync}/bin/rsync --progress --human-readable"; - cpr = "${rsync}/bin/rsync --progress --human-readable --recursive"; - - ccat = "${coreutils}/bin/cat"; - cat = "${bat}/bin/bat"; - - htop = "${bottom}/bin/btm"; - hhtop = "${htop}/bin/htop"; - - dig = "${dog}/bin/dog"; - - # Flags are incompatible, so they are suffixed by -x - psx = "${procs}/bin/procs"; - findx = "${fd}/bin/fd"; - - ag="${ripgrep}/bin/rg"; - - lls = "${coreutils}/bin/ls --color=always"; - ls = "${exa}/bin/exa"; - la = "${exa}/bin/exa -lah --changed --time-style long-iso --git --group"; - lsa = "la"; - - killall = "echo \"killall is dangerous on non-gnu platforms. Using 'pkill -x'\"; pkill -x"; - }; - - # ░█▀▀░█▀█░█░░░█▀█░█▀▄░▀█▀░▀▀█░█▀▀░█▀▄ - # ░█░░░█░█░█░░░█░█░█▀▄░░█░░▄▀░░█▀▀░█░█ - # ░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀░ - - # Normal commands, just with colors. - - "Colorized" = { - ip = "ip --color=always"; - diff = "diff --color=auto"; - grep = "grep --color=always"; - # TODO: doesn't work - # make = "${colormake}/bin/colormake"; - }; - - # ░█▀▄░█▀▀░█▄█░▀█▀░█▀█░█▀▄░█▀▀░█▀▄░█▀▀ - # ░█▀▄░█▀▀░█░█░░█░░█░█░█░█░█▀▀░█▀▄░▀▀█ - # ░▀░▀░▀▀▀░▀░▀░▀▀▀░▀░▀░▀▀░░▀▀▀░▀░▀░▀▀▀ - - # Stuff that I constantly forget... - - "Reminders" = { - regex-escapechars = "echo \"[\\^$.|?*+()\""; - aliases = "${coreutils}/bin/cat $HOME/${config.xdg.dataFile.aliases.target}"; - }; - - # ░█▀█░▀█▀░█░█ - # ░█░█░░█░░▄▀▄ - # ░▀░▀░▀▀▀░▀░▀ - - # Nix related aliases - - "Nix Stuff" = { - nxr = "sudo nixos-rebuild switch"; - - nix-check-syntax = "nix-instantiate --parse-only"; - - nxr-hm = "sudo nixos-rebuild switch --flake ~/nix#home-manager-tester"; - nxr-ks = "sudo nixos-rebuild switch --flake ~/nix#kasei"; - - hms = toString inputs.nix-attr-search.packages.${pkgs.system}.home-manager-search; - nxo = toString inputs.nix-attr-search.packages.${pkgs.system}.nix-option-search; - }; - - # ░█▀▀░█░█░█▀▀░▀█▀░█▀▀░█▄█░█▀▄ - # ░▀▀█░░█░░▀▀█░░█░░█▀▀░█░█░█░█ - # ░▀▀▀░░▀░░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀░ - - # Systemd related aliases - - "Systemd Stuff" = { - scr = "sudo systemctl restart"; - scs = "systemctl status"; - scc = "systemctl cat"; - scf = "systemctl list-units --failed"; - jx = "journalctl -xeu"; - }; - - # ░█▀▀░█▀█░█▀▀░▀█▀░█░█░█▀█░█▀▄░█▀▀ - # ░▀▀█░█░█░█▀▀░░█░░█▄█░█▀█░█▀▄░█▀▀ - # ░▀▀▀░▀▀▀░▀░░░░▀░░▀░▀░▀░▀░▀░▀░▀▀▀ - - # Aliases that are so long/piped that they could be considered new software. - - "Software" = { - - skusho = "${maim}/bin/maim --hidecursor --nokeyboard $(echo $SCREENSHOT_DIR)/$(date_%s).png"; - skushoclip = shellPipe [ - "${maim}/bin/maim --hidecursor --nokeyboard --select" - "${xclip}/bin/xclip -selection clipboard -target image/png -in" - ]; - - dp-check = shellPipe [ - "ls -l /proc/$(pidof dropbox)/fd" - "egrep -v 'pipe:|socket:|/dev'" - "grep \"${config.services.dropbox.path}/[^.]\"" - ]; - - subdirs-to-cbz = shellJoin [ - "for dir in \"./*\";" - " ${zip}/bin/zip -r \"$dir.cbz\" \"$d\";" - "done" - ]; - - connectedIps = shellPipe [ - "netstat -tn 2>/dev/null" - "grep :$1" - "awk '{print $5}'" - "cut -d: -f1" - "sort" - "uniq -c" - "sort -nr" - "head" - ]; - - path = "echo $PATH | sed -e 's/:/\\n/g' ${colorSlashes} | sort"; - - wowify = "${toilet}/bin/toilet -f pagga | ${lolcat}/bin/lolcat"; - - aliasc = let - colorAliasNames = colorRed "\\(^[^=]*\\)=" {middle = "\\1"; after = "\\t";}; - # The '[^]]' (character before /nix should not be ']') is there so that this - # alias definition won't be removed. - removeNixLinks = "-e 's|\\([^]]\\)/nix/store/.*/bin/|\\1|'"; - in - shellPipe [ - "alias" - "sed ${colorAliasNames} ${removeNixLinks}" - "column -ts $'\\t'" - ]; - - ports = let - colorFirstColumn = colorRed "(^[^ ]+)" {middle = "\\1";}; - in - shellPipe [ - "sudo netstat -tulpn" - "grep LISTEN" - "sed -r 's/\\s+/ /g'" - "cut -d' ' -f 4,7" - "column -t" - "sed -r ${colorFirstColumn} ${colorSlashes}" - ]; - }; - - # ░█▀█░█░░░▀█▀░█▀█░█▀▀░█▀▀░█▀▀ - # ░█▀█░█░░░░█░░█▀█░▀▀█░█▀▀░▀▀█ - # ░▀░▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀ - - # Normal commands that are just shortened. What would normally be considered - # the "technically correct definition" of an alias - - "Actual Aliases" = { - # dp = "${dropbox-cli}/bin/dropbox"; - - # Having 'watch' with a space after as an alias, enables it to expand other aliases - watch = "${procps}/bin/watch "; - - concatPdfs = shellThen [ - "echo \"${extendedLib.termColors.front.red "Concatenating all pdfs in current directory to 'out.pdf'"}\"" - "${poppler_utils}/bin/pdfunite *.pdf out.pdf" - ]; - - m = "${ncmpcpp}/bin/ncmpcpp"; - p = "${python39Packages.ipython}/bin/ipython"; - s = "${sxiv}/bin/sxiv"; - v = "${mpv}/bin/mpv"; - zt = "${zathura}/bin/zathura"; - }; - - # ░█▄█░▀█▀░█▀▀░█▀▀ - # ░█░█░░█░░▀▀█░█░░ - # ░▀░▀░▀▀▀░▀▀▀░▀▀▀ - - # I didn't know where else to put these ¯\_(ツ)_/¯ - - "Misc" = { - youtube-dl-list = shellJoin [ - "${yt-dlp}/bin/yt-dlp" - "-f \"bestvideo[ext=mp4]+bestaudio[e=m4a]/bestvideo+bestaudio\"" - "-o \"%(playlist_index)s-%(title)s.%(ext)s\"" - ]; - - music-dl = "${yt-dlp}/bin/yt-dlp --extract-audio -f \"bestaudio[ext=m4a]/best\""; - music-dl-list = shellJoin [ - "${yt-dlp}/bin/yt-dlp" - "--extract-audio" - "-f \"bestaudio[ext=m4a]/best\"" - "-o \"%(playlist_index)s-%(title)s.%(ext)s\"" - ]; - - view-latex = "${texlive.combined.scheme-full}/bin/latexmk -pdf -pvc main.tex"; - - reload-tmux = "${tmux}/bin/tmux source $HOME/.config/tmux/tmux.conf"; - }; - - # ░█▀▀░█▀▀░█▀█░█▀▀░█▀▄░█▀█░▀█▀░█▀▀░█▀▄ - # ░█░█░█▀▀░█░█░█▀▀░█▀▄░█▀█░░█░░█▀▀░█░█ - # ░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░▀░▀░▀░░▀░░▀▀▀░▀▀░ - - # Code generated commands - - "Generated" = { - "cds" = let - inherit (lib.strings) concatStringsSep; - inherit (extendedLib.strings) repeatString; - - inherit (lib.lists) range flatten replicate; - inherit (lib.attrsets) nameValuePair listToAttrs; - - nthCds = n: [ - ("cd" + (repeatString "." (n + 1))) - ("cd." + toString n) - (repeatString "." (n + 1)) - ("." + toString n) - (".." + toString n) - ]; - realCommand = n: "cd " + (concatStringsSep "/" (replicate n "..")); - - nthCdsAsNameValuePairs = n: map (cmd: nameValuePair cmd (realCommand n)) (nthCds n); - allCdNameValuePairs = flatten (map nthCdsAsNameValuePairs (range 1 9)); - in - listToAttrs allCdNameValuePairs; - - "Package Managers" = let - inherit (lib.attrsets) nameValuePair listToAttrs; - - packageManagers = [ - "apt" - "dpkg" - "flatpak" - "pacman" - "pamac" - "paru" - "rpm" - "snap" - "xbps" - "yay" - "yum" - ]; - - command = "${coreutils}/bin/cat $HOME/${config.xdg.dataFile.packageManagerLecture.target}"; - nameValuePairs = map (pm: nameValuePair pm command) packageManagers; - in listToAttrs nameValuePairs; - }; - }; - - # TODO: flatten functions - functions = { - all = { - md-to-pdf = functors.shellJoin.wrap [ - "pandoc \"$1\"" - "-f gfm" - "-V linkcolor:blue" - "-V geometry:a4paper" - "-V geometry:margin=2cm" - "-V mainfont=\"Droid Sans\"" - "--pdf-engine=xelatex" - "-o \"$2\"" - ]; - }; - }; - - variables = { - POWERLEVEL9K_LEFT_PROMPT_ELEMENTS = ["dir" "vcs"]; - # NIX_PATH = ''$HOME/.nix-defexpr/channels$\{NIX_PATH:+:}$NIX_PATH''; - }; - - flattened.aliases = let - inherit (lib.attrsets) mapAttrs attrValues filterAttrs isAttrs; - inherit (extendedLib.attrsets) concatAttrs; - inherit (lib.strings) isString concatStringsSep; - - applyFunctor = attrset: functors.${attrset.type}.apply attrset; - - # TODO: better naming - allAttrValuesAreStrings = attrset: let - - # [ {String} ] - filteredAliases = [(filterAttrs (n: v: isString v) attrset)]; - - # [ {String} ] - remainingFunctors = let - functorSet = filterAttrs (n: v: isAttrs v && isFunctor v) attrset; - appliedFunctorSet = mapAttrs (n: v: applyFunctor v) functorSet; - in [ appliedFunctorSet ]; - - # [ {AttrSet} ] - remainingAliasSets = attrValues (filterAttrs (n: v: isAttrs v && !(isFunctor v)) attrset); - - # [ {String} ] - recursedAliasSets = filteredAliases - ++ (remainingFunctors) - ++ (map allAttrValuesAreStrings remainingAliasSets); - in concatAttrs recursedAliasSets; - - in - allAttrValuesAreStrings _module.args.shellOptions.aliases; - }; - - xdg.dataFile = { - aliases = { - text = let - inherit (lib.strings) stringLength; - inherit (extendedLib.strings) unlines wrap' replaceStrings' repeatString; - inherit (lib.attrsets) attrValues mapAttrs isAttrs; - inherit (lib.lists) remove; - inherit (lib.trivial) mapNullable; - inherit (extendedLib.termColors.front) red green blue; - - # int -> String -> AttrSet -> String - stringifyCategory = level: name: category: - unlines - (["${repeatString " " level}[${green name}]"] ++ - (attrValues (mapAttrs (n: v: let - # String - indent = repeatString " " level; - - # String -> String - removeNixLinks = text: let - maybeMatches = builtins.match "(|.*[^)])(/nix/store/.*/bin/).*" text; - matches = mapNullable (remove "") maybeMatches; - in - if (maybeMatches == null) - then text - else replaceStrings' matches "" text; - - applyFunctor = attrset: let - applied = functors.${attrset.type}.stringify attrset; - indent' = indent + (repeatString " " ((stringLength " -> \"") + (stringLength n))) + " "; - in - replaceStrings' ["\n"] ("\n" + indent') applied; - - recurse = stringifyCategory (level + 1) n v; - in - if !(isAttrs v) then "${indent} ${red n} -> ${wrap' (blue "\"") (removeNixLinks v)}" else - if isFunctor v then "${indent} ${red n} -> ${wrap' (blue "\"") (removeNixLinks (applyFunctor v))}" else - recurse) category))); - in - (stringifyCategory 0 "Aliases" _module.args.shellOptions.aliases) + "\n"; - }; - packageManagerLecture = { - target = "package-manager.lecture"; - text = let - inherit (extendedLib.strings) unlines; - inherit (extendedLib.termColors.front) red blue; - in unlines [ - ((red "This package manager is not installed on ") + (blue "NixOS") + (red ".")) - ((red "Either use ") + ("\"nix-env -i\"") + (red " or install it through a configuration file.")) - "" - ]; - }; - }; -}