From 3f348914131ffdbcae21cd4a4f7e3db7e2255116 Mon Sep 17 00:00:00 2001 From: TheGeneralist <180094941+thegeneralist01@users.noreply.github.com> Date: Sun, 18 Jan 2026 22:12:00 +0100 Subject: [PATCH] config: command-line revamp --- .zshrc | 1 + AGENTS.md | 11 + flake.lock | 70 +++++ flake.nix | 53 ++-- lib/system.nix | 8 +- modules/common/amp.nix | 44 +-- modules/common/bat.nix | 21 ++ modules/common/custom-options.nix | 7 + modules/common/ghostty.nix | 2 +- modules/common/home-manager.nix | 11 +- modules/common/neovim.nix | 122 ++++---- modules/common/nushell/config.nu | 73 ----- modules/common/nushell/default.nix | 123 -------- modules/common/nushell/env.nu | 35 --- modules/common/packages.nix | 29 +- modules/common/ripgrep.nix | 16 ++ modules/common/shell/0_nushell.nix | 35 +++ modules/common/shell/0_nushell.nu | 442 +++++++++++++++++++++++++++++ modules/common/shell/aliases.nix | 55 ++++ modules/common/shell/carapace.nix | 12 + modules/common/shell/default.nix | 86 ++++++ modules/common/shell/direnv.nix | 44 +++ modules/common/shell/vivid.nix | 8 + modules/common/shell/zoxide.nix | 47 +++ modules/common/theme.nix | 15 + modules/darwin/homebrew.nix | 22 ++ modules/linux/shell/default.nix | 17 ++ rebuild.nu | 67 +++++ 28 files changed, 1141 insertions(+), 335 deletions(-) create mode 120000 .zshrc create mode 100644 modules/common/bat.nix delete mode 100644 modules/common/nushell/config.nu delete mode 100644 modules/common/nushell/default.nix delete mode 100644 modules/common/nushell/env.nu create mode 100644 modules/common/ripgrep.nix create mode 100644 modules/common/shell/0_nushell.nix create mode 100644 modules/common/shell/0_nushell.nu create mode 100644 modules/common/shell/aliases.nix create mode 100644 modules/common/shell/carapace.nix create mode 100644 modules/common/shell/default.nix create mode 100644 modules/common/shell/direnv.nix create mode 100644 modules/common/shell/vivid.nix create mode 100644 modules/common/shell/zoxide.nix create mode 100644 modules/common/theme.nix create mode 100644 modules/darwin/homebrew.nix create mode 100644 modules/linux/shell/default.nix create mode 100755 rebuild.nu diff --git a/.zshrc b/.zshrc new file mode 120000 index 0000000..ad9849f --- /dev/null +++ b/.zshrc @@ -0,0 +1 @@ +/nix/store/mlnm2lb8zaplnmaqb9k0pfprdwqbdn8b-home-manager-files/.zshrc \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 274fa04..deafdf2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -96,6 +96,10 @@ lib: inputs: self: lib.mkSystem "" ./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//configuration.nix` + ### Adding a New Host 1. Create `hosts//` directory 2. Add `default.nix` with system type @@ -129,6 +133,10 @@ lib: inputs: self: lib.mkSystem "" ./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 "" ./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 diff --git a/flake.lock b/flake.lock index a10d509..c07cced 100644 --- a/flake.lock +++ b/flake.lock @@ -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" } }, diff --git a/flake.nix b/flake.nix index 6281518..efe19b0 100644 --- a/flake.nix +++ b/flake.nix @@ -3,55 +3,74 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - + home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; - + nix-darwin = { url = "github:nix-darwin/nix-darwin/master"; 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"; inputs.home-manager.follows = "home-manager"; inputs.darwin.follows = "nix-darwin"; }; - + ghostty = { url = "github:ghostty-org/ghostty"; }; - + fenix = { url = "github:nix-community/fenix"; inputs.nixpkgs.follows = "nixpkgs"; }; }; - 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 {}; - - # Darwin configurations for macOS hosts - darwinConfigurations = hostConfigs.darwin or {}; - + nixosConfigurations = hostConfigs.nixos or { }; + + # Darwin configurations for macOS hosts + 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 diff --git a/lib/system.nix b/lib/system.nix index 08c80c8..555994e 100644 --- a/lib/system.nix +++ b/lib/system.nix @@ -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 diff --git a/modules/common/amp.nix b/modules/common/amp.nix index 379ed7e..c788a25 100644 --- a/modules/common/amp.nix +++ b/modules/common/amp.nix @@ -1,25 +1,31 @@ -{ config, lib, pkgs, ... }: +{ + config, + lib, + ... +}: let enableAmp = (!config.onLinux) || (!config.isServer); - 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 + 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 + export PATH="${ + lib.makeBinPath [ + pkgs.coreutils + pkgs.gnugrep + pkgs.curl + pkgs.bash + ] + }:$PATH" - export PATH="${lib.makeBinPath [ - pkgs.coreutils - pkgs.gnugrep - pkgs.curl - pkgs.bash - ]}:$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 - ''; - }; + # 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 lib.mkIf enableAmp { home-manager.sharedModules = [ ampHomeModule ]; diff --git a/modules/common/bat.nix b/modules/common/bat.nix new file mode 100644 index 0000000..dd58dac --- /dev/null +++ b/modules/common/bat.nix @@ -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"; + }; + }; + }]; +} diff --git a/modules/common/custom-options.nix b/modules/common/custom-options.nix index ba8252c..9535eda 100644 --- a/modules/common/custom-options.nix +++ b/modules/common/custom-options.nix @@ -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."; }; + }; } diff --git a/modules/common/ghostty.nix b/modules/common/ghostty.nix index dc2276d..69d59f6 100644 --- a/modules/common/ghostty.nix +++ b/modules/common/ghostty.nix @@ -11,7 +11,7 @@ clearDefaultKeybinds = false; settings = { # theme = "tokyonight"; - theme = "Gruvbox Dark Hard"; + theme = config.theme.ghosttyTheme; font-family = "Berkeley Mono"; font-size = 16; diff --git a/modules/common/home-manager.nix b/modules/common/home-manager.nix index 76b3871..3c068ef 100644 --- a/modules/common/home-manager.nix +++ b/modules/common/home-manager.nix @@ -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 = [{ diff --git a/modules/common/neovim.nix b/modules/common/neovim.nix index 020eac5..977009f 100644 --- a/modules/common/neovim.nix +++ b/modules/common/neovim.nix @@ -1,62 +1,74 @@ -{ pkgs, config, lib, ... }: let +{ + pkgs, + config, + lib, + ... +}: +let inherit (lib) optionals optionalAttrs; -in { +in +{ environment.variables.EDITOR = "nvim"; - home-manager.sharedModules = [{ - programs.neovim = { - enable = true; - }; - - home.sessionVariables = { - EDITOR = "nvim"; - }; - - home.packages = with pkgs; [ - # Lua - luajitPackages.luarocks_bootstrap - lua-language-server - - python313 - python313Packages.pip - uv - python313Packages.virtualenv - basedpyright - black - - nodejs - nodePackages."sass" - ] ++ optionals config.onLinux [ - #gcc_multi - ]; - - home.file = { - ".config/nvim" = { - source = ../dotfiles/nvim; - force = true; - recursive = true; + home-manager.sharedModules = [ + { + programs.neovim = { + enable = true; }; - ".npmrc" = { - force = true; - text = '' - prefix=~/.npm-packages - color=true - ''; - }; - } // optionalAttrs config.onLinux { - ".config/i3status" = { - source = ../dotfiles/i3status; - force = true; - recursive = true; - }; - }; - # TODO: make this normal - # programs.npm.npmrc = '' - # prefix=~/.npm-packages - # color=true - # ''; + home.sessionVariables = { + EDITOR = "nvim"; + }; - home.sessionPath = [ "node_modules/.bin" ]; - }]; + home.packages = + with pkgs; + [ + # Lua + luajitPackages.luarocks_bootstrap + lua-language-server + + python313 + python313Packages.pip + uv + python313Packages.virtualenv + basedpyright + black + + nodejs + nodePackages."sass" + ] + ++ optionals config.onLinux [ + #gcc_multi + ]; + + home.file = { + ".config/nvim" = { + source = ../dotfiles/nvim; + force = true; + recursive = true; + }; + ".npmrc" = { + force = true; + text = '' + prefix=~/.npm-packages + color=true + ''; + }; + } + // optionalAttrs config.onLinux { + ".config/i3status" = { + source = ../dotfiles/i3status; + force = true; + recursive = true; + }; + }; + + # 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" + ]; + } + ]; } diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu deleted file mode 100644 index fbdd986..0000000 --- a/modules/common/nushell/config.nu +++ /dev/null @@ -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| - 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. 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 diff --git a/modules/common/nushell/default.nix b/modules/common/nushell/default.nix deleted file mode 100644 index 65a9f0b..0000000 --- a/modules/common/nushell/default.nix +++ /dev/null @@ -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" ]; - }) - ]; -} diff --git a/modules/common/nushell/env.nu b/modules/common/nushell/env.nu deleted file mode 100644 index 841d25f..0000000 --- a/modules/common/nushell/env.nu +++ /dev/null @@ -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 diff --git a/modules/common/packages.nix b/modules/common/packages.nix index 9f9ba54..5abdf00 100644 --- a/modules/common/packages.nix +++ b/modules/common/packages.nix @@ -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 + ]; } diff --git a/modules/common/ripgrep.nix b/modules/common/ripgrep.nix new file mode 100644 index 0000000..15137c7 --- /dev/null +++ b/modules/common/ripgrep.nix @@ -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" + ]; + }; + }]; +} diff --git a/modules/common/shell/0_nushell.nix b/modules/common/shell/0_nushell.nix new file mode 100644 index 0000000..ffa8f6f --- /dev/null +++ b/modules/common/shell/0_nushell.nix @@ -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; + }; + })]; +} diff --git a/modules/common/shell/0_nushell.nu b/modules/common/shell/0_nushell.nu new file mode 100644 index 0000000..a0c4951 --- /dev/null +++ b/modules/common/shell/0_nushell.nu @@ -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 diff --git a/modules/common/shell/aliases.nix b/modules/common/shell/aliases.nix new file mode 100644 index 0000000..30f039b --- /dev/null +++ b/modules/common/shell/aliases.nix @@ -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}"; + }; +} diff --git a/modules/common/shell/carapace.nix b/modules/common/shell/carapace.nix new file mode 100644 index 0000000..6167138 --- /dev/null +++ b/modules/common/shell/carapace.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: { + environment.systemPackages = [ + pkgs.carapace + pkgs.fish + pkgs.zsh + pkgs.inshellisense + ]; + + home-manager.sharedModules = [{ + programs.carapace.enable = true; + }]; +} diff --git a/modules/common/shell/default.nix b/modules/common/shell/default.nix new file mode 100644 index 0000000..d5e4634 --- /dev/null +++ b/modules/common/shell/default.nix @@ -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 + ''; + } + )) + + ]; +} diff --git a/modules/common/shell/direnv.nix b/modules/common/shell/direnv.nix new file mode 100644 index 0000000..7df82ca --- /dev/null +++ b/modules/common/shell/direnv.nix @@ -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 + } + ) + ''; + }) + ]; +} diff --git a/modules/common/shell/vivid.nix b/modules/common/shell/vivid.nix new file mode 100644 index 0000000..18f3ebc --- /dev/null +++ b/modules/common/shell/vivid.nix @@ -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 + ''; +} diff --git a/modules/common/shell/zoxide.nix b/modules/common/shell/zoxide.nix new file mode 100644 index 0000000..0d570aa --- /dev/null +++ b/modules/common/shell/zoxide.nix @@ -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 + ''; + }]; +} diff --git a/modules/common/theme.nix b/modules/common/theme.nix new file mode 100644 index 0000000..558686f --- /dev/null +++ b/modules/common/theme.nix @@ -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."; + }; + }; +} diff --git a/modules/darwin/homebrew.nix b/modules/darwin/homebrew.nix new file mode 100644 index 0000000..6961e3f --- /dev/null +++ b/modules/darwin/homebrew.nix @@ -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; + }; +} diff --git a/modules/linux/shell/default.nix b/modules/linux/shell/default.nix new file mode 100644 index 0000000..b06e7f2 --- /dev/null +++ b/modules/linux/shell/default.nix @@ -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; + }; +} diff --git a/rebuild.nu b/rebuild.nu new file mode 100755 index 0000000..d9cb5bc --- /dev/null +++ b/rebuild.nu @@ -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 + } +}