main.rs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. use matzo::interp::State;
  2. use clap::{Arg, App};
  3. #[derive(Debug)]
  4. struct Opts {
  5. seed: Option<u64>,
  6. files: Vec<String>,
  7. }
  8. impl Opts {
  9. fn parse() -> Opts {
  10. let matches = App::new("Matzo")
  11. .setting(clap::AppSettings::TrailingVarArg)
  12. .version(format!("git {}", env!("VERGEN_GIT_SHA")).as_ref())
  13. .author("Getty Ritter <matzo@infinitenegativeutility.com>")
  14. .about("A language for random text")
  15. .arg(Arg::with_name("seed")
  16. .short("s")
  17. .long("seed")
  18. .value_name("NUMBER")
  19. .help("Sets a custom RNG seed")
  20. .takes_value(true))
  21. .arg(Arg::with_name("input")
  22. .value_name("FILES")
  23. .help("Files to evaluate")
  24. .multiple(true)
  25. .takes_value(true))
  26. .get_matches();
  27. let seed = matches.value_of("seed").map(|s| s.parse().unwrap());
  28. let mut files = Vec::new();
  29. if let Some(fs) = matches.values_of("input") {
  30. files.extend(fs.map(|x| x.to_string()));
  31. }
  32. Opts { seed, files }
  33. }
  34. }
  35. fn matzo_version() -> String {
  36. format!("matzo (git {})", env!("VERGEN_GIT_SHA"))
  37. }
  38. fn run_repl(seed: Option<u64>) -> Result<(), Box<dyn std::error::Error>> {
  39. let mut rl = rustyline::Editor::<matzo::repl::Repl>::new();
  40. let state = if let Some(s) = seed {
  41. State::new_from_seed(s)
  42. } else {
  43. State::new()
  44. };
  45. let state = std::rc::Rc::new(std::cell::RefCell::new(state));
  46. rl.set_helper(Some(matzo::repl::Repl::new(state.clone())));
  47. println!("{}", ansi_term::Colour::Blue.bold().paint(matzo_version()),);
  48. println!("{}", ansi_term::Colour::Blue.paint("(work-in-progress)"),);
  49. loop {
  50. let line = match rl.readline(">>> ") {
  51. Ok(ln) => ln,
  52. Err(rustyline::error::ReadlineError::Eof)
  53. | Err(rustyline::error::ReadlineError::Interrupted) => return Ok(()),
  54. err => err?,
  55. };
  56. if let Err(err) = state.borrow_mut().run_repl(&line) {
  57. eprintln!(
  58. "{} {}",
  59. ansi_term::Colour::Red.bold().paint("error:"),
  60. ansi_term::Colour::Red.paint(format!("{}", err)),
  61. );
  62. }
  63. }
  64. }
  65. fn main() {
  66. let opts = Opts::parse();
  67. if opts.files.is_empty() {
  68. run_repl(opts.seed).unwrap();
  69. return;
  70. }
  71. let state = if let Some(s) = opts.seed {
  72. State::new_from_seed(s)
  73. } else {
  74. State::new()
  75. };
  76. for arg in opts.files {
  77. let buf = std::fs::read_to_string(arg).unwrap();
  78. if let Err(err) = state.run(&buf) {
  79. eprintln!(
  80. "{} {}",
  81. ansi_term::Colour::Red.bold().paint("error:"),
  82. ansi_term::Colour::Red.paint(format!("{}", err)),
  83. );
  84. }
  85. }
  86. }