Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Accept and parse EDN Query and Transact commands (#453)#465

Merged
fluffyemily merged 5 commits into
fluffyemily/open-dbfrom
fluffyemily/parse_edn
May 30, 2017
Merged

Accept and parse EDN Query and Transact commands (#453)#465
fluffyemily merged 5 commits into
fluffyemily/open-dbfrom
fluffyemily/parse_edn

Conversation

@fluffyemily
Copy link
Copy Markdown
Contributor

@fluffyemily fluffyemily commented May 16, 2017

#453

depends on #463

Copy link
Copy Markdown
Member

@ncalexan ncalexan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is looking good.

However, I found the expression of continuation with more: Option<Command> difficult to process. Can you fold these patches down a little, so that I can see the final form?

}

#[test]
fn test_transact_parser_complete_edn() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A transaction is a vector-of-vectors or a vector-of-maps, in order to handle multiple assertions. So

.t [[:db/add "t" ...]
     [:db/add "r" ...]]

}

pub fn command(s: &str) -> Command {
let skip_spaces = skip_many(space());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the spaces() parser from combine::char. I've found that let p = || ... and then p() is more natural than cloning the parser.

]))
.skip(eof())
.parse(s)
.map(|x| x.0)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh? This seems like unnecessary whitespace.

.and(many::<Vec<_>, _>(try(any()))));

let query_parser = string(QUERY_COMMAND)
.and(edn_arg_parser.clone())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my other commit with .skip and .then for avoiding these indexing operations.


let edn_arg_parser = skip_spaces.clone()
.and(opening_brace_parser.clone()
.and(many::<Vec<_>, _>(try(any()))));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why you need to try here? any will either consume and succeed or not consume and fail; there shouldn't be consume and fail.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why, but if I leave the try out, I get no output at all from the many.

pub static HELP_COMMAND: &'static str = &"help";
pub static OPEN_COMMAND: &'static str = &"open";
pub static CLOSE_COMMAND: &'static str = &"close";
pub static QUERY_COMMAND: &'static str = &"q";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have synonyms, ".query" for ".q", ".transact" for ".t"?

@fluffyemily fluffyemily force-pushed the fluffyemily/open-db branch from c0adac7 to b3ff534 Compare May 19, 2017 12:39
@fluffyemily fluffyemily force-pushed the fluffyemily/parse_edn branch 2 times, most recently from 6489e57 to 874a10a Compare May 22, 2017 12:18
There must be some way that I can retain the eof() after the `then` that means I don't have to move the skip on spaces and eof

Make in process command storing clearer.

Add comments around in process commands.
Add alternative commands for transact/t and query/q
Copy link
Copy Markdown
Member

@ncalexan ncalexan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, this is getting cleaner. I'd like to understand what the advantage of checking for argument counts, etc, during parsing is. Is your goal to maintain user input that parses but isn't semantically correct across invocations, allowing the user to edit their work in place?

I think that parsing and interpretation should be separate stages; and that user's should use up/down (maybe via rlwrap) to get their previous, incorrect input. That might simplify a lot of the error handling you're baking into the parser.

Comment thread tools/cli/src/mentat_cli/repl.rs Outdated

loop {
let res = input.read_input(if more.is_some() { MORE_PROMPT } else { DEFAULT_PROMPT });
let res = input.read_input(more.clone());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised you need this clone, since you're joining strings in read_input, not re-using them.

Some(Command::Transact(args)) => {
Command::Transact(args + " " + &line)
},
_ => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to explicitly match Some(...) and None here, so that the compiler will tell you when you need to handle cases. I feel like there's an abstraction around continuable commands vs. non-continuable commands missing here, but it's your choice how to express this.

Command::Transact(args + " " + &line)
},
_ => {
try!(command(&self.buffer))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer ...? to try!(...); it's the modern expression in Rust. Are you really only doing this evaluation for the error result? You should consume the result of any Result, using let _ = ... if needed; the compiler should be warning you that you're dropping a result on the floor here.

let edn_arg_parser = || spaces()
.with(try(string("["))
.or(try(string("{")))
.then(|d| parser(move |input| {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, you're trying to parse any line prefixed by optional space and either [ or {. I think you can do that with:

spaces()
    .with(look_ahead(string("[").or(string("{")))
        .with(many(any()))

Using then and a special parser like you do is ingenious but definitely not a natural expression using combine :) You might also do this as

spaces().then(many(any())).and_then(|line| {
    if line.starts_with("[") || line.starts_with("{") {
        Ok(...)
    } else {
        Err(...)  
    }
})

but then you need to know a lot more about error handling in combine. Stick to the defined combinators for easiest use.

pub static QUERY_COMMAND: &'static str = &"q";
pub static TRANSACT_COMMAND: &'static str = &"t";
pub static QUERY_COMMAND: &'static str = &"query";
pub static ALT_QUERY_COMMAND: &'static str = &"q";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you label these SHORT_ and LONG_, your try clauses will read more clearly.


#[test]
fn test_open_parser_no_args_trailing_whitespace() {
let input = ".open ";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that expect_err is in 1.17.0 stable, so we can use it -- but we need to bump

static MIN_VERSION: &'static str = ">= 1.15.1";
as a Pre: part to stop folks failing here (as I just did locally!).

Comment thread tools/cli/src/mentat_cli/repl.rs Outdated
/// Runs the REPL interactively.
pub fn run(&mut self) {
let mut more: Option<Command> = None;
let mut more = false;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a compiler warning with this patch sequence that reveals that more is only assigned to, not read. This is vestigial?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I had removed that here, but it turns out it was done elsewhere. Removing...

.skip(eof())
.map(|args| {
if args.len() > 0 {
return Err(cli::ErrorKind::CommandParse(format!("Unrecognized argument {:?}", args[0])).into());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a handy bail! macro specifically to make this type of early return more pleasant.

@fluffyemily fluffyemily requested a review from ncalexan May 26, 2017 13:45
Copy link
Copy Markdown
Member

@ncalexan ncalexan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit comment is missing "r" in the "r=nalexander" part.

There is trailing whitespace throughout.

If you are done with this patch, it's good enough to land -- we can revisit the parser as we iterate.

Sorry for the delayed review!

})));

let query_parser = try(string(QUERY_COMMAND)).or(try(string(ALT_QUERY_COMMAND)))
let edn_arg_parser = || spaces()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any movement or discussion of #465 (comment) -- did you try and fail to improve this, or do you particularly like the expression as is?

Improving this would avoid .into_iter().collect() two places below, which is a strong sign that your types are wrong: IIUC, you're collecting Vec<String> (where each string is one character!) into a String. That's going to inefficient.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really? I could've sworn I totally rewrote that.

Looking at it, I rewrote it blow here but didn't delete the old one. I think things might've gone wiggy in the rebasing.

let transact_parser = try(string(TRANSACT_COMMAND)).or(try(string(ALT_TRANSACT_COMMAND)))
let transact_parser = try(string(LONG_TRANSACT_COMMAND)).or(try(string(SHORT_TRANSACT_COMMAND)))
.with(edn_arg_parser())
.map( |x| {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no leading space before the argument: .map(|x| { ....

@fluffyemily fluffyemily force-pushed the fluffyemily/parse_edn branch 2 times, most recently from 3aa1e5f to 00af587 Compare May 30, 2017 09:58
Emily Toop added 2 commits May 30, 2017 10:58
* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.
* Send queries and transactions to mentat and output the results

move outputting query and transaction results out of store and into repl

* Add query and transact commands to help

* Execute queries and transacts passed in at startup

* Address review comments =nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Execute command line args in order

* Addressing rebase issues
@fluffyemily fluffyemily merged commit abcbdf5 into fluffyemily/open-db May 30, 2017
@fluffyemily fluffyemily deleted the fluffyemily/parse_edn branch May 30, 2017 10:05
fluffyemily pushed a commit that referenced this pull request May 30, 2017
* Open named database OR default to in memory database if no name provided

Rearrange workspace to allow import of mentat crate in cli crate

Create store object inside repl when started for connecting to mentat

Use provided DB name to open connection in store

Accept DB name as command line arg.

Open on CLI start

Implement '.open' command to open desired DB from inside CLI

* Implement Close command to close current DB.
* Closes existing open db and opens new in memory db

* Review comment: Use `combine` to parse arguments.

Move over to using Result rather than enums with err

* Accept and parse EDN Query and Transact commands (#453) (#465)

* Parse query and transact commands

* Implement is_complete for transactions and queries

* Improve query parser. Am still not happy with it though.

There must be some way that I can retain the eof() after the `then` that means I don't have to move the skip on spaces and eof

Make in process command storing clearer.

Add comments around in process commands.
Add alternative commands for transact/t and query/q

* Address review comments r=nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Send queries and transactions to mentat and output the results (#466)

* Send queries and transactions to mentat and output the results

move outputting query and transaction results out of store and into repl

* Add query and transact commands to help

* Execute queries and transacts passed in at startup

* Address review comments =nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Execute command line args in order

* Addressing rebase issues
fluffyemily pushed a commit that referenced this pull request Nov 21, 2017
* Open named database OR default to in memory database if no name provided

Rearrange workspace to allow import of mentat crate in cli crate

Create store object inside repl when started for connecting to mentat

Use provided DB name to open connection in store

Accept DB name as command line arg.

Open on CLI start

Implement '.open' command to open desired DB from inside CLI

* Implement Close command to close current DB.
* Closes existing open db and opens new in memory db

* Review comment: Use `combine` to parse arguments.

Move over to using Result rather than enums with err

* Accept and parse EDN Query and Transact commands (#453) (#465)

* Parse query and transact commands

* Implement is_complete for transactions and queries

* Improve query parser. Am still not happy with it though.

There must be some way that I can retain the eof() after the `then` that means I don't have to move the skip on spaces and eof

Make in process command storing clearer.

Add comments around in process commands.
Add alternative commands for transact/t and query/q

* Address review comments r=nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Send queries and transactions to mentat and output the results (#466)

* Send queries and transactions to mentat and output the results

move outputting query and transaction results out of store and into repl

* Add query and transact commands to help

* Execute queries and transacts passed in at startup

* Address review comments =nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Execute command line args in order

* Addressing rebase issues
fluffyemily pushed a commit that referenced this pull request Nov 21, 2017
* Open named database OR default to in memory database if no name provided

Rearrange workspace to allow import of mentat crate in cli crate

Create store object inside repl when started for connecting to mentat

Use provided DB name to open connection in store

Accept DB name as command line arg.

Open on CLI start

Implement '.open' command to open desired DB from inside CLI

* Implement Close command to close current DB.
* Closes existing open db and opens new in memory db

* Review comment: Use `combine` to parse arguments.

Move over to using Result rather than enums with err

* Accept and parse EDN Query and Transact commands (#453) (#465)

* Parse query and transact commands

* Implement is_complete for transactions and queries

* Improve query parser. Am still not happy with it though.

There must be some way that I can retain the eof() after the `then` that means I don't have to move the skip on spaces and eof

Make in process command storing clearer.

Add comments around in process commands.
Add alternative commands for transact/t and query/q

* Address review comments r=nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Send queries and transactions to mentat and output the results (#466)

* Send queries and transactions to mentat and output the results

move outputting query and transaction results out of store and into repl

* Add query and transact commands to help

* Execute queries and transacts passed in at startup

* Address review comments =nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Execute command line args in order

* Addressing rebase issues
fluffyemily pushed a commit that referenced this pull request Nov 21, 2017
* Create mentat command line.
* Create tools directory containing new crate for mentat_cli.
* Add simple cli with mentat prompt.

* Remove rustc-serialize dependency

* Open DB inside CLI (#452) (#463)

* Open named database OR default to in memory database if no name provided

Rearrange workspace to allow import of mentat crate in cli crate

Create store object inside repl when started for connecting to mentat

Use provided DB name to open connection in store

Accept DB name as command line arg.

Open on CLI start

Implement '.open' command to open desired DB from inside CLI

* Implement Close command to close current DB.
* Closes existing open db and opens new in memory db

* Review comment: Use `combine` to parse arguments.

Move over to using Result rather than enums with err

* Accept and parse EDN Query and Transact commands (#453) (#465)

* Parse query and transact commands

* Implement is_complete for transactions and queries

* Improve query parser. Am still not happy with it though.

There must be some way that I can retain the eof() after the `then` that means I don't have to move the skip on spaces and eof

Make in process command storing clearer.

Add comments around in process commands.
Add alternative commands for transact/t and query/q

* Address review comments r=nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Send queries and transactions to mentat and output the results (#466)

* Send queries and transactions to mentat and output the results

move outputting query and transaction results out of store and into repl

* Add query and transact commands to help

* Execute queries and transacts passed in at startup

* Address review comments =nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Execute command line args in order

* Addressing rebase issues

* Exit CLI (#457) (#484) r-rnewman

* Implement exit command for cli tool

* Address review comments r=rnewman

* Include exit commands in help

* Show schema of current DB (#487)

* Fixing rebase issues

* addressing nit

* Match updated dependencies on CLI crate and remove unused import
RDR8 pushed a commit to RDR8/mentat that referenced this pull request Mar 12, 2018
* Create mentat command line.
* Create tools directory containing new crate for mentat_cli.
* Add simple cli with mentat prompt.

* Remove rustc-serialize dependency

* Open DB inside CLI (mozilla#452) (mozilla#463)

* Open named database OR default to in memory database if no name provided

Rearrange workspace to allow import of mentat crate in cli crate

Create store object inside repl when started for connecting to mentat

Use provided DB name to open connection in store

Accept DB name as command line arg.

Open on CLI start

Implement '.open' command to open desired DB from inside CLI

* Implement Close command to close current DB.
* Closes existing open db and opens new in memory db

* Review comment: Use `combine` to parse arguments.

Move over to using Result rather than enums with err

* Accept and parse EDN Query and Transact commands (mozilla#453) (mozilla#465)

* Parse query and transact commands

* Implement is_complete for transactions and queries

* Improve query parser. Am still not happy with it though.

There must be some way that I can retain the eof() after the `then` that means I don't have to move the skip on spaces and eof

Make in process command storing clearer.

Add comments around in process commands.
Add alternative commands for transact/t and query/q

* Address review comments r=nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Send queries and transactions to mentat and output the results (mozilla#466)

* Send queries and transactions to mentat and output the results

move outputting query and transaction results out of store and into repl

* Add query and transact commands to help

* Execute queries and transacts passed in at startup

* Address review comments =nalexander.

* Bump rust version number.
* Use `bail` when throwing errors.
* Improve edn parser.
* Remove references to unused `more` flag.
* Improve naming of query and transact commands.

* Execute command line args in order

* Addressing rebase issues

* Exit CLI (mozilla#457) (mozilla#484) r-rnewman

* Implement exit command for cli tool

* Address review comments r=rnewman

* Include exit commands in help

* Show schema of current DB (mozilla#487)

* Fixing rebase issues

* addressing nit

* Match updated dependencies on CLI crate and remove unused import
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants