From 9e34213cf8dd05e96a11468e0ecb7ed6e5f92284 Mon Sep 17 00:00:00 2001 From: fredrikr79 Date: Sun, 28 Sep 2025 20:02:55 +0200 Subject: [PATCH] get nushell to work --- configuration.nix | 7 +- home.nix | 36 +++++++ home/config/nushell/.gitignore | 1 + home/config/nushell/config.nu | 110 +++++++++++++++++++++ home/config/nushell/themes/dracula.nu | 131 ++++++++++++++++++++++++++ 5 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 home/config/nushell/.gitignore create mode 100644 home/config/nushell/config.nu create mode 100644 home/config/nushell/themes/dracula.nu diff --git a/configuration.nix b/configuration.nix index 90bec30..2394cef 100644 --- a/configuration.nix +++ b/configuration.nix @@ -261,7 +261,6 @@ in discord #tree ]; - shell = pkgs.nushell; }; # List packages installed in system profile. To search, run: @@ -532,4 +531,10 @@ in powerManagement.powertop.enable = true; # services.auto-cpufreq.enable = true; + + programs.bash.interactiveShellInit = '' + if ![XTERM = "dumb"]; then + exec nu + fi + ''; } diff --git a/home.nix b/home.nix index 0ab65fb..b7a9184 100644 --- a/home.nix +++ b/home.nix @@ -111,6 +111,7 @@ in ".doom.d".source = home/doom.d; ".config/jj".source = home/config/jj; ".icons/default".source = "${pkgs.vanilla-dmz}/share/icons/Vanilla-DMZ"; + ".config/nushell/themes".source = home/config/nushell/themes; }; home.sessionVariables = { @@ -1273,4 +1274,39 @@ in }; }; }; + + programs.nushell = { + enable = true; + configFile.source = ./home/config/nushell/config.nu; + shellAliases = { + hibernate = "systemctl hibernate"; + suspend = "systemctl suspend"; + logout = "sudo pkill -u fredrikr"; + lock = "/home/fredrikr/.logout.sh"; + nv = "nvim"; + e = "emacsclient -c -a 'emacs'"; + nnn = "nnn -e"; + jl = "jj log"; + jla = ''jj log -r "all()"''; + jll = "jj log --no-pager --limit 5"; + }; + }; + + programs.carapace = { + enable = true; + enableNushellIntegration = true; + }; + + programs.starship = { + enable = true; + settings = { + add_newline = false; + character = { + success_symbol = "λ(bold green)"; + error_symbol = "λ(bold red)"; + }; + }; + }; + + home.shell.enableNushellIntegration = true; } diff --git a/home/config/nushell/.gitignore b/home/config/nushell/.gitignore new file mode 100644 index 0000000..344505f --- /dev/null +++ b/home/config/nushell/.gitignore @@ -0,0 +1 @@ +nu_scripts/ diff --git a/home/config/nushell/config.nu b/home/config/nushell/config.nu new file mode 100644 index 0000000..535183c --- /dev/null +++ b/home/config/nushell/config.nu @@ -0,0 +1,110 @@ +# # config.nu +# # +# # Installed by: +# # version = "0.106.1" +# # +# # This file is used to override default Nushell settings, define +# # (or import) custom commands, or run any other startup tasks. +# # See https://www.nushell.sh/book/configuration.html +# # +# # Nushell sets "sensible defaults" for most configuration settings, +# # so your `config.nu` only needs to override these defaults if desired. +# # +# # You can open this file in your default editor using: +# # config nu +# # +# # You can also pretty-print and page through the documentation for configuration +# # options using: +# # config nu --doc | nu-highlight | less -R + + +### +### stolen from https://wiki.nixos.org/wiki/Nushell +### + +# Completions +# mainly pieced together from https://www.nushell.sh/cookbook/external_completers.html + +# carapce completions https://www.nushell.sh/cookbook/external_completers.html#carapace-completer +# + fix https://www.nushell.sh/cookbook/external_completers.html#err-unknown-shorthand-flag-using-carapace +# enable the package and integration bellow +let carapace_completer = {|spans: list| + carapace $spans.0 nushell ...$spans + | from json + | if ($in | default [] | where value == $"($spans | last)ERR" | is-empty) { $in } else { null } +} +# some completions are only available through a bridge +# eg. tailscale +# https://carapace-sh.github.io/carapace-bin/setup.html#nushell +$env.CARAPACE_BRIDGES = 'zsh,bash,inshellisense' + +# zoxide completions https://www.nushell.sh/cookbook/external_completers.html#zoxide-completer +let zoxide_completer = {|spans| + $spans | skip 1 | zoxide query -l ...$in | lines | where {|x| $x != $env.PWD} +} + +# multiple completions +# the default will be carapace, but you can also switch to fish +# https://www.nushell.sh/cookbook/external_completers.html#alias-completions +let multiple_completers = {|spans| + ## alias fixer start https://www.nushell.sh/cookbook/external_completers.html#alias-completions + let expanded_alias = scope aliases + | where name == $spans.0 + | get -o 0.expansion + + let spans = if $expanded_alias != null { + $spans + | skip 1 + | prepend ($expanded_alias | split row ' ' | take 1) + } else { + $spans + } + ## alias fixer end + + match $spans.0 { + __zoxide_z | __zoxide_zi => $zoxide_completer + _ => $carapace_completer + } | do $in $spans +} + +$env.config = { + buffer_editor: "nvim", + show_banner: false, + completions: { + case_sensitive: false # case-sensitive completions + quick: true # set to false to prevent auto-selecting completions + partial: true # set to false to prevent partial filling of the prompt + algorithm: "fuzzy" # prefix or fuzzy + external: { + # set to false to prevent nushell looking into $env.PATH to find more suggestions + enable: true + # set to lower can improve completion performance at the cost of omitting some options + max_results: 100 + completer: $multiple_completers + } + }, + hooks: { + pre_prompt: [{ || + if (which direnv | is-empty) { + return + } + + direnv export json | from json | default {} | load-env + if 'ENV_CONVERSIONS' in $env and 'PATH' in $env.ENV_CONVERSIONS { + $env.PATH = do $env.ENV_CONVERSIONS.PATH.from_string $env.PATH + } + }] + } +} +$env.PATH = ($env.PATH | + split row (char esep) | + prepend /home/myuser/.apps | + append /usr/bin/env +) + +### +### end steal +### + +source ./themes/dracula.nu + diff --git a/home/config/nushell/themes/dracula.nu b/home/config/nushell/themes/dracula.nu new file mode 100644 index 0000000..0f80870 --- /dev/null +++ b/home/config/nushell/themes/dracula.nu @@ -0,0 +1,131 @@ +# Retrieve the theme settings +export def main [] { + return { + binary: '#b45bcf' + block: '#62d6e8' + cell-path: '#e9e9f4' + closure: '#a1efe4' + custom: '#f7f7fb' + duration: '#00f769' + float: '#ea51b2' + glob: '#f7f7fb' + int: '#b45bcf' + list: '#a1efe4' + nothing: '#ea51b2' + range: '#00f769' + record: '#a1efe4' + string: '#ebff87' + + bool: {|| if $in { '#a1efe4' } else { '#00f769' } } + + datetime: {|| (date now) - $in | + if $in < 1hr { + { fg: '#ea51b2' attr: 'b' } + } else if $in < 6hr { + '#ea51b2' + } else if $in < 1day { + '#00f769' + } else if $in < 3day { + '#ebff87' + } else if $in < 1wk { + { fg: '#ebff87' attr: 'b' } + } else if $in < 6wk { + '#a1efe4' + } else if $in < 52wk { + '#62d6e8' + } else { 'dark_gray' } + } + + filesize: {|e| + if $e == 0b { + '#e9e9f4' + } else if $e < 1mb { + '#a1efe4' + } else {{ fg: '#62d6e8' }} + } + + shape_and: { fg: '#b45bcf' attr: 'b' } + shape_binary: { fg: '#b45bcf' attr: 'b' } + shape_block: { fg: '#62d6e8' attr: 'b' } + shape_bool: '#a1efe4' + shape_closure: { fg: '#a1efe4' attr: 'b' } + shape_custom: '#ebff87' + shape_datetime: { fg: '#a1efe4' attr: 'b' } + shape_directory: '#a1efe4' + shape_external: '#a1efe4' + shape_external_resolved: '#a1efe4' + shape_externalarg: { fg: '#ebff87' attr: 'b' } + shape_filepath: '#a1efe4' + shape_flag: { fg: '#62d6e8' attr: 'b' } + shape_float: { fg: '#ea51b2' attr: 'b' } + shape_garbage: { fg: '#FFFFFF' bg: '#FF0000' attr: 'b' } + shape_glob_interpolation: { fg: '#a1efe4' attr: 'b' } + shape_globpattern: { fg: '#a1efe4' attr: 'b' } + shape_int: { fg: '#b45bcf' attr: 'b' } + shape_internalcall: { fg: '#a1efe4' attr: 'b' } + shape_keyword: { fg: '#b45bcf' attr: 'b' } + shape_list: { fg: '#a1efe4' attr: 'b' } + shape_literal: '#62d6e8' + shape_match_pattern: '#ebff87' + shape_matching_brackets: { attr: 'u' } + shape_nothing: '#ea51b2' + shape_operator: '#00f769' + shape_or: { fg: '#b45bcf' attr: 'b' } + shape_pipe: { fg: '#b45bcf' attr: 'b' } + shape_range: { fg: '#00f769' attr: 'b' } + shape_raw_string: { fg: '#f7f7fb' attr: 'b' } + shape_record: { fg: '#a1efe4' attr: 'b' } + shape_redirection: { fg: '#b45bcf' attr: 'b' } + shape_signature: { fg: '#ebff87' attr: 'b' } + shape_string: '#ebff87' + shape_string_interpolation: { fg: '#a1efe4' attr: 'b' } + shape_table: { fg: '#62d6e8' attr: 'b' } + shape_vardecl: { fg: '#62d6e8' attr: 'u' } + shape_variable: '#b45bcf' + + foreground: '#e9e9f4' + cursor: '#e9e9f4' + + empty: '#62d6e8' + header: { fg: '#ebff87' attr: 'b' } + hints: '#626483' + leading_trailing_space_bg: { attr: 'n' } + row_index: { fg: '#ebff87' attr: 'b' } + search_result: { fg: '#ea51b2' bg: '#e9e9f4' } + separator: '#e9e9f4' + } +} + +# Update the Nushell configuration +export def --env "set color_config" [] { + $env.config.color_config = (main) +} + +# Update terminal colors +export def "update terminal" [] { + let theme = (main) + + # Set terminal colors + let osc_screen_foreground_color = '10;' + let osc_cursor_color = '12;' + + $" + (ansi -o $osc_screen_foreground_color)($theme.foreground)(char bel) + (ansi -o $osc_cursor_color)($theme.cursor)(char bel) + " + # Line breaks above are just for source readability + # but create extra whitespace when activating. Collapse + # to one line and print with no-newline + | str replace --all "\n" '' + | print -n $"($in)\r" +} + +export module activate { + export-env { + set color_config + update terminal + } +} + +# Activate the theme when sourced +use activate