Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructured how commands like list, help, quit are parsed to implement save #555

Merged
merged 32 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
47fd928
Added .DS_Store to gitignore
rben01 Sep 7, 2024
34d43a3
Implemented commands like `list`, `help`, `save` (new) with more flex…
rben01 Sep 7, 2024
2d45512
Added Info command
rben01 Sep 7, 2024
5a0ff28
Tests for Command
rben01 Sep 7, 2024
3e89134
Continued REPL if `save dst` errored instead of just exiting
rben01 Sep 7, 2024
1318619
Reduced some copy-pasted code
rben01 Sep 7, 2024
9ef2f8b
Merge branch 'master' into commands
rben01 Sep 7, 2024
314ad41
Merge branch 'commands' of https://github.com/rben01/numbat into comm…
rben01 Sep 7, 2024
4615178
Passed `code_source_id` to `parse_command` instead of a `Resolver`
rben01 Sep 8, 2024
32bf547
Made struct `CommandParser` and reimplemented command parsing in term…
rben01 Sep 8, 2024
01ab601
Fixed bug where `resolver.add_code_source` was run twice per non-comm…
rben01 Sep 8, 2024
2723c14
Enum-ified command kind, making it strongly typed (no need for `unrea…
rben01 Sep 8, 2024
f929215
Changed `InvalidCommand` to take a `String` instead of `&'static str`
rben01 Sep 8, 2024
336eeca
Replaced trailing space characters in two tests with `\x20` to preven…
rben01 Sep 8, 2024
4cd8c56
Removed alias "ls" for "list" command
rben01 Sep 8, 2024
6fed904
Removed unused `CommandParser::set_code_source_id`
rben01 Sep 8, 2024
1f34d27
Initial, simple implementation of saving per-session history
rben01 Sep 15, 2024
50dd0fd
Moved `session_history` storage from `Cli::repl` into `Cli::repl_loop`
rben01 Sep 15, 2024
6b1a863
Simplified history implementation, at the cost of one allocation when…
rben01 Sep 15, 2024
ac1bd61
Renamed session history file to history.nbt
rben01 Sep 15, 2024
f89083e
Moved pushing to session history out of `parse_and_evaluate` and into…
rben01 Sep 17, 2024
8f2a804
Replaced boolean `errored` with isomorphic but clearer `Result<(), ()…
rben01 Sep 18, 2024
e4e6c37
Moved `writeln!` arg into format string
rben01 Sep 18, 2024
efb7250
Minor cleanup
rben01 Sep 21, 2024
ea859dd
Restored accidentatlly removed alias `?` for `help`
rben01 Sep 21, 2024
20d6815
Merge branch 'sharkdp:master' into commands
rben01 Sep 21, 2024
3f987a2
Merge branch 'commands' of https://github.com/rben01/numbat into comm…
rben01 Sep 21, 2024
87b0812
Merge branch 'session-history' into commands
rben01 Sep 21, 2024
b0361a9
Updated cli docs
rben01 Sep 21, 2024
8a278bc
Removed `ls` as alias for command `list` in web version for consisten…
rben01 Sep 22, 2024
5c55c45
Replaced `CommandKind::new` with `impl FromStr for CommandKind` (isom…
rben01 Sep 22, 2024
ab4205e
Merge branch 'master' into commands
sharkdp Sep 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/target
.DS_Store
168 changes: 84 additions & 84 deletions numbat-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ use config::{ColorMode, Config, ExchangeRateFetchingPolicy, IntroBanner, PrettyP
use highlighter::NumbatHighlighter;

use itertools::Itertools;
use numbat::command::{CommandParser, SourcelessCommandParser};
use numbat::diagnostic::ErrorDiagnostic;
use numbat::help::help_markup;
use numbat::markup as m;
use numbat::module_importer::{BuiltinModuleImporter, ChainedImporter, FileSystemImporter};
use numbat::pretty_print::PrettyPrint;
use numbat::resolver::CodeSource;
use numbat::{command, RuntimeError};
use numbat::{Context, NumbatError};
use numbat::{InterpreterSettings, NameResolutionError};

Expand Down Expand Up @@ -347,95 +349,93 @@ impl Cli {
if !line.trim().is_empty() {
rl.add_history_entry(&line)?;

match line.trim() {
"list" | "ls" => {
println!(
"{}",
ansi_format(
&self.context.lock().unwrap().print_environment(),
false
)
);
}
"list functions" | "ls functions" => {
println!(
"{}",
ansi_format(
&self.context.lock().unwrap().print_functions(),
false
)
);
}
"list dimensions" | "ls dimensions" => {
println!(
"{}",
ansi_format(
&self.context.lock().unwrap().print_dimensions(),
false
)
);
}
"list variables" | "ls variables" => {
println!(
"{}",
ansi_format(
&self.context.lock().unwrap().print_variables(),
false
)
);
}
"list units" | "ls units" => {
println!(
"{}",
ansi_format(&self.context.lock().unwrap().print_units(), false)
);
}
"clear" => {
rl.clear_screen()?;
}
"quit" | "exit" => {
return Ok(());
}
"help" | "?" => {
let help = help_markup();
print!("{}", ansi_format(&help, true));
// currently, the ansi formatter adds indents
// _after_ each newline and so we need to manually
// add an extra blank line to absorb this indent
println!();
}
_ => {
if let Some(keyword) = line.strip_prefix("info ") {
let help = self
.context
.lock()
.unwrap()
.print_info_for_keyword(keyword.trim());
println!("{}", ansi_format(&help, true));
continue;
}
let result = self.parse_and_evaluate(
&line,
CodeSource::Text,
if interactive {
ExecutionMode::Interactive
} else {
ExecutionMode::Normal
},
self.config.pretty_print,
);

match result {
std::ops::ControlFlow::Continue(()) => {}
std::ops::ControlFlow::Break(ExitStatus::Success) => {
return Ok(());
// if we enter here, the line looks like a command
if let Some(sourceless_parser) = SourcelessCommandParser::new(&line) {
let mut parser = CommandParser::new(
sourceless_parser,
self.context
.lock()
.unwrap()
.resolver_mut()
.add_code_source(CodeSource::Text, &line),
);

match parser.parse_command() {
Ok(command) => match command {
command::Command::Help => {
let help = help_markup();
print!("{}", ansi_format(&help, true));
// currently, the ansi formatter adds indents
// _after_ each newline and so we need to manually
// add an extra blank line to absorb this indent
println!();
}
command::Command::Info { item } => {
let help = self
.context
.lock()
.unwrap()
.print_info_for_keyword(item);
println!("{}", ansi_format(&help, true));
}
command::Command::List { items } => {
let context = self.context.lock().unwrap();
let m = match items {
None => context.print_environment(),
Some(command::ListItems::Functions) => {
context.print_functions()
}
Some(command::ListItems::Dimensions) => {
context.print_dimensions()
}
Some(command::ListItems::Variables) => {
context.print_variables()
}
Some(command::ListItems::Units) => {
context.print_units()
}
};
println!("{}", ansi_format(&m, false));
}
std::ops::ControlFlow::Break(ExitStatus::Error) => {
bail!("Interpreter stopped due to error")
command::Command::Clear => rl.clear_screen()?,
command::Command::Save { dst } => {
if rl.save_history(dst).is_err() {
let error = RuntimeError::FileWrite(PathBuf::from(dst));
self.print_diagnostic(error);
continue;
};
}
command::Command::Quit => return Ok(()),
},
Err(e) => {
self.print_diagnostic(e);
continue;
}
}

continue;
}

let result = self.parse_and_evaluate(
&line,
CodeSource::Text,
if interactive {
ExecutionMode::Interactive
} else {
ExecutionMode::Normal
},
self.config.pretty_print,
);

match result {
std::ops::ControlFlow::Continue(()) => {}
std::ops::ControlFlow::Break(ExitStatus::Success) => {
return Ok(());
}
std::ops::ControlFlow::Break(ExitStatus::Error) => {
bail!("Interpreter stopped due to error")
}
};
}
}
Err(ReadlineError::Interrupted) => {}
Expand Down
Loading
Loading