Skip to content

Commit e51c1b2

Browse files
committed
Squash all previous edits; also doc updated run-tests command.
1 parent cbedc84 commit e51c1b2

3 files changed

Lines changed: 256 additions & 27 deletions

File tree

crates/nu-std/CONTRIBUTING.md

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# Contributing
2+
3+
Welcome to the Nushell standard library and thank you for considering contributing!
4+
5+
## Ideas for the standard library
6+
7+
If you've got a great idea, or just want to contribute to open source
8+
by working on the Nushell standard library,
9+
we invite you to talk to the team before you start coding.
10+
You'll find we're friendly, passionate about Nushell and always open to new ideas!
11+
12+
You'll generally find the team members on
13+
[Discord standard-library channel](https://discord.com/channels/601130461678272522/1075541668922658868),
14+
and can have preliminary discussions there to clarify the issues involved.
15+
16+
You can open a [Github issue](https://github.com/nushell/nushell/issues/new/choose)
17+
to have a more focused discussion of your idea.
18+
19+
Generally, we think the standard library should contain items that are
20+
relevant to most/all Nushell users regardless of the application space they're working in.
21+
If your idea isn't quite so broadly applicable,
22+
consider publishing it in [nu_scripts](https://github.com/nushell/nu_scripts).
23+
24+
Preliminary discussions should focus on the *user benefit* your idea would provide.
25+
How many users will be affected by your idea, how much would it help them solve a problem or work more productively?
26+
Given consensus on the user benefit, the team will be motivated to
27+
help you create, deploy and maintain a solution long term.
28+
29+
## Lifecycle of a change
30+
31+
1. Verify the team thinks your idea is potentially relevant and useful, as above.
32+
1. If it's more than a simple bug fix, open a placeholder PR
33+
as soon as you get started and [set it to draft status][github_draft_pr].
34+
This will alert other contributors that you're working in this area and let you
35+
advertise roughly what scope of changes you're thinking of.
36+
See [below](#the_pr) for details.
37+
1. Get things working in your local development environment.
38+
If you have questions along the way, you can post a question in your PR
39+
or have a more casual discussion with Nushell fans on
40+
[Discord implementation-chat channel](https://discord.com/channels/601130461678272522/615962413203718156)
41+
1. When you get to an appropriate state of doneness, push your changes to the PR and remove the draft status.
42+
2. Team members and other contributors will then review your PR.
43+
Respond to any review comments they raise and address them one way or another.
44+
(Not all comments demand you make a change!)
45+
1. When you and the team are comfortable with the PR,
46+
a team member will merge it into the repo and you can delete your working branch.
47+
2. If you've added a whole new command or made a breaking change,
48+
(strongly) consider writing it up for the release notes.
49+
Currently, release notes are maintained in a different repo, [nushell.github.io](https://github.com/nushell/nushell.github.io).
50+
Make your change in a local clone of that repo and submit a PR to the release notes repo to get it integrated.
51+
52+
## Developing
53+
(All paths below shown relative to the root folder of the git repository containing the standard library.)
54+
### Setup
55+
56+
0. Install the Rust toolchain and Nushell build tools. See [nushell CONTRIBUTING](https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md) for details.
57+
The standard library is tightly coupled to a particular version of Nushell interpreter,
58+
you need to be running that version to test your changes
59+
(unlike a "normal" script module library).
60+
61+
1. Clone the Nushell repo containing the standard library and create a feature branch for your development work.
62+
Currently, that's the [Nushell interpreter source repo](https://github.com/nushell/nushell).
63+
Once you set your working directory to the root of this repository, you'll generally leave it there throughout the session.
64+
```
65+
git clone https://github.com/nushell/nushell
66+
cd nushell
67+
git checkout -b <featureBranch>
68+
```
69+
1. In your IDE, open the folder within the repository containing the standard library.
70+
The folder is currently `./crates/nu-std`, and it is a Rust crate, containing a `Cargo.toml`
71+
and subfolders:
72+
* `src/` (which contains the Rust code to load the standard library modules into memory for efficiency),
73+
* `lib` (which contains all the script module sources for the standard library),
74+
* `tests/` (unit tests for lib).
75+
### The PR
76+
Assuming you've already validated the need with other Nushell contributors, you're focusing on design and implementation
77+
at this point. Share your thinking all along the way!
78+
79+
You can open a [draft][github_draft_pr] pull request based on a small, placeholder code change
80+
and use the PR comments to outline your design and user interface. You'll get feedback from
81+
other contributors that may lead to a more robust and perhaps more idomatic solution.
82+
The threads in the PR can be a convenient reference for you when writing release notes and
83+
for others on the team when researching issues.
84+
85+
Note that the PR will not get final code review or be merged until you remove the draft status.
86+
### Design considerations
87+
The standard library consists of Nushell custom commands and their associated environment variables, packaged in script modules underneath module `std`. For background on scripts, custom commands and modules, see
88+
[Modules chapter of the Nushell book](https://www.nushell.sh/book/modules.html).
89+
90+
To add a completely new module, for example, a `foo` command and some `foo subcommand`s,
91+
you will be dealing with 2 new source files: the module source itself (`./crates/nu-std/lib/foo.nu`) and a unit tests file (`./crates/nu-std/tests/test_foo`); and will be modifying 1 or 2 existing files (`./crates/nu-std/lib/mod.nu` and possibly `./crates/nu-std/src/lib.rs`). This is described below:
92+
93+
1. Source for a custom command `foo` should go in `./crates/nu-std/lib/foo.nu`.
94+
95+
* A source file will typically implement multiple subcommands and possibly a main command as well.
96+
Use `export def` to make these names public to your users.
97+
* If your command is updating environment variables, you must use `export def-env` (instead of `export def`)
98+
to define the subcommand, `export-env {}` to initialize the environment variables and `let-env` to update them.
99+
For an example of a custom command which modifies environment variables,
100+
see: `./crates/nu-std/lib/dirs.nu`.
101+
For an example of a custom command which does *not* modify environment variables, see: `./crates/nu-std/lib/assert.nu`.
102+
* If your standard library module wishes to use a utility from another module of the standard library,
103+
for example `log info`,
104+
you need to import it directly from its module in the `use` statement.
105+
```shell
106+
... your foo.nu ...
107+
export def mycommand [] {
108+
use log "log info"
109+
. . .
110+
log info "info level log message"
111+
. . .
112+
}
113+
```
114+
This is `use log "log info"` rather than `use std "log info"` (which is the usual way commands are imported
115+
from the standard library) because your `foo` module is also a child module under `std`.
116+
117+
1. Unit tests for `foo` should go in `./crates/nu-std/tests/test_foo.nu`. Thou shalt provide unit tests to cover your changes.
118+
* Unit tests should use one of the `assert` commands to check a condition and report the failure in a standard format.
119+
* To import `assert` commands for use in your test, import them via `use std` (unlike the `use log` for your source code; the tests are not modules under `std`). For example:
120+
```shell
121+
... your test_foo.nu ...
122+
def test1 [] {
123+
use std
124+
. . .
125+
std assert greater $l $r
126+
. . .
127+
std assert $predicate
128+
}
129+
130+
def test2 [] {
131+
use std ['assert greater' assert]
132+
. . .
133+
assert greater $l $r
134+
. . .
135+
assert $predicate
136+
}
137+
```
138+
The choice of import style is up to you.
139+
140+
141+
2. A `foo` command will be exposed to the user as `std foo` (at a minimum).
142+
To enable this, update file `./crates/nu-std/lib/mod.nu` and add this code:
143+
```
144+
export use foo * # command doesn't update environment
145+
export-env {
146+
use bar * # command *does* update environment
147+
}
148+
```
149+
The `use *` hoists the public definitions in `foo.nu` into `mod.nu` and thus into the `std` namespace.
150+
151+
1. Some commands from the standard library are also preloaded, so user can invoke them without explicit
152+
import via `use std ...`.
153+
A command implemented as `std foo`, can be preloaded as a bare `foo`:
154+
* modify `./crates/nu-std/src/lib.rs`,
155+
* find the initialization of the "prelude" at line 90 or thereabouts
156+
* add `("foo", "foo")`
157+
* or, to be preloaded as `std foo`, add `("std foo", "foo")`.
158+
159+
(This code may be restructured soon: if you can't find it, check with the team on Discord.)
160+
Note that you will need to recompile the Nushell interpreter to test this change,
161+
see [Nushell CONTRIBUTING#Setup](https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md#setup).
162+
163+
More design guidelines:
164+
165+
1. Ensure your custom command provides useful help.
166+
This is done with comments before the `def` for the custom command.
167+
1. Use `error make` to report can't-proceed errors to user, not `log error`.
168+
2. Use `log info` to provide verbose progress messages that the user can optionally enable for troubleshooting.
169+
e.g:
170+
```shell
171+
NU_LOG_LEVEL=INFO foo # verbose messages from command foo
172+
```
173+
1. Use `assert` in unit tests to check for and report failures.
174+
175+
### Useful Commands
176+
177+
- Run all unit tests for the standard library:
178+
179+
```shell
180+
cargo run -- -c 'use std; NU_LOG_LEVEL=ERROR std run-tests'
181+
182+
```
183+
Note that this uses the debug version of NU interpreter from the same repo, which is the usual development scenario.
184+
Log level 'ERROR' shows only failures (meaning no output is the desired outcome).
185+
Log level 'INFO' shows progress by module and 'DEBUG' show each individual test.
186+
187+
- Run all tests for a specific test module, e.g, `crates/nu-std/tests/test_foo.nu`
188+
189+
```shell
190+
cargo run -- -c 'use std; NU_LOG_LEVEL=INFO std run-tests --module test_foo'
191+
```
192+
193+
- Run a custom command with additional logging (assuming you have instrumented
194+
the command with `log <level>`, as we recommend.)
195+
196+
```shell
197+
NU_LOG_LEVEL=INFO std foo bar bas # verbose
198+
NU_LOG_LEVEL=DEBUG std foo bar bas # very verbose
199+
```
200+
- Build and run Nushell (e.g, if you modify the prelude):
201+
202+
```shell
203+
cargo run
204+
```
205+
## Git commit and repo conventions
206+
The standard library project uses the same protocols and conventions
207+
for squashing git commits and handling github PRs as the core Nushell project.
208+
Please see [nushell CONTRIBUTING#git_etiquette](https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md#git-etiquette) for details.
209+
210+
[github_draft_pr]:(https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request)

crates/nu-std/README.md

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,48 @@
33
<img src="https://media.giphy.com/media/hvRJCLFzcasrR4ia7z/giphy.gif" width="28"></img>
44
</h1>
55

6-
The standard library is a pure-`nushell` collection of commands to allow anyone to build
7-
complex applications using standardized tools gathered incrementally.
6+
The standard library is a pure-`nushell` collection of custom commands which
7+
provide interactive utilities and building blocks for users writing casual scripts or complex applications.
88

9-
In this library, you might find `rust`-like `assert` commands to write tests, tools to
10-
manipulate paths and strings, etc, etc, ...
11-
12-
## :toolbox: use the standard library in the REPL or in scripts
13-
in order to "import" the standard library to either the interactive [*REPL*][REPL] of
14-
`nushell` or inside some `.nu` script, you might want to use the
15-
[`use`](https://nushell.sh/commands/docs/use.html) command!
16-
```bash
17-
use std
9+
To see what's here:
10+
```
11+
〉use std
12+
〉help commands | select name usage | where name =~ "std "
13+
╭────┬─────────────────────────────┬────────────────────────────────────────────────────────────────╮
14+
│ # │ name │ usage │
15+
│ 0 │ std assert │ Universal assert command │
16+
│ 1 │ std assert equal │ Assert $left == $right │
17+
. . .
18+
│ 11 │ std clip │ put the end of a pipe into the system clipboard. │
19+
│ 12 │ std dirs add │ Add one or more directories to the list. │
20+
. . .
21+
├────┼─────────────────────────────┼────────────────────────────────────────────────────────────────┤
22+
│ # │ name │ usage │
23+
╰────┴─────────────────────────────┴────────────────────────────────────────────────────────────────╯
1824
```
1925

20-
## :pencil2: contribute to the standard library
21-
- all the commands of the standard_library are located in [`std.nu`](std.nu)
22-
- the tests are located in files that have a name starting with "test_", e.g. [`test_std.nu`](test_std.nu)
23-
- a test runner, at [`tests.nu`](tests.nu), allows to run all the tests automatically
24-
25-
### :wrench: add new commands
26-
- add new standard commands by appending to [`std.nu`](std.nu)
27-
- add associated tests to [`test_std.nu`](tests_std.nu) or preferably to `test_<submodule>.nu`.
28-
- define a new exported (!) `test_<feature>` command
29-
- import the `assert` functions you need at the top of the functions, e.g. `use std.nu "assert eq"`
26+
## :toolbox: Using the standard library in the REPL or in scripts
27+
All commands in the standard library must be "imported" into the running environment
28+
(the interactive read-execute-print-loop (REPL) or a `.nu` script) using the
29+
[`use`](https://nushell.sh/commands/docs/use.html) command.
3030

31-
### :test_tube: run the tests
32-
the following call should return no errors
33-
```bash
34-
NU_LOG_LEVEL=DEBUG cargo run -- -c "use std; std run-tests --path crates/nu-std"
31+
You can choose to import the whole module, but then must refer to individual commands with a `std` prefix, e.g:
3532
```
33+
use std
34+
. . .
35+
std log debug "Running now"
36+
std assert (1 == 2)
37+
```
38+
Or you can enumerate the specific commands you want to import and invoke them without the `std` prefix.
39+
```
40+
use std ["log debug" assert]
41+
. . .
42+
log debug "Running again"
43+
assert (2 == 1)
44+
```
45+
This is probably the form of import you'll want to add to your `env.nu` for interactive use.
3646

37-
> **Warning**
38-
> the `cargo run --` part of this command is important to ensure the version of `nushell` and the version of the library are the same.
47+
## :pencil2: contribute to the standard library
48+
You're invited to contribute to the standard library!
49+
See [CONTRIBUTING.md]([./CONTRIBUTING.md](https://github.com/nushell/nushell/blob/main/crates/nu-std/CONTRIBUTING.md))
50+
for details

crates/nu-std/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ pub fn load_standard_library(
7979
("xml", include_str!("../lib/xml.nu")),
8080
];
8181

82+
// Define commands to be preloaded into the default (top level, unprefixed) namespace.
83+
// User can invoke these without having to `use std` beforehand.
84+
// Entries are: (name to add to default namespace, path under std to find implementation)
85+
//
86+
// Conventionally, for a command implemented as `std foo`, the name added
87+
// is either `std foo` or bare `foo`, not some arbitrary rename.
88+
8289
let prelude = vec![
8390
("std help", "help"),
8491
("std help commands", "help commands"),

0 commit comments

Comments
 (0)