Move std top-level commands to submodules

This commit is contained in:
NotTheDr01ds 2024-09-14 00:27:32 -04:00
parent 6372a4bf02
commit 021f91cb72
5 changed files with 218 additions and 215 deletions

View File

@ -19,16 +19,18 @@ pub fn load_standard_library(
let mut std_files = vec![ let mut std_files = vec![
("mod.nu", include_str!("../std/mod.nu")), ("mod.nu", include_str!("../std/mod.nu")),
("core.nu", include_str!("../std/core.nu")), ("core.nu", include_str!("../std/core.nu")),
("assert.nu", include_str!("../std/assert.nu")),
("bench.nu", include_str!("../std/bench.nu")),
("dirs.nu", include_str!("../std/dirs.nu")), ("dirs.nu", include_str!("../std/dirs.nu")),
("dt.nu", include_str!("../std/dt.nu")), ("dt.nu", include_str!("../std/dt.nu")),
("formats.nu", include_str!("../std/formats.nu")),
("help.nu", include_str!("../std/help.nu")), ("help.nu", include_str!("../std/help.nu")),
("input.nu", include_str!("../std/input.nu")),
("iter.nu", include_str!("../std/iter.nu")), ("iter.nu", include_str!("../std/iter.nu")),
("log.nu", include_str!("../std/log.nu")), ("log.nu", include_str!("../std/log.nu")),
("assert.nu", include_str!("../std/assert.nu")),
("xml.nu", include_str!("../std/xml.nu")),
("input.nu", include_str!("../std/input.nu")),
("math.nu", include_str!("../std/math.nu")), ("math.nu", include_str!("../std/math.nu")),
("formats.nu", include_str!("../std/formats.nu")), ("util.nu", include_str!("../std/util.nu")),
("xml.nu", include_str!("../std/xml.nu")),
]; ];
let mut working_set = StateWorkingSet::new(engine_state); let mut working_set = StateWorkingSet::new(engine_state);

View File

@ -0,0 +1,71 @@
# run a piece of `nushell` code multiple times and measure the time of execution.
#
# this command returns a benchmark report of the following form:
# ```
# record<
# mean: duration
# std: duration
# times: list<duration>
# >
# ```
#
# > **Note**
# > `std bench --pretty` will return a `string`.
#
# # Examples
# measure the performance of simple addition
# > std bench { 1 + 2 } -n 10 | table -e
# ╭───────┬────────────────────╮
# │ mean │ 4µs 956ns │
# │ std │ 4µs 831ns │
# │ │ ╭───┬────────────╮ │
# │ times │ │ 0 │ 19µs 402ns │ │
# │ │ │ 1 │ 4µs 322ns │ │
# │ │ │ 2 │ 3µs 352ns │ │
# │ │ │ 3 │ 2µs 966ns │ │
# │ │ │ 4 │ 3µs │ │
# │ │ │ 5 │ 3µs 86ns │ │
# │ │ │ 6 │ 3µs 84ns │ │
# │ │ │ 7 │ 3µs 604ns │ │
# │ │ │ 8 │ 3µs 98ns │ │
# │ │ │ 9 │ 3µs 653ns │ │
# │ │ ╰───┴────────────╯ │
# ╰───────┴────────────────────╯
#
# get a pretty benchmark report
# > std bench { 1 + 2 } --pretty
# 3µs 125ns +/- 2µs 408ns
export def main [
code: closure # the piece of `nushell` code to measure the performance of
--rounds (-n): int = 50 # the number of benchmark rounds (hopefully the more rounds the less variance)
--verbose (-v) # be more verbose (namely prints the progress)
--pretty # shows the results in human-readable format: "<mean> +/- <stddev>"
] {
let times = (
seq 1 $rounds | each {|i|
if $verbose { print -n $"($i) / ($rounds)\r" }
timeit { do $code } | into int | into float
}
)
if $verbose { print $"($rounds) / ($rounds)" }
let report = {
mean: ($times | math avg | from ns)
min: ($times | math min | from ns)
max: ($times | math max | from ns)
std: ($times | math stddev | from ns)
times: ($times | each { from ns })
}
if $pretty {
$"($report.mean) +/- ($report.std)"
} else {
$report
}
}
# convert an integer amount of nanoseconds to a real duration
def "from ns" [] {
[$in "ns"] | str join | into duration
}

View File

@ -1,6 +1,7 @@
# std.nu, `used` to load all standard library components # std.nu, `used` to load all standard library components
export module core.nu export module core.nu
export module bench.nu
export module assert.nu export module assert.nu
export module dirs.nu export module dirs.nu
export module dt.nu export module dt.nu
@ -10,205 +11,9 @@ export module input.nu
export module iter.nu export module iter.nu
export module log.nu export module log.nu
export module math.nu export module math.nu
export module util.nu
export module xml.nu export module xml.nu
export-env { export-env {
use dirs.nu [] use dirs.nu []
use log.nu [] use log.nu []
} }
# 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 equal $env.PATH ["bar" "baz" "foo" "fooo"]
#
# print (std path add "returned" --ret)
# }
# ╭───┬──────────╮
# │ 0 │ returned │
# │ 1 │ bar │
# │ 2 │ baz │
# │ 3 │ foo │
# │ 4 │ fooo │
# ╰───┴──────────╯
# ```
# - adding paths based on the operating system
# ```nushell
# >_ std path add {linux: "foo", windows: "bar", darwin: "baz"}
# ```
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 span = (metadata $paths).span
let paths = $paths | flatten
if ($paths | is-empty) or ($paths | length) == 0 {
error make {msg: "Empty input", label: {
text: "Provide at least one string or a record",
span: $span
}}
}
let path_name = if "PATH" in $env { "PATH" } else { "Path" }
let paths = $paths | each {|p|
let p = match ($p | describe | str replace --regex '<.*' '') {
"string" => $p,
"record" => { $p | get --ignore-errors $nu.os-info.name },
}
$p | path expand --no-symlink
}
if null in $paths or ($paths | is-empty) {
error make {msg: "Empty input", label: {
text: $"Received a record, that does not contain a ($nu.os-info.name) key",
span: $span
}}
}
load-env {$path_name: (
$env
| get $path_name
| split row (char esep)
| if $append { append $paths } else { prepend $paths }
)}
if $ret {
$env | get $path_name
}
}
# convert an integer amount of nanoseconds to a real duration
def "from ns" [] {
[$in "ns"] | str join | into duration
}
# run a piece of `nushell` code multiple times and measure the time of execution.
#
# this command returns a benchmark report of the following form:
# ```
# record<
# mean: duration
# std: duration
# times: list<duration>
# >
# ```
#
# > **Note**
# > `std bench --pretty` will return a `string`.
#
# # Examples
# measure the performance of simple addition
# > std bench { 1 + 2 } -n 10 | table -e
# ╭───────┬────────────────────╮
# │ mean │ 4µs 956ns │
# │ std │ 4µs 831ns │
# │ │ ╭───┬────────────╮ │
# │ times │ │ 0 │ 19µs 402ns │ │
# │ │ │ 1 │ 4µs 322ns │ │
# │ │ │ 2 │ 3µs 352ns │ │
# │ │ │ 3 │ 2µs 966ns │ │
# │ │ │ 4 │ 3µs │ │
# │ │ │ 5 │ 3µs 86ns │ │
# │ │ │ 6 │ 3µs 84ns │ │
# │ │ │ 7 │ 3µs 604ns │ │
# │ │ │ 8 │ 3µs 98ns │ │
# │ │ │ 9 │ 3µs 653ns │ │
# │ │ ╰───┴────────────╯ │
# ╰───────┴────────────────────╯
#
# get a pretty benchmark report
# > std bench { 1 + 2 } --pretty
# 3µs 125ns +/- 2µs 408ns
export def bench [
code: closure # the piece of `nushell` code to measure the performance of
--rounds (-n): int = 50 # the number of benchmark rounds (hopefully the more rounds the less variance)
--verbose (-v) # be more verbose (namely prints the progress)
--pretty # shows the results in human-readable format: "<mean> +/- <stddev>"
] {
let times = (
seq 1 $rounds | each {|i|
if $verbose { print -n $"($i) / ($rounds)\r" }
timeit { do $code } | into int | into float
}
)
if $verbose { print $"($rounds) / ($rounds)" }
let report = {
mean: ($times | math avg | from ns)
min: ($times | math min | from ns)
max: ($times | math max | from ns)
std: ($times | math stddev | from ns)
times: ($times | each { from ns })
}
if $pretty {
$"($report.mean) +/- ($report.std)"
} else {
$report
}
}
# the cute and friendly mascot of Nushell :)
export def ellie [] {
let ellie = [
" __ ,",
" .--()°'.'",
"'|, . ,'",
" !_-(_\\",
]
$ellie | str join "\n" | $"(ansi green)($in)(ansi reset)"
}
# repeat anything a bunch of times, yielding a list of *n* times the input
#
# # Examples
# repeat a string
# > "foo" | std repeat 3 | str join
# "foofoofoo"
export def repeat [
n: int # the number of repetitions, must be positive
]: any -> list<any> {
let item = $in
if $n < 0 {
let span = metadata $n | get span
error make {
msg: $"(ansi red_bold)invalid_argument(ansi reset)"
label: {
text: $"n should be a positive integer, found ($n)"
span: $span
}
}
}
if $n == 0 {
return []
}
1..$n | each { $item }
}
# return a null device file.
#
# # Examples
# run a command and ignore it's stderr output
# > cat xxx.txt e> (null-device)
export def null-device []: nothing -> path {
if ($nu.os-info.name | str downcase) == "windows" {
'\\.\NUL'
} else {
"/dev/null"
}
}

124
crates/nu-std/std/util.nu Normal file
View File

@ -0,0 +1,124 @@
# 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 equal $env.PATH ["bar" "baz" "foo" "fooo"]
#
# print (std path add "returned" --ret)
# }
# ╭───┬──────────╮
# │ 0 │ returned │
# │ 1 │ bar │
# │ 2 │ baz │
# │ 3 │ foo │
# │ 4 │ fooo │
# ╰───┴──────────╯
# ```
# - adding paths based on the operating system
# ```nushell
# >_ std path add {linux: "foo", windows: "bar", darwin: "baz"}
# ```
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 span = (metadata $paths).span
let paths = $paths | flatten
if ($paths | is-empty) or ($paths | length) == 0 {
error make {msg: "Empty input", label: {
text: "Provide at least one string or a record",
span: $span
}}
}
let path_name = if "PATH" in $env { "PATH" } else { "Path" }
let paths = $paths | each {|p|
let p = match ($p | describe | str replace --regex '<.*' '') {
"string" => $p,
"record" => { $p | get --ignore-errors $nu.os-info.name },
}
$p | path expand --no-symlink
}
if null in $paths or ($paths | is-empty) {
error make {msg: "Empty input", label: {
text: $"Received a record, that does not contain a ($nu.os-info.name) key",
span: $span
}}
}
load-env {$path_name: (
$env
| get $path_name
| split row (char esep)
| if $append { append $paths } else { prepend $paths }
)}
if $ret {
$env | get $path_name
}
}
# the cute and friendly mascot of Nushell :)
export def ellie [] {
let ellie = [
" __ ,",
" .--()°'.'",
"'|, . ,'",
" !_-(_\\",
]
$ellie | str join "\n" | $"(ansi green)($in)(ansi reset)"
}
# repeat anything a bunch of times, yielding a list of *n* times the input
#
# # Examples
# repeat a string
# > "foo" | std repeat 3 | str join
# "foofoofoo"
export def repeat [
n: int # the number of repetitions, must be positive
]: any -> list<any> {
let item = $in
if $n < 0 {
let span = metadata $n | get span
error make {
msg: $"(ansi red_bold)invalid_argument(ansi reset)"
label: {
text: $"n should be a positive integer, found ($n)"
span: $span
}
}
}
if $n == 0 {
return []
}
1..$n | each { $item }
}
# return a null device file.
#
# # Examples
# run a command and ignore it's stderr output
# > cat xxx.txt e> (null-device)
export def null-device []: nothing -> path {
if ($nu.os-info.name | str downcase) == "windows" {
'\\.\NUL'
} else {
"/dev/null"
}
}

View File

@ -1,4 +1,4 @@
use std use std util
#[test] #[test]
def path_add [] { def path_add [] {
@ -11,19 +11,19 @@ def path_add [] {
assert equal (get_path) [] assert equal (get_path) []
std path add "/foo/" util path add "/foo/"
assert equal (get_path) (["/foo/"] | path expand) assert equal (get_path) (["/foo/"] | path expand)
std path add "/bar/" "/baz/" util path add "/bar/" "/baz/"
assert equal (get_path) (["/bar/", "/baz/", "/foo/"] | path expand) assert equal (get_path) (["/bar/", "/baz/", "/foo/"] | path expand)
load-env {$path_name: []} load-env {$path_name: []}
std path add "foo" util path add "foo"
std path add "bar" "baz" --append util path add "bar" "baz" --append
assert equal (get_path) (["foo", "bar", "baz"] | path expand) assert equal (get_path) (["foo", "bar", "baz"] | path expand)
assert equal (std path add "fooooo" --ret) (["fooooo", "foo", "bar", "baz"] | path expand) assert equal (util path add "fooooo" --ret) (["fooooo", "foo", "bar", "baz"] | path expand)
assert equal (get_path) (["fooooo", "foo", "bar", "baz"] | path expand) assert equal (get_path) (["fooooo", "foo", "bar", "baz"] | path expand)
load-env {$path_name: []} load-env {$path_name: []}
@ -35,11 +35,11 @@ def path_add [] {
android: "quux", android: "quux",
} }
std path add $target_paths util path add $target_paths
assert equal (get_path) ([($target_paths | get $nu.os-info.name)] | path expand) assert equal (get_path) ([($target_paths | get $nu.os-info.name)] | path expand)
load-env {$path_name: [$"(["/foo", "/bar"] | path expand | str join (char esep))"]} load-env {$path_name: [$"(["/foo", "/bar"] | path expand | str join (char esep))"]}
std path add "~/foo" util path add "~/foo"
assert equal (get_path) (["~/foo", "/foo", "/bar"] | path expand) assert equal (get_path) (["~/foo", "/foo", "/bar"] | path expand)
} }
} }
@ -63,7 +63,7 @@ def path_add_expand [] {
with-env {$path_name: []} { with-env {$path_name: []} {
def get_path [] { $env | get $path_name } def get_path [] { $env | get $path_name }
std path add $link_dir util path add $link_dir
assert equal (get_path) ([$link_dir]) assert equal (get_path) ([$link_dir])
} }
@ -72,11 +72,12 @@ def path_add_expand [] {
#[test] #[test]
def repeat_things [] { def repeat_things [] {
std assert error { "foo" | std repeat -1 } use std assert
assert error { "foo" | util repeat -1 }
for x in ["foo", [1 2], {a: 1}] { for x in ["foo", [1 2], {a: 1}] {
std assert equal ($x | std repeat 0) [] assert equal ($x | util repeat 0) []
std assert equal ($x | std repeat 1) [$x] assert equal ($x | util repeat 1) [$x]
std assert equal ($x | std repeat 2) [$x $x] assert equal ($x | util repeat 2) [$x $x]
} }
} }