Open DB inside CLI (#452)#463
Conversation
| static COMMANDS: &'static [CommandDef] = &[ | ||
| CommandDef{name: "open", args: Some("<database>"), | ||
| accepts: CmdArgs::Text, | ||
| help: "Open a database with the provided name. Creates a new database of that name if it doesn't already exist."}, |
There was a problem hiding this comment.
Is this a path, a URI, or a name?
There was a problem hiding this comment.
Should we also add close?
| ]; | ||
|
|
||
| /// Looks up a command name by what may be an abbreviated prefix. | ||
| /// Returns the `CommandDef` structure if one is found. |
There was a problem hiding this comment.
This is a hacky way of doing what getopts calls abbreviation to uniqueness. It'll only work so long as none of your commands share a prefix — close and create, for example, will clash for .c.
Think about whether you need to do this.
| /// Looks up a command name by what may be an abbreviated prefix. | ||
| /// Returns the `CommandDef` structure if one is found. | ||
| pub fn lookup_command(name: &str) -> Option<&'static CommandDef> { | ||
| for cmd in COMMANDS.iter() { |
There was a problem hiding this comment.
Use .find instead of iterating manually. This becomes a one-liner.
| } | ||
|
|
||
| /// Calls the given closure for each command whose name begins with `prefix`. | ||
| pub fn search_command<F>(prefix: &str, mut f: F) |
| } | ||
| }, | ||
| InputError(err) => { | ||
| if let Some(err) = err { |
There was a problem hiding this comment.
When will we not have an error in the input error? In that case, can we have a different enum?
| fn handle_command(&mut self, cmd: String, args: Option<String>) { | ||
| println!("{:?} {:?}", cmd, args); | ||
| match lookup_command(&cmd).map(|c| c.name) { | ||
| Some("open") => { |
There was a problem hiding this comment.
Look up map_or and unwrap_or and friends.
| match self { | ||
| &Command::Query(_) | | ||
| &Command::Transact(_) => false, | ||
| _ => true |
There was a problem hiding this comment.
Enumerate every command rather than using _ — that way this'll fail to compile if you add a new command and forget to extend this match!
| Command::Help(args) | ||
| }); | ||
|
|
||
| let open_parser = string(OPEN_COMMAND).and(space()).and(many1::<Vec<_>, _>(alpha_num()).and(eof())).map(|x| { |
There was a problem hiding this comment.
Shouldn't this be skip_many(space())?
There was a problem hiding this comment.
For a file path you'll need more than alpha_num:
mentat=> .open /tmp/foo.db
Invalid command ".open /tmp/foo.db"
mentat=> .open foo.db
Invalid command ".open foo.db"
| .and(choice::<[&mut Parser<Input = _, Output = Command>; 3], _> | ||
| ([&mut try(help_parser), | ||
| &mut try(open_parser), | ||
| &mut try(close_parser),])) |
There was a problem hiding this comment.
If you put .skip(eof()) on the end here, you can remove it from the parsers above.
| match self.reader { | ||
| Some(ref mut r) => { | ||
| r.set_prompt(prompt); | ||
| r.read_line().ok().and_then(|line| line) |
There was a problem hiding this comment.
Why do we need that and_then?
| } | ||
|
|
||
| fn db_output_name(db_name: &String) -> String { | ||
| if db_name.is_empty() { "in memory db".to_string() } else { db_name.clone() } |
| // CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations under the License. | ||
|
|
||
| use combine::{eof, many, many1, sep_by, skip_many, token, Parser}; |
|
|
||
| let close_parser = string(CLOSE_COMMAND).and(skip_many(space())).and(eof()).map( |_| Command::Close ); | ||
|
|
||
| token('.') |
There was a problem hiding this comment.
Allow leading whitespace?
mentat=> .help
Invalid command " .help"
| } | ||
| } else { | ||
| for arg in args { | ||
| let msg = COMMAND_HELP.get(arg.as_str()); |
There was a problem hiding this comment.
You should allow the command arg to start with a . — I immediately typed .help .open and got all of the commands, 'cos it wanted .help open.
| Command::Open(db) => { | ||
| self.store.open(Some(db)); | ||
| }, | ||
| Command::Close => self.store.close(), |
There was a problem hiding this comment.
mentat=> .open foo
Database "foo" opened
mentat=> .close
Database "foo" closed
mentat=> .close
Database "in memory db" closed
mentat=> .close
Database "in memory db" closed
I think we should consider having quit == close, and open = close+open, just like sqlite3.
There was a problem hiding this comment.
so to close the existing db and open a new in-memory DB would be
mentat=> .open
to close existing db and exit would be
mentat=> .quit
?
ncalexan
left a comment
There was a problem hiding this comment.
I suggested some parsing changes and some changes to the types, specifically around using Result. Feel free to counter; I haven't read your interactions with @rnewman, which would probably cover this.
For the next review round, let's fold this down to 1-2 commits. The iteration of the change sequence is not helping review.
|
|
||
| [workspace] | ||
| members = [] | ||
| members = ["tools/cli"] |
There was a problem hiding this comment.
Hmm, I had to go read https://github.com/nox/rust-rfcs/blob/master/text/1525-cargo-workspace.md to understand this. Should we be using workspaces more generally? If I understand correctly, we could make most of the existing crates share a workspace, avoiding to rebuild shared dependencies.
| // CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations under the License. | ||
|
|
||
| use combine::{any, eof, many, many1, sep_by, skip_many, token, Parser}; |
There was a problem hiding this comment.
We settled on the
use very::{
long,
vertical,
list,
style,
};|
|
||
| pub fn command(s: &str) -> Command { | ||
| let help_parser = string(HELP_COMMAND) | ||
| .and(skip_many(space())) |
There was a problem hiding this comment.
.with and .skip let you drop leading and trailing input, respectively. So this is equivalent to
string("help").with(skip_many(space())).with(many::<Vec<_>, _> ...Then you won't need to index in the way you are.
| let help_parser = string(HELP_COMMAND) | ||
| .and(skip_many(space())) | ||
| .and(many::<Vec<_>, _>(try(any()))) | ||
| .map(|x| { |
There was a problem hiding this comment.
So, you're parsing whitespace separated strings here; why not use combine to do this? I'll push a patch to show what I mean.
| Help(Vec<String>), | ||
| Open(String), | ||
| Close, | ||
| Err(String), |
There was a problem hiding this comment.
You've encoded errors into your Command type, which seems unnatural to me. Why not use Result<Command, AppropriateErrorType> as appropriate?
| } | ||
|
|
||
| impl Command { | ||
| pub fn is_complete(&self) -> bool { |
There was a problem hiding this comment.
A comment explaining what "complete" means would help.
| } | ||
| } | ||
|
|
||
| #[test] |
| } | ||
| } | ||
|
|
||
| fn help_command(&self, args: Vec<String>) { |
There was a problem hiding this comment.
Github wouldn't let me comment on the tools/cli/src/mentat_cli/store.rs file, so here it is:
I expect we will want to grow this into something (like Conn) in core, so rather than expect() and swallowing the underlying error, can we return Result<Store, AppropriateErrorType> and handle errors like this at a higher level?
If you really want Store to be CLI specific and to handle errors inline, I think you need to surface the underlying error in some way.
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
* Closes existing open db and opens new in memory db
Move over to using Result rather than enums with err
c0adac7 to
b3ff534
Compare
* 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
* 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
* 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
* 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
* 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
.open [db_name]#452