From 9e589a9d93daeb62115d7851c6a5635d3a3d4924 Mon Sep 17 00:00:00 2001 From: Antoine Stevan <44101798+amtoine@users.noreply.github.com> Date: Tue, 28 Feb 2023 00:52:47 +0100 Subject: [PATCH] FEATURE: add the first draft of the standard library (#8150) hello there :wave: :yum: as discussed over on the discord server, in `#standard-library`, there is this new project of putting together a bunch of "_standard_" scripts and functions and propose a `nushell` "_standard library_". this PR is the first one in that direction :tada: > **Note** > ~~this PR is still a draft to have some feedback :relieved:~~ > this PR is now **READY FOR REVIEW** :tada: # Description this PR implements the following few commands: - the `assert` familly with a private helper `_assert` - a version of the `match` statement i've also added some examples in the docstrings of the functions :+1: # User-Facing Changes the standard library can now be used with ```bash use crates/nu-utils/src/sample_config/std.nu ``` from the root of the `nushell` source # Tests + Formatting i've written a first draft of a [`tests.nu`](https://github.com/amtoine/nushell/blob/feature/first-draft-of-the-standard-library/crates/nu-utils/src/sample_config/tests.nu) module which - tests the `assert` familly of function in `test_assert` - tests the rest of the standard library in `tests` the tests are run with ```bash nu crates/nu-utils/src/sample_config/tests.nu ``` through the `main` function and should give no error :+1: > **Note** > if you change one of the test line, there should be an error popping when running the tests :wink: # After Submitting > **Warning** > to be coming --- crates/nu-utils/src/sample_config/std.nu | 124 +++++++++++++++++++++ crates/nu-utils/src/sample_config/tests.nu | 46 ++++++++ 2 files changed, 170 insertions(+) create mode 100644 crates/nu-utils/src/sample_config/std.nu create mode 100644 crates/nu-utils/src/sample_config/tests.nu diff --git a/crates/nu-utils/src/sample_config/std.nu b/crates/nu-utils/src/sample_config/std.nu new file mode 100644 index 0000000000..b3c71cbe05 --- /dev/null +++ b/crates/nu-utils/src/sample_config/std.nu @@ -0,0 +1,124 @@ +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 + } +} diff --git a/crates/nu-utils/src/sample_config/tests.nu b/crates/nu-utils/src/sample_config/tests.nu new file mode 100644 index 0000000000..f5cccaac07 --- /dev/null +++ b/crates/nu-utils/src/sample_config/tests.nu @@ -0,0 +1,46 @@ +use std.nu + +def test_assert [] { + def test_failing [code: closure] { + let code_did_run = (try { do $code; true } catch { false }) + + if $code_did_run { + error make {msg: (view source $code)} + } + } + + std assert true + std assert (1 + 2 == 3) + test_failing { std assert false } + test_failing { std assert (1 + 2 == 4) } + + std assert eq (1 + 2) 3 + test_failing { std assert eq 1 "foo" } + test_failing { std assert eq (1 + 2) 4) } + + std assert ne (1 + 2) 4 + test_failing { std assert ne 1 "foo" } + test_failing { std assert ne (1 + 2) 3) } +} + +def tests [] { + use std.nu assert + + let branches = { + 1: { -1 } + 2: { -2 } + } + + assert ((std match 1 $branches) == -1) + assert ((std match 2 $branches) == -2) + assert ((std match 3 $branches) == $nothing) + + assert ((std match 1 $branches { 0 }) == -1) + assert ((std match 2 $branches { 0 }) == -2) + assert ((std match 3 $branches { 0 }) == 0) +} + +def main [] { + test_assert + tests +}