1
Fork 0
mirror of https://github.com/thegeneralist01/config.git synced 2026-03-07 10:59:55 +01:00

config: command-line revamp

This commit is contained in:
TheGeneralist 2026-01-18 22:12:00 +01:00
parent 802a38f61b
commit 3f34891413
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
28 changed files with 1141 additions and 335 deletions

1
.zshrc Symbolic link
View file

@ -0,0 +1 @@
/nix/store/mlnm2lb8zaplnmaqb9k0pfprdwqbdn8b-home-manager-files/.zshrc

View file

@ -96,6 +96,10 @@ lib: inputs: self: lib.mkSystem "<os>" ./configuration.nix
1. Create `.nix` file in appropriate `modules/` subdirectory
2. Module is auto-discovered and loaded
### Theme Defaults
- `modules/common/theme.nix` defines shared theme options used by multiple modules (e.g., `bat`, `ghostty`)
- Adjust `config.theme.*` there or override per-host in `hosts/<hostname>/configuration.nix`
### Adding a New Host
1. Create `hosts/<hostname>/` directory
2. Add `default.nix` with system type
@ -129,6 +133,10 @@ lib: inputs: self: lib.mkSystem "<os>" ./configuration.nix
- Custom options available via `lib.mkOption`
- Flake inputs follow nixpkgs for consistency
### Rebuild Helper
- `rebuild.nu` at repo root wraps `nh` for local/remote rebuilds
- Shell alias `rebuild` points to the script (defined in `modules/common/shell/aliases.nix`)
## Debugging Tips
### Build Issues
@ -147,6 +155,9 @@ lib: inputs: self: lib.mkSystem "<os>" ./configuration.nix
2. Check file extension is `.nix`
3. Ensure valid Nix syntax
### Nushell Warnings
1. Deprecated `get -i` warning from direnv integration is a short-term workaround in `modules/common/shell/direnv.nix` (custom Nushell hook with `get -o` and HM integration disabled) until upstream home-manager updates.
## Performance Optimizations
### Recommended Practices

70
flake.lock generated
View file

@ -27,6 +27,23 @@
"type": "github"
}
},
"brew-src": {
"flake": false,
"locked": {
"lastModified": 1763638478,
"narHash": "sha256-n/IMowE9S23ovmTkKX7KhxXC2Yq41EAVFR2FBIXPcT8=",
"owner": "Homebrew",
"repo": "brew",
"rev": "fbfdbaba008189499958a7aeb1e2c36ab10c067d",
"type": "github"
},
"original": {
"owner": "Homebrew",
"ref": "5.0.3",
"repo": "brew",
"type": "github"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
@ -125,6 +142,38 @@
"type": "github"
}
},
"homebrew-cask": {
"flake": false,
"locked": {
"lastModified": 1768764933,
"narHash": "sha256-U8UFISH6KTaxdT3MQyijMVkzxRjN3ODx6Zq+7/4wuEc=",
"owner": "homebrew",
"repo": "homebrew-cask",
"rev": "5f0ccf9a04a39e43b1a5d2d4e917bb2e8a531ae6",
"type": "github"
},
"original": {
"owner": "homebrew",
"repo": "homebrew-cask",
"type": "github"
}
},
"homebrew-core": {
"flake": false,
"locked": {
"lastModified": 1768760767,
"narHash": "sha256-g9YWsVsG65xzqLR2oB88dEvE9bc+3XUdFTVa8t/dnGg=",
"owner": "homebrew",
"repo": "homebrew-core",
"rev": "d630258aab3a6491a5c9f6e86803bfe56bbce442",
"type": "github"
},
"original": {
"owner": "homebrew",
"repo": "homebrew-core",
"type": "github"
}
},
"nix-darwin": {
"inputs": {
"nixpkgs": [
@ -146,6 +195,24 @@
"type": "github"
}
},
"nix-homebrew": {
"inputs": {
"brew-src": "brew-src"
},
"locked": {
"lastModified": 1764473698,
"narHash": "sha256-C91gPgv6udN5WuIZWNehp8qdLqlrzX6iF/YyboOj6XI=",
"owner": "zhaofengli",
"repo": "nix-homebrew",
"rev": "6a8ab60bfd66154feeaa1021fc3b32684814a62a",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"repo": "nix-homebrew",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1755186698,
@ -200,7 +267,10 @@
"fenix": "fenix",
"ghostty": "ghostty",
"home-manager": "home-manager",
"homebrew-cask": "homebrew-cask",
"homebrew-core": "homebrew-core",
"nix-darwin": "nix-darwin",
"nix-homebrew": "nix-homebrew",
"nixpkgs": "nixpkgs"
}
},

View file

@ -14,6 +14,18 @@
inputs.nixpkgs.follows = "nixpkgs";
};
nix-homebrew.url = "github:zhaofengli/nix-homebrew";
homebrew-core = {
url = "github:homebrew/homebrew-core";
flake = false;
};
homebrew-cask = {
url = "github:homebrew/homebrew-cask";
flake = false;
};
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs";
@ -31,27 +43,34 @@
};
};
outputs = inputs@{ self, nixpkgs, nix-darwin, ... }:
outputs =
inputs@{
self,
nixpkgs,
nix-darwin,
...
}:
let
# Extend nixpkgs lib with darwin and custom functions
lib = nixpkgs.lib.extend (
_: _: nix-darwin.lib // (import ./lib inputs)
);
lib = nixpkgs.lib.extend (_: _: nix-darwin.lib // (import ./lib inputs));
# Import host configurations
hostConfigs = import ./hosts { inherit lib inputs self; };
in
{
# NixOS configurations for Linux hosts
nixosConfigurations = hostConfigs.nixos or {};
nixosConfigurations = hostConfigs.nixos or { };
# Darwin configurations for macOS hosts
darwinConfigurations = hostConfigs.darwin or {};
darwinConfigurations = hostConfigs.darwin or { };
# Development shells
devShells = lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ] (system:
let pkgs = nixpkgs.legacyPackages.${system};
in {
devShells = lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ] (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
default = pkgs.mkShell {
buildInputs = with pkgs; [
nil

View file

@ -20,10 +20,6 @@ let
in
concatMap getModule (attrValues inputs);
# Shared arguments for all configurations
specialArgs = inputs // {
inherit inputs self;
};
# Collect platform-specific modules
modulesCommon = collectModules ../modules/common;
@ -54,7 +50,9 @@ in
else modulesLinux ++ inputModulesNixos;
in
systemBuilder {
inherit specialArgs;
specialArgs = inputs // {
inherit inputs self os;
};
modules = [
overlayModule

View file

@ -1,23 +1,29 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
...
}:
let
enableAmp = (!config.onLinux) || (!config.isServer);
ampHomeModule = { lib, pkgs, ... }: {
ampHomeModule =
{ lib, pkgs, ... }:
{
home.sessionPath = [ "$HOME/.amp/bin" ];
home.activation.ampInstall = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
amp_bin="$HOME/.amp/bin/amp"
if [ -x "$amp_bin" ]; then
exit 0
fi
export PATH="${lib.makeBinPath [
if [ ! -x "$amp_bin" ]; then
export PATH="${
lib.makeBinPath [
pkgs.coreutils
pkgs.gnugrep
pkgs.curl
pkgs.bash
]}:$PATH"
]
}:$PATH"
# Prevent installer from trying to mutate shell rc files (Home Manager manages those).
SHELL="amp-installer" ${pkgs.curl}/bin/curl -fsSL https://ampcode.com/install.sh | ${pkgs.bash}/bin/bash
fi
'';
};
in

21
modules/common/bat.nix Normal file
View file

@ -0,0 +1,21 @@
{ config, ... }: {
environment.variables = {
MANPAGER = "bat --plain";
PAGER = "bat --plain";
};
environment.shellAliases = {
cat = "bat";
less = "bat --plain";
};
home-manager.sharedModules = [{
programs.bat = {
enable = true;
config = {
theme = config.theme.batTheme;
pager = "less --quit-if-one-screen --RAW-CONTROL-CHARS";
};
};
}];
}

View file

@ -8,10 +8,17 @@ in {
description = "Whether the system is running on Linux";
};
isDarwin = mkOption {
type = types.bool;
default = pkgs.stdenv.isDarwin;
description = "Whether the system is running on Darwin (macOS)";
};
isServer = mkOption {
type = types.bool;
default = config.nixpkgs.hostPlatform.isAarch64;
description = "Whether the system is a server. Determined by the processor architecture.";
};
};
}

View file

@ -11,7 +11,7 @@
clearDefaultKeybinds = false;
settings = {
# theme = "tokyonight";
theme = "Gruvbox Dark Hard";
theme = config.theme.ghosttyTheme;
font-family = "Berkeley Mono";
font-size = 16;

View file

@ -1,7 +1,16 @@
{
{ inputs, lib, os, ... }:
let
isDarwin = os == "darwin";
isLinux = os == "linux";
in {
imports =
lib.optional isDarwin inputs.home-manager.darwinModules.home-manager
++ lib.optional isLinux inputs.home-manager.nixosModules.home-manager;
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
backupFileExtension = lib.mkDefault "home.bak";
};
home-manager.sharedModules = [{

View file

@ -1,9 +1,17 @@
{ pkgs, config, lib, ... }: let
{
pkgs,
config,
lib,
...
}:
let
inherit (lib) optionals optionalAttrs;
in {
in
{
environment.variables.EDITOR = "nvim";
home-manager.sharedModules = [{
home-manager.sharedModules = [
{
programs.neovim = {
enable = true;
};
@ -12,7 +20,9 @@ in {
EDITOR = "nvim";
};
home.packages = with pkgs; [
home.packages =
with pkgs;
[
# Lua
luajitPackages.luarocks_bootstrap
lua-language-server
@ -26,7 +36,8 @@ in {
nodejs
nodePackages."sass"
] ++ optionals config.onLinux [
]
++ optionals config.onLinux [
#gcc_multi
];
@ -43,7 +54,8 @@ in {
color=true
'';
};
} // optionalAttrs config.onLinux {
}
// optionalAttrs config.onLinux {
".config/i3status" = {
source = ../dotfiles/i3status;
force = true;
@ -51,12 +63,12 @@ in {
};
};
# TODO: make this normal
# programs.npm.npmrc = ''
# prefix=~/.npm-packages
# color=true
# '';
home.sessionPath = [ "node_modules/.bin" ];
}];
# TODO: the two from the last (below) should be somehow moved to their own files
home.sessionPath = [
"node_modules/.bin"
"/opt/homebrew/bin"
"$HOME/.npm-packages/bin"
];
}
];
}

View file

@ -1,73 +0,0 @@
$env.config.buffer_editor = "/etc/profiles/per-user/thegeneralist/bin/nvim"
$env.config.show_banner = false
$env.config = {
shell_integration: {
osc2: false
osc7: true
osc8: true
osc9_9: false
osc133: true
osc633: true
reset_application_mode: true
}
}
$env.config.completions = {
algorithm: prefix
case_sensitive: false
partial: true
quick: true
external: {
enable: true
max_results: 100
completer: {|tokens: list<string>|
let expanded = scope aliases | where name == $tokens.0 | get --optional expansion.0
mut expanded_tokens = if $expanded != null and $tokens.0 != "cd" {
$expanded | split row " " | append ($tokens | skip 1)
} else {
$tokens
}
$expanded_tokens.0 = ($expanded_tokens.0 | str trim --left --char "^")
fish --command $"complete '--do-complete=($expanded_tokens | str join ' ')'"
| $"value(char tab)description(char newline)" + $in
| from tsv --flexible --no-infer
}
}
}
# Basic Aliases
alias v = nvim .
alias ff = fastfetch --load-config examples/10.jsonc
alias g = glimpse --interactive -o both -f llm.md
def gg [] {
open llm.md | save -r /dev/stdout | ^xclip -sel c
}
alias c = clear
alias e = exa
alias ea = exa -a
alias ela = exa -la
alias l = ls
alias la = ls -a
alias lal = ls -la
def greeting [] {
let quotes = [
"What is impossible for you is not impossible for me."
"Why do we fall, Master Wayne? So that we can learn to pick ourselves up. - Alfred Pennyworth"
"Endure, Master Wayne. Take it. Theyll hate you for it, but thats the point of Batman. He can be the outcast. He can make the choice… that no one else can make. The right choice. - Alfred Pennyworth"
"— I never said thank you.\n— And you will never have to."
"A hero can be anyone, even a man doing something as simple and reassuring as putting a coat on a young boy's shoulders to let him know that the world hadn't ended. - Batman"
"— Come with me. Save yourself. You don't owe these ppl anymore, you've given them everything.\n— Not everything. Not yet."
"The night is always darkest before the dawn, but I promise you, the dawn is coming. - Harvey Dent"
"It's not who you are underneath, but what you do that defines you. - Batman"
"The idea was to be a symbol. Batman... could be anybody. That was the point. - Bruce Wayne"
]
echo ($quotes | get (random int 0..(($quotes | length) - 1)))
}
greeting

View file

@ -1,123 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
inherit (lib)
readFile
getExe
mkIf
optionalAttrs
;
in
{
# TODO: starship + change the zoxide src
# TODO: Rust tooling
environment =
optionalAttrs config.onLinux {
sessionVariables.SHELLS = [
(getExe pkgs.nushell)
(getExe pkgs.zsh)
];
}
// {
shells = mkIf (!config.onLinux) [
pkgs.nushell
pkgs.zsh
];
systemPackages = with pkgs; [
nushell
fish
zoxide
vivid
ripgrep
yazi
jq
yq-go
eza
fzf
gh
fastfetch
carapace
bat
bat-extras.core
];
shellAliases = {
v = "nvim .";
vi = "vim";
vim = "nvim";
ff = "fastfetch --load-config examples/10.jsonc";
g = "glimpse --interactive -o both -f llm.md";
gg = "open llm.md | save -r /dev/stdout | ^xclip -sel c";
rn = "yazi";
cat = "bat";
c = "clear";
e = "exa";
ea = "exa -a";
el = "exa -la";
l = "ls -a";
la = "ls -a";
ll = "ls -la";
cl = "c; l";
ap = "cd ~/personal";
ad = "cd ~/Downloads";
ab = "cd ~/books";
a = "cd ~";
ah = "cd ~/dotfiles/hosts/thegeneralist";
ai3 = "nvim /home/thegeneralist/dotfiles/hosts/thegeneralist/dotfiles/i3/config";
rb = "nh os switch . -v -- --show-trace --verbose";
};
};
home-manager.sharedModules = [
{
home = {
sessionPath = [ "$HOME/.amp/bin" "$HOME/.npm-packages/bin" "/opt/homebrew/bin" ];
file = {
".zshrc" =
let
configFile = ./config.nu;
envFile = ./env.nu;
in
{
text = "exec nu --env-config ${envFile} --config ${configFile}";
force = true;
};
".config/nushell/zoxide.nu".source = pkgs.runCommand "zoxide.nu" { } ''
${getExe pkgs.zoxide} init nushell --cmd cd > $out
'';
".config/nushell/ls_colors.txt".source = pkgs.runCommand "ls_colors.txt" { } ''
${getExe pkgs.vivid} generate gruvbox-dark-hard > $out
'';
};
};
}
(homeArgs: {
programs.nushell = {
enable = true;
package = pkgs.nushell;
configFile.text = readFile ./config.nu;
envFile.text = readFile ./env.nu;
environmentVariables = config.environment.variables // homeArgs.config.home.sessionVariables;
};
programs.carapace = {
enable = true;
enableZshIntegration = true;
enableNushellIntegration = true;
};
programs.zsh = {
enable = true;
sessionVariables = config.environment.variables // homeArgs.config.home.sessionVariables;
};
home.sessionPath = [ "/Users/thegeneralist/.cargo/bin" ];
})
];
}

View file

@ -1,35 +0,0 @@
$env.ENV_CONVERSIONS.PATH = {
from_string: {|string|
$string | split row (char esep) | path expand --no-symlink
}
to_string: {|value|
$value | path expand --no-symlink | str join (char esep)
}
}
$env.LS_COLORS = (open ~/.config/nushell/ls_colors.txt)
source ~/.config/nushell/zoxide.nu
# Extra PATHs
# $env.PATH = [
# # ($env.HOME | path join ".amp/bin")
# # "/home/thegeneralist/AppImages"
# # ($env.HOME | path join "personal/zen")
# # ($env.HOME | path join ".local/scripts")
# # ($env.HOME | path join ".local/bin")
# # ($env.HOME | path join ".bun/bin")
# # ($env.HOME | path join ".nix-profile/bin")
# # "/nix/var/nix/profiles/default/bin"
# # ($env.HOME | path join ".local/share/pnpm")
# # "/usr/bin"
# # "/usr/sbin"
# # "/sbin"
# # "/Applications/Ghostty.app/Contents/MacOS"
# # ($env.HOME | path join ".local/bin")
# # ($env.HOME | path join ".cargo/env")
# # ($env.HOME | path join ".cargo/bin")
# # "/usr/local/go/bin"
# # ($env.HOME | path join "go/bin")
# # ($env.HOME | path join ".npm-packages/bin")
# ] ++ $env.PATH

View file

@ -1,8 +1,8 @@
{ pkgs, lib, ...}: let
inherit (lib) attrValues;
{ pkgs, lib, ... }: let
inherit (lib) optionals;
in {
environment.systemPackages = attrValues {
inherit (pkgs)
environment.systemPackages =
(with pkgs; [
wget
zsh
neovim
@ -32,6 +32,23 @@ in {
pciutils
usbutils
;
};
nushell
fish
zoxide
vivid
ripgrep
yazi
jq
yq-go
eza
fzf
gh
fastfetch
carapace
bat
])
++ optionals (pkgs ? bat-extras && pkgs.bat-extras ? core) [
pkgs.bat-extras.core
];
}

View file

@ -0,0 +1,16 @@
{ ... }: {
environment.shellAliases = {
todo = /* sh */ ''rg "todo|fixme" --colors match:fg:yellow --colors match:style:bold'';
todos = /* sh */ "nvim ~/todo.md";
};
home-manager.sharedModules = [{
programs.ripgrep = {
enable = true;
arguments = [
"--line-number"
"--smart-case"
];
};
}];
}

View file

@ -0,0 +1,35 @@
{ config, lib, pkgs, ... }: let
inherit (lib) attrNames attrValues const filterAttrs flatten listToAttrs mapAttrs mapAttrsToList readFile replaceStrings;
package = pkgs.nushell;
in {
home-manager.sharedModules = [(homeArgs: let
config' = homeArgs.config;
environmentVariables = let
variablesMap = config'.variablesMap
|> mapAttrsToList (name: value: [
{ name = "\$${name}"; inherit value; }
{ name = "\${${name}}"; inherit value; }
])
|> flatten
|> listToAttrs;
in config.environment.variables
|> mapAttrs (const <| replaceStrings (attrNames variablesMap) (attrValues variablesMap))
|> filterAttrs (name: const <| name != "TERM");
in {
shells."0" = package;
programs.nushell = {
enable = true;
inherit package;
inherit environmentVariables;
shellAliases = config.environment.shellAliases
|> filterAttrs (_: value: value != null);
configFile.text = readFile ./0_nushell.nu;
};
})];
}

View file

@ -0,0 +1,442 @@
use std/clip
use std null_device
$env.config.history.file_format = "sqlite"
$env.config.history.isolation = false
$env.config.history.max_size = 10_000_000
$env.config.history.sync_on_enter = true
$env.config.show_banner = false
$env.config.rm.always_trash = false
$env.config.recursion_limit = 100
$env.config.edit_mode = "vi"
$env.config.cursor_shape.emacs = "line"
$env.config.cursor_shape.vi_insert = "line"
$env.config.cursor_shape.vi_normal = "block"
$env.CARAPACE_BRIDGES = "inshellisense,carapace,zsh,fish,bash"
$env.config.completions.algorithm = "substring"
$env.config.completions.sort = "smart"
$env.config.completions.case_sensitive = false
$env.config.completions.quick = true
$env.config.completions.partial = true
$env.config.completions.use_ls_colors = true
$env.config.use_kitty_protocol = true
$env.config.shell_integration.osc2 = true
$env.config.shell_integration.osc7 = true
$env.config.shell_integration.osc8 = true
$env.config.shell_integration.osc9_9 = true
$env.config.shell_integration.osc133 = true
$env.config.shell_integration.osc633 = true
$env.config.shell_integration.reset_application_mode = true
$env.config.bracketed_paste = true
$env.config.use_ansi_coloring = "auto"
$env.config.error_style = "fancy"
$env.config.highlight_resolved_externals = true
$env.config.display_errors.exit_code = false
$env.config.display_errors.termination_signal = true
$env.config.footer_mode = 25
$env.config.table.mode = "single"
$env.config.table.index_mode = "always"
$env.config.table.show_empty = true
$env.config.table.padding.left = 1
$env.config.table.padding.right = 1
$env.config.table.trim.methodology = "wrapping"
$env.config.table.trim.wrapping_try_keep_words = true
$env.config.table.trim.truncating_suffix = "..."
$env.config.table.header_on_separator = true
$env.config.table.abbreviated_row_count = null
$env.config.table.footer_inheritance = true
$env.config.table.missing_value_symbol = $"(ansi magenta_bold)nope(ansi reset)"
$env.config.datetime_format.table = null
$env.config.datetime_format.normal = $"(ansi blue_bold)%Y(ansi reset)(ansi yellow)-(ansi blue_bold)%m(ansi reset)(ansi yellow)-(ansi blue_bold)%d(ansi reset)(ansi black)T(ansi magenta_bold)%H(ansi reset)(ansi yellow):(ansi magenta_bold)%M(ansi reset)(ansi yellow):(ansi magenta_bold)%S(ansi reset)"
$env.config.filesize.unit = "metric"
$env.config.filesize.show_unit = true
$env.config.filesize.precision = 1
$env.config.render_right_prompt_on_last_line = false
$env.config.float_precision = 2
$env.config.ls.use_ls_colors = true
$env.config.hooks.pre_prompt = []
$env.config.hooks.pre_execution = [
{||
commandline
| str trim
| if ($in | is-not-empty) { print $"(ansi title)($in) — nu(char bel)" }
}
]
$env.config.hooks.env_change = {}
$env.config.hooks.display_output = {||
tee { table --expand | print }
| try { if $in != null { $env.last = $in } }
}
$env.config.hooks.command_not_found = []
# `nu-highlight` with default colors
def nu-highlight-default [] {
let input = $in
$env.config.color_config = {}
$input | nu-highlight
}
# Copy the current commandline, add syntax highlighting, wrap it in a
# markdown code block, copy that to the system clipboard.
def "nu-keybind commandline-copy" []: nothing -> nothing {
commandline
| nu-highlight-default
| [
"```ansi"
$in
"```"
]
| str join (char nl)
| clip copy --ansi
}
$env.config.keybindings ++= [
{
name: copy_color_commandline
modifier: control_alt
keycode: char_c
mode: [ emacs vi_insert vi_normal ]
event: {
send: executehostcommand
cmd: 'nu-keybind commandline-copy'
}
}
]
$env.config.color_config.bool = {||
if $in {
"light_green_bold"
} else {
"light_red_bold"
}
}
$env.config.color_config.string = {||
if $in =~ "^(#|0x)[a-fA-F0-9]+$" {
$in | str replace "0x" "#"
} else {
"white"
}
}
$env.config.color_config.row_index = "light_yellow_bold"
$env.config.color_config.header = "light_yellow_bold"
do --env {
def prompt-header [
--left-char: string
]: nothing -> string {
let code = $env.LAST_EXIT_CODE
let body = do {
mut body = []
# SSH INDICATOR `@hostname`
if ($env.SSH_CONNECTION? | is-not-empty) {
let hostname = try {
hostname
} catch {
"remote"
}
$body ++= [ $"(ansi light_green_bold)@($hostname)" ]
}
# PATH OR JJ PROJECT `~/Downloads` or `ncc -> modules`
let pwd = pwd | path expand
let jj_workspace_root = try {
jj workspace root err> $null_device
}
$body ++= [ (if $jj_workspace_root != null {
let subpath = $pwd | path relative-to $jj_workspace_root
let subpath = if ($subpath | is-not-empty) {
$" (ansi magenta_bold)→(ansi reset) (ansi blue)($subpath)"
}
$"(ansi light_yellow_bold)($jj_workspace_root | path basename)($subpath)"
} else {
let pwd = if ($pwd | str starts-with $env.HOME) {
"~" | path join ($pwd | path relative-to $env.HOME)
} else {
$pwd
}
$"(ansi cyan)($pwd)"
}) ]
$body | str join $"(ansi reset) "
}
let prefix = do {
mut prefix = []
# EXIT CODE
if $code != 0 {
$prefix ++= [ $"(ansi light_red_bold)($code)" ]
}
# COMMAND DURATION
let command_duration = ($env.CMD_DURATION_MS | into int) * 1ms
if $command_duration > 2sec {
$prefix ++= [ $"(ansi light_magenta_bold)($command_duration)" ]
}
$"(ansi light_yellow_bold)($left_char)($prefix | each { $'┫($in)(ansi light_yellow_bold)┣' } | str join '━')━(ansi reset)"
}
let suffix = do {
mut suffix = []
# NIX SHELL
if ($env.IN_NIX_SHELL? | is-not-empty) {
$suffix ++= [ $"(ansi light_blue_bold)nix" ]
}
$suffix | each { $'(ansi light_yellow_bold)•(ansi reset) ($in)(ansi reset)' } | str join " "
}
([ $prefix, $body, $suffix ] | str join " ") + (char newline)
}
$env.PROMPT_INDICATOR = $"(ansi light_yellow_bold)┃(ansi reset) "
$env.PROMPT_INDICATOR_VI_NORMAL = $env.PROMPT_INDICATOR
$env.PROMPT_INDICATOR_VI_INSERT = $env.PROMPT_INDICATOR
$env.PROMPT_MULTILINE_INDICATOR = $env.PROMPT_INDICATOR
$env.PROMPT_COMMAND = {||
prompt-header --left-char "┏"
}
$env.PROMPT_COMMAND_RIGHT = {||
let jj_status = try {
jj --quiet --color always --ignore-working-copy log --no-graph --revisions @ --template '
separate(
" ",
if(empty, label("empty", "(empty)")),
coalesce(
surround(
"\"",
"\"",
if(
description.first_line().substr(0, 24).starts_with(description.first_line()),
description.first_line().substr(0, 24),
description.first_line().substr(0, 23) ++ "…"
)
),
label(if(empty, "empty"), description_placeholder)
),
bookmarks.join(", "),
change_id.shortest(),
commit_id.shortest(),
if(conflict, label("conflict", "(conflict)")),
if(divergent, label("divergent prefix", "(divergent)")),
if(hidden, label("hidden prefix", "(hidden)")),
)
' err> $null_device
} catch {
""
}
$jj_status
}
$env.TRANSIENT_PROMPT_INDICATOR = " "
$env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = $env.TRANSIENT_PROMPT_INDICATOR
$env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = $env.TRANSIENT_PROMPT_INDICATOR
$env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = $env.TRANSIENT_PROMPT_INDICATOR
$env.TRANSIENT_PROMPT_COMMAND = {||
prompt-header --left-char "━"
}
$env.TRANSIENT_PROMPT_COMMAND_RIGHT = $env.PROMPT_COMMAND_RIGHT
}
let menus = [
{
name: completion_menu
only_buffer_difference: false
marker: $env.PROMPT_INDICATOR
type: {
layout: ide
min_completion_width: 0
max_completion_width: 150
max_completion_height: 25
padding: 0
border: false
cursor_offset: 0
description_mode: "prefer_right"
min_description_width: 0
max_description_width: 50
max_description_height: 10
description_offset: 1
correct_cursor_pos: true
}
style: {
text: white
selected_text: white_reverse
description_text: yellow
match_text: { attr: u }
selected_match_text: { attr: ur }
}
}
{
name: history_menu
only_buffer_difference: true
marker: $env.PROMPT_INDICATOR
type: {
layout: list
page_size: 10
}
style: {
text: white
selected_text: white_reverse
}
}
]
$env.config.menus = $env.config.menus
| where name not-in ($menus | get name)
| append $menus
# Retrieve the output of the last command.
def _ []: nothing -> any {
$env.last?
}
# Create a directory and cd into it.
def --env mc [path: path]: nothing -> nothing {
mkdir $path
cd $path
}
# Create a directory, cd into it and initialize version control.
def --env mcg [path: path]: nothing -> nothing {
mkdir $path
cd $path
jj git init --colocate
}
def --env "nu-complete jc" [commandline: string] {
let stor = stor open
if $stor.jc_completions? == null {
stor create --table-name jc_completions --columns { value: str, description: str, is_flag: bool }
}
if $stor.jc_completions_ran? == null {
stor create --table-name jc_completions_ran --columns { _: bool }
}
if $stor.jc_completions_ran == [] { try {
let about = ^jc --about
| from json
let magic = $about
| get parsers
| each { { value: $in.magic_commands?, description: $in.description } }
| where value != null
| flatten
let options = $about
| get parsers
| select argument description
| rename value description
let inherent = ^jc --help
| lines
| split list ""
| where { $in.0? == "Options:" } | get 0
| skip 1
| each { str trim }
| parse "{short}, {long} {description}"
| update description { str trim }
| each {|record|
[[value, description];
[$record.short, $record.description],
[$record.long, $record.description],
]
}
| flatten
for entry in $magic {
stor insert --table-name jc_completions --data-record ($entry | insert is_flag false)
}
for entry in ($options ++ $inherent) {
stor insert --table-name jc_completions --data-record ($entry | insert is_flag true)
}
stor insert --table-name jc_completions_ran --data-record { _: true }
} }
if ($commandline | str contains "-") {
$stor.jc_completions
} else {
$stor.jc_completions
| where is_flag == 0
} | select value description
}
# Run `jc` (JSON Converter).
def --wrapped jc [...arguments: string@"nu-complete jc"]: [any -> table, any -> record, any -> string] {
let run = ^jc ...$arguments | complete
if $run.exit_code != 0 {
error make {
msg: "jc exection failed"
label: {
text: ($run.stderr | str replace "jc:" "" | str replace "Error -" "" | str trim)
span: (metadata $arguments).span
}
}
}
if "--help" in $arguments or "-h" in $arguments {
$run.stdout
} else {
$run.stdout | from json
}
}
# Your custom greeting
def greeting [] {
let quotes = [
"What is impossible for you is not impossible for me."
"Why do we fall, Master Wayne? So that we can learn to pick ourselves up. - Alfred Pennyworth"
"Endure, Master Wayne. Take it. They'll hate you for it, but that's the point of Batman. He can be the outcast. He can make the choice… that no one else can make. The right choice. - Alfred Pennyworth"
"— I never said thank you.\n— And you will never have to."
"A hero can be anyone, even a man doing something as simple and reassuring as putting a coat on a young boy's shoulders to let him know that the world hadn't ended. - Batman"
"— Come with me. Save yourself. You don't owe these ppl anymore, you've given them everything.\n— Not everything. Not yet."
"The night is always darkest before the dawn, but I promise you, the dawn is coming. - Harvey Dent"
"It's not who you are underneath, but what you do that defines you. - Batman"
"The idea was to be a symbol. Batman... could be anybody. That was the point. - Bruce Wayne"
]
echo ($quotes | get (random int 0..(($quotes | length) - 1)))
}
greeting

View file

@ -0,0 +1,55 @@
{
environment.shellAliases = {
# Basic file operations (from RGBCube)
l = "ls --all";
la = "ls --all";
ll = "ls --long";
lla = "ls --long --all";
sl = "ls";
cp = "cp --recursive --verbose --progress";
mk = "mkdir";
mv = "mv --verbose";
rm = "rm --recursive --verbose";
pstree = "pstree -g 3";
tree = "eza --tree --git-ignore --group-directories-first";
# Editor aliases
v = "nvim .";
vi = "vim";
vim = "nvim";
# Utilities
ff = "fastfetch --load-config examples/10.jsonc";
g = "glimpse --interactive -o both -f llm.md";
rn = "yazi";
cat = "bat";
c = "clear";
# Eza aliases
e = "eza";
ea = "eza -a";
el = "eza -la";
ela = "eza -la";
# Git aliases
gs = "git status";
ga = "git add";
gc = "git commit";
gp = "git push";
gl = "git log";
gd = "git diff";
gco = "git checkout";
gb = "git branch";
gm = "git merge";
gr = "git remote";
gcl = "git clone";
gst = "git stash";
gpl = "git pull";
# Rebuild helper
rb = "nh darwin switch . -- --extra-experimental-features \"nix-command pipe-operators\"";
rebuild = "${../../../rebuild.nu}";
};
}

View file

@ -0,0 +1,12 @@
{ pkgs, ... }: {
environment.systemPackages = [
pkgs.carapace
pkgs.fish
pkgs.zsh
pkgs.inshellisense
];
home-manager.sharedModules = [{
programs.carapace.enable = true;
}];
}

View file

@ -0,0 +1,86 @@
{
config,
lib,
...
}:
let
inherit (lib)
attrsToList
catAttrs
const
flatten
getAttr
mapAttrsToList
mkIf
mkOption
sortOn
toInt
unique
;
mkConst =
value:
mkOption {
default = value;
readOnly = true;
};
mkValue =
default:
mkOption {
inherit default;
};
in
{
environment.shells =
config.home-manager.users
|> mapAttrsToList (const <| getAttr "shellsByPriority")
|> flatten
|> unique;
home-manager.sharedModules = [
(
homeArgs:
let
config' = homeArgs.config;
in
{
options.shells = mkValue { };
options.shellsByPriority = mkConst (
config'.shells |> attrsToList |> sortOn ({ name, ... }: toInt name) |> catAttrs "value"
);
options.variablesMap = mkConst {
HOME = config'.home.homeDirectory;
USER = config'.home.username;
XDG_CACHE_HOME = config'.xdg.cacheHome;
XDG_CONFIG_HOME = config'.xdg.configHome;
XDG_DATA_HOME = config'.xdg.dataHome;
XDG_STATE_HOME = config'.xdg.stateHome;
};
}
)
(mkIf config.isDarwin (
homeArgs:
let
config' = homeArgs.config;
in
{
home.file.".zshrc".text = # zsh
''
export PATH="/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/etc/profiles/per-user/$USER/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin''${PATH:+:}''${PATH}"
source ${config'.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh
if [ -z "$INTELLIJ_ENVIRONMENT_READER" ]; then
SHELL='${lib.getExe <| lib.head config'.shellsByPriority}' exec "$SHELL"
fi
'';
}
))
];
}

View file

@ -0,0 +1,44 @@
{ lib, ... }: {
home-manager.sharedModules = [
(homeArgs: let
direnv = lib.getExe homeArgs.config.programs.direnv.package;
in {
programs.direnv = {
enable = true;
nix-direnv.enable = true;
enableNushellIntegration = false;
};
programs.nushell.extraConfig = lib.mkAfter /* nu */ ''
$env.config = ($env.config? | default {})
$env.config.hooks = ($env.config.hooks? | default {})
$env.config.hooks.pre_prompt = (
$env.config.hooks.pre_prompt?
| default []
| append {||
${direnv} export json
| from json --strict
| default {}
| items {|key, value|
let value = do (
{
"PATH": {
from_string: {|s| $s | split row (char esep) | path expand --no-symlink }
to_string: {|v| $v | path expand --no-symlink | str join (char esep) }
}
}
| merge ($env.ENV_CONVERSIONS? | default {})
| get -o $key
| get -o from_string
| if ($in | is-empty) { {|x| $x} } else { $in }
) $value
return [ $key $value ]
}
| into record
| load-env
}
)
'';
})
];
}

View file

@ -0,0 +1,8 @@
{ lib, pkgs, ... }: let
inherit (lib) getExe readFile;
in {
environment.variables.LS_COLORS = readFile <|
pkgs.runCommand "ls_colors.txt" {} ''
${getExe pkgs.vivid} generate gruvbox-dark-hard > $out
'';
}

View file

@ -0,0 +1,47 @@
{ lib, pkgs, ... }: let
inherit (lib) getExe;
zoxide = getExe pkgs.zoxide;
in {
home-manager.sharedModules = [{
programs.zoxide = {
enable = true;
options = [ "--cmd cd" ];
enableNushellIntegration = false;
};
programs.nushell.extraConfig = /* nu */ ''
# Zoxide integration with full path
$env.config = ($env.config? | default {})
$env.config.hooks = ($env.config.hooks? | default {})
$env.config.hooks.env_change = ($env.config.hooks.env_change? | default {})
$env.config.hooks.env_change.PWD = ($env.config.hooks.env_change.PWD? | default [])
let __zoxide_hooked = ($env.config.hooks.env_change.PWD | any { try { get __zoxide_hook } catch { false } })
if not $__zoxide_hooked {
$env.config.hooks.env_change.PWD = ($env.config.hooks.env_change.PWD | append {
__zoxide_hook: true,
code: {|_, dir| ${zoxide} add -- $dir}
})
}
def --env __zoxide_z [...rest: string] {
let path = if ($rest | length) == 0 {
$env.HOME
} else if ($rest | length) == 1 and ($rest.0 == "-") {
$env.OLDPWD
} else {
${zoxide} query --exclude (pwd) -- ...$rest | str trim -r -c (char newline)
}
cd $path
}
def --env __zoxide_zi [...rest: string] {
let path = ${zoxide} query --interactive -- ...$rest | str trim -r -c (char newline)
cd $path
}
alias cd = __zoxide_z
alias cdi = __zoxide_zi
'';
}];
}

15
modules/common/theme.nix Normal file
View file

@ -0,0 +1,15 @@
{ lib, ... }: {
options.theme = {
batTheme = lib.mkOption {
type = lib.types.str;
default = "gruvbox-dark";
description = "Theme name for bat.";
};
ghosttyTheme = lib.mkOption {
type = lib.types.str;
default = "Gruvbox Dark Hard";
description = "Theme name for Ghostty.";
};
};
}

View file

@ -0,0 +1,22 @@
{
homebrew-core,
homebrew-cask,
config,
...
}:
{
homebrew = {
enable = true;
};
nix-homebrew = {
enable = true;
user = config.system.primaryUser;
taps."homebrew/homebrew-core" = homebrew-core;
taps."homebrew/homebrew-cask" = homebrew-cask;
mutableTaps = false;
};
}

View file

@ -0,0 +1,17 @@
{ config, lib, pkgs, ... }: let
inherit (lib) concatStringsSep const flatten getAttr mapAttrsToList mkForce unique;
in {
users.defaultUserShell = pkgs.zsh;
environment.sessionVariables.SHELLS = config.home-manager.users
|> mapAttrsToList (const <| getAttr "shellsByPriority")
|> flatten
|> map (drv: "${drv}${drv.shellPath}")
|> unique
|> concatStringsSep ":";
environment.shellAliases = {
ls = mkForce null;
l = mkForce null;
};
}

67
rebuild.nu Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env nu
def --wrapped sync [...arguments] {
(rsync
--archive
--compress
--delete --recursive --force
--delete-excluded
--delete-missing-args
--human-readable
--delay-updates
...$arguments)
}
# Rebuild a NixOS / Darwin config.
def main --wrapped [
host: string = "" # The host to build.
--remote # Whether if this is a remote host. The config will be built on this host if it is.
...arguments # The arguments to pass to `nh {os,darwin} switch` and `nix` (separated by --).
]: nothing -> nothing {
let host = if ($host | is-not-empty) {
if $host != (hostname) and not $remote {
print $"(ansi yellow_bold)warn:(ansi reset) building local configuration for hostname that does not match the local machine"
}
$host
} else if $remote {
print $"(ansi red_bold)error:(ansi reset) hostname not specified for remote build"
exit 1
} else {
(hostname)
}
if $remote {
ssh -tt ("root@" + $host) "
rm --recursive --force ncc
"
git ls-files
| sync --files-from - ./ $"root@($host):ncc"
ssh -tt ("root@" + $host) $"
cd ncc
./rebuild.nu ($host) ($arguments | str join ' ')
"
return
}
let args_split = $arguments | prepend "" | split list "--"
let nh_flags = [
"--hostname" $host
] | append ($args_split | get 0 | where { $in != "" })
let nix_flags = [
"--accept-flake-config"
"--extra-experimental-features" "pipe-operators"
] | append ($args_split | get --optional 1 | default [])
if (uname | get kernel-name) == "Darwin" {
nh darwin switch . ...$nh_flags -- ...$nix_flags
} else {
NH_BYPASS_ROOT_CHECK=true nh os switch . ...$nh_flags -- ...$nix_flags
}
}