extern crate caldyn;
extern crate rustyline;
extern crate shellexpand;
use caldyn::Context;
use rustyline::Editor;
use std::io;
use std::io::prelude::*;
fn main() {
let args = std::env::args().collect::<Vec<_>>();
if args.len() > 1 {
eval_args(&args[1..]);
} else {
repl()
}
}
fn eval_args(args: &[String]) {
let input = args.join(" ");
match caldyn::eval(&input, None) {
Ok(value) => println!("{}", value),
Err(error) => {
let _ = writeln!(io::stderr(), "{}", error);
}
}
}
fn repl() {
let history_path = &shellexpand::tilde("~/.calcrs_history").into_owned();
let mut editor = Editor::<()>::new();
let _ = editor.load_history(history_path);
let mut context = Context::new();
loop {
let line = editor.readline(">> ");
match line {
Ok(line) => {
editor.add_history_entry(&line);
if line.contains('=') {
add_variable(&mut context, &line);
} else {
match caldyn::eval(&line, &context) {
Ok(value) => println!("{}", value),
Err(error) => {
let _ = writeln!(io::stderr(), "{}", error);
}
}
}
}
Err(_) => break,
}
}
let _ = editor.save_history(history_path);
}
fn add_variable(context: &mut Context, line: &str) {
assert!(line.contains('='));
let splitted = line.split('=').collect::<Vec<_>>();
if splitted.len() != 2 {
let _ = writeln!(io::stderr(), "error: too many = signs");
return;
}
let var = splitted[0].trim();
let value = splitted[1];
if !caldyn::is_variable(var) {
let _ = writeln!(io::stderr(), "error: '{}' is not a valid variable name", var);
return;
}
match caldyn::eval(value, &*context) {
Ok(value) => context.set(var, value),
Err(error) => {
let _ = writeln!(io::stderr(), "{}", error);
}
}
}