nushell/crates/nu-utils/standard_library/std.nu
Bob Hyman 2e01bf9cba
add dirs command to std lib (#8368)
# Description

Prototype replacement for `enter`, `n`, `p`, `exit` built-ins
implemented as scripts in standard library.
MVP-level capabilities (rough hack), for feedback please. Not intended
to merge and ship as is.

_(Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.)_

# User-Facing Changes
New command in standard library

```nushell
〉use ~/src/rust/nushell/crates/nu-utils/standard_library/dirs.nu
---------------------------------------------- /home/bobhy ----------------------------------------------
〉help dirs
module dirs.nu -- maintain list of remembered directories + navigate them

todo:
* expand relative to absolute paths (or relative to some prefix?)
* what if user does `cd` by hand?

Module: dirs

Exported commands:
  add (dirs add), drop, next (dirs next), prev (dirs prev), show (dirs show)

This module exports environment.
---------------------------------------------- /home/bobhy ----------------------------------------------
〉dirs add ~/src/rust/nushell /etc ~/.cargo
-------------------------------------- /home/bobhy/src/rust/nushell --------------------------------------
〉dirs next 2
------------------------------------------- /home/bobhy/.cargo -------------------------------------------
〉dirs show
╭───┬─────────┬────────────────────╮
│ # │ current │        path        │
├───┼─────────┼────────────────────┤
│ 0 │         │ /home/bobhy        │
│ 1 │         │ ~/src/rust/nushell │
│ 2 │         │ /etc               │
│ 3 │ ==>     │ ~/.cargo           │
╰───┴─────────┴────────────────────╯
------------------------------------------- /home/bobhy/.cargo -------------------------------------------
〉dirs drop
---------------------------------------------- /home/bobhy ----------------------------------------------
〉dirs show
╭───┬─────────┬────────────────────╮
│ # │ current │        path        │
├───┼─────────┼────────────────────┤
│ 0 │ ==>     │ /home/bobhy        │
│ 1 │         │ ~/src/rust/nushell │
│ 2 │         │ /etc               │
╰───┴─────────┴────────────────────╯
---------------------------------------------- /home/bobhy ----------------------------------------------
〉
```
# Tests + Formatting

Haven't even looked at stdlib `tests.nu` yet.

Other todos:
* address module todos.
* integrate into std lib, rather than as standalone module. Somehow
arrange for `use .../standard_library/std.nu` to load this module
without having to put all the source in `std.nu`?
*  Maybe command should be `std dirs ...`?   
* what else do `enter` and `exit` do that this should do? Then deprecate
those commands.

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2023-03-11 16:31:09 -06:00

183 lines
5.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# std.nu, `used` to load all standard library components
# ----------- sub modules to be loaded as part of stdlib ------------------
# (choose flavor of import that puts your functions in the right namespace)
# This imports into std top-level namespace: std <subcommand>
# export use dirs.nu *
# This imports into std *sub* namespace: std dirs <subcommand>
# export use dirs.nu
# You could also advise the user to `use` your submodule directly
# to put the subcommands at the top level: dirs <subcommand>
export use dirs.nu
# the directory stack -- export-env from submodule doesn't work?
export-env {
let-env DIRS_POSITION = 0
let-env DIRS_LIST = [($env.PWD | path expand)]
}
# ---------------- builtin std functions --------------------
def _assert [
cond: bool
msg: string
] {
if not $cond {
error make {msg: $msg}
}
}
# ```nushell
# >_ assert ($a == 3)
# >_ assert ($a != 3)
# Error:
# × condition given to `assert` does not hold
# ╭─[entry #12:5:1]
# 5 │ if not $cond {
# 6 │ error make {msg: $msg}
# · ─────┬────
# · ╰── originates from here
# 7 │ }
# ╰────
# ```
export def assert [cond: bool] {
_assert $cond "condition given to `assert` does not hold"
}
# ```nushell
# >_ assert_eq $a "a string"
# Error:
# × left and right operand of `assert eq` should have the same type
# ╭─[entry #12:5:1]
# 5 │ if not $cond {
# 6 │ error make {msg: $msg}
# · ─────┬────
# · ╰── originates from here
# 7 │ }
# ╰────
#
# >_ assert_eq $a 3
# >_ assert_eq $a 1
# Error:
# × left is not equal to right
# ╭─[entry #12:5:1]
# 5 │ if not $cond {
# 6 │ error make {msg: $msg}
# · ─────┬────
# · ╰── originates from here
# 7 │ }
# ╰────
# ```
export def "assert eq" [left: any, right: any] {
_assert (($left | describe) == ($right | describe)) $"left and right operand of `assert eq` should have the same type"
_assert ($left == $right) "left is not equal to right"
}
# ```nushell
# >_ assert_ne $a "a string"
# Error:
# × left and right operand of `assert eq` should have the same type
# ╭─[entry #12:5:1]
# 5 │ if not $cond {
# 6 │ error make {msg: $msg}
# · ─────┬────
# · ╰── originates from here
# 7 │ }
# ╰────
#
# >_ assert_ne $a 1
# >_ assert_ne $a 3
# Error:
# × left is equal to right
# ╭─[entry #12:5:1]
# 5 │ if not $cond {
# 6 │ error make {msg: $msg}
# · ─────┬────
# · ╰── originates from here
# 7 │ }
# ╰────
# ```
export def "assert ne" [left: any, right: any] {
_assert (($left | describe) == ($right | describe)) $"left and right operand of `assert eq` should have the same type"
_assert ($left != $right) "left is equal to right"
}
# ```nushell
# >_ let branches = {
# ))) 1: { print "this is the 1st branch"}
# ))) 2: { print "this is the 2nd branch" }
# ))) 3: { print "this is the 3rd branch" }
# ))) 4: { print "this is the 4th branch" }
# ))) }
#
# >_ match 1 $branches
# ))) match 2 $branches
# ))) match 3 $branches
# ))) match 4 $branches
# ))) match 5 $branches
# this is the 1st branch
# this is the 2nd branch
# this is the 3rd branch
# this is the 4th branch
#
# >_ match 1 $branches { "this is the default branch" }
# ))) match 2 $branches { "this is the default branch" }
# ))) match 3 $branches { "this is the default branch" }
# ))) match 4 $branches { "this is the default branch" }
# ))) match 5 $branches { "this is the default branch" }
# this is the 1st branch
# this is the 2nd branch
# this is the 3rd branch
# this is the 4th branch
# this is the default branch
# ```
export def match [
input:string
matchers:record
default?: block
] {
if (($matchers | get -i $input) != null) {
$matchers | get $input | do $in
} else if ($default != null) {
do $default
}
}
# Add the given paths to the PATH.
#
# # Example
# - adding some dummy paths to an empty PATH
# ```nushell
# >_ with-env [PATH []] {
# std path add "foo"
# std path add "bar" "baz"
# std path add "fooo" --append
#
# assert eq $env.PATH ["bar" "baz" "foo" "fooo"]
#
# print (std path add "returned" --ret)
# }
# ╭───┬──────────╮
# │ 0 │ returned │
# │ 1 │ bar │
# │ 2 │ baz │
# │ 3 │ foo │
# │ 4 │ fooo │
# ╰───┴──────────╯
# ```
export def-env "path add" [
--ret (-r) # return $env.PATH, useful in pipelines to avoid scoping.
--append (-a) # append to $env.PATH instead of prepending to.
...paths # the paths to add to $env.PATH.
] {
let-env PATH = (
$env.PATH
| if $append { append $paths }
else { prepend $paths }
)
if $ret {
$env.PATH
}
}