parser/
parser.rs

1// [[file:../gosh-shell.note::70d3dbdb][70d3dbdb]]
2#![deny(warnings)]
3
4use gosh_repl::{Actionable, Interpreter};
5
6use gut::cli::*;
7use gut::prelude::*;
8// 70d3dbdb ends here
9
10// [[file:../gosh-shell.note::724d9a95][724d9a95]]
11#[derive(Parser, Debug)]
12#[clap(disable_help_subcommand = true)]
13enum Cmd {
14    /// Quit shell.
15    #[command(name = "quit", alias = "q", alias = "exit")]
16    Quit {},
17
18    /// Show available commands.
19    #[command(name = "help", alias = "h", alias = "?")]
20    Help {},
21
22    /// Load file from `path` for processing.
23    #[command(name = "load")]
24    Load {
25        #[clap(name = "FILENAME")]
26        path: String,
27    },
28}
29// 724d9a95 ends here
30
31// [[file:../gosh-shell.note::a252f98f][a252f98f]]
32#[derive(Debug, Default, Clone)]
33struct Action {
34    // state var during REPL
35    _state: Option<Vec<String>>,
36}
37
38impl Actionable for Action {
39    type Command = Cmd;
40
41    /// Take action on REPL commands. Return Ok(true) will exit shell
42    /// loop.
43    fn act_on(&mut self, cmd: &Cmd) -> Result<bool> {
44        match cmd {
45            Cmd::Quit {} => return Ok(true),
46
47            Cmd::Help {} => {
48                let mut app = Cmd::command();
49                if let Err(err) = app.print_help() {
50                    eprintln!("clap error: {err:?}");
51                }
52                println!("");
53            }
54
55            o => {
56                eprintln!("{:?}: not implemented yet!", o);
57            }
58        }
59
60        Ok(false)
61    }
62}
63// a252f98f ends here
64
65// [[file:../gosh-shell.note::f12dda7e][f12dda7e]]
66mod cli {
67    #![deny(warnings)]
68
69    use super::*;
70    use std::path::PathBuf;
71
72    #[derive(Parser, Debug)]
73    pub struct ReplCli {
74        /// Execute REPL script
75        #[clap(short = 'x')]
76        script_file: Option<PathBuf>,
77
78        #[clap(flatten)]
79        verbose: Verbosity,
80    }
81
82    impl ReplCli {
83        pub fn enter_main() -> Result<()> {
84            let args: Vec<String> = std::env::args().collect();
85
86            let action = Action::default();
87            // enter shell mode or subcommands mode
88            if args.len() > 1 {
89                let args = Self::parse();
90                args.verbose.setup_logger();
91
92                if let Some(script_file) = &args.script_file {
93                    info!("Execute script file: {:?}", script_file);
94                    Interpreter::new(action).interpret_script_file(script_file)?;
95                } else {
96                    info!("Reading batch script from stdin ..");
97                    let mut buffer = String::new();
98                    std::io::stdin().read_to_string(&mut buffer)?;
99                    Interpreter::new(action).interpret_script(&buffer)?;
100                }
101            } else {
102                Interpreter::new(action).with_prompt("gosh> ").run()?;
103            }
104
105            Ok(())
106        }
107    }
108}
109// f12dda7e ends here
110
111// [[file:../gosh-shell.note::e817ae85][e817ae85]]
112fn main() -> Result<()> {
113    cli::ReplCli::enter_main()?;
114    Ok(())
115}
116// e817ae85 ends here