Parse query and transact commands

This commit is contained in:
Emily Toop 2017-05-16 12:21:53 +01:00
parent b3ff534690
commit 102e528310

View file

@ -9,7 +9,9 @@
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
use combine::{ use combine::{
any,
eof, eof,
many,
many1, many1,
satisfy, satisfy,
sep_end_by, sep_end_by,
@ -31,11 +33,13 @@ use errors as cli;
pub static HELP_COMMAND: &'static str = &"help"; pub static HELP_COMMAND: &'static str = &"help";
pub static OPEN_COMMAND: &'static str = &"open"; pub static OPEN_COMMAND: &'static str = &"open";
pub static CLOSE_COMMAND: &'static str = &"close"; pub static CLOSE_COMMAND: &'static str = &"close";
pub static QUERY_COMMAND: &'static str = &"q";
pub static TRANSACT_COMMAND: &'static str = &"t";
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum Command { pub enum Command {
Transact(Vec<String>), Transact(String),
Query(Vec<String>), Query(String),
Help(Vec<String>), Help(Vec<String>),
Open(String), Open(String),
Close, Close,
@ -89,12 +93,37 @@ pub fn command(s: &str) -> Result<Command, cli::Error> {
Ok(Command::Close) Ok(Command::Close)
}); });
let opening_brace_parser = try(string("["))
.or(try(string("{")));
let edn_arg_parser = spaces()
.and(opening_brace_parser.clone()
.and(many::<Vec<_>, _>(try(any()))));
let query_parser = string(QUERY_COMMAND)
.and(edn_arg_parser.clone())
.map( |x| {
let args = (x.1).1;
let content: String = args.1.iter().collect();
Ok(Command::Query(format!("{}{}", args.0, content)))
});
let transact_parser = string(TRANSACT_COMMAND)
.and(edn_arg_parser.clone())
.map( |x| {
let args = (x.1).1;
let content: String = args.1.iter().collect();
Ok(Command::Transact(format!("{}{}", args.0, content)))
});
spaces() spaces()
.skip(token('.')) .skip(token('.'))
.with(choice::<[&mut Parser<Input = _, Output = Result<Command, cli::Error>>; 3], _> .with(choice::<[&mut Parser<Input = _, Output = Result<Command, cli::Error>>; 5], _>
([&mut try(help_parser), ([&mut try(help_parser),
&mut try(open_parser), &mut try(open_parser),
&mut try(close_parser),])) &mut try(close_parser),
&mut try(query_parser),
&mut try(transact_parser)]))
.skip(spaces()) .skip(spaces())
.skip(eof()) .skip(eof())
.parse(s) .parse(s)
@ -206,6 +235,13 @@ mod tests {
assert_eq!(err.to_string(), "Missing required argument"); assert_eq!(err.to_string(), "Missing required argument");
} }
#[test]
fn test_open_parser_no_args_trailing_whitespace() {
let input = ".open ";
let err = command(&input).expect_err("Expected an error");
assert_eq!(err.to_string(), "Missing required argument");
}
#[test] #[test]
fn test_close_parser_with_args() { fn test_close_parser_with_args() {
let input = ".close arg1"; let input = ".close arg1";
@ -233,6 +269,94 @@ mod tests {
} }
} }
#[test]
fn test_query_parser_complete_edn() {
let input = ".q [:find ?x :where [?x foo/bar ?y]]";
let cmd = command(&input).expect("Expected query command");
match cmd {
Command::Query(edn) => assert_eq!(edn, "[:find ?x :where [?x foo/bar ?y]]"),
_ => assert!(false)
}
}
#[test]
fn test_query_parser_incomplete_edn() {
let input = ".q [:find ?x\r\n";
let cmd = command(&input).expect("Expected query command");
match cmd {
Command::Query(edn) => assert_eq!(edn, "[:find ?x\r\n"),
_ => assert!(false)
}
}
#[test]
fn test_query_parser_empty_edn() {
let input = ".q {}";
let cmd = command(&input).expect("Expected query command");
match cmd {
Command::Query(edn) => assert_eq!(edn, "{}"),
_ => assert!(false)
}
}
#[test]
fn test_query_parser_no_edn() {
let input = ".q ";
let err = command(&input).expect_err("Expected an error");
assert_eq!(err.to_string(), format!("Invalid command {:?}", input));
}
#[test]
fn test_query_parser_invalid_start_char() {
let input = ".q :find ?x";
let err = command(&input).expect_err("Expected an error");
assert_eq!(err.to_string(), format!("Invalid command {:?}", input));
}
#[test]
fn test_transact_parser_complete_edn() {
let input = ".t [:db/add \"s\" :db/ident :foo/uuid]";
let cmd = command(&input).expect("Expected transact command");
match cmd {
Command::Transact(edn) => assert_eq!(edn, "[:db/add \"s\" :db/ident :foo/uuid]"),
_ => assert!(false)
}
}
#[test]
fn test_transact_parser_incomplete_edn() {
let input = ".t {\r\n";
let cmd = command(&input).expect("Expected transact command");
match cmd {
Command::Transact(edn) => assert_eq!(edn, "{\r\n"),
_ => assert!(false)
}
}
#[test]
fn test_transact_parser_empty_edn() {
let input = ".t {}";
let cmd = command(&input).expect("Expected transact command");
match cmd {
Command::Transact(edn) => assert_eq!(edn, "{}"),
_ => assert!(false)
}
}
#[test]
fn test_transact_parser_no_edn() {
let input = ".t ";
let err = command(&input).expect_err("Expected an error");
assert_eq!(err.to_string(), format!("Invalid command {:?}", input));
}
#[test]
fn test_transact_parser_invalid_start_char() {
let input = ".t :db/add \"s\" :db/ident :foo/uuid";
let err = command(&input).expect_err("Expected an error");
assert_eq!(err.to_string(), format!("Invalid command {:?}", input));
}
#[test] #[test]
fn test_parser_preceeding_trailing_whitespace() { fn test_parser_preceeding_trailing_whitespace() {
let input = " .close "; let input = " .close ";