* Implement exit command for cli tool * Address review comments r=rnewman * Include exit commands in help
This commit is contained in:
parent
46fc1615fb
commit
ecc926086a
|
@ -13,7 +13,6 @@ use combine::{
|
|||
eof,
|
||||
look_ahead,
|
||||
many1,
|
||||
parser,
|
||||
satisfy,
|
||||
sep_end_by,
|
||||
token,
|
||||
|
@ -29,8 +28,6 @@ use combine::combinator::{
|
|||
try
|
||||
};
|
||||
|
||||
use combine::primitives::Consumed;
|
||||
|
||||
use errors as cli;
|
||||
|
||||
use edn;
|
||||
|
@ -42,14 +39,17 @@ pub static LONG_QUERY_COMMAND: &'static str = &"query";
|
|||
pub static SHORT_QUERY_COMMAND: &'static str = &"q";
|
||||
pub static LONG_TRANSACT_COMMAND: &'static str = &"transact";
|
||||
pub static SHORT_TRANSACT_COMMAND: &'static str = &"t";
|
||||
pub static LONG_EXIT_COMMAND: &'static str = &"exit";
|
||||
pub static SHORT_EXIT_COMMAND: &'static str = &"e";
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Command {
|
||||
Transact(String),
|
||||
Query(String),
|
||||
Close,
|
||||
Exit,
|
||||
Help(Vec<String>),
|
||||
Open(String),
|
||||
Close,
|
||||
Query(String),
|
||||
Transact(String),
|
||||
}
|
||||
|
||||
impl Command {
|
||||
|
@ -65,7 +65,8 @@ impl Command {
|
|||
},
|
||||
&Command::Help(_) |
|
||||
&Command::Open(_) |
|
||||
&Command::Close => true
|
||||
&Command::Close |
|
||||
&Command::Exit => true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +87,9 @@ impl Command {
|
|||
&Command::Close => {
|
||||
format!(".{}", CLOSE_COMMAND)
|
||||
},
|
||||
&Command::Exit => {
|
||||
format!(".{}", LONG_EXIT_COMMAND)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,18 +116,29 @@ pub fn command(s: &str) -> Result<Command, cli::Error> {
|
|||
}
|
||||
Ok(Command::Open(args[0].clone()))
|
||||
});
|
||||
|
||||
let no_arg_parser = || arguments()
|
||||
.skip(spaces())
|
||||
.skip(eof());
|
||||
|
||||
let close_parser = string(CLOSE_COMMAND)
|
||||
.with(arguments())
|
||||
.skip(spaces())
|
||||
.skip(eof())
|
||||
.with(no_arg_parser())
|
||||
.map(|args| {
|
||||
if args.len() > 0 {
|
||||
if !args.is_empty() {
|
||||
bail!(cli::ErrorKind::CommandParse(format!("Unrecognized argument {:?}", args[0])) );
|
||||
}
|
||||
Ok(Command::Close)
|
||||
});
|
||||
|
||||
let exit_parser = try(string(LONG_EXIT_COMMAND)).or(try(string(SHORT_EXIT_COMMAND)))
|
||||
.with(no_arg_parser())
|
||||
.map(|args| {
|
||||
if !args.is_empty() {
|
||||
bail!(cli::ErrorKind::CommandParse(format!("Unrecognized argument {:?}", args[0])) );
|
||||
}
|
||||
Ok(Command::Exit)
|
||||
});
|
||||
|
||||
let edn_arg_parser = || spaces()
|
||||
.with(look_ahead(string("[").or(string("{")))
|
||||
.with(many1::<Vec<_>, _>(try(any())))
|
||||
|
@ -146,10 +161,11 @@ pub fn command(s: &str) -> Result<Command, cli::Error> {
|
|||
|
||||
spaces()
|
||||
.skip(token('.'))
|
||||
.with(choice::<[&mut Parser<Input = _, Output = Result<Command, cli::Error>>; 5], _>
|
||||
.with(choice::<[&mut Parser<Input = _, Output = Result<Command, cli::Error>>; 6], _>
|
||||
([&mut try(help_parser),
|
||||
&mut try(open_parser),
|
||||
&mut try(close_parser),
|
||||
&mut try(exit_parser),
|
||||
&mut try(query_parser),
|
||||
&mut try(transact_parser)]))
|
||||
.parse(s)
|
||||
|
@ -294,6 +310,43 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exit_parser_with_args() {
|
||||
let input = ".exit arg1";
|
||||
let err = command(&input).expect_err("Expected an error");
|
||||
assert_eq!(err.to_string(), format!("Invalid command {:?}", input));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exit_parser_no_args() {
|
||||
let input = ".exit";
|
||||
let cmd = command(&input).expect("Expected exit command");
|
||||
match cmd {
|
||||
Command::Exit => assert!(true),
|
||||
_ => assert!(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exit_parser_no_args_trailing_whitespace() {
|
||||
let input = ".exit ";
|
||||
let cmd = command(&input).expect("Expected exit command");
|
||||
match cmd {
|
||||
Command::Exit => assert!(true),
|
||||
_ => assert!(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exit_parser_short_command() {
|
||||
let input = ".e";
|
||||
let cmd = command(&input).expect("Expected exit command");
|
||||
match cmd {
|
||||
Command::Exit => assert!(true),
|
||||
_ => assert!(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_query_parser_complete_edn() {
|
||||
let input = ".q [:find ?x :where [?x foo/bar ?y]]";
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashMap;
|
||||
use std::process;
|
||||
|
||||
use error_chain::ChainedError;
|
||||
|
||||
use mentat::query::QueryResults;
|
||||
use mentat_core::TypedValue;
|
||||
|
@ -21,6 +24,8 @@ use command_parser::{
|
|||
SHORT_QUERY_COMMAND,
|
||||
LONG_TRANSACT_COMMAND,
|
||||
SHORT_TRANSACT_COMMAND,
|
||||
LONG_EXIT_COMMAND,
|
||||
SHORT_EXIT_COMMAND,
|
||||
};
|
||||
use input::InputReader;
|
||||
use input::InputResult::{
|
||||
|
@ -37,6 +42,8 @@ use store::{
|
|||
lazy_static! {
|
||||
static ref COMMAND_HELP: HashMap<&'static str, &'static str> = {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(LONG_EXIT_COMMAND, "Close the current database and exit the REPL.");
|
||||
map.insert(SHORT_EXIT_COMMAND, "Shortcut for `.exit`. Close the current database and exit the REPL.");
|
||||
map.insert(HELP_COMMAND, "Show help for commands.");
|
||||
map.insert(OPEN_COMMAND, "Open a database at path.");
|
||||
map.insert(LONG_QUERY_COMMAND, "Execute a query against the current open database.");
|
||||
|
@ -103,18 +110,25 @@ impl Repl {
|
|||
Err(e) => println!("{}", e.to_string())
|
||||
};
|
||||
},
|
||||
Command::Close => {
|
||||
let old_db_name = self.store.db_name.clone();
|
||||
match self.store.close() {
|
||||
Ok(_) => println!("Database {:?} closed", db_output_name(&old_db_name)),
|
||||
Err(e) => println!("{}", e.to_string())
|
||||
};
|
||||
},
|
||||
Command::Close => self.close(),
|
||||
Command::Query(query) => self.execute_query(query),
|
||||
Command::Transact(transaction) => self.execute_transact(transaction),
|
||||
Command::Exit => {
|
||||
self.close();
|
||||
println!("Exiting...");
|
||||
process::exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn close(&mut self) {
|
||||
let old_db_name = self.store.db_name.clone();
|
||||
match self.store.close() {
|
||||
Ok(_) => println!("Database {:?} closed", db_output_name(&old_db_name)),
|
||||
Err(e) => println!("{}", e.display())
|
||||
};
|
||||
}
|
||||
|
||||
fn help_command(&self, args: Vec<String>) {
|
||||
if args.is_empty() {
|
||||
for (cmd, msg) in COMMAND_HELP.iter() {
|
||||
|
|
Loading…
Reference in a new issue