Skip to content

Commit

Permalink
Implemented help commands and added notice thereof to help output
Browse files Browse the repository at this point in the history
  • Loading branch information
rben01 committed Sep 28, 2024
1 parent b2410ca commit f0e965e
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 9 deletions.
4 changes: 2 additions & 2 deletions numbat-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ impl Cli {

match parser.parse_command() {
Ok(command) => match command {
command::Command::Help => {
let help = help_markup();
command::Command::Help { help_kind } => {
let help = help_markup(help_kind);
print!("{}", ansi_format(&help, true));
// currently, the ansi formatter adds indents
// _after_ each newline and so we need to manually
Expand Down
87 changes: 81 additions & 6 deletions numbat/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ pub enum ListItems {
Units,
}

enum QuitAlias {
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum QuitAlias {
Quit,
Exit,
}

enum CommandKind {
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CommandKind {
Help,
Info,
List,
Expand All @@ -46,9 +49,15 @@ impl FromStr for CommandKind {
}
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum HelpKind {
BasicHelp,
AllCommands,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Command<'a> {
Help,
Help { help_kind: HelpKind },
Info { item: &'a str },
List { items: Option<ListItems> },
Clear,
Expand Down Expand Up @@ -194,8 +203,24 @@ impl<'a> CommandParser<'a> {
pub fn parse_command(&mut self) -> Result<Command, ParseError> {
let command = match &self.inner.command_kind {
CommandKind::Help => {
self.ensure_zero_args("help", "; use `info <item>` for information about an item")?;
Command::Help
let help_kind = self.inner.args.next();

if self.inner.args.next().is_some() {
return Err(self.err_through_end_from(2, "`help` takes at most one argument"));
}

let help_kind = match help_kind {
None => HelpKind::BasicHelp,
Some("commands") => HelpKind::AllCommands,
_ => {
return Err(self.err_at_idx(
1,
"if provided, the argument to `help` must be \"commands\"",
))
}
};

Command::Help { help_kind }
}
CommandKind::Clear => {
self.ensure_zero_args("clear", "")?;
Expand Down Expand Up @@ -430,7 +455,12 @@ mod test {

#[test]
fn test_args() {
assert_eq!(parse!("help").unwrap(), Command::Help);
assert_eq!(
parse!("help").unwrap(),
Command::Help {
help_kind: HelpKind::BasicHelp
}
);
assert!(parse!("help arg").is_err());
assert!(parse!("help arg1 arg2").is_err());

Expand Down Expand Up @@ -485,4 +515,49 @@ mod test {
assert_eq!(parse!("save .").unwrap(), Command::Save { dst: "." });
assert!(parse!("save arg1 arg2").is_err());
}

#[test]
fn test_help() {
assert_eq!(
parse!("help").unwrap(),
Command::Help {
help_kind: HelpKind::BasicHelp
}
);
assert_eq!(
parse!("help commands").unwrap(),
Command::Help {
help_kind: HelpKind::AllCommands
}
);
}

#[test]
fn test_list() {
assert_eq!(parse!("list").unwrap(), Command::List { items: None });
assert_eq!(
parse!("list functions").unwrap(),
Command::List {
items: Some(ListItems::Functions)
}
);
assert_eq!(
parse!("list dimensions").unwrap(),
Command::List {
items: Some(ListItems::Dimensions)
}
);
assert_eq!(
parse!("list variables").unwrap(),
Command::List {
items: Some(ListItems::Variables)
}
);
assert_eq!(
parse!("list units").unwrap(),
Command::List {
items: Some(ListItems::Units)
}
);
}
}
126 changes: 125 additions & 1 deletion numbat/src/help.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::command::HelpKind;
/// Print a help, linking the documentation, and live-running some examples
/// in an isolated context.
use crate::markup as m;
Expand Down Expand Up @@ -39,7 +40,7 @@ fn evaluate_example(context: &mut Context, input: &str) -> m::Markup {
markup
}

pub fn help_markup() -> m::Markup {
fn basic_help_markup() -> m::Markup {
let mut output = m::nl()
+ m::text("Numbat is a statically typed programming language for scientific computations")
+ m::nl()
Expand All @@ -65,5 +66,128 @@ pub fn help_markup() -> m::Markup {
output += m::text(">>> ") + m::text(example) + m::nl();
output += evaluate_example(&mut example_context, example) + m::nl();
}

output += m::text("Numbat supports a number of commands. Use ")
+ m::string("help commands")
+ m::text(" for more info.")
+ m::nl();

output
}

fn all_commands_markup() -> m::Markup {
fn m_cmd(cmd: &'static str) -> m::Markup {
m::keyword(cmd)
}

fn m_arg(arg: &'static str) -> m::Markup {
m::value(arg)
}

fn cmd(
cmd: &'static str,
args: impl AsRef<[&'static str]>,
aliases: impl AsRef<[&'static str]>,
help: &'static str,
) -> m::Markup {
cmd_fmt(cmd, args, aliases, m::text(help))
}

fn cmd_fmt(
cmd: &'static str,
args: impl AsRef<[&'static str]>,
aliases: impl AsRef<[&'static str]>,
help: m::Markup,
) -> m::Markup {
let indent = m::text(" ");
let mut output = indent.clone();
output += m_cmd(cmd);
for arg in args.as_ref() {
output += m::space();
output += m_arg(arg)
}

output += m::text(": ");
output += help;

let aliases = aliases.as_ref();
let mut aliases_iter = aliases.iter();
if let Some(first_alias) = aliases_iter.next() {
if aliases.len() == 1 {
output += m::text(" (alias: ");
} else {
output += m::text(" (aliases: ");
}
output += m_cmd(first_alias);

for alias in aliases_iter {
output += m::text(", ");
output += m_cmd(alias);
}
output += m::text(")");
}

output += m::nl();

output
}

m::nl()
+ m::text("Numbat supports the following commands:")
+ m::nl()
+ cmd("help", [], ["?"], "show a basic introduction to Numbat")
+ cmd(
"help",
["commands"],
["?"],
"show the list of Numbat commands and information about them",
)
+ cmd(
"info",
["<identifier>"],
[],
"get more info about a particular item, such as a function, variable, or unit",
)
+ cmd("list", [], [], "show all currently defined items")
+ cmd_fmt(
"list",
["<what>"],
[],
m::text("show all currently defined items of the specified type, where ")
+ m_arg("<what>")
+ m::text(" is one of ")
+ m_arg("functions")
+ m::text(", ")
+ m_arg("definitions")
+ m::text(", ")
+ m_arg("variables")
+ m::text(", or ")
+ m_arg("units"),
)
+ cmd("clear", [], [], "clear the current screen contents")
+ cmd_fmt(
"save",
[],
[],
m::text("save the current session history to ")
+ m_arg("history.nbt")
+ m::text(" in the current directory"),
)
+ cmd_fmt(
"save",
["<dst>"],
[],
m::text("save the current session history to file ")
+ m_arg("<dst>")
+ m::text("; the recommended file extension is ")
+ m::string(".nbt"),
)
+ cmd("exit", [], ["quit"], "exit Numbat")
}

pub fn help_markup(help_kind: HelpKind) -> m::Markup {
match help_kind {
HelpKind::BasicHelp => basic_help_markup(),
HelpKind::AllCommands => all_commands_markup(),
}
}

0 comments on commit f0e965e

Please sign in to comment.