/* relish: versatile lisp shell * Copyright (C) 2021 Aidan Hahn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ use dirs::home_dir; use relish::ast::{eval, lex, Ctr, Seg, SymTable}; use relish::aux::configure; use relish::stdlib::{dynamic_stdlib, static_stdlib}; use rustyline::error::ReadlineError; use rustyline::Editor; use std::env; fn main() { let mut rl = Editor::<()>::new(); const HIST_FILE: &str = "/.relish_hist"; const CONFIG_FILE_DEFAULT: &str = "/.relishrc"; let home_dir = home_dir().unwrap().to_str().unwrap().to_owned(); let hist_file_name = home_dir.clone() + HIST_FILE; let cfg_file_name = home_dir + CONFIG_FILE_DEFAULT; if !hist_file_name.is_empty() { rl.load_history(&hist_file_name) .unwrap_or_else(|err: ReadlineError| eprintln!("{}", err)); } let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap_or_else(|err: String| eprintln!("{}", err)); dynamic_stdlib(&mut syms).unwrap_or_else(|err: String| eprintln!("{}", err)); { // scope the below borrow of syms let cfg_file = env::var("RELISH_CFG_FILE").unwrap_or(cfg_file_name); configure(cfg_file.clone(), &mut syms) .unwrap_or_else(|err: String| eprintln!("failed to load script {}\n{}", cfg_file, err)); } dynamic_stdlib(&mut syms).unwrap_or_else(|err: String| eprintln!("{}", err)); loop { let s = *syms .call_symbol(&"CFG_RELISH_PROMPT".to_string(), &Seg::new(), true) .unwrap_or_else(|err: String| { eprintln!("{}", err); Box::new(Ctr::String("".to_string())) }); let readline_prompt = s.to_string(); let user_doc = rl.readline(&readline_prompt); match user_doc { Ok(line) => { rl.add_history_entry(line.as_str()); let l = line.as_str().to_owned(); match lex(&l) { Ok(a) => match eval(&a, &mut syms) { Ok(a) => println!("{}", a), Err(s) => println!("{}", s), }, Err(s) => println!("{}", s), } } Err(ReadlineError::Interrupted) => break, Err(ReadlineError::Eof) => return, Err(err) => { eprintln!("Prompt error: {:?}", err); break; } } } if !hist_file_name.is_empty() { rl.save_history(&hist_file_name).unwrap(); } }