Commit abcc540

HPCesia <me@hpcesia.com>
2026-10-12 07:26:51
shell: use nushell + ble.sh instead
1 parent 574db02
modules/core/shell/default.nix
@@ -0,0 +1,37 @@
+{den, ...}: {
+  den.aspects.core.includes = [den.aspects.core.shell];
+  den.aspects.core.shell = {
+    nixos = {
+      programs.bash = {
+        enable = true;
+        completion.enable = true;
+        blesh.enable = true;
+      };
+
+      programs.starship = {
+        enable = true;
+        enableBashIntegration = true;
+        settings = fromTOML (builtins.readFile ./starship.toml);
+      };
+    };
+
+    provides.to-users = {
+      hjem = {lib, ...}: {
+        files.".bashrc".text = lib.mkOrder 2000 ''
+          # Make bash history save immediately
+          shopt -s histappend
+          __ix_history_flush() {
+            history -a
+          }
+          if [[ ";''${PROMPT_COMMAND[*]:-};" != *";__ix_history_flush;"* ]]; then
+            if [[ "$(declare -p PROMPT_COMMAND 2>&1)" == "declare -a"* ]]; then
+              PROMPT_COMMAND=(__ix_history_flush "''${PROMPT_COMMAND[@]}")
+            else
+              PROMPT_COMMAND="__ix_history_flush''${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
+            fi
+          fi
+        '';
+      };
+    };
+  };
+}
modules/core/shell/nushell.nix
@@ -0,0 +1,80 @@
+{den, ...}: {
+  den.aspects.core.shell.includes = [den.aspects.core.shell.nushell];
+  den.aspects.core.shell.nushell = {
+    persistHome = {config, ...}: {
+      directories = [
+        "${config.xdg.config.directory}/nushell"
+      ];
+    };
+
+    nixos = {
+      programs.nushell = {
+        enable = true;
+      };
+    };
+
+    provides.to-users = {
+      hjem = {
+        pkgs,
+        lib,
+        ...
+      }: let
+        carapace = pkgs.carapace.overrideAttrs {
+          version = "1.8.0";
+          src = pkgs.fetchFromGitHub {
+            owner = "carapace-sh";
+            repo = "carapace-bin";
+            tag = "v1.8.0";
+            hash = "sha256-KO+fD81PyIK8gcNQfeyQgn6YMGSSvndyU4Efu5ZQZxE=";
+          };
+          vendorHash = "sha256-6Pm1lsRGiY3tfEV9T17SX5ZEssIyRWyrjgKlOlUzcZQ=";
+        };
+
+        carapace-wrapped = pkgs.symlinkJoin {
+          name = "carapace-wrapped";
+          paths = [carapace];
+          nativeBuildInputs = [pkgs.makeWrapper];
+          postBuild = ''
+            wrapProgram $out/bin/carapace \
+              --set CARAPACE_MATCH 1 \
+              --set CARAPACE_BRIDGES "bash" \
+              --suffix PATH ${lib.makeBinPath [pkgs.carapace-bridge]}
+          '';
+          inherit (carapace) meta;
+        };
+      in {
+        packages = [carapace-wrapped];
+
+        files.".bashrc".text = lib.mkOrder 1000 ''
+          # Auto launch nushell for interactive shells
+          if [[ $- == *i* ]] && grep -qv nu /proc/$PPID/comm && [[ -z "''${IX_NO_AUTO_NUSHELL:-}" ]]; then
+            SHELL=${lib.getExe pkgs.nushell} exec ${lib.getExe pkgs.nushell}
+          fi
+        '';
+
+        xdg.config.files."nushell/config.nu".text = ''
+          $env.config.table.mode = "single"
+          $env.config.show_banner = false
+          $env.config.history = {
+            file_format: sqlite
+            max_size: 1_000_000
+            sync_on_enter: true
+            isolation: true
+          }
+
+          source ${
+            pkgs.runCommand "carapace-nushell-config.nu" {} ''
+              ${lib.getExe carapace-wrapped} _carapace nushell | sed 's|"/homeless-shelter|$"($env.HOME)|g' >> "$out"
+            ''
+          }
+
+          use ${
+            pkgs.runCommand "starship-nushell-config.nu" {} ''
+              ${lib.getExe pkgs.starship} init nu >> "$out"
+            ''
+          }
+        '';
+      };
+    };
+  };
+}
modules/core/shell/starship.toml
@@ -0,0 +1,42 @@
+"$schema" = 'https://starship.rs/config-schema.json'
+
+format = """
+$username\
+$hostname\
+[: ]()\
+$directory\
+$line_break\
+$character
+"""
+
+right_format = """
+$time
+"""
+
+[username]
+show_always = true
+style_user = "green bold"
+style_root = "red bold"
+format = '[$user]($style)'
+
+[hostname]
+ssh_only = false
+style = "dimmed white bold"
+format = '[@$hostname]($style)'
+
+[directory]
+style = "blue"
+read_only_style = "red"
+read_only = "[ro]"
+format = '[$path]($style)[$read_only]($read_only_style)'
+
+[character]
+success_symbol = "[\\$](bold green)"
+error_symbol = "[\\$](bold red)"
+format = "$symbol "
+
+[time]
+format = "[ $time]($style)"
+time_format = "%R"
+utc_time_offset = "local"
+style = "dimmed white"
modules/core/shell.nix
@@ -1,83 +0,0 @@
-{den, ...}: {
-  den.aspects.core.includes = [den.aspects.core.shell];
-  den.aspects.core.shell = {
-    nixos = {pkgs, ...}: let
-    in {
-      environment.systemPackages = [pkgs.nur.repos.hpcesia.flyline];
-
-      programs.bash = {
-        enable = true;
-        completion.enable = true;
-        interactiveShellInit = ''
-          enable -f ${pkgs.nur.repos.hpcesia.flyline}/lib/libflyline.so flyline
-          flyline mouse --mode disabled
-          flyline set-cursor --backend terminal
-        '';
-        promptInit = ''
-          # Provide a nice prompt if the terminal supports it.
-          if [ "$TERM" != "dumb" ] || [ -n "$INSIDE_EMACS" ]; then
-            PROMPT_COLOR="1;31m"
-            ((UID)) && PROMPT_COLOR="1;32m"
-            # Show the hostname only when connected via SSH.
-            SSH_HOST=""
-            [ -n "$SSH_CONNECTION" ] && SSH_HOST="@$HOSTNAME"
-            if [ -n "$INSIDE_EMACS" ]; then
-              # Emacs term mode doesn't support xterm title escape sequence (\e]0;)
-              PS1="\[\033[$PROMPT_COLOR\]\u$SSH_HOST\[\033[0m\]: \[\033[1;34m\]\w\[\033[0m\]\n\[\033[$PROMPT_COLOR\]\\$\[\033[0m\] "
-            else
-              PS1="\[\033[$PROMPT_COLOR\]\u$SSH_HOST\[\033[0m\]: \[\033[1;34m\]\w\[\033[0m\]\n\[\033[$PROMPT_COLOR\]\\$\[\033[0m\] "
-              PS1="\[\e]0;\u@\h: \w\a\]$PS1"
-            fi
-            if test "$TERM" = "xterm"; then
-              PS1="\[\033]2;\h:\u:\w\007\]$PS1"
-            fi
-            # To separate previous command output
-            PROMPT_RULER="\e[90m─\e[0m"
-
-            PS1_FINAL="\[\033[$PROMPT_COLOR\]\u@\h\\$\[\033[0m\] "
-            PROMPT_RULER_FINAL="empty-line"
-          fi
-        '';
-      };
-    };
-
-    provides.to-users = {
-      hjem = {lib, ...}: {
-        files.".bashrc".text = lib.mkOrder 2000 ''
-          # Make bash history save immediately
-          shopt -s histappend
-          __ix_history_flush() {
-            history -a
-          }
-          if [[ ";''${PROMPT_COMMAND[*]:-};" != *";__ix_history_flush;"* ]]; then
-            if [[ "$(declare -p PROMPT_COMMAND 2>&1)" == "declare -a"* ]]; then
-              PROMPT_COMMAND=(__ix_history_flush "''${PROMPT_COMMAND[@]}")
-            else
-              PROMPT_COMMAND="__ix_history_flush''${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
-            fi
-          fi
-
-          # Fix Flyline panic in Zellij
-          __ix_fix_term_size() {
-            local rows cols
-            IFS=' ' read -r rows cols < <(stty size 2>/dev/null)
-            if [ "''${cols:-0}" -gt 0 ] && [ "''${rows:-0}" -gt 0 ]; then
-              export COLUMNS="$cols" LINES="$rows"
-            else
-              [ "''${COLUMNS:-0}" -gt 0 ] || COLUMNS=80
-              [ "''${LINES:-0}" -gt 0 ] || LINES=24
-              export COLUMNS LINES
-            fi
-          }
-          if [[ ";''${PROMPT_COMMAND[*]:-};" != *";__ix_fix_term_size;"* ]]; then
-            if [[ "$(declare -p PROMPT_COMMAND 2>&1)" == "declare -a"* ]]; then
-              PROMPT_COMMAND=(__ix_fix_term_size "''${PROMPT_COMMAND[@]}")
-            else
-              PROMPT_COMMAND="__ix_fix_term_size''${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
-            fi
-          fi
-        '';
-      };
-    };
-  };
-}
modules/dev/zellij/default.nix
@@ -1,7 +1,8 @@
-{
+{den, ...}: {
   den.aspects.dev.zellij = {
     provides.to-users = {
       hjem = {
+        host,
         pkgs,
         lib,
         config,
@@ -92,6 +93,12 @@
         files.".bashrc".text = lib.mkOrder 3000 ''
           alias -- zj=zellij
         '';
+
+        xdg.config.files."nushell/config.nu".text =
+          lib.mkIf
+          (host.hasAspect den.aspects.core.shell.nushell) ''
+            alias zj = zellij
+          '';
       };
     };
   };
modules/dev/direnv.nix
@@ -1,4 +1,4 @@
-{
+{den, ...}: {
   den.aspects.dev.direnv = {
     cacheHome = {config, ...}: {
       directories = [
@@ -8,6 +8,7 @@
 
     provides.to-users = {
       hjem = {
+        host,
         pkgs,
         lib,
         ...
@@ -22,6 +23,50 @@
           #Load nix-direnv
           source ${pkgs.nix-direnv}/share/nix-direnv/direnvrc
         '';
+
+        xdg.config.files."nushell/config.nu".text =
+          lib.mkIf
+          (host.hasAspect den.aspects.core.shell.nushell)
+          (lib.mkAfter ''
+            $env.config = ($env.config? | default {})
+            $env.config.hooks = ($env.config.hooks? | default {})
+            $env.config.hooks.pre_prompt = (
+              $env.config.hooks.pre_prompt?
+              | default []
+              | append {||
+                let direnv = (
+                  ${lib.getExe pkgs.direnv} export json
+                  | from json --strict
+                  | default {}
+                )
+
+                for key in ($direnv | columns) {
+                  if ($direnv | get $key) == null {
+                      hide-env --ignore-errors $key
+                  }
+                }
+
+                $direnv
+                | 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 ([[value, optional, insensitive]; [$key, true, true] [from_string, true, false]] | into cell-path)
+                    | if ($in | is-empty) { {|x| $x} } else { $in }
+                  ) $value
+                  return [ $key $value ]
+                }
+                | where {|pair| $pair.1 != null }
+                | into record
+                | load-env
+              }
+            )
+          '');
       };
     };
   };
modules/dev/yazi.nix
@@ -1,6 +1,11 @@
-{
+{den, ...}: {
   den.aspects.dev.yazi = {
-    hjem = {pkgs, ...}: let
+    hjem = {
+      host,
+      pkgs,
+      lib,
+      ...
+    }: let
       auto-layout = pkgs.yaziPlugins.mkYaziPlugin {
         pname = "auto-layout.yazi";
         version = "unstable-25-07-30";
@@ -30,6 +35,20 @@
         }
       '';
 
+      xdg.config.files."nushell/config.nu".text =
+        lib.mkIf
+        (host.hasAspect den.aspects.core.shell.nushell) ''
+          def --env yy [...args] {
+            let tmp = (mktemp -t "yazi-cwd.XXXXX")
+            ^yazi ...$args --cwd-file $tmp
+            let cwd = (open $tmp)
+            if $cwd != "" and $cwd != $env.PWD {
+              cd $cwd
+            }
+            rm -fp $tmp
+          }
+        '';
+
       xdg.config.files = {
         "yazi/plugins/auto-layout.yazi".source = auto-layout;
         "yazi/plugins/clipboard.yazi".source = pkgs.yaziPlugins.clipboard;
modules/dev/zoxide.nix
@@ -1,4 +1,4 @@
-{
+{den, ...}: {
   den.aspects.dev.zoxide = {
     cacheHome = {config, ...}: {
       directories = [
@@ -7,6 +7,7 @@
     };
 
     hjem = {
+      host,
       pkgs,
       lib,
       ...
@@ -16,6 +17,16 @@
       files.".bashrc".text = lib.mkOrder 2000 ''
         eval "$(${lib.getExe pkgs.zoxide} init bash)"
       '';
+
+      xdg.config.files."nushell/config.nu".text =
+        lib.mkIf
+        (host.hasAspect den.aspects.core.shell.nushell) ''
+          source ${
+            pkgs.runCommand "zoxide-nushell-config.nu" {} ''
+              ${lib.getExe pkgs.zoxide} init nushell >> "$out"
+            ''
+          }
+        '';
     };
   };
 }