“This is the 13th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”


To distinguish the command

Going back to the project, as I mentioned above, the first thing is being able to distinguish between MetaCommand and SQLCommand. You can see it in main.rs by calling get_command_type(command: &string), which returns an enumeration of type Rep ::CommandType, Rep: : CommanType: : SQLCommand (String) and rep: : CommanType: : MetaCommand two options (String). This way I can easily distinguish between the two types of input and take appropriate action on each:

fn main() -> rustyline::Result< > () {let _matches = App::new("Rust-SQLite") .version(crate_version! ()) .author(crate_authors! ()) .about(crate_description! ()) .get_matches();let config = get_config();
    let helper = REPLHelper::default();
    let mut repl = Editor::with_config(config);
    repl.set_helper(Some(helper));
		// loop to receive commands
    loop {
        let p = format!("rust-lite> ");
        repl.helper_mut()
            .expect("No helper found")
            .colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
        // <http://bixense.com/clicolors/>

        let readline = repl.readline(&p);
        match readline {
            Ok(command) => {
                repl.add_history_entry(command.as_str());
                // Parsing repl::CommandType
                match get_command_type(&command.trim().to_owned()) {
                    CommandType::SQLCommand(_cmd) => {
                        // process_command -> {tokenizing, parsing and executing}
                        let _ = match process_command(&command) {
                            Ok(response) => println!("{}",response),
                            Err(err) => println!("An error occured: {}", err),
                        };
                    }
                    CommandType::MetaCommand(cmd) => {
                        // handle_meta_command parses and executes the MetaCommand
                        let _ = match handle_meta_command(cmd) {
                            Ok(response) => println!("{}",response),
                            Err(err) => println!("An error occured: {}", err), }; }}}Err(ReadlineError::Interrupted) => {
                break;
            }
            Err(ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("An error occured: {:? }", err);
                break; }}}Ok(())
Copy the code

Meta Commands

Take a look at meta_command:

The first is the definition of the enumerated type, and to improve the user experience, I’ve added an Unknown option to match any MetaCommands that haven’t been defined yet.

After that, we have a block that implements the FMT ::Display trait, which helps us define how custom types are output to the terminal. For example, we want to use println! Use them in.

Then later, you’ll see another impl block with fn new() as our MetaCommand type constructor. I say this because Rust is not an object-oriented language, so fn new() is not like constructors in languages like Java, in fact, you can call it as much as you want instead of new.

#[derive(Debug, PartialEq)]
pub enum MetaCommand {
    Exit,
    Help,
    Open(String),
    Unknown,
}

// Is responsible for translating types into formatted text
impl fmt::Display for MetaCommand {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            MetaCommand::Exit => f.write_str(".exit"),
            MetaCommand::Help => f.write_str(".help"),
            MetaCommand::Open(_) => f.write_str(".open"),
            MetaCommand::Unknown => f.write_str("Unknown command"),}}}impl MetaCommand {
    pub fn new(command: String) -> MetaCommand {
        let args: VecThe < &str> = command.split_whitespace().collect();
        let cmd = args[0].to_owned();
        match cmd.as_ref() {
            ".exit" => MetaCommand::Exit,
            ".help" => MetaCommand::Help,
            ".open" => MetaCommand::Open(command),
            _ => MetaCommand::Unknown,
        }
    }
}
/ / processing
pub fn handle_meta_command(command: MetaCommand) -> Result<String> {
    match command {
        MetaCommand::Exit => std::process::exit(0),
        MetaCommand::Help => {
            Ok(format!("{} {} {} {}".".help - Display this message\n".".open <FILENAME> - Reopens a persistent database.\n".".ast <QUERY> - Show the AST for QUERY.\n".".exit - Quits this application"))
        },
        MetaCommand::Open(args) => Ok(format!("To be implemented: {}", args)),
        MetaCommand::Unknown => Err(SQLRiteError::UnknownCommand(format!("Unknown command or invalid arguments. Enter '.help'"))),}}Copy the code