Rewrite the way we read in files.
* Move file reading into Input rather than repl. * Handle file command in run in repl. * Create unexecuted_commands list containing all of the commands left to execute and handle them inside run. * Move command line args into unexecuted_commands.
This commit is contained in:
parent
ced479c466
commit
401abde971
3 changed files with 62 additions and 67 deletions
|
@ -13,7 +13,6 @@ use combine::{
|
||||||
eof,
|
eof,
|
||||||
look_ahead,
|
look_ahead,
|
||||||
many1,
|
many1,
|
||||||
parser,
|
|
||||||
satisfy,
|
satisfy,
|
||||||
sep_end_by,
|
sep_end_by,
|
||||||
token,
|
token,
|
||||||
|
@ -29,8 +28,6 @@ use combine::combinator::{
|
||||||
try
|
try
|
||||||
};
|
};
|
||||||
|
|
||||||
use combine::primitives::Consumed;
|
|
||||||
|
|
||||||
use errors as cli;
|
use errors as cli;
|
||||||
|
|
||||||
use edn;
|
use edn;
|
||||||
|
|
|
@ -13,8 +13,15 @@ use std::io::stdin;
|
||||||
use linefeed::Reader;
|
use linefeed::Reader;
|
||||||
use linefeed::terminal::DefaultTerminal;
|
use linefeed::terminal::DefaultTerminal;
|
||||||
|
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use self::InputResult::*;
|
use self::InputResult::*;
|
||||||
|
|
||||||
|
use edn;
|
||||||
|
|
||||||
use command_parser::{
|
use command_parser::{
|
||||||
Command,
|
Command,
|
||||||
command
|
command
|
||||||
|
@ -71,6 +78,44 @@ impl InputReader {
|
||||||
self.reader.is_some()
|
self.reader.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_file(&mut self, filename: &String) -> Result<Vec<InputResult>, cli::Error> {
|
||||||
|
let path = Path::new(&filename);
|
||||||
|
let display = path.display();
|
||||||
|
|
||||||
|
let f = match File::open(&path) {
|
||||||
|
Err(err) => bail!(cli::ErrorKind::FileError(display.to_string(), err.to_string())),
|
||||||
|
Ok(file) => file,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buffer = String::new();
|
||||||
|
|
||||||
|
let file = BufReader::new(&f);
|
||||||
|
let mut cmd_err: Option<edn::ParseError> = None;
|
||||||
|
|
||||||
|
let mut results: Vec<InputResult> = Vec::new();
|
||||||
|
for line in file.lines() {
|
||||||
|
let l = line.unwrap();
|
||||||
|
println!("{}", l);
|
||||||
|
buffer.push_str(&l);
|
||||||
|
let cmd = Command::Transact(buffer.to_string());
|
||||||
|
let (is_complete, err) = cmd.is_complete();
|
||||||
|
if is_complete {
|
||||||
|
results.push(InputResult::MetaCommand(cmd));
|
||||||
|
buffer.clear();
|
||||||
|
cmd_err = None;
|
||||||
|
} else {
|
||||||
|
cmd_err = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(err) = cmd_err {
|
||||||
|
bail!(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(results)
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads a single command, item, or statement from `stdin`.
|
/// Reads a single command, item, or statement from `stdin`.
|
||||||
/// Returns `More` if further input is required for a complete result.
|
/// Returns `More` if further input is required for a complete result.
|
||||||
/// In this case, the input received so far is buffered internally.
|
/// In this case, the input received so far is buffered internally.
|
||||||
|
|
|
@ -9,19 +9,8 @@
|
||||||
// specific language governing permissions and limitations under the License.
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::BufReader;
|
|
||||||
use std::io::BufRead;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::path::Path;
|
|
||||||
use error_chain::ChainedError;
|
use error_chain::ChainedError;
|
||||||
|
|
||||||
use errors as cli;
|
|
||||||
|
|
||||||
use edn;
|
|
||||||
|
|
||||||
use mentat::query::QueryResults;
|
|
||||||
use mentat_core::TypedValue;
|
|
||||||
|
|
||||||
use command_parser::{
|
use command_parser::{
|
||||||
Command,
|
Command,
|
||||||
HELP_COMMAND,
|
HELP_COMMAND,
|
||||||
|
@ -33,6 +22,7 @@ use command_parser::{
|
||||||
READ_COMMAND,
|
READ_COMMAND,
|
||||||
};
|
};
|
||||||
use input::InputReader;
|
use input::InputReader;
|
||||||
|
use input::InputResult;
|
||||||
use input::InputResult::{
|
use input::InputResult::{
|
||||||
MetaCommand,
|
MetaCommand,
|
||||||
Empty,
|
Empty,
|
||||||
|
@ -76,17 +66,27 @@ impl Repl {
|
||||||
pub fn run(&mut self, startup_commands: Option<Vec<Command>>) {
|
pub fn run(&mut self, startup_commands: Option<Vec<Command>>) {
|
||||||
let mut input = InputReader::new();
|
let mut input = InputReader::new();
|
||||||
|
|
||||||
|
let mut unexecuted_commands: Vec<InputResult> = Vec::new();
|
||||||
|
|
||||||
if let Some(cmds) = startup_commands {
|
if let Some(cmds) = startup_commands {
|
||||||
for command in cmds.iter() {
|
unexecuted_commands.append(&mut cmds.into_iter().map(|c| MetaCommand(c.clone())).collect());
|
||||||
println!("{}", command.output());
|
|
||||||
self.handle_command(command.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let res = input.read_input();
|
let res = if unexecuted_commands.len() > 0 { Ok(unexecuted_commands.remove(0)) } else { input.read_input() };
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
|
Ok(MetaCommand(Command::Read(files))) => {
|
||||||
|
for file in files {
|
||||||
|
let file_res = input.read_file(&file);
|
||||||
|
if let Ok(commands) = file_res {
|
||||||
|
unexecuted_commands.append(&mut commands.clone());
|
||||||
|
} else {
|
||||||
|
println!("{:?}", file_res.err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Ok(MetaCommand(cmd)) => {
|
Ok(MetaCommand(cmd)) => {
|
||||||
debug!("read command: {:?}", cmd);
|
debug!("read command: {:?}", cmd);
|
||||||
self.handle_command(cmd);
|
self.handle_command(cmd);
|
||||||
|
@ -123,7 +123,7 @@ impl Repl {
|
||||||
},
|
},
|
||||||
Command::Query(query) => self.execute_query(query),
|
Command::Query(query) => self.execute_query(query),
|
||||||
Command::Transact(transaction) => self.execute_transact(transaction),
|
Command::Transact(transaction) => self.execute_transact(transaction),
|
||||||
Command::Read(file) => self.read_files(file),
|
Command::Read(_) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,53 +169,6 @@ impl Repl {
|
||||||
Result::Err(err) => println!("{}.", err.display()),
|
Result::Err(err) => println!("{}.", err.display()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_files(&mut self, files: Vec<String>) {
|
|
||||||
for file in files {
|
|
||||||
let res = self.read_file(file);
|
|
||||||
if res.is_err() {
|
|
||||||
match res.unwrap_err() {
|
|
||||||
cli::Error(err, _) => { println!("{}", err) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_file(&mut self, file: String) -> Result<(), cli::Error> {
|
|
||||||
let path = Path::new(&file);
|
|
||||||
let display = path.display();
|
|
||||||
|
|
||||||
let f = match File::open(&path) {
|
|
||||||
Err(err) => bail!(cli::ErrorKind::FileError(display.to_string(), err.to_string())),
|
|
||||||
Ok(file) => file,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut buffer = String::new();
|
|
||||||
let mut cmd_err: Option<edn::ParseError> = None;
|
|
||||||
|
|
||||||
let file = BufReader::new(&f);
|
|
||||||
for line in file.lines() {
|
|
||||||
let l = line.unwrap();
|
|
||||||
println!("{}", l);
|
|
||||||
buffer.push_str(&l);
|
|
||||||
let cmd = Command::Transact(buffer.to_string());
|
|
||||||
let (is_complete, err) = cmd.is_complete();
|
|
||||||
if is_complete {
|
|
||||||
self.handle_command(cmd);
|
|
||||||
buffer.clear();
|
|
||||||
cmd_err = None;
|
|
||||||
} else {
|
|
||||||
cmd_err = err;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(err) = cmd_err {
|
|
||||||
println!("\nUnable to parse edn: {}", err.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in a new issue