refactor the CONTRIBUTING.md guidelines for nu-std (#8912)

## Description
just a little refactor of `CONTRIBUTING.md` of the standard library in
`nu-std`.
- see the new version
[here](https://github.com/amtoine/nushell/blob/stblib/refactor/CONTRIBUTING-guidelines/crates/nu-std/CONTRIBUTING.md).

> **Note**
> actually, that one might be best reviewed commit by commit 😋 
> i tried to be as explicit as possible 😌 

- i fixed the width to `80` columns
- cc/ @bobhy, if you want to jump in and find broken links / bad changes
This commit is contained in:
Antoine Stevan 2023-04-19 22:21:27 +02:00 committed by GitHub
parent ed64a44b82
commit d42c2b2dbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 189 additions and 150 deletions

View File

@ -1,108 +1,132 @@
# Contributing # Contributing
Welcome to the Nushell standard library and thank you for considering contributing! Welcome to the Nushell standard library and thank you for considering
contributing!
## Ideas for the standard library ## Ideas for the standard library
If you've got a great idea, or just want to contribute to open source by
If you've got a great idea, or just want to contribute to open source working on the Nushell standard library, we invite you to talk to the team
by working on the Nushell standard library, before you start coding. You'll find we're friendly, passionate about Nushell
we invite you to talk to the team before you start coding. and always open to new ideas!
You'll find we're friendly, passionate about Nushell and always open to new ideas!
You'll generally find the team members on You'll generally find the team members on
[Discord standard-library channel](https://discord.com/channels/601130461678272522/1075541668922658868), [Discord `#standard-library` channel][discord#standard-library] and can have
and can have preliminary discussions there to clarify the issues involved. preliminary discussions there to clarify the issues involved.
You can open a [Github issue](https://github.com/nushell/nushell/issues/new/choose) You can open a [Github issue][new-issue] to have a more focused discussion of
to have a more focused discussion of your idea. your idea.
Generally, we think the standard library should contain items that are Generally, we think the standard library should contain items that are relevant
relevant to most/all Nushell users regardless of the application space they're working in. to most/all Nushell users regardless of the application space they're working
If your idea isn't quite so broadly applicable, in. If your idea isn't quite so broadly applicable, consider publishing it in
consider publishing it in [nu_scripts](https://github.com/nushell/nu_scripts). [`nu_scripts`].
Preliminary discussions should focus on the *user benefit* your idea would provide. Preliminary discussions should focus on the *user benefit* your idea would
How many users will be affected by your idea, how much would it help them solve a problem or work more productively? provide.
Given consensus on the user benefit, the team will be motivated to
help you create, deploy and maintain a solution long term. How many users will be affected by your idea, how much would it help them solve
a problem or work more productively? Given consensus on the user benefit, the
team will be motivated to help you create, deploy and maintain a solution long
term.
## Lifecycle of a change ## Lifecycle of a change
1. Verify the team thinks your idea is potentially relevant and useful, as
1. Verify the team thinks your idea is potentially relevant and useful, as above. above.
1. If it's more than a simple bug fix, open a placeholder PR 1. If it's more than a simple bug fix, open a placeholder PR as soon as you get
as soon as you get started and [set it to draft status][github_draft_pr]. started and [set it to draft status][github_draft_pr].
This will alert other contributors that you're working in this area and let you This will alert other contributors that you're working in this area and let
advertise roughly what scope of changes you're thinking of. you advertise roughly what scope of changes you're thinking of. See
See [below](#the_pr) for details. [below](#the-pr) for details.
1. Get things working in your local development environment. 1. Get things working in your local development environment.
If you have questions along the way, you can post a question in your PR If you have questions along the way, you can post a question in your PR or
or have a more casual discussion with Nushell fans on have a more casual discussion with Nushell fans on
[Discord implementation-chat channel](https://discord.com/channels/601130461678272522/615962413203718156) [Discord `#implementation-chat` channel][discord#implementation-chat].
1. When you get to an appropriate state of doneness, push your changes to the PR and remove the draft status. 1. When you get to an appropriate state of doneness, push your changes to the
2. Team members and other contributors will then review your PR. PR and remove the draft status.
Respond to any review comments they raise and address them one way or another. 1. Team members and other contributors will then review your PR.
(Not all comments demand you make a change!) Respond to any review comments they raise and address them one way or
1. When you and the team are comfortable with the PR, another. (Not all comments demand you make a change!)
a team member will merge it into the repo and you can delete your working branch. 1. When you and the team are comfortable with the PR, a team member will merge
2. If you've added a whole new command or made a breaking change, it into the repo and you can delete your working branch.
(strongly) consider writing it up for the release notes. 1. If you've added a whole new command or made a breaking change,
Currently, release notes are maintained in a different repo, [nushell.github.io](https://github.com/nushell/nushell.github.io). (strongly) consider writing it up for the release notes.
Make your change in a local clone of that repo and submit a PR to the release notes repo to get it integrated. Currently, release notes are maintained in a different repo,
[`nushell.github.io`]. Make your change in a local clone of that repo and
submit a PR to the release notes repo to get it integrated.
## Developing ## Developing
(All paths below shown relative to the root folder of the git repository containing the standard library.) (All paths below shown relative to the root folder of the git repository
containing the standard library.)
### Setup ### Setup
0. Install the Rust toolchain and Nushell build tools.
0. Install the Rust toolchain and Nushell build tools. See [nushell CONTRIBUTING](https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md) for details. See [`nushell`'s `CONTRIBUTING.md`][`CONTRIBUTING.md`] for details. The
The standard library is tightly coupled to a particular version of Nushell interpreter, standard library is tightly coupled to a particular version of Nushell
you need to be running that version to test your changes interpreter, you need to be running that version to test your changes (unlike
(unlike a "normal" script module library). a "normal" script module library).
1. Clone the Nushell repo containing the standard library and create a feature
1. Clone the Nushell repo containing the standard library and create a feature branch for your development work. branch for your development work.
Currently, that's the [Nushell interpreter source repo](https://github.com/nushell/nushell). Currently, that's the [Nushell interpreter source repo][`nushell`].
Once you set your working directory to the root of this repository, you'll generally leave it there throughout the session. Once you set your working directory to the root of this repository, you'll
``` generally leave it there throughout the session.
```shell
git clone https://github.com/nushell/nushell git clone https://github.com/nushell/nushell
cd nushell cd nushell
git checkout -b <featureBranch> git checkout -b <featureBranch>
``` ```
1. In your IDE, open the folder within the repository containing the standard library. 1. In your IDE, open the folder within the repository containing the standard
The folder is currently `./crates/nu-std`, and it is a Rust crate, containing a `Cargo.toml` library. The folder is currently `./crates/nu-std`, and it is a Rust crate,
and subfolders: containing a `Cargo.toml` and subfolders:
* `src/` (which contains the Rust code to load the standard library modules into memory for efficiency), * `src/` (which contains the Rust code to load the standard library modules
* `lib` (which contains all the script module sources for the standard library), into memory for efficiency),
* `tests/` (unit tests for lib). * `lib` (which contains all the script module sources for the standard
library),
* `tests/` (unit tests for lib).
### The PR ### The PR
Assuming you've already validated the need with other Nushell contributors, you're focusing on design and implementation Assuming you've already validated the need with other Nushell contributors,
at this point. Share your thinking all along the way! you're focusing on design and implementation at this point. Share your thinking
all along the way!
You can open a [draft][github_draft_pr] pull request based on a small, placeholder code change You can open a [draft][github_draft_pr] pull request based on a small,
and use the PR comments to outline your design and user interface. You'll get feedback from placeholder code change and use the PR comments to outline your design and user
other contributors that may lead to a more robust and perhaps more idomatic solution. interface. You'll get feedback from other contributors that may lead to a more
The threads in the PR can be a convenient reference for you when writing release notes and robust and perhaps more idomatic solution. The threads in the PR can be a
for others on the team when researching issues. convenient reference for you when writing release notes and for others on the
team when researching issues.
> **Note**
> the PR will not get final code review or be merged until you remove the draft
> status.
Note that the PR will not get final code review or be merged until you remove the draft status.
### Design considerations ### Design considerations
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 The standard library consists of Nushell custom commands and their associated
[Modules chapter of the Nushell book](https://www.nushell.sh/book/modules.html). environment variables, packaged in script modules underneath module `std`. For
background on scripts, custom commands and modules, see the
[Modules chapter of the Nushell book][book@modules].
To add a completely new module, for example, a `foo` command and some `foo subcommand`s, To add a completely new module, for example, a `foo` command and some
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: `foo subcommand`s, 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:
1. Source for a custom command `foo` should go in `./crates/nu-std/lib/foo.nu`. 1. Source for a custom command `foo` should go in `./crates/nu-std/lib/foo.nu`.
* A source file will typically implement multiple subcommands and possibly
* A source file will typically implement multiple subcommands and possibly a main command as well. a main command as well.
Use `export def` to make these names public to your users. Use `export def` to make these names public to your users.
* If your command is updating environment variables, you must use `export def-env` (instead of `export def`) * If your command is updating environment variables, you must use
to define the subcommand, `export-env {}` to initialize the environment variables and `let-env` to update them. `export def-env` (instead of `export def`) to define the subcommand,
For an example of a custom command which modifies environment variables, `export-env {}` to initialize the environment variables and `let-env` to
see: `./crates/nu-std/lib/dirs.nu`. update them. For an example of a custom command which modifies
For an example of a custom command which does *not* modify environment variables, see: `./crates/nu-std/lib/assert.nu`. environment variables, see: `./crates/nu-std/lib/dirs.nu`.
* If your standard library module wishes to use a utility from another module of the standard library, For an example of a custom command which does *not* modify environment
for example `log info`, variables, see: `./crates/nu-std/lib/assert.nu`.
you need to import it directly from its module in the `use` statement. * If your standard library module wishes to use a utility from another
```shell module of the standard library, for example `log info`, you need to
import it directly from its module in the `use` statement.
```nushell
... your foo.nu ... ... your foo.nu ...
export def mycommand [] { export def mycommand [] {
use log "log info" use log "log info"
@ -111,13 +135,17 @@ you will be dealing with 2 new source files: the module source itself (`./crate
. . . . . .
} }
``` ```
This is `use log "log info"` rather than `use std "log info"` (which is the usual way commands are imported This is `use log "log info"` rather than `use std "log info"` (which is
from the standard library) because your `foo` module is also a child module under `std`. the usual way commands are imported from the standard library) because
your `foo` module is also a child module under `std`.
1. Unit tests for `foo` should go in `./crates/nu-std/tests/test_foo.nu`. Thou shalt provide unit tests to cover your changes. 1. Unit tests for `foo` should go in `./crates/nu-std/tests/test_foo.nu`. Thou
* Unit tests should use one of the `assert` commands to check a condition and report the failure in a standard format. shalt provide unit tests to cover your changes.
* 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: * Unit tests should use one of the `assert` commands to check a condition
```shell and report the failure in a standard format.
* 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:
```nushell
... your test_foo.nu ... ... your test_foo.nu ...
def test1 [] { def test1 [] {
use std use std
@ -131,80 +159,90 @@ you will be dealing with 2 new source files: the module source itself (`./crate
use std ['assert greater' assert] use std ['assert greater' assert]
. . . . . .
assert greater $l $r assert greater $l $r
. . . . . .
assert $predicate assert $predicate
} }
``` ```
The choice of import style is up to you. The choice of import style is up to you.
1. A `foo` command will be exposed to the user as `std foo` (at a minimum).
To enable this, update file `./crates/nu-std/lib/mod.nu` and add this code:
```nushell
export use foo * # command doesn't update environment
export-env {
use bar * # command *does* update environment
}
```
The `use *` hoists the public definitions in `foo.nu` into `mod.nu` and
thus into the `std` namespace.
1. Some commands from the standard library are also preloaded, so user can
invoke them without explicit import via `use std ...`.
A command implemented as `std foo`, can be preloaded as a bare `foo`:
* modify `./crates/nu-std/src/lib.rs`,
* find the initialization of the "prelude" at line 90 or thereabouts
* add `("foo", "foo")`
* or, to be preloaded as `std foo`, add `("std foo", "foo")`.
(This code may be restructured soon: if you can't find it, check with the
2. A `foo` command will be exposed to the user as `std foo` (at a minimum). team on Discord.)
To enable this, update file `./crates/nu-std/lib/mod.nu` and add this code: > **Note**
``` > that you will need to recompile the Nushell interpreter to test this
export use foo * # command doesn't update environment > change, see the ["setup" section][`CONTRIBUTING.md`#setup] of Nushell's
export-env { > `CONTRIBUTING.md`.
use bar * # command *does* update environment
}
```
The `use *` hoists the public definitions in `foo.nu` into `mod.nu` and thus into the `std` namespace.
1. Some commands from the standard library are also preloaded, so user can invoke them without explicit
import via `use std ...`.
A command implemented as `std foo`, can be preloaded as a bare `foo`:
* modify `./crates/nu-std/src/lib.rs`,
* find the initialization of the "prelude" at line 90 or thereabouts
* add `("foo", "foo")`
* or, to be preloaded as `std foo`, add `("std foo", "foo")`.
(This code may be restructured soon: if you can't find it, check with the team on Discord.)
Note that you will need to recompile the Nushell interpreter to test this change,
see [Nushell CONTRIBUTING#Setup](https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md#setup).
More design guidelines: More design guidelines:
1. Ensure your custom command provides useful help. 1. Ensure your custom command provides useful help.
This is done with comments before the `def` for the custom command. This is done with comments before the `def` for the custom command.
1. Use `error make` to report can't-proceed errors to user, not `log error`. 1. Use `error make` to report can't-proceed errors to user, not `log error`.
2. Use `log info` to provide verbose progress messages that the user can optionally enable for troubleshooting. 1. Use `log info` to provide verbose progress messages that the user can
e.g: optionally enable for troubleshooting. e.g:
```shell ```nushell
NU_LOG_LEVEL=INFO foo # verbose messages from command foo NU_LOG_LEVEL=INFO foo # verbose messages from command foo
``` ```
1. Use `assert` in unit tests to check for and report failures. 1. Use `assert` in unit tests to check for and report failures.
### Useful Commands ### Useful Commands
- Run all unit tests for the standard library:
- Run all unit tests for the standard library: ```nushell
```shell
cargo run -- -c 'use std; NU_LOG_LEVEL=ERROR std run-tests' cargo run -- -c 'use std; NU_LOG_LEVEL=ERROR std run-tests'
``` ```
Note that this uses the debug version of NU interpreter from the same repo, which is the usual development scenario. > **Note**
Log level 'ERROR' shows only failures (meaning no output is the desired outcome). > this uses the debug version of NU interpreter from the same repo, which is
Log level 'INFO' shows progress by module and 'DEBUG' show each individual test. > the usual development scenario.
> Log level 'ERROR' shows only failures (meaning no output is the desired
- Run all tests for a specific test module, e.g, `crates/nu-std/tests/test_foo.nu` > outcome).
> Log level 'INFO' shows progress by module and 'DEBUG' show each individual
```shell > test.
- Run all tests for a specific test module, e.g,
`crates/nu-std/tests/test_foo.nu`
```nushell
cargo run -- -c 'use std; NU_LOG_LEVEL=INFO std run-tests --module test_foo' cargo run -- -c 'use std; NU_LOG_LEVEL=INFO std run-tests --module test_foo'
``` ```
- Run a custom command with additional logging (assuming you have instrumented - Run a custom command with additional logging (assuming you have instrumented
the command with `log <level>`, as we recommend.) the command with `log <level>`, as we recommend.)
```nushell
```shell
NU_LOG_LEVEL=INFO std foo bar bas # verbose NU_LOG_LEVEL=INFO std foo bar bas # verbose
NU_LOG_LEVEL=DEBUG std foo bar bas # very verbose NU_LOG_LEVEL=DEBUG std foo bar bas # very verbose
``` ```
- Build and run Nushell (e.g, if you modify the prelude): - Build and run Nushell (e.g, if you modify the prelude):
```nushell
```shell
cargo run cargo run
``` ```
## Git commit and repo conventions
The standard library project uses the same protocols and conventions
for squashing git commits and handling github PRs as the core Nushell project.
Please see [nushell CONTRIBUTING#git_etiquette](https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md#git-etiquette) for details.
[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) ## Git commit and repo conventions
The standard library project uses the same protocols and conventions
for squashing git commits and handling github PRs as the core Nushell project.
Please see the ["Git etiquette" section][`CONTRIBUTING.md`#git-etiquette] of
Nushell's `CONTRIBUTING.md` for details.
[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
[discord#standard-library]: https://discord.com/channels/601130461678272522/1075541668922658868
[discord#implementation-chat]: https://discord.com/channels/601130461678272522/615962413203718156
[new-issue]: https://github.com/nushell/nushell/issues/new/choose
[`nushell`]: https://github.com/nushell/nushell
[`nu_scripts`]: https://github.com/nushell/nu_scripts
[`nushell.github.io`]: https://github.com/nushell/nushell.github.io
[`CONTRIBUTING.md`]: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md
[`CONTRIBUTING.md`#setup]: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md#setup
[`CONTRIBUTING.md`#git-etiquette]: https://github.com/nushell/nushell/blob/main/CONTRIBUTING.md#git-etiquette
[book@modules]: https://www.nushell.sh/book/modules.html

View File

@ -3,15 +3,16 @@
<img src="https://media.giphy.com/media/hvRJCLFzcasrR4ia7z/giphy.gif" width="28"></img> <img src="https://media.giphy.com/media/hvRJCLFzcasrR4ia7z/giphy.gif" width="28"></img>
</h1> </h1>
The standard library is a pure-`nushell` collection of custom commands which The standard library is a pure-`nushell` collection of custom commands which
provide interactive utilities and building blocks for users writing casual scripts or complex applications. provide interactive utilities and building blocks for users writing casual scripts or complex applications.
To see what's here: To see what's here:
``` ```
use std > use std
help commands | select name usage | where name =~ "std " > help commands | select name usage | where name =~ "std "
╭────┬─────────────────────────────┬────────────────────────────────────────────────────────────────╮ ╭────┬─────────────────────────────┬────────────────────────────────────────────────────────────────╮
│ # │ name │ usage │ │ # │ name │ usage │
├────┼─────────────────────────────┼────────────────────────────────────────────────────────────────┤
│ 0 │ std assert │ Universal assert command │ │ 0 │ std assert │ Universal assert command │
│ 1 │ std assert equal │ Assert $left == $right │ │ 1 │ std assert equal │ Assert $left == $right │
. . . . . .
@ -24,27 +25,27 @@ To see what's here:
``` ```
## :toolbox: Using the standard library in the REPL or in scripts ## :toolbox: Using the standard library in the REPL or in scripts
All commands in the standard library must be "imported" into the running environment All commands in the standard library must be "imported" into the running environment
(the interactive read-execute-print-loop (REPL) or a `.nu` script) using the (the interactive read-execute-print-loop (REPL) or a `.nu` script) using the
[`use`](https://nushell.sh/commands/docs/use.html) command. [`use`](https://nushell.sh/commands/docs/use.html) command.
You can choose to import the whole module, but then must refer to individual commands with a `std` prefix, e.g: You can choose to import the whole module, but then must refer to individual commands with a `std` prefix, e.g:
``` ```nushell
use std use std
. . .
std log debug "Running now" std log debug "Running now"
std assert (1 == 2) std assert (1 == 2)
``` ```
Or you can enumerate the specific commands you want to import and invoke them without the `std` prefix. Or you can enumerate the specific commands you want to import and invoke them without the `std` prefix.
``` ```nushell
use std ["log debug" assert] use std ["log debug" assert]
. . .
log debug "Running again" log debug "Running again"
assert (2 == 1) assert (2 == 1)
``` ```
This is probably the form of import you'll want to add to your `env.nu` for interactive use. This is probably the form of import you'll want to add to your `env.nu` for interactive use.
## :pencil2: contribute to the standard library ## :pencil2: contribute to the standard library
You're invited to contribute to the standard library! You're invited to contribute to the standard library! See [CONTRIBUTING.md] for details
See [CONTRIBUTING.md]([./CONTRIBUTING.md](https://github.com/nushell/nushell/blob/main/crates/nu-std/CONTRIBUTING.md))
for details [CONTRIBUTING.md]: https://github.com/nushell/nushell/blob/main/crates/nu-std/CONTRIBUTING.md