diff --git a/nushell/atuin.nu b/nushell/atuin.nu index 7e4ba55..bdd748d 100644 --- a/nushell/atuin.nu +++ b/nushell/atuin.nu @@ -1,4 +1,3 @@ -# ============================================================================= $env.ATUIN_SESSION = (atuin uuid) hide-env -i ATUIN_HISTORY_ID @@ -6,100 +5,99 @@ hide-env -i ATUIN_HISTORY_ID let ATUIN_KEYBINDING_TOKEN = $"# (random uuid)" let _atuin_pre_execution = {|| - if ($nu | get -i history-enabled) == false { - return - } - let cmd = (commandline) - if ($cmd | is-empty) { - return - } - if not ($cmd | str starts-with $ATUIN_KEYBINDING_TOKEN) { - $env.ATUIN_HISTORY_ID = (atuin history start -- $cmd) - } + if ($nu | get -i history-enabled) == false { + return + } + let cmd = (commandline) + if ($cmd | is-empty) { + return + } + if not ($cmd | str starts-with $ATUIN_KEYBINDING_TOKEN) { + $env.ATUIN_HISTORY_ID = (atuin history start -- $cmd) + } } -# ============================================================================= let _atuin_pre_prompt = {|| - let last_exit = $env.LAST_EXIT_CODE - if 'ATUIN_HISTORY_ID' not-in $env { - return - } - with-env { ATUIN_LOG: error } { - do { atuin history end $'--exit=($last_exit)' -- $env.ATUIN_HISTORY_ID } | complete - - } - hide-env ATUIN_HISTORY_ID + let last_exit = $env.LAST_EXIT_CODE + if 'ATUIN_HISTORY_ID' not-in $env { + return + } + with-env {ATUIN_LOG: error} { + do { atuin history end $'--exit=($last_exit)' -- $env.ATUIN_HISTORY_ID } | complete + } + hide-env ATUIN_HISTORY_ID } -# ============================================================================= def _atuin_search_cmd [...flags: string] { - let nu_version = do { - let version = version - let major = $version.major? - if $major != null { - # These members are only available in versions > 0.92.2 - [$major $version.minor $version.patch] - } else { - # So fall back to the slower parsing when they're missing - $version.version | split row '.' | into int - } + let nu_version = do { + let version = version + let major = $version.major? + if $major != null { + # These members are only available in versions > 0.92.2 + [$major $version.minor $version.patch] + } else { + # So fall back to the slower parsing when they're missing + $version.version | split row '.' | into int } - [ - $ATUIN_KEYBINDING_TOKEN, - ([ - `with-env { ATUIN_LOG: error, ATUIN_QUERY: (commandline) } {`, - (if $nu_version.0 <= 0 and $nu_version.1 <= 90 { 'commandline' } else { 'commandline edit' }), - (if $nu_version.1 >= 92 { '(run-external atuin search' } else { '(run-external --redirect-stderr atuin search' }), - ($flags | append [--interactive] | each {|e| $'"($e)"'}), - (if $nu_version.1 >= 92 { ' e>| str trim)' } else {' | complete | $in.stderr | str substring ..-1)'}), - `}`, - ] | flatten | str join ' '), - ] | str join "\n" + } + [ + $ATUIN_KEYBINDING_TOKEN + ( + [ + `with-env { ATUIN_LOG: error, ATUIN_QUERY: (commandline) } {` + (if $nu_version.0 <= 0 and $nu_version.1 <= 90 { 'commandline' } else { 'commandline edit' }) + (if $nu_version.1 >= 92 { '(run-external atuin search' } else { '(run-external --redirect-stderr atuin search' }) + ($flags | append [--interactive] | each {|e| $'"($e)"' }) + (if $nu_version.1 >= 92 { ' e>| str trim)' } else { ' | complete | $in.stderr | str substring ..-1)' }) + `}` + ] | flatten | str join ' ' + ) + ] | str join "\n" } -# ============================================================================= $env.config = ($env | default {} config).config $env.config = ($env.config | default {} hooks) $env.config = ( - $env.config | upsert hooks ( - $env.config.hooks - | upsert pre_execution ( - $env.config.hooks | get -i pre_execution | default [] | append $_atuin_pre_execution) - | upsert pre_prompt ( - $env.config.hooks | get -i pre_prompt | default [] | append $_atuin_pre_prompt) + $env.config | upsert hooks ( + $env.config.hooks + | upsert pre_execution ( + $env.config.hooks | get -i pre_execution | default [] | append $_atuin_pre_execution ) + | upsert pre_prompt ( + $env.config.hooks | get -i pre_prompt | default [] | append $_atuin_pre_prompt + ) + ) ) $env.config = ($env.config | default [] keybindings) $env.config = ( - $env.config | upsert keybindings ( - $env.config.keybindings - | append { - name: atuin - modifier: control - keycode: char_r - mode: [emacs, vi_normal, vi_insert] - event: { send: executehostcommand cmd: (_atuin_search_cmd) } - } - ) + $env.config | upsert keybindings ( + $env.config.keybindings + | append { + name: atuin + modifier: control + keycode: char_r + mode: [emacs vi_normal vi_insert] + event: {send: executehostcommand cmd: (_atuin_search_cmd)} + } + ) ) $env.config = ( - $env.config | upsert keybindings ( - $env.config.keybindings - | append { - name: atuin - modifier: none - keycode: up - mode: [emacs, vi_normal, vi_insert] - event: { - until: [ - {send: menuup} - {send: executehostcommand cmd: (_atuin_search_cmd '--shell-up-key-binding') } - ] - } - } - ) + $env.config | upsert keybindings ( + $env.config.keybindings + | append { + name: atuin + modifier: none + keycode: up + mode: [emacs vi_normal vi_insert] + event: { + until: [ + {send: menuup} + {send: executehostcommand cmd: (_atuin_search_cmd '--shell-up-key-binding')} + ] + } + } + ) ) -# ============================================================================= diff --git a/nushell/completions.nu b/nushell/completions.nu index e564b13..6d0f758 100644 --- a/nushell/completions.nu +++ b/nushell/completions.nu @@ -1,46 +1,30 @@ -$env.config.completions = { - algorithm: prefix - sort: smart - case_sensitive: false - quick: true - partial: true - use_ls_colors: true - external: { - enable: true - max_results: 10 - completer: {|spans: list| - # if the current command is an alias, get it's expansion - let expanded_alias = (scope aliases | where name == $spans.0 | get -i 0 | get -i expansion) +$env.PATH = ($env.PATH | split row (char esep) | prepend "/home/cr/.config/carapace/bin") - # overwrite - let spans = (if $expanded_alias != null { - # put the first word of the expanded alias first in the span - $spans | skip 1 | prepend ($expanded_alias | split row " " | take 1) - } else { - $spans | skip 1 | prepend ($spans.0) - }) +def --env get-env [name] { $env | get $name } +def --env set-env [name, value] { load-env { $name: $value } } +def --env unset-env [name] { hide-env $name } - carapace $spans.0 nushell ...$spans - | from json - } - } - +let carapace_completer = {|spans| + # if the current command is an alias, get it's expansion + let expanded_alias = (scope aliases | where name == $spans.0 | get -i 0 | get -i expansion) + + # overwrite + let spans = (if $expanded_alias != null { + # put the first word of the expanded alias first in the span + $spans | skip 1 | prepend ($expanded_alias | split row " " | take 1) + } else { + $spans | skip 1 | prepend ($spans.0) + }) + + carapace $spans.0 nushell ...$spans + | from json } -$env.config.menus ++= [ - { - marker: $"(ansi yellow)┣ " - name: completion_menu - only_buffer_difference: false - style: { - description_text: yellow - selected_text: red_reverse - text: yellow - } - type: { - col_padding: 2 - col_width: 20 - columns: 1 - layout: columnar - } - } -] + +mut current = (($env | default {} config).config | default {} completions) +$current.completions = ($current.completions | default {} external) +$current.completions.external = ($current.completions.external +| default true enable +| default { $carapace_completer } completer) + +$env.config = $current + diff --git a/nushell/config.nu b/nushell/config.nu index 8bf1135..6c846f6 100644 --- a/nushell/config.nu +++ b/nushell/config.nu @@ -1,23 +1,23 @@ $env.config = { - bracketed_paste: true - buffer_editor: "hx" - datetime_format: {} - edit_mode: vi - error_style: fancy - float_precision: 2 - footer_mode: 25 + bracketed_paste: true + buffer_editor: "hx" + datetime_format: {} + edit_mode: vi + error_style: fancy + float_precision: 2 + footer_mode: 25 render_right_prompt_on_last_line: false - show_banner: false - use_ansi_coloring: true - use_kitty_protocol: true + show_banner: false + use_ansi_coloring: true + use_kitty_protocol: true shell_integration: { - osc2: false - osc7: true - osc8: true - osc9_9: false - osc133: true - osc633: true + osc2: false + osc7: true + osc8: true + osc9_9: false + osc133: true + osc633: true reset_application_mode: true } } @@ -32,37 +32,37 @@ $env.config.rm.always_trash = true $env.config.table = { header_on_separator: false index_mode: always - mode: light - padding: { left: 1 right: 1 } + mode: light + padding: {left: 1 right: 1} show_empty: true trim: { - methodology: wrapping + methodology: wrapping wrapping_try_keep_words: true - truncating_suffix: "..." + truncating_suffix: "..." } } $env.config.explore = { - command_bar_text: { fg: "#C4C9C6" } - highlight: { fg: black bg: yellow } + command_bar_text: {fg: "#C4C9C6"} + highlight: {fg: black bg: yellow} status: { - error: { fg: white bg: red } - warn: {} - info: {} + error: {fg: white bg: red} + warn: {} + info: {} } - status_bar_background: { fg: "#1D1F21" bg: "#C4C9C6" } + status_bar_background: {fg: "#1D1F21" bg: "#C4C9C6"} table: { - split_line: { fg: "#404040" } - selected_cell: { bg: light_blue } - selected_row: {} + split_line: {fg: "#404040"} + selected_cell: {bg: light_blue} + selected_row: {} selected_column: {} } } $env.config.history = { - file_format: sqlite - isolation: false - max_size: 100_000 + file_format: sqlite + isolation: false + max_size: 100_000 sync_on_enter: true } @@ -72,7 +72,7 @@ $env.config.cursor_shape = { } $env.config.hooks = { - command_not_found: {||} + command_not_found: {|| } pre_execution: [ { @@ -86,39 +86,38 @@ $env.config.hooks = { } ] - pre_prompt: [ { - if (which direnv | is-empty) { + if (which direnv | is-empty) { return - } + } - direnv export json | from json | default {} | load-env - # Direnv outputs $PATH as a string, but nushell silently breaks if isn't a list-like table. - # The following behemoth of Nu code turns this into nu's format while following the standards of how to handle quotes, use it if you need quote handling instead of the line below it: - # $env.PATH = $env.PATH | parse --regex ('' + `((?:(?:"(?:(?:\\[\\"])|.)*?")|(?:'.*?')|[^` + (char env_sep) + `]*)*)`) | each {|x| $x.capture0 | parse --regex `(?:"((?:(?:\\"|.))*?)")|(?:'(.*?)')|([^'"]*)` | each {|y| if ($y.capture0 != "") { $y.capture0 | str replace -ar `\\([\\"])` `$1` } else if ($y.capture1 != "") { $y.capture1 } else $y.capture2 } | str join } - $env.PATH = $env.PATH | split row (char env_sep) + direnv export json | from json | default {} | load-env + # Direnv outputs $PATH as a string, but nushell silently breaks if isn't a list-like table. + # The following behemoth of Nu code turns this into nu's format while following the standards of how to handle quotes, use it if you need quote handling instead of the line below it: + # $env.PATH = $env.PATH | parse --regex ('' + `((?:(?:"(?:(?:\\[\\"])|.)*?")|(?:'.*?')|[^` + (char env_sep) + `]*)*)`) | each {|x| $x.capture0 | parse --regex `(?:"((?:(?:\\"|.))*?)")|(?:'(.*?)')|([^'"]*)` | each {|y| if ($y.capture0 != "") { $y.capture0 | str replace -ar `\\([\\"])` `$1` } else if ($y.capture1 != "") { $y.capture1 } else $y.capture2 } | str join } + $env.PATH = $env.PATH | split row (char env_sep) } ] } $env.config.menus = [ { - marker: $"(ansi yellow)╋ " - name: help_menu + marker: $"(ansi yellow)╋ " + name: help_menu only_buffer_difference: true style: { description_text: yellow - selected_text: red_reverse - text: yellow + selected_text: red_reverse + text: yellow } type: { - col_padding: 2 - col_width: 20 - columns: 4 + col_padding: 2 + col_width: 20 + columns: 4 description_rows: 10 - layout: description - selection_rows: 4 + layout: description + selection_rows: 4 } } ] @@ -128,190 +127,187 @@ $env.config.keybindings = [ name: copy_commandline modifier: alt keycode: char_c - mode: [ vi_normal vi_insert ] + mode: [vi_normal vi_insert] event: { send: executehostcommand cmd: 'commandline | nu-highlight | $"```ansi\n($in)\n```" | wl-copy $in' } } { - name: completion_menu + name: escape modifier: none - keycode: tab - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: menu name: completion_menu } - { send: menunext } - { edit: complete } - ] - } + keycode: escape + mode: [vi_normal vi_insert] + event: {send: esc} } { - name: escape - modifier: none - keycode: escape - mode: [ vi_normal vi_insert ] - event: { send: esc } - } - { - name: cancel_command + name: cancel_command modifier: control - keycode: char_c - mode: [ vi_normal vi_insert ] - event: { send: ctrlc } + keycode: char_c + mode: [vi_normal vi_insert] + event: {send: ctrlc} } { - name: quit_shell + name: quit_shell modifier: control - keycode: char_d - mode: [ vi_normal vi_insert ] - event: { send: ctrld } + keycode: char_d + mode: [vi_normal vi_insert] + event: {send: ctrld} } { - name: clear_screen + name: clear_screen modifier: control - keycode: char_l - mode: [ vi_normal vi_insert ] - event: { send: clearscreen } + keycode: char_l + mode: [vi_normal vi_insert] + event: {send: clearscreen} } { - name: open_command_editor + name: open_command_editor modifier: control - keycode: char_o - mode: [ vi_normal vi_insert ] - event: { send: openeditor } + keycode: char_o + mode: [vi_normal vi_insert] + event: {send: openeditor} } { - name: abbr + name: abbr modifier: control - keycode: space - mode: [ vi_normal vi_insert ] + keycode: space + mode: [vi_normal vi_insert] event: [ - { send: menu name: abbr_menu } - { edit: insertchar, value: " " } + {send: menu name: abbr_menu} + {edit: insertchar value: " "} ] } { - name: move_down + name: move_down modifier: none - keycode: down - mode: [ vi_normal vi_insert ] - event: { + keycode: down + mode: [vi_normal vi_insert] + event: { until: [ - { send: menudown } - { send: down } + {send: menudown} + {send: down} ] } } { - name: move_left + name: move_left modifier: none - keycode: left - mode: [ vi_normal vi_insert ] - event: { + keycode: left + mode: [vi_normal vi_insert] + event: { until: [ - { send: menuleft } - { send: left } + {send: menuleft} + {send: left} ] } } { - name: move_right_or_take_history_hint + name: move_right_or_take_history_hint modifier: none - keycode: right - mode: [ vi_normal vi_insert ] - event: { + keycode: right + mode: [vi_normal vi_insert] + event: { until: [ - { send: historyhintcomplete } - { send: menuright } - { send: right } + {send: historyhintcomplete} + {send: menuright} + {send: right} ] } } { - name: move_one_word_left + name: move_one_word_left modifier: control - keycode: left - mode: [ vi_normal vi_insert ] - event: { edit: movewordleft } + keycode: left + mode: [vi_normal vi_insert] + event: {edit: movewordleft} } { - name: move_one_word_right_or_take_history_hint + name: move_one_word_right_or_take_history_hint modifier: control - keycode: right - mode: [ vi_normal vi_insert ] - event: { + keycode: right + mode: [vi_normal vi_insert] + event: { until: [ - { send: historyhintwordcomplete } - { edit: movewordright } + {send: historyhintwordcomplete} + {edit: movewordright} ] } } { - name: move_to_line_start + name: move_to_line_start modifier: control - keycode: char_a - mode: [ vi_normal vi_insert ] - event: { edit: movetolinestart } + keycode: char_a + mode: [vi_normal vi_insert] + event: {edit: movetolinestart} } { - name: move_to_line_end_or_take_history_hint + name: move_to_line_end_or_take_history_hint modifier: control - keycode: char_e - mode: [ vi_normal vi_insert ] - event: { + keycode: char_e + mode: [vi_normal vi_insert] + event: { until: [ - { send: historyhintcomplete } - { edit: movetolineend } + {send: historyhintcomplete} + {edit: movetolineend} ] } } { - name: delete_one_character_backward + name: delete_one_character_backward modifier: none - keycode: backspace - mode: vi_insert - event: { edit: backspace } + keycode: backspace + mode: vi_insert + event: {edit: backspace} } { - name: delete_one_word_backward + name: delete_one_word_backward modifier: control - keycode: backspace - mode: vi_insert - event: { edit: backspaceword } + keycode: backspace + mode: vi_insert + event: {edit: backspaceword} } { - name: newline_or_run_command + name: newline_or_run_command modifier: none - keycode: enter - mode: vi_insert - event: { send: enter } + keycode: enter + mode: vi_insert + event: {send: enter} } { - name: take_history_hint + name: take_history_hint modifier: control - keycode: char_f - mode: [ vi_normal vi_insert ] - event: { + keycode: char_f + mode: [vi_normal vi_insert] + event: { until: [ - { send: historyhintcomplete } + {send: historyhintcomplete} ] } } ] -source ./atuin.nu -source ./zoxide.nu +let autoload_dir = $nu.user-autoload-dirs.0 +mkdir $autoload_dir + +zoxide init nushell --cmd cd | save -f ($autoload_dir | path join zoxide.nu) +atuin init nu | save -f ($autoload_dir | path join atuin.nu) +carapace _carapace nushell | save -f ($autoload_dir | path join carapace.nu) + source ./source_profile.nu -source ./completions.nu source ./prompt.nu # fix sudo by prepending /run/wrappers/bin to the PATH. $env.PATH = ($env.PATH | split row (char esep) | prepend '/run/wrappers/bin') $env.LS_COLORS = (vivid generate lava) $env.EDITOR = "hx" -$env.CARAPACE_BRIDGES = 'zsh,fish,bash,inshellisense' +$env.CARAPACE_BRIDGES = 'carapace,clap,inshellisense,fish' +$env.CARAPACE_MATCH = 1 + + +# Set environment variables according to the path of the clone +$env.TOPIARY_CONFIG_FILE = ($env.HOME | path join .config | path join topiary languages.ncl) +$env.TOPIARY_LANGUAGE_DIR = ($env.HOME | path join .config | path join topiary languages) # The prompt indicators are environmental variables that represent # the state of the prompt. diff --git a/nushell/prompt.nu b/nushell/prompt.nu index bcee93d..dd64c95 100644 --- a/nushell/prompt.nu +++ b/nushell/prompt.nu @@ -1,55 +1,57 @@ use std null_device -export-env { load-env { - PROMPT_COMMAND: {|| - let exit_code = $env.LAST_EXIT_CODE - let jj_root = try { ^jj root err> $null_device } catch { "" } - $env.LAST_EXIT_CODE = 0 - let vcs_root = if not ($jj_root | is-empty ) { $jj_root } else {""} - - mut path_segment = "" - if not (($vcs_root | is-empty) or ($env.PWD == $vcs_root)) { - # vcs_root is not empty, we're not in the vcs_root of the project - $path_segment = [($vcs_root | path basename), ($env.PWD | path basename)] | str join " @ " - } else { - $path_segment = $env.PWD | path basename - } - - let exit_code_segment = if ($exit_code == 0) { - "" - } else { - $"(ansi yellow)━┫(ansi red)($exit_code)(ansi yellow)┣━" - } +export-env { + load-env { + PROMPT_COMMAND: {|| + let exit_code = $env.LAST_EXIT_CODE + let jj_root = try { ^jj root err> $null_device } catch { "" } + $env.LAST_EXIT_CODE = 0 + let vcs_root = if not ($jj_root | is-empty) { $jj_root } else { "" } - [$"(ansi yellow)┏",$exit_code_segment,"━ ", $path_segment, "\n"] | str join + mut path_segment = "" + if not (($vcs_root | is-empty) or ($env.PWD == $vcs_root)) { + # vcs_root is not empty, we're not in the vcs_root of the project + $path_segment = [($vcs_root | path basename) ($env.PWD | path basename)] | str join " @ " + } else { + $path_segment = $env.PWD | path basename + } - } - TRANSIENT_PROMPT_COMMAND: {|| - let path_segment = $env.PWD | path basename - - let exit_code_segment = if ($env.LAST_EXIT_CODE == 0) { - "" - } else { - $"(ansi yellow)━┫(ansi red)($env.LAST_EXIT_CODE)(ansi yellow)┣━" - } + let exit_code_segment = if ($exit_code == 0) { + "" + } else { + $"(ansi yellow)━┫(ansi red)($exit_code)(ansi yellow)┣━" + } - [$"(ansi yellow)━",$exit_code_segment,"━ ", $path_segment] | str join - } -PROMPT_INDICATOR_VI_INSERT: $"(ansi yellow)┃ " -PROMPT_INDICATOR_VI_NORMAL: $"(ansi yellow)┋ " -# PROMPT_MULTILINE_INDICATOR: "::: " -PROMPT_MULTILINE_INDICATOR: $"(ansi yellow)┃ " -TRANSIENT_PROMPT_INDICATOR_VI_INSERT: " " -TRANSIENT_PROMPT_INDICATOR_VI_NORMAL: " " -TRANSIENT_PROMPT_MULTILINE_INDICATOR: $"(ansi yellow)┃ " + [$"(ansi yellow)┏" $exit_code_segment "━ " $path_segment "\n"] | str join + } + TRANSIENT_PROMPT_COMMAND: {|| + let path_segment = $env.PWD | path basename - config: ($env.config? | default {} | merge { - render_right_prompt_on_last_line: true - }) + let exit_code_segment = if ($env.LAST_EXIT_CODE == 0) { + "" + } else { + $"(ansi yellow)━┫(ansi red)($env.LAST_EXIT_CODE)(ansi yellow)┣━" + } -PROMPT_COMMAND_RIGHT: {|| - let jj_status = try { - jj --quiet --color always --ignore-working-copy log --no-graph --revisions @ --template ' + [$"(ansi yellow)━" $exit_code_segment "━ " $path_segment] | str join + } + PROMPT_INDICATOR_VI_INSERT: $"(ansi yellow)┃ " + PROMPT_INDICATOR_VI_NORMAL: $"(ansi yellow)┋ " + # PROMPT_MULTILINE_INDICATOR: "::: " + PROMPT_MULTILINE_INDICATOR: $"(ansi yellow)┃ " + TRANSIENT_PROMPT_INDICATOR_VI_INSERT: " " + TRANSIENT_PROMPT_INDICATOR_VI_NORMAL: " " + TRANSIENT_PROMPT_MULTILINE_INDICATOR: $"(ansi yellow)┃ " + + config: ( + $env.config? | default {} | merge { + render_right_prompt_on_last_line: true + } + ) + + 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)")), @@ -73,8 +75,10 @@ PROMPT_COMMAND_RIGHT: {|| if(hidden, label("hidden prefix", "(hidden)")), ) ' err> $null_device - } catch { - "" + } catch { + "" + } + $jj_status + } } - $jj_status -}}} +} diff --git a/nushell/source_profile.nu b/nushell/source_profile.nu old mode 100755 new mode 100644 index 81dfe26..ef7e92b --- a/nushell/source_profile.nu +++ b/nushell/source_profile.nu @@ -13,7 +13,7 @@ if not ($env_vars_file | path exists) { | lines | parse 'export {name}="{value}"' | transpose --header-row --as-record - | tee {load-env $in} + | tee { load-env $in } | to nuon | save --force $env_vars_file } else { diff --git a/nushell/zoxide.nu b/nushell/zoxide.nu index 079b95a..5c3463f 100644 --- a/nushell/zoxide.nu +++ b/nushell/zoxide.nu @@ -11,50 +11,66 @@ export-env { $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 "nu-complete zoxide path" [context: string] { - let parts = $context | split row -r "[ /]" | skip 1 - { - options: { - sort: false, - completion_algorithm: substring, - case_sensitive: false, - }, - completions: ( - ^zoxide query --list --exclude $env.PWD -- ...$parts - | lines - | first 10 - | each {|p| $p | path relative-to $env.PWD | $"($in)/"} - - # | each {|p| echo p | path basename} + $env.config.hooks.env_change.PWD = ( + $env.config.hooks.env_change.PWD | append { + __zoxide_hook: true + code: {|_ dir| zoxide add -- $dir } + } ) - # | each {|p| echo p | path basename | $"($in)/"}), } } -# Jump to a directory using only keywords. -def --env --wrapped __zoxide_z [...rest: string@"nu-complete zoxide path"] { - let path = match $rest { - [] => {'~'}, - [ '-' ] => {'-'}, - [ $arg ] if ($arg | path expand | path type) == 'dir' => {$arg} - _ => { - zoxide query --exclude $env.PWD -- ...$rest | str trim -r -c "\n" +module zoxide-commands { + def "nu-complete zoxide path" [context: string] { + let parts = $context | str trim --left | split row " " | skip 1 | each { str downcase } + let completions = ( + ^zoxide query --list --exclude $env.PWD -- ...$parts + | lines + | each {|dir| + if ($parts | length) <= 1 { + $dir + } else { + let dir_lower = $dir | str downcase + let rem_start = $parts | drop 1 | reduce --fold 0 {|part rem_start| + ($dir_lower | str index-of --range $rem_start.. $part) + ($part | str length) + } + { + value: ($dir | str substring $rem_start..) + description: $dir + } + } + } + ) + { + options: { + sort: false + completion_algorithm: prefix + positional: false + case_sensitive: false + } + completions: $completions } } - cd $path + + # Jump to a directory using only keywords. + export def --env --wrapped __zoxide_z [...rest: string@"nu-complete zoxide path"] { + let path = match $rest { + [] => { '~' } + ['-'] => { '-' } + [$arg] if ($arg | path expand | path type) == 'dir' => { $arg } + _ => { + ^zoxide query --exclude $env.PWD -- ...$rest | str trim -r -c "\n" + } + } + cd $path + } + + # Jump to a directory using interactive search. + export def --env --wrapped __zoxide_zi [...rest: string@"nu-complete zoxide path"] { + cd $'(^zoxide query --interactive -- ...$rest | str trim -r -c "\n")' + } + alias cd = __zoxide_z + alias ci = __zoxide_zi } -# Jump to a directory using interactive search. -def --env --wrapped __zoxide_zi [...rest:string@"nu-complete zoxide path"] { - cd $'(zoxide query --interactive -- ...$rest | str trim -r -c "\n")' -} - -alias cd = __zoxide_z -alias ci = __zoxide_zi +use zoxide-commands *