mirror of
https://github.com/nushell/nushell.git
synced 2024-11-23 00:43:33 +01:00
parent
188a352c6f
commit
487fafbca3
@ -13,6 +13,7 @@ mod nu_plugin;
|
||||
mod nu_signature;
|
||||
mod source;
|
||||
mod tags;
|
||||
mod tutor;
|
||||
mod unalias;
|
||||
mod version;
|
||||
|
||||
@ -33,5 +34,6 @@ pub use ignore::Ignore;
|
||||
pub use let_::Let;
|
||||
pub use source::Source;
|
||||
pub use tags::Tags;
|
||||
pub use tutor::Tutor;
|
||||
pub use unalias::Unalias;
|
||||
pub use version::{version, Version};
|
||||
|
407
crates/nu-command/src/commands/core_commands/tutor.rs
Normal file
407
crates/nu-command/src/commands/core_commands/tutor.rs
Normal file
@ -0,0 +1,407 @@
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Signature, SyntaxShape, UntaggedValue};
|
||||
|
||||
pub struct Tutor;
|
||||
|
||||
impl WholeStreamCommand for Tutor {
|
||||
fn name(&self) -> &str {
|
||||
"tutor"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("tutor")
|
||||
.optional(
|
||||
"search",
|
||||
SyntaxShape::String,
|
||||
"item to search for, or 'list' to list available tutorials",
|
||||
)
|
||||
.named(
|
||||
"find",
|
||||
SyntaxShape::String,
|
||||
"Search tutorial for a phrase",
|
||||
Some('f'),
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Run the tutorial. To begin, run: tutor"
|
||||
}
|
||||
|
||||
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
tutor(args)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Begin the tutorial",
|
||||
example: "tutor begin",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Search a tutorial by phrase",
|
||||
example: "tutor -f \"$in\"",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn tutor(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.name_tag();
|
||||
let scope = args.scope().clone();
|
||||
|
||||
let search: Option<String> = args.opt(0).unwrap_or(None);
|
||||
let find: Option<String> = args.get_flag("find")?;
|
||||
|
||||
let search_space = vec![
|
||||
(vec!["begin"], begin_tutor()),
|
||||
(
|
||||
vec!["table", "tables", "row", "rows", "column", "columns"],
|
||||
table_tutor(),
|
||||
),
|
||||
(vec!["cell", "cells"], cell_tutor()),
|
||||
(
|
||||
vec![
|
||||
"expr",
|
||||
"exprs",
|
||||
"expressions",
|
||||
"subexpression",
|
||||
"subexpressions",
|
||||
"sub-expression",
|
||||
"sub-expressions",
|
||||
],
|
||||
expression_tutor(),
|
||||
),
|
||||
(vec!["echo"], echo_tutor()),
|
||||
(vec!["each", "iteration", "iter"], each_tutor()),
|
||||
(
|
||||
vec!["var", "vars", "variable", "variables"],
|
||||
variable_tutor(),
|
||||
),
|
||||
(vec!["block", "blocks"], block_tutor()),
|
||||
(vec!["shorthand", "shorthands"], shorthand_tutor()),
|
||||
];
|
||||
|
||||
if let Some(find) = find {
|
||||
let mut results = vec![];
|
||||
for search_group in search_space {
|
||||
if search_group.1.contains(&find.as_str()) {
|
||||
results.push(search_group.0[0].to_string())
|
||||
}
|
||||
}
|
||||
|
||||
let message = format!("You can find '{}' in the following topics:\n{}\n\nYou can learn about a topic using `tutor` followed by the name of the topic.\nFor example: `tutor table` to open the table topic.\n\n",
|
||||
find,
|
||||
results.into_iter().map(|x| format!("- {}", x)).join("\n")
|
||||
);
|
||||
|
||||
return Ok(display(tag, &scope, &message));
|
||||
} else if let Some(search) = search {
|
||||
for search_group in search_space {
|
||||
if search_group.0.contains(&search.as_str()) {
|
||||
return Ok(display(tag, &scope, search_group.1));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(display(tag, &scope, default_tutor()))
|
||||
}
|
||||
|
||||
fn default_tutor() -> &'static str {
|
||||
r#"
|
||||
Welcome to the Nushell tutorial!
|
||||
|
||||
With the `tutor` command, you'll be able to learn a lot about how Nushell
|
||||
works along with many fun tips and tricks to speed up everyday tasks.
|
||||
|
||||
To get started, you can use `tutor begin`.
|
||||
|
||||
"#
|
||||
}
|
||||
|
||||
fn begin_tutor() -> &'static str {
|
||||
r#"
|
||||
Nushell is a structured shell and programming language. One way to begin
|
||||
using it is to try a few of the commands.
|
||||
|
||||
The first command to try is `ls`. The `ls` command will show you a list
|
||||
of the files in the current directory. Notice that these files are shown
|
||||
as a table. Each column of this table not only tells us what is being
|
||||
shown, but also gives us a way to work with the data.
|
||||
|
||||
You can combine the `ls` command with other commands using the pipeline
|
||||
symbol '|'. This allows data to flow from one command to the next.
|
||||
|
||||
For example, if we only wanted the name column, we could do:
|
||||
```
|
||||
ls | select name
|
||||
```
|
||||
Notice that we still get a table, but this time it only has one column:
|
||||
the name column.
|
||||
|
||||
You can continue to learn more about tables by running:
|
||||
```
|
||||
tutor tables
|
||||
```
|
||||
If at any point, you'd like to restart this tutorial, you can run:
|
||||
```
|
||||
tutor begin
|
||||
```
|
||||
"#
|
||||
}
|
||||
|
||||
fn table_tutor() -> &'static str {
|
||||
r#"
|
||||
The most common form of data in Nushell is the table. Tables contain rows and
|
||||
columns of data. In each cell of the table, there is data that you can access
|
||||
using Nushell commands.
|
||||
|
||||
To get the 3rd row in the table, you can use the `nth` command:
|
||||
```
|
||||
ls | nth 2
|
||||
```
|
||||
This will get the 3rd (note that `nth` is zero-based) row in the table created
|
||||
by the `ls` command. You can use `nth` on any table created by other commands
|
||||
as well.
|
||||
|
||||
You can also access the column of data in one of two ways. If you want to want
|
||||
to keep the column as part of a new table, you can use `select`.
|
||||
```
|
||||
ls | select name
|
||||
```
|
||||
This runs `ls` and returns only the "name" column of the table.
|
||||
|
||||
If, instead, you'd like to get access to the values inside of the column, you
|
||||
can use the `get` command.
|
||||
```
|
||||
ls | get name
|
||||
```
|
||||
This allows us to get to the list of strings that are the filenames rather
|
||||
than having a full table. In some cases, this can make the names easier to
|
||||
work with.
|
||||
|
||||
You can continue to learn more about working with cells of the table by
|
||||
running:
|
||||
```
|
||||
tutor cells
|
||||
```
|
||||
"#
|
||||
}
|
||||
|
||||
fn cell_tutor() -> &'static str {
|
||||
r#"
|
||||
Working with cells of data in the table is a key part of working with data in
|
||||
Nushell. Because of this, there is a rich list of commands to work with cells
|
||||
as well as handy shorthands for accessing cells.
|
||||
|
||||
Cells can hold simple values like strings and numbers, or more complex values
|
||||
like lists and tables.
|
||||
|
||||
To reach a cell of data from a table, you can combine a row operation and a
|
||||
column operation.
|
||||
```
|
||||
ls | nth 4 | get name
|
||||
```
|
||||
You can combine these operations into one step using a shortcut.
|
||||
```
|
||||
(ls).4.name
|
||||
```
|
||||
Names/strings represent columns names and numbers represent row numbers.
|
||||
|
||||
The `(ls)` is a form of expression. You can continue to learn more about
|
||||
expressions by running:
|
||||
```
|
||||
tutor expressions
|
||||
```
|
||||
You can also learn about these cell shorthands by running:
|
||||
```
|
||||
tutor shorthands
|
||||
```
|
||||
"#
|
||||
}
|
||||
|
||||
fn expression_tutor() -> &'static str {
|
||||
r#"
|
||||
Expressions give you the power to mix calls to commands with math. The
|
||||
simplest expression is a single value like a string or number.
|
||||
```
|
||||
3
|
||||
```
|
||||
Expressions can also include math operations like addition or division.
|
||||
```
|
||||
10 / 2
|
||||
```
|
||||
Normally, an expression is one type of operation: math or commands. You can
|
||||
mix these types by using subexpressions. Subexpressions are just like
|
||||
expressions, but they're wrapped in parentheses `()`.
|
||||
```
|
||||
10 * (3 + 4)
|
||||
```
|
||||
Here we use parentheses to create a higher math precedence in the math
|
||||
expression.
|
||||
```
|
||||
echo (2 + 3)
|
||||
```
|
||||
You can continue to learn more about the `echo` command by running:
|
||||
```
|
||||
tutor echo
|
||||
```
|
||||
"#
|
||||
}
|
||||
|
||||
fn echo_tutor() -> &'static str {
|
||||
r#"
|
||||
The `echo` command in Nushell is a powerful tool for not only seeing values,
|
||||
but also for creating new ones.
|
||||
```
|
||||
echo "Hello"
|
||||
```
|
||||
You can echo output. This output, if it's not redirected using a "|" pipeline
|
||||
will be displayed to the screen.
|
||||
```
|
||||
echo 1..10
|
||||
```
|
||||
You can also use echo to work with individual values of a range. In this
|
||||
example, `echo` will create the values from 1 to 10 as a list.
|
||||
```
|
||||
echo 1 2 3 4 5
|
||||
```
|
||||
You can also create lists of values by passing `echo` multiple arguments.
|
||||
This can be helpful if you want to later processes these values.
|
||||
|
||||
The `echo` command can pair well with the `each` command which can run
|
||||
code on each row, or item, of input.
|
||||
|
||||
You can continue to learn more about the `echo` command by running:
|
||||
```
|
||||
tutor each
|
||||
```
|
||||
"#
|
||||
}
|
||||
|
||||
fn each_tutor() -> &'static str {
|
||||
r#"
|
||||
The `each` command gives us a way of working with each individual row or
|
||||
element of a list one at a time. It reads these in from the pipeline and
|
||||
runs a block on each element. A block is a group of pipelines.
|
||||
```
|
||||
echo 1 2 3 | each { $it + 10}
|
||||
```
|
||||
This example iterates over each element sent by `echo`, giving us three new
|
||||
values that are the original value + 10. Here, the `$it` is a variable that
|
||||
is the name given to the block's parameter by default.
|
||||
|
||||
You can learn more about blocks by running:
|
||||
```
|
||||
tutor blocks
|
||||
```
|
||||
You can also learn more about variables by running:
|
||||
```
|
||||
tutor variables
|
||||
```
|
||||
"#
|
||||
}
|
||||
|
||||
fn variable_tutor() -> &'static str {
|
||||
r#"
|
||||
Variables are an important way to store values to be used later. To create a
|
||||
variable, you can use the `let` keyword. The `let` command will create a
|
||||
variable and then assign it a value in one step.
|
||||
```
|
||||
let $x = 3
|
||||
```
|
||||
Once created, we can refer to this variable by name.
|
||||
```
|
||||
$x
|
||||
```
|
||||
Nushell also comes with built-in variables. The `$nu` variable is a reserved
|
||||
variable that contains a lot of information about the currently running
|
||||
instance of Nushell. The `$it` variable is the name given to block parameters
|
||||
if you don't specify one. And `$in` is the variable that allows you to work
|
||||
with all of the data coming in from the pipeline in one place.
|
||||
|
||||
"#
|
||||
}
|
||||
|
||||
fn block_tutor() -> &'static str {
|
||||
r#"
|
||||
Blocks are a special form of expression that hold code to be run at a later
|
||||
time. Often, you'll see blocks as one of the arguments given to commands
|
||||
like `each` and `if`.
|
||||
```
|
||||
ls | each {|x| $x.name}
|
||||
```
|
||||
The above will create a list of the filenames in the directory.
|
||||
```
|
||||
if $true { echo "it's true" } { echo "it's not true" }
|
||||
```
|
||||
This `if` call will run the first block if the expression is true, or the
|
||||
second block if the expression is false.
|
||||
|
||||
"#
|
||||
}
|
||||
|
||||
fn shorthand_tutor() -> &'static str {
|
||||
r#"
|
||||
You can access cells in a table using a shorthand notation sometimes called a
|
||||
"column path" or "cell path". These paths allow you to go from a table to
|
||||
rows, columns, or cells inside of the table.
|
||||
|
||||
Shorthand paths are made from rows numbers, column names, or both. You can use
|
||||
them on any variable or subexpression.
|
||||
```
|
||||
$nu.cwd
|
||||
```
|
||||
The above accesses the built-in `$nu` variable, gets its table, and then uses
|
||||
the shorthand path to retrieve only the cell data inside the "cwd" column.
|
||||
```
|
||||
(ls).name.4
|
||||
```
|
||||
This will retrieve the cell data in the "name" column on the 5th row (note:
|
||||
row numbers are zero-based).
|
||||
|
||||
Rows and columns don't need to come in any specific order. You can get the
|
||||
same value using:
|
||||
```
|
||||
(ls).4.name
|
||||
```
|
||||
"#
|
||||
}
|
||||
|
||||
fn display(tag: Tag, scope: &Scope, help: &str) -> OutputStream {
|
||||
let help = help.split('`');
|
||||
|
||||
let mut build = String::new();
|
||||
let mut code_mode = false;
|
||||
let palette = nu_engine::DefaultPalette {};
|
||||
|
||||
for item in help {
|
||||
if code_mode {
|
||||
code_mode = false;
|
||||
|
||||
//TODO: support no-color mode
|
||||
let colored_example = nu_engine::Painter::paint_string(item, scope, &palette);
|
||||
build.push_str(&format!("{}", colored_example));
|
||||
} else {
|
||||
code_mode = true;
|
||||
build.push_str(item);
|
||||
}
|
||||
}
|
||||
|
||||
OutputStream::one(UntaggedValue::string(build).into_value(tag))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ShellError;
|
||||
use super::Tutor;
|
||||
|
||||
#[test]
|
||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
use crate::examples::test as test_examples;
|
||||
|
||||
test_examples(Tutor {})
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||
whole_stream_command(Alias),
|
||||
whole_stream_command(Unalias),
|
||||
whole_stream_command(Ignore),
|
||||
whole_stream_command(Tutor),
|
||||
// System/file operations
|
||||
whole_stream_command(Exec),
|
||||
whole_stream_command(Pwd),
|
||||
|
Loading…
Reference in New Issue
Block a user