Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| lib:repl [2019/01/03 07:14] – old revision restored (2018/12/31 23:35) sprowell | lib:repl [2020/11/15 23:14] (current) – Stopped at printing; more needs to be done. sprowell | ||
|---|---|---|---|
| Line 9: | Line 9: | ||
| * Coloring of error and other message types. | * Coloring of error and other message types. | ||
| - | The REPL support | + | The REPL supports |
| ===== Simplest Use ===== | ===== Simplest Use ===== | ||
| Line 15: | Line 15: | ||
| The minimum that must be done is to make a new instance of the '' | The minimum that must be done is to make a new instance of the '' | ||
| - | The one wrinkle is that you must provide some data to the constructor. | + | The one wrinkle is that you must provide some data to the constructor. |
| <code Rust [enable_line_numbers=" | <code Rust [enable_line_numbers=" | ||
| use relision:: | use relision:: | ||
| + | use relision:: | ||
| fn main() { | fn main() { | ||
| + | configure_logging(); | ||
| let mut repl = repl:: | let mut repl = repl:: | ||
| repl.run(); | repl.run(); | ||
| Line 25: | Line 27: | ||
| </ | </ | ||
| - | We can try this. | + | Note the '' |
| + | |||
| + | We can try this. This example is '' | ||
| < | < | ||
| Line 47: | Line 51: | ||
| Let's add a custom evaluator for lines. | Let's add a custom evaluator for lines. | ||
| - | To do this we need to create a function that takes a ''& | + | To do this we need to create a function that takes a ''& |
| - | * If the returned '' | + | * If the returned '' |
| * If the Boolean is '' | * If the Boolean is '' | ||
| Line 55: | Line 59: | ||
| <code Rust [enable_line_numbers=" | <code Rust [enable_line_numbers=" | ||
| - | fn echo(line: & | + | use relision:: |
| + | |||
| + | fn echo<U>(line: & | ||
| let answer = line.to_uppercase(); | let answer = line.to_uppercase(); | ||
| let cont = answer != " | let cont = answer != " | ||
| Line 62: | Line 68: | ||
| </ | </ | ||
| - | We install | + | The ''< |
| + | |||
| + | We install | ||
| <code Rust [enable_line_numbers=" | <code Rust [enable_line_numbers=" | ||
| + | use relision:: | ||
| + | use relision:: | ||
| + | |||
| + | fn echo< | ||
| + | let answer = line.to_uppercase(); | ||
| + | let cont = answer != " | ||
| + | (Some(answer), | ||
| + | } | ||
| + | |||
| fn main() { | fn main() { | ||
| - | let mut repl = repl:: | + | let mut repl = repl:: |
| repl.set_eval(echo); | repl.set_eval(echo); | ||
| repl.run(); | repl.run(); | ||
| Line 72: | Line 89: | ||
| </ | </ | ||
| - | Let's try this. | + | Let's try this. You can run this from the source distribution with ''< |
| < | < | ||
| Line 94: | Line 111: | ||
| ===== Adding a New Command ===== | ===== Adding a New Command ===== | ||
| - | We can add a new command to the REPL using the `add_command` method. | + | We can add a new command to the REPL using the '' |
| - | We will use our `echo` function for this, but we don't want to quit when the user enters | + | We will use our '' |
| + | |||
| + | We will also change the prompt, using '' | ||
| <code Rust [enable_line_numbers=" | <code Rust [enable_line_numbers=" | ||
| - | fn noop(_line: & | + | use relision:: |
| + | use relision:: | ||
| + | |||
| + | fn noop<U>(_line: & | ||
| (None, true) | (None, true) | ||
| + | } | ||
| + | |||
| + | fn echo< | ||
| + | let answer = line.to_uppercase(); | ||
| + | let cont = answer != " | ||
| + | (Some(answer), | ||
| } | } | ||
| Line 106: | Line 134: | ||
| let mut repl = repl:: | let mut repl = repl:: | ||
| repl.set_eval(echo); | repl.set_eval(echo); | ||
| - | | + | |
| // Install a custom command (using a closure). | // Install a custom command (using a closure). | ||
| repl.add_command( | repl.add_command( | ||
| Line 116: | Line 144: | ||
| |line, context| (echo(line, context).0, true), | |line, context| (echo(line, context).0, true), | ||
| ); | ); | ||
| + | |||
| // Install a custom colon command (using a function pointer). | // Install a custom colon command (using a function pointer). | ||
| repl.add_command( | repl.add_command( | ||
| Line 126: | Line 154: | ||
| noop, | noop, | ||
| ); | ); | ||
| + | |||
| + | // Set the prompt and start the REPL. | ||
| + | repl.set_prompt(" | ||
| repl.run(); | repl.run(); | ||
| } | } | ||
| </ | </ | ||
| - | Again, let's try this. | + | Again, let's try this. Note that this is '' |
| < | < | ||
| Commands start with a colon (:). Enter :help for help. | Commands start with a colon (:). Enter :help for help. | ||
| - | > :help | + | repl> :help |
| Commands can be abbreviated to the first few characters that uniquely identify them. | Commands can be abbreviated to the first few characters that uniquely identify them. | ||
| Line 144: | Line 175: | ||
| :quit Quit the REPL. | :quit Quit the REPL. | ||
| - | > :echo I'm not shouting. | + | repl> :echo I'm not shouting. |
| I'M NOT SHOUTING. | I'M NOT SHOUTING. | ||
| - | > :noop This is ignored. | + | repl> :noop This is ignored. |
| - | > :echo quit | + | repl> :echo quit |
| QUIT | QUIT | ||
| - | > quit | + | repl> quit |
| QUIT | QUIT | ||
| </ | </ | ||
| - | ===== Tweaks | + | ===== User Data ===== |
| + | |||
| + | Our functions will probably want to do something a little more sophisticated, | ||
| + | |||
| + | * The line editor (provided by the [[https:// | ||
| + | * The terminal (provided by the [[https:// | ||
| + | * The current value of the " | ||
| + | * Some user data, which can hold anything we want. | ||
| + | |||
| + | ==== Reading a Line ==== | ||
| + | |||
| + | You can read a line from the console using '' | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | Lines read in this way are not automatically added to the history; you can use '' | ||
| + | |||
| + | ==== Printing ==== | ||
| + | |||
| + | The context provides '' | ||
| + | |||
| + | Let's add a guessing game to the program. | ||
| + | |||
| + | <code Rust [enable_line_numbers=" | ||
| + | pub struct Counts { | ||
| + | pub win: u32, | ||
| + | pub lose: u32, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Now we will specialize '' | ||
| + | |||
| + | <code Rust [enable_line_numbers=" | ||
| + | fn guess(_line: | ||
| + | let limit = 10; | ||
| + | let high = 100; | ||
| + | // Tell the user the rules. | ||
| + | sayln!(context, | ||
| + | sayln!(context, | ||
| + | context.get().win + context.get().lose, | ||
| + | sayln!(context, | ||
| + | // Pick a random number. | ||
| + | let secret = rand:: | ||
| + | // Collect guesses. | ||
| + | let mut attempt = 1; | ||
| + | while attempt < limit { | ||
| + | // Get the next guess. | ||
| + | let line = context.editor.readline( | ||
| + | format!(" | ||
| + | match line { | ||
| + | Ok(text) => { | ||
| + | sayln!(context, | ||
| + | match text.trim().parse::< | ||
| + | Ok(number) => { | ||
| + | if number < secret { | ||
| + | sayln!(context, | ||
| + | } else if number > secret { | ||
| + | sayln!(context, | ||
| + | } else { | ||
| + | sayln!(context, | ||
| + | context.get_mut().win += 1; | ||
| + | return (None, true); | ||
| + | } | ||
| + | }, | ||
| + | Err(_) => { | ||
| + | sayln!(context, | ||
| + | } | ||
| + | } | ||
| + | }, | ||
| + | Err(ReadlineError:: | ||
| + | // This is a CTRL+C. | ||
| + | sayln!(context, | ||
| + | return (None, true); | ||
| + | }, | ||
| + | Err(ReadlineError:: | ||
| + | // This is end of file (CTRL+D). | ||
| + | sayln!(context, | ||
| + | return (None, true); | ||
| + | }, | ||
| + | Err(err) => { | ||
| + | // This is just an error. | ||
| + | error!(" | ||
| + | } | ||
| + | } | ||
| + | attempt += 1; | ||
| + | } // Collect guesses. | ||
| + | context.get_mut().lose += 1; | ||
| + | sayln!(context, | ||
| + | (None, true) | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | There is a lot going on in this function. | ||
| + | |||
| + | If you wanted to add the line to the history, you would do the following. | ||
| + | |||
| + | <code Rust [enable_line_numbers=true]> | ||
| + | context.editor.add_history_entry(text.clone()); | ||
| + | </ | ||
| - | There are a few other things that can be tweaked. | ||