Compare commits
8 Commits
9d0e69f916
...
faf2242539
| Author | SHA1 | Date | |
|---|---|---|---|
| faf2242539 | |||
| 27069e324f | |||
| 829f209300 | |||
| 06bc420948 | |||
| b806359fd6 | |||
| 0c4f555dec | |||
| 19dfb32cf6 | |||
| 79b325676d |
Generated
+21
@@ -150,6 +150,26 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nix-index-database": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780816331,
|
||||||
|
"narHash": "sha256-0BYqs8yKWkOz2Q7+SP18N5E5gmDKSo6LSxIVIa0wWes=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nix-index-database",
|
||||||
|
"rev": "1a2ea89c917781e88508d9fd2b507f2d2a0e173c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nix-index-database",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixos-apple-silicon": {
|
"nixos-apple-silicon": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
@@ -231,6 +251,7 @@
|
|||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"nix-darwin": "nix-darwin",
|
"nix-darwin": "nix-darwin",
|
||||||
"nix-homebrew": "nix-homebrew",
|
"nix-homebrew": "nix-homebrew",
|
||||||
|
"nix-index-database": "nix-index-database",
|
||||||
"nixos-apple-silicon": "nixos-apple-silicon",
|
"nixos-apple-silicon": "nixos-apple-silicon",
|
||||||
"nixos-wsl": "nixos-wsl",
|
"nixos-wsl": "nixos-wsl",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
|
|||||||
@@ -28,6 +28,12 @@
|
|||||||
url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons";
|
url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
# Prebuilt nix-index database so "command not found -> which package
|
||||||
|
# provides it" works immediately (no manual `nix-index` run). See shell.nix.
|
||||||
|
nix-index-database = {
|
||||||
|
url = "github:nix-community/nix-index-database";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
vim-fugitive
|
vim-fugitive
|
||||||
vim-indent-guides
|
vim-indent-guides
|
||||||
catppuccin-vim
|
catppuccin-vim
|
||||||
|
vim-tmux-navigator # Ctrl-h/j/k/l moves between vim splits and tmux panes
|
||||||
];
|
];
|
||||||
settings = {
|
settings = {
|
||||||
expandtab = false;
|
expandtab = false;
|
||||||
|
|||||||
+62
-5
@@ -1,6 +1,11 @@
|
|||||||
# Version control: git + delta pager + commitizen. The work host layers
|
# Version control: git + delta pager + commitizen. The work host layers
|
||||||
# commit signing and an email override on top (see work/default.nix).
|
# commit signing and an email override on top (see work/default.nix).
|
||||||
{ pkgs, fullName, ... }:
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
fullName,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
home.packages = [
|
home.packages = [
|
||||||
pkgs.commitizen
|
pkgs.commitizen
|
||||||
@@ -11,13 +16,65 @@
|
|||||||
package = pkgs.gitFull;
|
package = pkgs.gitFull;
|
||||||
settings = {
|
settings = {
|
||||||
user.name = fullName;
|
user.name = fullName;
|
||||||
push = {
|
# Personal identity. mkDefault so the work module overrides it on the work
|
||||||
autoSetupRemote = true;
|
# host (and to merge cleanly with that plain definition there).
|
||||||
|
user.email = lib.mkDefault "iam@emmathe.dev";
|
||||||
|
push.autoSetupRemote = true;
|
||||||
|
init.defaultBranch = "main";
|
||||||
|
|
||||||
|
# Rebase-centric pulls (matches the "always a branch, linear history"
|
||||||
|
# workflow); stash/restore and reorder fixups automatically.
|
||||||
|
pull.rebase = true;
|
||||||
|
rebase = {
|
||||||
|
autoStash = true;
|
||||||
|
autoSquash = true;
|
||||||
};
|
};
|
||||||
init = {
|
|
||||||
defaultBranch = "main";
|
fetch.prune = true; # drop deleted remote-tracking branches
|
||||||
|
merge.conflictStyle = "zdiff3"; # show the common ancestor in conflicts
|
||||||
|
diff = {
|
||||||
|
algorithm = "histogram";
|
||||||
|
colorMoved = "default";
|
||||||
};
|
};
|
||||||
|
rerere.enabled = true; # remember + replay conflict resolutions
|
||||||
|
commit.verbose = true; # full diff in the commit-message editor
|
||||||
|
branch.sort = "-committerdate"; # most-recent branches first
|
||||||
|
column.ui = "auto";
|
||||||
|
help.autocorrect = "prompt";
|
||||||
|
|
||||||
|
alias = {
|
||||||
|
st = "status";
|
||||||
|
co = "checkout";
|
||||||
|
sw = "switch";
|
||||||
|
br = "branch";
|
||||||
|
ci = "commit";
|
||||||
|
last = "log -1 HEAD";
|
||||||
|
unstage = "reset HEAD --";
|
||||||
|
lg = "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' --all";
|
||||||
|
# commitizen (Conventional Commits, its default ruleset): `git cz c` ->
|
||||||
|
# `cz commit`, `git cz bump`, etc. `git cc` is a shortcut for the prompt.
|
||||||
|
cz = "!cz";
|
||||||
|
cc = "!cz commit";
|
||||||
|
};
|
||||||
|
|
||||||
|
# SSH commit signing on personal hosts too (the work module sets the same
|
||||||
|
# on the work host). mkDefault so a host without the key in its ssh-agent
|
||||||
|
# can override to false -- otherwise commits there would fail. Reuses the
|
||||||
|
# existing ssh key; a dedicated personal key can be swapped in later.
|
||||||
|
gpg.format = "ssh";
|
||||||
|
user.signingkey = "key::ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJMVgeRKnfX1G8coU3nAobI485aeUpGTMqH7+zbKI8o emma.thorpe@cloud.com";
|
||||||
|
commit.gpgsign = lib.mkDefault true;
|
||||||
|
tag.gpgsign = lib.mkDefault true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Global ignore file (~/.config/git/ignore).
|
||||||
|
ignores = [
|
||||||
|
"result"
|
||||||
|
"result-*"
|
||||||
|
".direnv"
|
||||||
|
"*.swp"
|
||||||
|
".DS_Store"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.delta = {
|
programs.delta = {
|
||||||
|
|||||||
+172
-11
@@ -1,6 +1,17 @@
|
|||||||
# Interactive shell: zsh + tmux. Wanted on every host.
|
# Interactive shell: zsh + tmux. Wanted on every host.
|
||||||
{ lib, ... }:
|
|
||||||
{
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
# Prebuilt nix-index database -> working command-not-found
|
||||||
|
# ("cmd not found -> which nix package provides it"), no manual indexing.
|
||||||
|
inputs.nix-index-database.homeModules.default
|
||||||
|
];
|
||||||
|
|
||||||
programs.zsh = {
|
programs.zsh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableCompletion = true;
|
enableCompletion = true;
|
||||||
@@ -21,25 +32,109 @@
|
|||||||
"^[OB"
|
"^[OB"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
history.append = true;
|
history = {
|
||||||
|
append = true; # append, don't overwrite, on shell exit
|
||||||
|
size = 100000; # in-memory (HISTSIZE)
|
||||||
|
save = 100000; # on-disk (SAVEHIST)
|
||||||
|
ignoreDups = true; # drop consecutive duplicates
|
||||||
|
ignoreSpace = true; # leading-space commands stay out of history
|
||||||
|
expireDuplicatesFirst = true;
|
||||||
|
share = true; # live-share history across sessions
|
||||||
|
extended = true; # record timestamps
|
||||||
|
};
|
||||||
oh-my-zsh = {
|
oh-my-zsh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
plugins = [
|
plugins = [
|
||||||
"git"
|
"git"
|
||||||
"man"
|
"man"
|
||||||
|
"sudo" # double-Esc prefixes the last command with sudo
|
||||||
|
"colored-man-pages"
|
||||||
|
"extract" # `extract <archive>` for any format
|
||||||
];
|
];
|
||||||
theme = "robbyrussell";
|
theme = "robbyrussell";
|
||||||
};
|
};
|
||||||
syntaxHighlighting.enable = true;
|
syntaxHighlighting.enable = true;
|
||||||
# Prefix the prompt with the hostname over SSH.
|
initContent = lib.mkMerge [
|
||||||
initContent = lib.mkOrder 1500 ''
|
# Auto-start tmux in every interactive terminal -- foot, iTerm2, the WSL
|
||||||
if [ "$SSH_CLIENT" ] || [ "$SSH_TTY" ]; then
|
# shell, the Linux console -- so a new terminal lands straight in the
|
||||||
export PS1="%M $PS1"
|
# multiplexer (session "main": attach if present, else create). Panes run
|
||||||
fi
|
# a plain non-login zsh (tmux's default-command "${SHELL}"). Order 200
|
||||||
'';
|
# runs before oh-my-zsh/compinit so the exec replaces the shell before
|
||||||
envExtra = ''
|
# that setup is wasted. Guards, each preventing a real breakage:
|
||||||
alias cls=clear
|
# interactive only -> don't hijack scp / `ssh host cmd` / scripted shells
|
||||||
'';
|
# $TMUX empty -> a pane's zsh won't re-exec tmux (infinite loop)
|
||||||
|
# not SSH -> don't force inbound SSH logins into a server tmux
|
||||||
|
# not VS Code -> its integrated terminal manages itself
|
||||||
|
# tmux on PATH -> a failed exec would otherwise kill the login shell
|
||||||
|
(lib.mkOrder 200 ''
|
||||||
|
if [[ $- == *i* ]] \
|
||||||
|
&& [[ -z "$TMUX" ]] \
|
||||||
|
&& [[ -z "$SSH_CONNECTION" && -z "$SSH_TTY" ]] \
|
||||||
|
&& [[ "$TERM_PROGRAM" != "vscode" ]] \
|
||||||
|
&& command -v tmux >/dev/null 2>&1; then
|
||||||
|
exec tmux new-session -A -s main
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
# Prefix the prompt with the hostname over SSH (mkAfter).
|
||||||
|
(lib.mkOrder 1500 ''
|
||||||
|
if [ "$SSH_CLIENT" ] || [ "$SSH_TTY" ]; then
|
||||||
|
export PS1="%M $PS1"
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
shellAliases = {
|
||||||
|
# eza's zsh integration also defines these; set explicitly so the
|
||||||
|
# icons/git intent is obvious.
|
||||||
|
ls = "eza --icons --git";
|
||||||
|
ll = "eza --icons --git -l";
|
||||||
|
la = "eza --icons --git -la";
|
||||||
|
lt = "eza --icons --git --tree";
|
||||||
|
cls = "clear";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Fuzzy finder: Ctrl-R fuzzy history, Ctrl-T files, Alt-C cd.
|
||||||
|
programs.fzf = {
|
||||||
|
enable = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Frecency directory jumping: `z <fragment>`.
|
||||||
|
programs.zoxide = {
|
||||||
|
enable = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Per-project environments auto-loaded on cd, with the Nix dev-shell cache.
|
||||||
|
programs.direnv = {
|
||||||
|
enable = true;
|
||||||
|
nix-direnv.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Modern ls (drives the ls aliases above).
|
||||||
|
programs.eza = {
|
||||||
|
enable = true;
|
||||||
|
git = true;
|
||||||
|
icons = "auto"; # boolean form is deprecated
|
||||||
|
};
|
||||||
|
|
||||||
|
# Syntax-highlighting pager, used as `bat` (acts like cat when piped).
|
||||||
|
programs.bat.enable = true;
|
||||||
|
|
||||||
|
# command-not-found backed by the prebuilt nix-index DB (module imported
|
||||||
|
# above). `comma` runs an uninstalled program once: `, cowsay hi`.
|
||||||
|
programs.nix-index.enable = true;
|
||||||
|
programs.nix-index-database.comma.enable = true;
|
||||||
|
|
||||||
|
# Nicer nixos-rebuild/home-manager (diffs) + a weekly user-GC timer.
|
||||||
|
programs.nh = {
|
||||||
|
enable = true;
|
||||||
|
flake = "$HOME/code/nixfiles";
|
||||||
|
clean = {
|
||||||
|
enable = true;
|
||||||
|
dates = "weekly";
|
||||||
|
extraArgs = "--keep 5 --keep-since 3d";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.tmux = {
|
programs.tmux = {
|
||||||
@@ -50,6 +145,33 @@
|
|||||||
keyMode = "vi";
|
keyMode = "vi";
|
||||||
historyLimit = 500000;
|
historyLimit = 500000;
|
||||||
mouse = true;
|
mouse = true;
|
||||||
|
escapeTime = 10; # was the 500ms default -> laggy ESC in vim
|
||||||
|
focusEvents = true; # let vim see focus changes (autoread)
|
||||||
|
baseIndex = 1; # sets both base-index and pane-base-index
|
||||||
|
|
||||||
|
plugins = with pkgs.tmuxPlugins; [
|
||||||
|
sensible
|
||||||
|
vim-tmux-navigator # Ctrl-h/j/k/l across vim splits and tmux panes
|
||||||
|
yank
|
||||||
|
{
|
||||||
|
# Catppuccin Mocha statusline (v2 API: flavour + window options must be
|
||||||
|
# set before the plugin loads, which home-manager does for plugin
|
||||||
|
# extraConfig; the status modules below go in the main extraConfig,
|
||||||
|
# which HM appends after all plugins).
|
||||||
|
plugin = catppuccin;
|
||||||
|
extraConfig = ''
|
||||||
|
set -g @catppuccin_flavor 'mocha'
|
||||||
|
set -g @catppuccin_window_status_style 'rounded'
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
resurrect # save/restore sessions
|
||||||
|
{
|
||||||
|
plugin = continuum; # auto-save + restore on tmux start (after resurrect)
|
||||||
|
extraConfig = ''
|
||||||
|
set -g @continuum-restore 'on'
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
# `reverseSplit = true` already binds s -> vertical and v -> horizontal
|
# `reverseSplit = true` already binds s -> vertical and v -> horizontal
|
||||||
# split (the dotfiles' vim-style splits).
|
# split (the dotfiles' vim-style splits).
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
@@ -75,6 +197,45 @@
|
|||||||
set -as terminal-features ",foot*:title"
|
set -as terminal-features ",foot*:title"
|
||||||
set -as terminal-features ",foot*:ccolour"
|
set -as terminal-features ",foot*:ccolour"
|
||||||
set -as terminal-features ",foot*:cstyle"
|
set -as terminal-features ",foot*:cstyle"
|
||||||
|
|
||||||
|
# No home-manager options for these.
|
||||||
|
set -g renumber-windows on
|
||||||
|
set -g set-clipboard on
|
||||||
|
|
||||||
|
# Catppuccin v2 statusline. Must run after the plugin has loaded;
|
||||||
|
# home-manager appends this extraConfig after the whole plugin list.
|
||||||
|
set -g status-left-length 100
|
||||||
|
set -g status-right-length 100
|
||||||
|
set -g status-left ""
|
||||||
|
set -g status-right "#{E:@catppuccin_status_application}"
|
||||||
|
set -ag status-right "#{E:@catppuccin_status_session}"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Add the key to the agent on first use, so the passphrase is typed once per
|
||||||
|
# login session rather than per commit/push (commit signing uses this agent).
|
||||||
|
# The work box keeps its own ssh config (see work/default.nix), so this only
|
||||||
|
# manages ~/.ssh/config on the personal hosts.
|
||||||
|
programs.ssh = {
|
||||||
|
enable = true;
|
||||||
|
addKeysToAgent = "yes";
|
||||||
|
# macOS: also cache in the login keychain (no prompt after first unlock).
|
||||||
|
# UseKeychain is unknown to non-Apple openssh, so only emit it on Darwin.
|
||||||
|
extraConfig = lib.optionalString pkgs.stdenv.hostPlatform.isDarwin ''
|
||||||
|
UseKeychain yes
|
||||||
|
'';
|
||||||
|
# Gitea remote (the flake's origin) -- required on every host. Pins the
|
||||||
|
# dedicated key so the right identity is offered. identitiesOnly avoids
|
||||||
|
# "too many authentication failures" when the agent holds several keys.
|
||||||
|
matchBlocks."code.emmathe.dev" = {
|
||||||
|
user = "git";
|
||||||
|
port = 30009; # Gitea listens on a non-default SSH port
|
||||||
|
identityFile = "~/.ssh/code.emmathe.dev";
|
||||||
|
identitiesOnly = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Run a user ssh-agent on Linux (macOS provides one via launchd). EDaaS also
|
||||||
|
# enables this in the work module; both being true merges cleanly.
|
||||||
|
services.ssh-agent.enable = lib.mkIf pkgs.stdenv.hostPlatform.isLinux true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
# The work box keeps its own (corporate) ~/.ssh/config; don't let the personal
|
||||||
|
# programs.ssh (shell.nix) take it over. The ssh-agent below still runs.
|
||||||
|
programs.ssh.enable = lib.mkForce false;
|
||||||
|
|
||||||
programs.git = {
|
programs.git = {
|
||||||
settings = {
|
settings = {
|
||||||
commit.gpgsign = true;
|
commit.gpgsign = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user