[go: up one dir, main page]

Module _concepts

Module _concepts 

Source
Available on crate feature unstable-doc only.
Expand description

§CLI Concepts

Note: this will be speaking towards the general case.

§Environmental context

When you run a command line application, it is inside a terminal emulator, or terminal. This handles integration with the rest of your system including user input, rendering, etc.

The terminal will run inside of itself an interactive shell. The shell is responsible for showing the prompt, receiving input including the command you are writing, letting that command take over until completion, and then repeating. This is called a read-eval-print loop, or REPL. Typically the shell will take the command you typed and split it into separate arguments, including handling of quoting, escaping, and globbing. The parsing and evaluation of the command is shell specific. The shell will then determine which application to run and then pass the full command-line as individual arguments to your program. These arguments are exposed in Rust as std::env::args_os.

Windows is an exception in Shell behavior in that the command is passed as an individual string, verbatim, and the application must split the arguments. std::env::args_os will handle the splitting for you but will not handle globs.

Takeaways:

  • Your application will only see quotes that have been escaped within the shell
    • e.g. to receive message="hello world", you may need to type 'message="hello world"' or message=\"hello world\"
  • If your applications needs to parse a string into arguments, you will need to pick a syntax and do it yourself
  • On Windows, you will need to handle globbing yourself if desired
    • wild can help with that

§Parsing

The first argument of std::env::args_os is the Command::bin_name which is usually limited to affecting Command::render_usage. Command::no_binary_name and Command::multicall exist for rare cases when this assumption is not valid.

Command-lines are a context-sensitive grammar, meaning the interpretation of an argument is based on the arguments that came before. Arguments come in one of several flavors:

  • Values
  • Flags
  • Subcommands

When examining the next argument,

  1. If it starts with a --, then that is a long Flag and all remaining text up to a = or the end is matched to a Arg::long, Command::long_flag, or alias.
    • Everything after the = is taken as a value and parsing a new argument is examined.
    • If no = is present, then Values will be taken according to Arg::num_args
    • We generally call a flag that takes a value an “option”
  2. If it starts with a -, then that is a sequence of short Flags where each character is matched against a Arg::short, Command::short_flag or alias until =, the end, or a short Flag takes values (see Arg::num_args)
  3. If its a --, that is an escape and all future arguments are considered to be a Value, even if they start with -- or -
  4. If it matches a Command::name, then the argument is a subcommand
  5. If there is an Arg at the next Arg::index, then the argument is considered a Positional argument

When a subcommand matches, all further arguments are parsed by that Command.

There are many settings that tweak this behavior, including:

Takeaways