mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
parent
879a8d2100
commit
c5d608216a
@ -295,6 +295,10 @@ where
|
||||
self.scope.lookup_sym(&key, true)
|
||||
}
|
||||
|
||||
pub fn scope_mut(&mut self) -> &mut Scope {
|
||||
&mut self.scope
|
||||
}
|
||||
|
||||
/// Puts the builder in validation mode.
|
||||
///
|
||||
/// Among other things this means that assertions will be evaluated and their results
|
||||
|
18
src/help/repl.txt
Normal file
18
src/help/repl.txt
Normal file
@ -0,0 +1,18 @@
|
||||
UCG repl help
|
||||
|
||||
The UCG repl allows you to enter ucg statements interactively. You can import
|
||||
files create named bindings and see the result of UCG expressions.
|
||||
|
||||
The repl understands some non-ucg command as well. Any command that starts with
|
||||
a '#' character is treated as a ucg repl command and is not parsed as a ucg
|
||||
statement. Repl commands are invalid inside a ucg statement and will result
|
||||
in a ucg parse error.
|
||||
|
||||
Currently supported commands are:
|
||||
|
||||
* #help
|
||||
- prints out this help text
|
||||
|
||||
* #del <name>
|
||||
- deletes a previously created named binding
|
||||
|
@ -28,6 +28,10 @@ impl StatementAccumulator {
|
||||
self.acc.len() + 1
|
||||
}
|
||||
|
||||
pub fn last_line(&self) -> Option<&String> {
|
||||
self.acc.last()
|
||||
}
|
||||
|
||||
/// Tells you if the latest line ends in the statement terminator.
|
||||
///
|
||||
/// Returns None if it wasn't a terminated statement and leaves the
|
||||
|
37
src/main.rs
37
src/main.rs
@ -513,6 +513,10 @@ fn env_help() {
|
||||
);
|
||||
}
|
||||
|
||||
fn print_repl_help() {
|
||||
println!(include_str!("help/repl.txt"));
|
||||
}
|
||||
|
||||
fn do_repl<C: Cache>(
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
@ -552,10 +556,41 @@ fn do_repl<C: Cache>(
|
||||
// loop
|
||||
let mut lines = ucglib::io::StatementAccumulator::new();
|
||||
println!("Welcome to the UCG repl. Ctrl-D to exit");
|
||||
println!("Type '#help' for help.");
|
||||
println!("");
|
||||
loop {
|
||||
// print prompt
|
||||
lines.push(editor.readline(&format!("{}> ", lines.next_line()))?);
|
||||
let line = editor.readline(&format!("{}> ", lines.next_line()))?;
|
||||
// TODO check for a repl command.
|
||||
// repl commands are only valid while not accumulating a statement;
|
||||
let trimmed = line.trim();
|
||||
if trimmed.starts_with("#") {
|
||||
// handle the various commands.
|
||||
if trimmed.starts_with("#help") {
|
||||
print_repl_help();
|
||||
} else if trimmed.starts_with("#del") {
|
||||
// remove a named binding from the builder output.
|
||||
let args: Vec<&str> = trimmed.split(" ").skip(1).collect();
|
||||
if args.len() != 1 {
|
||||
// print usage of the #del command
|
||||
eprintln!("The '#del' command expects a single argument specifying \nthe binding to delete.");
|
||||
} else {
|
||||
let key = ucglib::ast::PositionedItem {
|
||||
pos: ucglib::ast::Position::new(0, 0, 0),
|
||||
val: args[0].to_string(),
|
||||
};
|
||||
if let None = builder.scope_mut().build_output.remove(&key) {
|
||||
eprintln!("No such binding {}", key.val);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("Invalid repl command...");
|
||||
eprintln!("");
|
||||
print_repl_help();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
lines.push(line);
|
||||
// check to see if that line is a statement
|
||||
loop {
|
||||
// read a statement
|
||||
|
Loading…
x
Reference in New Issue
Block a user