{ lib, pkgs, inputs, # getFlakePkg', config, mainUser, ... }: let inherit (pkgs) nushell; cfg = config.programs.inshellah; nushellWrapped = pkgs.symlinkJoin { name = "nushell"; paths = [ nushell ]; nativeBuildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/nu \ --add-flags "--config ${nuConfig}" ''; passthru = nushell.passthru or { } // { shellPath = "/bin/nu"; }; }; theme = let pal = config.rice.palette.hex; ui = config.rice.roles pal; in '' let theme = { separator: "${pal.bright.yellow}" leading_trailing_space_bg: "${ui.highlight}" header: "${pal.normal.yellow}" empty: "${ui.muted}" bool: "${pal.bright.magenta}" int: "${pal.bright.magenta}" filesize: "${pal.bright.magenta}" duration: "${pal.bright.magenta}" date: "${pal.bright.cyan}" range: "${pal.bright.magenta}" float: "${pal.bright.magenta}" string: "${pal.normal.green}" nothing: "${ui.muted}" binary: "${pal.bright.magenta}" cell-path: "${pal.bright.blue}" row_index: "${pal.bright.blue}" record: "${pal.bright.cyan}" list: "${pal.bright.cyan}" block: "${pal.bright.cyan}" hints: "${ui.hint}" search_result: "${ui.highlight}" shape_and: "${pal.normal.red}" shape_binary: "${pal.bright.magenta}" shape_block: "${pal.bright.cyan}" shape_bool: "${pal.bright.magenta}" shape_custom: "${ui.accent}" shape_datetime: "${pal.bright.cyan}" shape_external: "${pal.normal.green}" shape_externalarg: "${pal.normal.green}" shape_filepath: "${pal.normal.green}" shape_flag: "${ui.accent}" shape_float: "${pal.bright.magenta}" shape_globpattern: "${pal.normal.green}" shape_int: "${pal.bright.magenta}" shape_internalcall: "${pal.normal.green}" shape_list: "${pal.bright.cyan}" shape_literal: "${pal.bright.magenta}" shape_operator: "${pal.bright.magenta}" shape_option: "${ui.accent}" shape_range: "${pal.bright.magenta}" shape_record: "${pal.bright.cyan}" shape_string: "${pal.normal.green}" shape_variable: "${pal.bright.blue}" }; $env.config = ($env.config | upsert color_config $theme) ''; prompt = '' do --env { def prompt-header [ --left-char: string ]: nothing -> string { let code = $env.LAST_EXIT_CODE let jj_workspace_root = try { jj workspace root err>| ignore } catch { "" } let hostname = if ($env.SSH_CONNECTION? | is-not-empty) { let hostname = try { hostname } catch { "remote" } $"(ansi light_green_bold)@($hostname)(ansi reset) " } else { "" } # https://github.com/nushell/nushell/issues/16205 # # Case insensitive filesystems strike again! let pwd = pwd | path expand let body = if ($jj_workspace_root | is-not-empty) { let subpath = $pwd | path relative-to $jj_workspace_root let subpath = if ($subpath | is-not-empty) { $"(ansi magenta_bold) → (ansi reset)(ansi blue)($subpath)" } $"($hostname)(ansi light_yellow_bold)($jj_workspace_root | path basename)($subpath)(ansi reset)" } else { let pwd = if ($pwd | str starts-with $env.HOME) { "~" | path join ($pwd | path relative-to $env.HOME) } else { $pwd } $"($hostname)(ansi cyan)($pwd)(ansi reset)" } let command_duration = ($env.CMD_DURATION_MS | into int) * 1ms let command_duration = if $command_duration <= 2sec { "" } else { $"┫(ansi light_magenta_bold)($command_duration)(ansi light_yellow_bold)┣━" } let exit_code = if $code == 0 { "" } else { $"┫(ansi light_red_bold)($code)(ansi light_yellow_bold)┣━" } let middle = if $command_duration == "" and $exit_code == "" { "━" } else { "" } $"(ansi light_yellow_bold)($left_char)($exit_code)($middle)($command_duration)(ansi reset) ($body)(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>| ignore } catch { "" } $jj_status } } ''; aliases = { "l" = "ls"; "la" = "ls -a"; "gco" = "git checkout"; "gcb" = "git checkout -b"; "gp" = "git push"; "gpf" = "git push --force"; "gl" = "git pull"; "ga" = "git add"; "gcam" = "git commit -am"; "gcl" = "git clone"; "gcd" = "git clone --depth 1"; "lg" = "lazygit"; ":q" = "exit"; "fg" = "job unfreeze"; "jobs" = "job list"; }; nuScriptsPath = "${pkgs.nu_scripts}/share/nu_scripts"; nuConfig = pkgs.writeText "config.nu" '' use std/config * ${lib.mapAttrsToList (n: v: "alias ${n} = ${v}") aliases |> lib.concatStringsSep "\n"} $env.NU_LIB_DIRS = ( $env.NU_LIB_DIRS | append "${nuScriptsPath}") use ${nuScriptsPath}/modules/capture-foreign-env source ${nuScriptsPath}/modules/formats/from-env.nu let nixos_env = ('source /etc/set-environment' | capture-foreign-env --shell bash) if ($nixos_env | describe | str starts-with "record") { $nixos_env | load-env } source ${(pkgs.runCommand "zoxide.nu" { } ''${pkgs.zoxide}/bin/zoxide init nushell >> "$out"'')} $env.config.buffer_editor = "${lib.getExe config.apps.editor}" # aliases # def fresh [] { clear ${./rice/header.sh} echo } def gap [] { git commit -a --amend --no-edit git push --force } # direnv $env.config = ($env.config? | default {}) $env.config.hooks = ($env.config.hooks? | default {}) $env.config.hooks.pre_prompt = ( $env.config.hooks.pre_prompt? | default [] | append {|| ${pkgs.direnv}/bin/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 ([[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 ] } | into record | load-env } ) # $cmd doesn't carry its args ? # $env.config.hooks.command_not_found = { |cmd| , $cmd; echo } $env.config.table.mode = "none"; $env.config.edit_mode = "vi"; $env.config.completions.algorithm = "fuzzy"; ${prompt} ${cfg.snippet} ${theme} $env.config.show_banner = false fresh ''; in { imports = [ inputs.inshellah.nixosModules.default ]; programs.inshellah = { enable = true; helpOnlyCommands = [ "nh" ]; }; programs.command-not-found.enable = false; programs.zoxide.enable = true; environment.shellAliases = { }; environment.systemPackages = [ nushellWrapped ]; environment.shells = [ nushellWrapped ]; users.defaultUserShell = nushellWrapped; console.font = "Lat2-Terminus16"; environment.variables = { EDITOR = "hx"; }; }