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:
Emily Toop 2017-06-01 12:20:18 +01:00
parent ced479c466
commit 401abde971
3 changed files with 62 additions and 67 deletions

View file

@ -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;

View file

@ -13,8 +13,15 @@ use std::io::stdin;
use linefeed::Reader;
use linefeed::terminal::DefaultTerminal;
use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::path::Path;
use self::InputResult::*;
use edn;
use command_parser::{
Command,
command
@ -71,6 +78,44 @@ impl InputReader {
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`.
/// Returns `More` if further input is required for a complete result.
/// In this case, the input received so far is buffered internally.

View file

@ -9,19 +9,8 @@
// specific language governing permissions and limitations under the License.
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 errors as cli;
use edn;
use mentat::query::QueryResults;
use mentat_core::TypedValue;
use command_parser::{
Command,
HELP_COMMAND,
@ -33,6 +22,7 @@ use command_parser::{
READ_COMMAND,
};
use input::InputReader;
use input::InputResult;
use input::InputResult::{
MetaCommand,
Empty,
@ -76,17 +66,27 @@ impl Repl {
pub fn run(&mut self, startup_commands: Option<Vec<Command>>) {
let mut input = InputReader::new();
let mut unexecuted_commands: Vec<InputResult> = Vec::new();
if let Some(cmds) = startup_commands {
for command in cmds.iter() {
println!("{}", command.output());
self.handle_command(command.clone());
}
unexecuted_commands.append(&mut cmds.into_iter().map(|c| MetaCommand(c.clone())).collect());
}
loop {
let res = input.read_input();
let res = if unexecuted_commands.len() > 0 { Ok(unexecuted_commands.remove(0)) } else { input.read_input() };
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)) => {
debug!("read command: {:?}", cmd);
self.handle_command(cmd);
@ -123,7 +123,7 @@ impl Repl {
},
Command::Query(query) => self.execute_query(query),
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()),
}
}
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)]