From 373783d388e420d3b0c7bca15db4d2e9d179c26f Mon Sep 17 00:00:00 2001 From: NotTheDr01ds <32344964+NotTheDr01ds@users.noreply.github.com> Date: Sun, 15 Sep 2024 14:37:59 -0400 Subject: [PATCH] Deprecate dirs/shells from autoloading rather than removing immediately --- crates/nu-std/src/lib.rs | 12 ++ crates/nu-std/std/deprecated_dirs/mod.nu | 161 +++++++++++++++++++++++ crates/nu-std/std/dirs/mod.nu | 62 +++++---- crates/nu-std/tests/test_dirs.nu | 5 +- 4 files changed, 211 insertions(+), 29 deletions(-) create mode 100644 crates/nu-std/std/deprecated_dirs/mod.nu diff --git a/crates/nu-std/src/lib.rs b/crates/nu-std/src/lib.rs index 4af23464a6..cc2fff688e 100644 --- a/crates/nu-std/src/lib.rs +++ b/crates/nu-std/src/lib.rs @@ -22,6 +22,10 @@ pub fn load_standard_library( ("assert", include_str!("../std/assert/mod.nu")), ("bench", include_str!("../std/bench/mod.nu")), ("dirs", include_str!("../std/dirs/mod.nu")), + ( + "deprecated_dirs", + include_str!("../std/deprecated_dirs/mod.nu"), + ), ("dt", include_str!("../std/dt/mod.nu")), ("formats", include_str!("../std/formats/mod.nu")), ("help", include_str!("../std/help/mod.nu")), @@ -52,6 +56,14 @@ pub fn load_standard_library( let source = r#" # Prelude use ([ std core ] | path join) * +use ([ std deprecated_dirs] | path join) [ + enter + shells + g + n + p + dexit +] "#; let _ = working_set.add_virtual_path(std_dir, VirtualPath::Dir(std_virt_paths)); diff --git a/crates/nu-std/std/deprecated_dirs/mod.nu b/crates/nu-std/std/deprecated_dirs/mod.nu new file mode 100644 index 0000000000..5590354b84 --- /dev/null +++ b/crates/nu-std/std/deprecated_dirs/mod.nu @@ -0,0 +1,161 @@ +# Maintain a list of working directories and navigate them + +# The directory stack. +# +# Exception: the entry for the current directory contains an +# irrelevant value. Instead, the source of truth for the working +# directory is $env.PWD. It has to be this way because cd doesn't +# know about this module. +# +# Example: the following state represents a user-facing directory +# stack of [/a, /var/tmp, /c], and we are currently in /var/tmp . +# +# PWD = /var/tmp +# DIRS_POSITION = 1 +# DIRS_LIST = [/a, /b, /c] +# +# This situation could arise if we started with [/a, /b, /c], then +# we changed directories from /b to /var/tmp. +export-env { + $env.DIRS_POSITION = 0 + $env.DIRS_LIST = [($env.PWD | path expand)] +} + +def deprecation_warning [ ] { +print -e $" +(ansi red)Warning:(ansi reset) The 'std dirs' module will no longer automatically +be loaded in the next release. To continue using the Shells +feature, and to remove this warning, please add the following +to your config.nu: + +use std/dirs aliases * + +Or see the documentation for more options. +" +} + +# Add one or more directories to the list. +# PWD becomes first of the newly added directories. +export def --env add [ + ...paths: string # directory or directories to add to working list +] { + deprecation_warning + + mut abspaths = [] + for p in $paths { + let exp = ($p | path expand) + if ($exp | path type) != 'dir' { + let span = (metadata $p).span + error make {msg: "not a directory", label: {text: "not a directory", span: $span } } + } + $abspaths = ($abspaths | append $exp) + } + + $env.DIRS_LIST = ($env.DIRS_LIST | insert ($env.DIRS_POSITION + 1) $abspaths | flatten) + + _fetch 1 +} + +export alias enter = add + +# Advance to the next directory in the list or wrap to beginning. +export def --env next [ + N:int = 1 # number of positions to move. +] { + deprecation_warning + _fetch $N +} + +export alias n = next + +# Back up to the previous directory or wrap to the end. +export def --env prev [ + N:int = 1 # number of positions to move. +] { + deprecation_warning + _fetch (-1 * $N) +} + +export alias p = prev + +# Drop the current directory from the list, if it's not the only one. +# PWD becomes the next working directory +export def --env drop [] { + deprecation_warning + if ($env.DIRS_LIST | length) > 1 { + $env.DIRS_LIST = ($env.DIRS_LIST | reject $env.DIRS_POSITION) + if ($env.DIRS_POSITION >= ($env.DIRS_LIST | length)) {$env.DIRS_POSITION = 0} + } + + # step to previous slot + _fetch -1 --forget_current --always_cd + +} + +export alias dexit = drop + +# Display current working directories. +export def --env show [] { + deprecation_warning + mut out = [] + for $p in ($env.DIRS_LIST | enumerate) { + let is_act_slot = $p.index == $env.DIRS_POSITION + $out = ($out | append [ + [active, path]; + [($is_act_slot), + (if $is_act_slot {$env.PWD} else {$p.item}) # show current PWD in lieu of active slot + ] + ]) + } + + $out +} + +export alias shells = show + +export def --env goto [shell?: int] { + deprecation_warning + if $shell == null { + return (show) + } + + if $shell < 0 or $shell >= ($env.DIRS_LIST | length) { + let span = (metadata $shell | get span) + error make { + msg: $"(ansi red_bold)invalid_shell_index(ansi reset)" + label: { + text: $"`shell` should be between 0 and (($env.DIRS_LIST | length) - 1)" + span: $span + } + } + } + + _fetch ($shell - $env.DIRS_POSITION) +} + +export alias g = goto + +# fetch item helper +def --env _fetch [ + offset: int, # signed change to position + --forget_current # true to skip saving PWD + --always_cd # true to always cd +] { + if not ($forget_current) { + # first record current working dir in current slot of ring, to track what CD may have done. + $env.DIRS_LIST = ($env.DIRS_LIST | upsert $env.DIRS_POSITION $env.PWD) + } + + # figure out which entry to move to + # nushell 'mod' operator is really 'remainder', can return negative values. + # see: https://stackoverflow.com/questions/13683563/whats-the-difference-between-mod-and-remainder + let len = ($env.DIRS_LIST | length) + mut pos = ($env.DIRS_POSITION + $offset) mod $len + if ($pos < 0) { $pos += $len} + + # if using a different position in ring, CD there. + if ($always_cd or $pos != $env.DIRS_POSITION) { + $env.DIRS_POSITION = $pos + cd ($env.DIRS_LIST | get $pos ) + } +} diff --git a/crates/nu-std/std/dirs/mod.nu b/crates/nu-std/std/dirs/mod.nu index bf935a84b9..d4596f35fe 100644 --- a/crates/nu-std/std/dirs/mod.nu +++ b/crates/nu-std/std/dirs/mod.nu @@ -22,7 +22,8 @@ export-env { } # Add one or more directories to the list. -# PWD becomes first of the newly added directories. +# The first directory listed becomes the new +# active directory. export def --env add [ ...paths: string # directory or directories to add to working list ] { @@ -38,32 +39,33 @@ export def --env add [ $env.DIRS_LIST = ($env.DIRS_LIST | insert ($env.DIRS_POSITION + 1) $abspaths | flatten) - _fetch 1 } -export alias enter = add - -# Advance to the next directory in the list or wrap to beginning. +# Make the next directory on the list the active directory. +# If the currenta ctive directory is the last in the list, +# then cycle to the top of the list. export def --env next [ N:int = 1 # number of positions to move. ] { _fetch $N } -export alias n = next - -# Back up to the previous directory or wrap to the end. +# Make the previous directory on the list the active directory. +# If the current active directory is the first in the list, +# then cycle to the end of the list. export def --env prev [ N:int = 1 # number of positions to move. ] { _fetch (-1 * $N) } -export alias p = prev - -# Drop the current directory from the list, if it's not the only one. -# PWD becomes the next working directory +# Drop the current directory from the list. +# The previous directory in the list becomes +# the new active directory. +# +# If there is only one directory in the list, +# then this command has no effect. export def --env drop [] { if ($env.DIRS_LIST | length) > 1 { $env.DIRS_LIST = ($env.DIRS_LIST | reject $env.DIRS_POSITION) @@ -75,10 +77,8 @@ export def --env drop [] { } -export alias dexit = drop - -# Display current working directories. -export def --env show [] { +# Display current working directories +export def --env main [] { mut out = [] for $p in ($env.DIRS_LIST | enumerate) { let is_act_slot = $p.index == $env.DIRS_POSITION @@ -93,29 +93,26 @@ export def --env show [] { $out } -export alias shells = show - -export def --env goto [shell?: int] { - if $shell == null { - return (show) +# Jump to directory by index +export def --env goto [dir_idx?: int] { + if $dir_idx == null { + return (main) } - if $shell < 0 or $shell >= ($env.DIRS_LIST | length) { - let span = (metadata $shell | get span) + if $dir_idx < 0 or $dir_idx >= ($env.DIRS_LIST | length) { + let span = (metadata $dir_idx | get span) error make { - msg: $"(ansi red_bold)invalid_shell_index(ansi reset)" + msg: $"(ansi red_bold)invalid_dirs_index(ansi reset)" label: { - text: $"`shell` should be between 0 and (($env.DIRS_LIST | length) - 1)" + text: $"`idx` should be between 0 and (($env.DIRS_LIST | length) - 1)" span: $span } } } - _fetch ($shell - $env.DIRS_POSITION) + _fetch ($dir_idx - $env.DIRS_POSITION) } -export alias g = goto - # fetch item helper def --env _fetch [ offset: int, # signed change to position @@ -140,3 +137,12 @@ def --env _fetch [ cd ($env.DIRS_LIST | get $pos ) } } + +export module aliases { + export alias shells = main + export alias enter = add + export alias dexit = drop + export alias p = prev + export alias n = next + export alias g = goto +} \ No newline at end of file diff --git a/crates/nu-std/tests/test_dirs.nu b/crates/nu-std/tests/test_dirs.nu index a2b9dcbd46..716ea59936 100644 --- a/crates/nu-std/tests/test_dirs.nu +++ b/crates/nu-std/tests/test_dirs.nu @@ -79,7 +79,7 @@ def dirs_command [] { assert length $env.DIRS_LIST 2 "drop removes from list" assert equal $env.PWD $c.path_b "drop changes PWD to previous in list (before dropped element)" - assert equal (dirs show) [[active path]; [false $c.base_path] [true $c.path_b]] "show table contains expected information" + assert equal (dirs) [[active path]; [false $c.base_path] [true $c.path_b]] "show table contains expected information" # Stack becomes: [BASE] dirs drop @@ -173,4 +173,7 @@ def dirs_goto [] { assert equal $env.PWD ($exp_dir | get $other_pos) "goto changed working directory correctly" } } + + # check that 'dirs goto' with no argument maps to `dirs` (main) + assert length (dirs goto) 3 }