zsh: port to sane.programs

This commit is contained in:
2024-05-18 08:01:06 +00:00
parent c987f13ef0
commit 3361f2bbe7
4 changed files with 232 additions and 238 deletions

View File

@@ -21,7 +21,7 @@
sane.roles.client = true; sane.roles.client = true;
sane.roles.handheld = true; sane.roles.handheld = true;
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell sane.programs.zsh.config.showDeadlines = false; # unlikely to act on them when in shell
sane.services.wg-home.enable = true; sane.services.wg-home.enable = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip; sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;

View File

@@ -15,7 +15,7 @@
}; };
sane.roles.build-machine.enable = true; sane.roles.build-machine.enable = true;
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist sane.programs.zsh.config.showDeadlines = false; # ~/knowledge doesn't always exist
sane.programs.consoleUtils.suggestedPrograms = [ sane.programs.consoleUtils.suggestedPrograms = [
"consoleMediaUtils" # notably, for go2tv / casting "consoleMediaUtils" # notably, for go2tv / casting
"pcConsoleUtils" "pcConsoleUtils"

View File

@@ -19,186 +19,182 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
inherit (lib) mkIf mkMerge mkOption types; cfg = config.sane.programs.zsh;
cfg = config.sane.zsh;
in in
{ {
imports = [ imports = [
./starship.nix ./starship.nix
]; ];
options = {
# TODO: port to sane.programs options sane.programs.zsh = {
sane.zsh = { configOption = with lib; mkOption {
showDeadlines = mkOption { default = {};
type = types.bool; type = types.submodule {
default = true; options.showDeadlines = mkOption {
description = "show upcoming deadlines (from my PKM) upon shell init"; type = types.bool;
}; default = true;
starship = mkOption { description = "show upcoming deadlines (from my PKM) upon shell init";
type = types.bool; };
default = true; options.starship = mkOption {
description = "enable starship prompt"; type = types.bool;
}; default = true;
guiIntegrations = mkOption { description = "enable starship prompt";
type = types.bool; };
default = config.sane.programs.guiApps.enabled; options.guiIntegrations = mkOption {
description = '' type = types.bool;
integrate with things like VTE, so that windowing systems can show the PWD in the title. default = config.sane.programs.guiApps.enabled;
drags in gtk+3. description = ''
''; integrate with things like VTE, so that windowing systems can show the PWD in the title.
drags in gtk+3.
'';
};
}; };
}; };
sandbox.enable = false; # TODO: i could at least sandbox the prompt (starship)!
persist.byStore.private = [
# we don't need to full zsh dir -- just the history file --
# but zsh will sometimes backup the history file and symlinking just the file messes things up
".local/share/zsh"
];
fs.".config/zsh/.zshrc".symlink.text = ''
# zsh/prezto complains if zshrc doesn't exist or is empty;
# preserve this comment to prevent that from ever happening.
'' + lib.optionalString cfg.config.showDeadlines ''
${pkgs.sane-scripts.deadlines}/bin/sane-deadlines
'' + ''
HISTFILE="$HOME/.local/share/zsh/history"
HISTSIZE=1000000
SAVEHIST=1000000
# auto-cd into any of these dirs by typing them and pressing 'enter':
hash -d 3rd="/home/colin/dev/3rd"
hash -d dev="/home/colin/dev"
hash -d knowledge="/home/colin/knowledge"
hash -d nixos="/home/colin/nixos"
hash -d nixpkgs="/home/colin/dev/3rd/nixpkgs"
hash -d ref="/home/colin/ref"
hash -d secrets="/home/colin/knowledge/secrets"
hash -d tmp="/home/colin/tmp"
hash -d uninsane="/home/colin/dev/uninsane"
hash -d Videos="/home/colin/Videos"
# emulate bash keybindings
bindkey -e
# fixup bindings not handled by bash, see: <https://wiki.archlinux.org/title/Zsh#Key_bindings>
# `bindkey -e` seems to define most of the `key` array. everything in the Arch defaults except for these:
key[Backspace]="''${terminfo[kbs]}"
key[Control-Left]="''${terminfo[kLFT5]}"
key[Control-Right]="''${terminfo[kRIT5]}"
key[Shift-Tab]="''${terminfo[kcbt]}"
bindkey -- "''${key[Delete]}" delete-char
bindkey -- "''${key[Control-Left]}" backward-word
bindkey -- "''${key[Control-Right]}" forward-word
# or manually recreate what i care about...
# key[Left]=''${terminfo[kcub1]}
# key[Right]=''${terminfo[kcuf1]}
# bindkey '^R' history-incremental-search-backward
# bindkey '^A' beginning-of-line
# bindkey '^E' end-of-line
# bindkey "^''${key[Left]}" backward-word
# bindkey "^''${key[Right]}" forward-word
# run any additional, sh-generic commands (useful for e.g. launching a login manager on login)
test -e ~/.profile && source ~/.profile
'';
}; };
config = mkMerge [
({
sane.programs.zsh = {
sandbox.enable = false; # TODO: i could at least sandbox the prompt (starship)!
persist.byStore.private = [
# we don't need to full zsh dir -- just the history file --
# but zsh will sometimes backup the history file and symlinking just the file messes things up
".local/share/zsh"
];
fs.".config/zsh/.zshrc".symlink.text = '' # enable zsh completions
# zsh/prezto complains if zshrc doesn't exist or is empty; environment.pathsToLink = lib.mkIf cfg.enabled [ "/share/zsh" ];
# preserve this comment to prevent that from ever happening.
'' + lib.optionalString cfg.showDeadlines ''
${pkgs.sane-scripts.deadlines}/bin/sane-deadlines
'' + ''
HISTFILE="$HOME/.local/share/zsh/history" programs.zsh = lib.mkIf cfg.enabled {
HISTSIZE=1000000 enable = true;
SAVEHIST=1000000 shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
"ecit" = "exit";
"exi5" = "exit";
"exiy" = "exit";
# ls helpers (eza is a nicer `ls`
"l" = "eza --oneline"; # show one entry per line
"ll" = "eza --long --time-style=long-iso";
# overcome poor defaults
"lsof" = "lsof -P"; #< lsof: use port *numbers*, not names
"tcpdump" = "tcpdump -n"; #< tcpdump: use port *numbers*, not names
};
setOptions = [
# docs: `man zshoptions`
# nixos defaults:
"HIST_FCNTL_LOCK"
"HIST_IGNORE_DUPS"
"HIST_EXPIRE_DUPS_FIRST"
"SHARE_HISTORY"
# customizations:
"AUTO_CD" # type directory name to go there
"AUTO_MENU" # show auto-complete menu on double-tab
"CDABLE_VARS" # allow auto-cd to use my `hash` aliases -- not just immediate subdirs
"CLOBBER" # allow `foo > bar.txt` to overwrite bar.txt
"NO_CORRECT" # don't try to correct commands
"PIPE_FAIL" # when `cmd_a | cmd_b`, make $? be non-zero if *any* of cmd_a or cmd_b fail
"RM_STAR_SILENT" # disable `rm *` confirmations
];
# auto-cd into any of these dirs by typing them and pressing 'enter': # .zshenv config:
hash -d 3rd="/home/colin/dev/3rd" shellInit = ''
hash -d dev="/home/colin/dev" ZDOTDIR=$HOME/.config/zsh
hash -d knowledge="/home/colin/knowledge" '';
hash -d nixos="/home/colin/nixos"
hash -d nixpkgs="/home/colin/dev/3rd/nixpkgs"
hash -d ref="/home/colin/ref"
hash -d secrets="/home/colin/knowledge/secrets"
hash -d tmp="/home/colin/tmp"
hash -d uninsane="/home/colin/dev/uninsane"
hash -d Videos="/home/colin/Videos"
# emulate bash keybindings # system-wide .zshrc config:
bindkey -e interactiveShellInit = ''
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
autoload -Uz zmv
# fixup bindings not handled by bash, see: <https://wiki.archlinux.org/title/Zsh#Key_bindings> HISTORY_IGNORE='(sane-shutdown *|sane-reboot *|rm *|nixos-rebuild.* switch|switch)'
# `bindkey -e` seems to define most of the `key` array. everything in the Arch defaults except for these:
key[Backspace]="''${terminfo[kbs]}"
key[Control-Left]="''${terminfo[kLFT5]}"
key[Control-Right]="''${terminfo[kRIT5]}"
key[Shift-Tab]="''${terminfo[kcbt]}"
bindkey -- "''${key[Delete]}" delete-char
bindkey -- "''${key[Control-Left]}" backward-word
bindkey -- "''${key[Control-Right]}" forward-word
# or manually recreate what i care about... # extra aliases
# key[Left]=''${terminfo[kcub1]} # TODO: move to `shellAliases` config?
# key[Right]=''${terminfo[kcuf1]} function c() {
# bindkey '^R' history-incremental-search-backward # list a dir after entering it
# bindkey '^A' beginning-of-line cd "$1"
# bindkey '^E' end-of-line eza --oneline
# bindkey "^''${key[Left]}" backward-word }
# bindkey "^''${key[Right]}" forward-word function deref() {
# convert a symlink into a plain file of the same content
if [ -L "$1" ] && [ -f "$1" ]; then
cp --dereference "$1" "$1.deref"
mv -f "$1.deref" "$1"
fi
chmod u+w "$1"
}
function nd() {
# enter a directory, creating it if necessary
mkdir -p "$1"
pushd "$1"
}
# run any additional, sh-generic commands (useful for e.g. launching a login manager on login) function repo() {
test -e ~/.profile && source ~/.profile # navigate to a local checkout of the source code for repo (i.e. package) $1
''; eval $(sane-clone "$1")
};
})
(mkIf config.sane.programs.zsh.enabled {
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
programs.zsh = {
enable = true;
shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
"ecit" = "exit";
"exi5" = "exit";
"exiy" = "exit";
# ls helpers (eza is a nicer `ls`
"l" = "eza --oneline"; # show one entry per line
"ll" = "eza --long --time-style=long-iso";
# overcome poor defaults
"lsof" = "lsof -P"; #< lsof: use port *numbers*, not names
"tcpdump" = "tcpdump -n"; #< tcpdump: use port *numbers*, not names
};
setOptions = [
# docs: `man zshoptions`
# nixos defaults:
"HIST_FCNTL_LOCK"
"HIST_IGNORE_DUPS"
"HIST_EXPIRE_DUPS_FIRST"
"SHARE_HISTORY"
# customizations:
"AUTO_CD" # type directory name to go there
"AUTO_MENU" # show auto-complete menu on double-tab
"CDABLE_VARS" # allow auto-cd to use my `hash` aliases -- not just immediate subdirs
"CLOBBER" # allow `foo > bar.txt` to overwrite bar.txt
"NO_CORRECT" # don't try to correct commands
"PIPE_FAIL" # when `cmd_a | cmd_b`, make $? be non-zero if *any* of cmd_a or cmd_b fail
"RM_STAR_SILENT" # disable `rm *` confirmations
];
# .zshenv config:
shellInit = ''
ZDOTDIR=$HOME/.config/zsh
'';
# system-wide .zshrc config:
interactiveShellInit = ''
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
autoload -Uz zmv
HISTORY_IGNORE='(sane-shutdown *|sane-reboot *|rm *|nixos-rebuild.* switch|switch)'
# extra aliases
# TODO: move to `shellAliases` config?
function c() {
# list a dir after entering it
cd "$1"
eza --oneline
}
function deref() {
# convert a symlink into a plain file of the same content
if [ -L "$1" ] && [ -f "$1" ]; then
cp --dereference "$1" "$1.deref"
mv -f "$1.deref" "$1"
fi
chmod u+w "$1"
}
function nd() {
# enter a directory, creating it if necessary
mkdir -p "$1"
pushd "$1"
}
function repo() {
# navigate to a local checkout of the source code for repo (i.e. package) $1
eval $(sane-clone "$1")
};
function switch() {
nix run '.#deploy.self'
}
'';
syntaxHighlighting.enable = true;
vteIntegration = cfg.guiIntegrations;
}; };
# enable a command-not-found hook to show nix packages that might provide the binary typed. function switch() {
# programs.nix-index.enableZshIntegration = true; nix run '.#deploy.self'
programs.command-not-found.enable = false; }
}) '';
];
syntaxHighlighting.enable = true;
vteIntegration = cfg.config.guiIntegrations;
};
# enable a command-not-found hook to show nix packages that might provide the binary typed.
# programs.nix-index.enableZshIntegration = lib.mkIf cfg.enabled true;
programs.command-not-found.enable = lib.mkIf cfg.enabled false;
} }

View File

@@ -4,7 +4,7 @@
{ config, lib, pkgs, ...}: { config, lib, pkgs, ...}:
let let
enabled = config.sane.zsh.starship; enabled = config.sane.programs.zsh.config.starship;
toml = pkgs.formats.toml {}; toml = pkgs.formats.toml {};
colors = { colors = {
# colors sorted by the order they appear in the status bar # colors sorted by the order they appear in the status bar
@@ -16,86 +16,84 @@ let
_06_blue = "#33658A"; _06_blue = "#33658A";
}; };
in { in {
config = lib.mkIf config.sane.zsh.starship { sane.programs.zsh.fs = lib.mkIf enabled {
sane.programs.zsh = lib.mkIf enabled { ".config/zsh/.zshrc".symlink.text = ''
fs.".config/zsh/.zshrc".symlink.text = '' eval "$(${pkgs.starship}/bin/starship init zsh)"
eval "$(${pkgs.starship}/bin/starship init zsh)" '';
''; ".config/starship.toml".symlink.target = toml.generate "starship.toml" {
fs.".config/starship.toml".symlink.target = toml.generate "starship.toml" { format = builtins.concatStringsSep "" [
format = builtins.concatStringsSep "" [ "[](${colors._01_purple})"
"[](${colors._01_purple})" "$os"
"$os" "$username"
"$username" "$hostname"
"$hostname" "[](bg:${colors._02_pink} fg:${colors._01_purple})"
"[](bg:${colors._02_pink} fg:${colors._01_purple})" "$directory"
"$directory" "[](fg:${colors._02_pink} bg:${colors._03_orange})"
"[](fg:${colors._02_pink} bg:${colors._03_orange})" "$git_branch"
"$git_branch" "$git_status"
"$git_status" "[](fg:${colors._03_orange} bg:${colors._04_teal})"
"[](fg:${colors._03_orange} bg:${colors._04_teal})" "[](fg:${colors._04_teal} bg:${colors._05_blue})"
"[](fg:${colors._04_teal} bg:${colors._05_blue})" "[](fg:${colors._05_blue} bg:${colors._06_blue})"
"[](fg:${colors._05_blue} bg:${colors._06_blue})" "$time"
"$time" "$status"
"$status" "[ ](fg:${colors._06_blue})"
"[ ](fg:${colors._06_blue})" ];
]; add_newline = false; # no blank line before prompt
add_newline = false; # no blank line before prompt
os.style = "bg:${colors._01_purple}"; os.style = "bg:${colors._01_purple}";
os.format = "[$symbol]($style)"; os.format = "[$symbol]($style)";
os.disabled = false; os.disabled = false;
# os.symbols.NixOS = "❄️"; # removes the space after logo # os.symbols.NixOS = "❄️"; # removes the space after logo
# TODO: tune foreground color of username # TODO: tune foreground color of username
username.style_user = "bg:${colors._01_purple}"; username.style_user = "bg:${colors._01_purple}";
username.style_root = "bold bg:${colors._01_purple}"; username.style_root = "bold bg:${colors._01_purple}";
username.format = "[$user ]($style)"; username.format = "[$user ]($style)";
hostname.style = "bold bg:${colors._01_purple}"; hostname.style = "bold bg:${colors._01_purple}";
hostname.format = "[$ssh_symbol$hostname ]($style)"; hostname.format = "[$ssh_symbol$hostname ]($style)";
directory.style = "bg:${colors._02_pink} fg:#ffffff"; directory.style = "bg:${colors._02_pink} fg:#ffffff";
directory.format = "[ $path ]($style)"; directory.format = "[ $path ]($style)";
directory.truncation_length = 3; directory.truncation_length = 3;
directory.truncation_symbol = "/"; directory.truncation_symbol = "/";
# git_branch.symbol = ""; # looks good in nerd fonts # git_branch.symbol = ""; # looks good in nerd fonts
git_branch.symbol = ""; git_branch.symbol = "";
git_branch.style = "bg:${colors._03_orange} fg:#ffffff"; git_branch.style = "bg:${colors._03_orange} fg:#ffffff";
# git_branch.style = "bg:#FF8262"; # git_branch.style = "bg:#FF8262";
git_branch.format = "[ $symbol $branch ]($style)"; git_branch.format = "[ $symbol $branch ]($style)";
git_status.style = "bold bg:${colors._03_orange} fg:#ffffff"; git_status.style = "bold bg:${colors._03_orange} fg:#ffffff";
# git_status.style = "bg:#FF8262"; # git_status.style = "bg:#FF8262";
git_status.format = "[$all_status$ahead_behind ]($style)"; git_status.format = "[$all_status$ahead_behind ]($style)";
git_status.ahead = "$count"; git_status.ahead = "$count";
git_status.behind = "$count"; git_status.behind = "$count";
# git_status.diverged = "⇣$behind_count⇡$ahead_count"; # git_status.diverged = "⇣$behind_count⇡$ahead_count";
git_status.diverged = "$ahead_count$behind_count"; git_status.diverged = "$ahead_count$behind_count";
git_status.modified = "*"; git_status.modified = "*";
git_status.stashed = ""; git_status.stashed = "";
git_status.untracked = ""; git_status.untracked = "";
time.disabled = true; time.disabled = true;
time.time_format = "%R"; # Hour:Minute Format time.time_format = "%R"; # Hour:Minute Format
time.style = "bg:${colors._06_blue}"; time.style = "bg:${colors._06_blue}";
time.format = "[ $time ]($style)"; time.format = "[ $time ]($style)";
status.disabled = false; status.disabled = false;
status.style = "bg:${colors._06_blue}"; status.style = "bg:${colors._06_blue}";
# status.success_symbol = "♥ "; # status.success_symbol = "♥ ";
# status.success_symbol = "💖"; # status.success_symbol = "💖";
# status.success_symbol = "💙"; # status.success_symbol = "💙";
# status.success_symbol = "💚"; # status.success_symbol = "💚";
# status.success_symbol = "💜"; # status.success_symbol = "💜";
# status.success_symbol = "✔️'"; # status.success_symbol = "✔️'";
status.success_symbol = ""; status.success_symbol = "";
status.symbol = ""; status.symbol = "";
# status.symbol = "❗️"; # status.symbol = "❗️";
# status.symbol = "‼️"; # status.symbol = "‼️";
status.format = "[$symbol]($style)"; status.format = "[$symbol]($style)";
};
}; };
}; };
} }