{ pkgs, lib, config, ... }: { home.packages = with pkgs; [ gum clipboard-jh ]; # ██████╗ ██╗████████╗ # ██╔════╝ ██║╚══██╔══╝ # ██║ ███╗██║ ██║ # ██║ ██║██║ ██║ # ╚██████╔╝██║ ██║ # ╚═════╝ ╚═╝ ╚═╝ programs.git = { enable = true; userName = "punkfairie"; userEmail = "marley@punkfairie.net"; signing = { signByDefault = true; key = null; }; lfs.enable = true; ignores = [ "tags*" "gems.tags" ]; attributes = [ # Auto-normalize line endings. "* text=auto" "*.png binary" "*.jpg binary" "*.jpeg binary" "*.bmp binary" ]; # ██████╗ ███████╗██╗ ████████╗ █████╗ # ██╔══██╗██╔════╝██║ ╚══██╔══╝██╔══██╗ # ██║ ██║█████╗ ██║ ██║ ███████║ # ██║ ██║██╔══╝ ██║ ██║ ██╔══██║ # ██████╔╝███████╗███████╗██║ ██║ ██║ # ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ delta = { enable = true; options = { navigate = true; # TODO: Add to rose-pine-nix syntax-theme = "rose-pine"; features = "mellow-barbet"; true-color = "always"; hyperlinks = true; }; }; # ██████╗ ██████╗ ███╗ ██╗███████╗██╗ ██████╗ # ██╔════╝██╔═══██╗████╗ ██║██╔════╝██║██╔════╝ # ██║ ██║ ██║██╔██╗ ██║█████╗ ██║██║ ███╗ # ██║ ██║ ██║██║╚██╗██║██╔══╝ ██║██║ ██║ # ╚██████╗╚██████╔╝██║ ╚████║██║ ██║╚██████╔╝ # ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ extraConfig = { core = { # Whitespace types to treat as errors. # blank-at-eol: looks for spaces at EOL. # -blank-at-eof: allows blank lines at EOF. # space-before-tab: looks for spaces immediately before tabs at the # beginning of the line. whitespace = "blank-at-eol,-blank-at-eof,space-before-tab"; # Prevent showing files whose names contain non-ASCII symbols as # unversioned. precomposeunicode = false; # Speed up commands involving untracked files such as `git status`. untrackedCache = true; }; # Do not guess the user's identity. user.useConfigOnly = true; color.diff = "always"; pretty = { lo = "tformat:%C(auto)%h%C(reset)%C(auto)%d%C(reset) %s %C(italic blue)%ad%C(reset) %C(241)%aN%C(reset)"; lc = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n"; lt = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n%w(0,7,7)%+(trailers:only,unfold)"; lf = "format:%C(auto)%h%C(reset)%C(auto)%d%C(reset) %C(italic 239)[P: %p] [T: %t]%C(reset)%n%C(white)Author:%C(reset) %aN %C(241)<%aE>%C(reset)%n %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%n%C(white)Commit:%C(reset) %cN %C(241)<%cE>%C(reset) %C(italic 239)[GPG: %G?% GK]%C(reset)%n %C(italic blue)%cd%C(reset) %C(italic cyan)(%cr)%C(reset)%w(0,4,4)%n%n%C(bold)%s%C(reset)%n%n%-b%n%n%-N%n"; rlo = "tformat:%C(auto)%h%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset)%C(auto)%d%C(reset) %gs %C(italic blue)%ad%C(reset) %C(241)%aN%C(reset)"; rlc = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n %C(white)⤷%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset) %gs %C(241)- %gN <%gE>%C(reset)%n"; rlt = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n %C(white)⤷%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset) %gs %C(241)- %gN <%gE>%C(reset)%n%w(0,7,7)%+(trailers:only,unfold)"; rlf = "format:%C(auto)%h%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset)%C(auto)%d%C(reset) %C(italic 239)[P: %p] [T: %t]%C(reset)%n%C(white)Author:%C(reset) %aN %C(241)<%aE>%C(reset)%n %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%n%C(white)Commit:%C(reset) %cN %C(241)<%cE>%C(reset) %C(italic 239)[GPG: %G?% GK]%C(reset)%n %C(italic blue)%cd%C(reset) %C(italic cyan)(%cr)%C(reset)%n%C(white)Reflog:%C(reset) %gN %C(241)<%gE>%C(reset)%n %C(italic)%gs%C(reset)%w(0,4,4)%n%n%C(bold)%s%C(reset)%n%n%-b%n%n%-N%n"; }; init.defaultBranch = "main"; status.showstash = true; push = { autoSetupRemote = true; # Push tags automatically. followTags = true; }; rebase.autosquash = true; merge = { # Use nvim for merging, specifically the view showing LOCAL, MERGED, # REMOTE. tool = "nvimdiff2"; # Include summaries of merged commits in merge commit messages. log = true; # delta. conflictstyle = "diff3"; }; mergetool = { keepBackup = false; hideResolved = true; }; diff = { # Detect when files are copied as well as renamed. renames = "copies"; # delta colorMoved = "default"; }; # Fix whitespace errors when applying a patch, as specified in # core.whitespace. apply.whitespace = "fix"; branch = { # Show most recently changed branches first. sort = "-committerdate"; autoSetupMerge = "simple"; }; credential.helper = "store"; }; # █████╗ ██╗ ██╗ █████╗ ███████╗███████╗███████╗ # ██╔══██╗██║ ██║██╔══██╗██╔════╝██╔════╝██╔════╝ # ███████║██║ ██║███████║███████╗█████╗ ███████╗ # ██╔══██║██║ ██║██╔══██║╚════██║██╔══╝ ╚════██║ # ██║ ██║███████╗██║██║ ██║███████║███████╗███████║ # ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ aliases = let fish_fns = config.programs.fish.functions; in { ### Staging ### a = "add"; aa = "add --all"; # Interactively stage parts of a file. apa = "add --patch"; da = "diff"; das = "diff --staged"; daw = "diff --word-diff"; # Show diff by word. dasw = "diff --staged --word-diff"; d = "!f() { git diff \"$@\" ':(exclude)package-lock.json' ':(exclude)*.lock'; }; f"; ds = "!f() { git diff --staged \"$@\" ':(exclude)package-lock.json' ':(exclude)*.lock'; }; f"; dw = "!f() { git diff --word-diff \"$@\" ':(exclude)package-lock.json' ':(exclude)*.lock'; }; f"; dsw = "!f() { git diff --staged --word-diff \"$@\" ':(exclude)package-lock.json' ':(exclude)*.lock'; }; f"; st = "status --short --branch"; stu = "status --short --branch --untracked-files"; stl = "status"; ### Committing ### c = "commit"; ce = "commit --amend"; cen = "commit --amend --no-edit --no-verify"; ca = "!git add --alll && git commit"; cae = "!git add --all && git commit --amend"; caen = "!git add --all && git commit --amend --no-edit --no-verify"; cfu = "commit --fixup"; rev = "revert"; ### Working Dir & Index Manipulation ### co = "checkout"; rt = "reset"; rts = "reset --soft"; # undo commits & stage their changes rs = "restore --worktree"; # revert local changes rst = "restore --staged"; # unstage things rsa = "restore --worktree --staged"; rss = "restore --worktree --source"; # specify a commit to revert to rsts = "restore --staged --source"; rsas = "restore --worktree --staged --source"; rmc = "rm --cached"; # leave worktree copy alone sta = "stash push"; stam = "stash push --message"; staa = "stash push --include-untracted"; staam = "stash push --include-untracted --message"; stap = "stash pop"; stal = "stash list"; stas = "stash show --text"; cl = "clean -force"; # remove untracked & unignored files cldr = "clean --dry-run"; ### Branches ### b = "branch"; cb = "checkout -b"; cm = lib.mkIf (fish_fns ? git_main_branch) "!git checkout $(git_main_branch)"; cd = lib.mkIf (fish_fns ? git_develop_branch) "!git checkout $(git_develop_branch)"; m = "merge"; mtl = "mergetool --no-prompt"; ma = "merge --abort"; cp = "cherry-pick"; cpa = "cherry-pick --abort"; cpc = "cherry-pick --continue"; cpq = "cherry-pick --quit"; ### Remotes ### p = "push"; pv = "push --verbose"; pdr = "push --dry-run"; pf = "push --force-with-lease --force-if-includes"; pfv = "push --verbose --force-with-lease --force-if-includes"; pff = "push --force"; pffv = "push --verbose --force"; f = "fetch"; fa = "fetch --all --prune"; pl = "pull"; plr = "pull --rebase"; sub = "submodule"; subu = "submodule update --init --recursive"; r = "remote"; rv = "remote --verbose"; ra = "remote add"; rrm = "remote remove"; rmv = "remote rename"; rset = "remote set-url"; rup = "remote update"; ### Logs ### # Current branch. l = "log --pretty=lc --graph"; lo = "log --pretty=lo --graph --date=human"; ls = "log --pretty=lo --graph --date=human --simplify-by-decoration"; lf = "log --pretty=lf --graph"; ld = "log --pretty=lf --graph --cc --stat"; lp = "log --pretty=lf --graph --cc --patch"; lr = "log -5 --pretty=lc --graph"; lro = "log -5 --pretty=lo --graph --date=human"; lrs = "log -5 --pretty=lo --graph --date=human --simplify-by-decoration"; lrf = "log -5 --pretty=lf --graph"; lrd = "log -5 --pretty=lf --graph --cc --stat"; lrp = "log -5 --pretty=lf --graph --cc --patch"; # All branches on all remotes. la = "log --pretty=lc --graph --all"; lao = "log --pretty=lo --graph --all --date=human"; las = "log --pretty=lo --graph --all --date=human --simplify-by-decoration"; laf = "log --pretty=lf --graph --all"; lad = "log --pretty=lf --graph --all --cc --stat"; lap = "log --pretty=lf --graph --all --cc --patch"; lar = "log -5 --pretty=lc --graph --all"; laro = "log -5 --pretty=lo --graph --all --date=human"; lars = "log -5 --pretty=lo --graph --all --date=human --simplify-by-decoration"; larf = "log -5 --pretty=lf --graph --all"; lard = "log -5 --pretty=lf --graph --all --cc --stat"; larp = "log -5 --pretty=lf --graph --all --cc --patch"; ### Shortcuts ### nevermind = "!git reset --hard head && git clean -df"; open = lib.mkIf (config.programs.fish.enable && (fish_fns ? git_open)) "!fish -c git_open"; chash = "!git log --oneline | gum filter --height 10 | cut -d' ' -f1 | cb &>/dev/null"; }; }; # ███╗ ███╗██╗███████╗ ██████╗ # ████╗ ████║██║██╔════╝██╔════╝ # ██╔████╔██║██║███████╗██║ # ██║╚██╔╝██║██║╚════██║██║ # ██║ ╚═╝ ██║██║███████║╚██████╗ # ╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ home.shellAbbrs = { g = "git"; }; programs.fish.functions = lib.mkIf config.programs.fish.enable { git_develop_branch = # fish '' command git rev-parse --git-dir &>/dev/null || return set -l branch for branch in dev devel develop development if command git show-ref -q --verify refs/heads/$branch echo $branch return 0 end end echo develop return 1 ''; git_main_branch = # fish '' command git rev-parse --git-dir &>/dev/null || return set -l ref for ref in refs/{heads,remotes/{origin,upstream}}/{main,trunk,mainline,default,master} if command git show-ref -q --verify $ref echo (basename $ref) return 0 end end echo main return 1 ''; git_current_branch = # fish '' set -l ref (git symbolic-ref --quiet HEAD 2>/dev/null) set -l ret $status if [ $ret -ne 0 ] [ $ret -eq 128 ] && return # no git repo set ref (git rev-parse --short HEAD 2>/dev/null) || return end echo (string replace "refs/heads/" "" $ref) ''; git_open = # fish '' set -f origin "$(git remote get-url origin)" switch "$origin" case "*github*" if command -v gh &>/dev/null gh repo view --web &>/dev/null else set_color red echo "[ERROR] Install gh-cli to open Github repos." >&2 set_color normal return 1 end case "https://*" open '$origin' >/dev/null & case "*" set_color red printf "[ERROR] Unrecognized origin %s" "$origin" >&2 return 1 end ''; }; } # ███╗ ██╗ ██████╗ ████████╗███████╗███████╗ # ████╗ ██║██╔═══██╗╚══██╔══╝██╔════╝██╔════╝ # ██╔██╗ ██║██║ ██║ ██║ █████╗ ███████╗ # ██║╚██╗██║██║ ██║ ██║ ██╔══╝ ╚════██║ # ██║ ╚████║╚██████╔╝ ██║ ███████╗███████║ # ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚══════╝╚══════╝ # PATH VALUES: # :/ - all files within the root of the working tree, so all files in the # repo, a la git add's --all option. # A note on reset, restore, and revert, paraphrased from `man git`, plus my # own on `rm`: # # revert - make a new commit that reverts a previous commit. # restore - undo uncommitted changes in the working tree. # reset - update the branch and change commit history. # rm - same as system rm; remove files, either from git's knowledge, the # working directory, or both. # # These are not a description of the *possible* uses, rather a narrowing of # the *intended* uses.