Skip to the content.

How nushell evaluates user input

Disclaim: due to redirection overhaul pr, this article is out of date, please check new version instead.


I’m always curious if we type something like ^ls -alh, how does nushell parse my input and execute the command.

This blog will note how nushell evaluates user input.

High level insight

At high level, the data flow will be something like this:

                           lex parse            lite parse                parse
user input command(string) ----------> Tokens ------------->  LiteBlocks ------------> Blocks

In detail:

  1. Tokens are components of user input command, which mainly separate by space, or pipe, or something else
  2. Lite parsing converts a stream of tokens to a syntax element structure(LiteBlock) that can be parsed.
  3. parsing from LiteBlock to AST Block.

Here are some examples of how nushell parses user input commands:

Example 1: ^ls -alh out> here11

After analysing tokens, nushell knows that it’s going to be two commands, one is ls -alh, the other is redirection indicator out> here11.

It contains more information about our commands, our pipeline contains 2 elements:

  1. first one is nushell expression, and it contains external call with name “ls” and arguments “-alh”
  2. second one is redirection indicator, it tells us that we need to redirect stdout to file “here11”.

Example 2: ^ls -alh | save --raw a.txt

It still contains two commands, one is ^ls -alh, the other one is save --raw a.txt.

It contains two elements:

  1. first one is nushell expression, it contains external call with name “ls” and arguments “-alh”
  2. second one is another nushell expression, it contains internal command, the command have declaration id 202(which is “save” command in our case), and a named argument called “raw”, a positional argument with value “a.txt”

Reference source code:

  1. eval_source function, it’s the main entrypoint in repl.
  2. parse function, as we look into the function body, we can see there are two function calls lex and parse_block.
  3. parse_block function accepts lex tokens, and invoke lite_parse to parse from tokens to LiteBlock, then convert from LiteBlock to nushell Block.
  4. Finally nushell call eval_block to evaluate Block.