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

View file

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

View file

@ -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)]