nushell/crates/nu-std/std/deprecated_dirs.nu
Douglas ad31f1cf26
Fix dirs removal warning (#14029)
# Description

* Primary purpose is to fix an issue with a missing escaped opening
parenthesis in the warning message when running an old `dirs` alias.
This was creating an error condition from improper interpolation.

Also

* Incorporates #13842 feedback from @kubouch by renaming `std/lib` to
`std/util`
* Removes duplication of code in `export-env`
* Renames submodule exports to `std/<submodule>` rather than
`./<submodule>` - No user-facing change other than `view files` appears
"prettier".
* In #13842, I converted the test cases to use `use std/<module>`
syntax. Previously, the tests were (effectively) using `use std *` (due
to pre-existing bugs, now fixed).

So "before", we only had test coverage on `use std *`, and "after" we
only had test coverage on `use std/<module>`. I've started adding test
cases so that we have coverage on *both* scenarios going forward.

For now, `formats` and `util` have been updated with tests for both
scenarios. I'll continue adding the others in future PRs.

# User-Facing Changes

No user-facing changes - Bug fix, refactor, and test cases only

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting

Still working on updating the Doc. I ran into the `dirs` issue while
writing it and rabbit-trailed to fix it in this PR.
2024-10-09 08:03:33 -05:00

162 lines
4.5 KiB
Plaintext

# 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 startup configuration \(typically env.nu or config.nu\):
use std/dirs shells-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 )
}
}