summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs96
1 files changed, 94 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs
index c9de2c5..80645df 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,98 @@
 #![forbid(unsafe_code)]
+use crate::commands::{ Command, CommandMap, Mode };
+use crate::error::*;
 
-fn main() {
-  println!("yay");
+use std::io::Write;
+
+mod commands;
+mod error;
+
+
+struct TopLevelMode {
+  command_map: Box<CommandMap<TopLevelMode>>,
+}
+
+impl TopLevelMode {
+  fn new() -> Result<Self> {
+    let mut command_map = Box::new(CommandMap::new());
+
+    command_map.insert(Command::new("help", |mode, _params| {
+      println!("help        Print this message.");
+      println!("quit        Exit the program.");
+
+      Ok(Some(mode))
+    }))?;
+
+    command_map.insert(Command::new("quit", |_mode, _params| {
+      Ok(None)
+    }))?;
+
+    Ok(TopLevelMode { command_map })
+  }
+}
+
+impl Mode for TopLevelMode {
+  fn prompt_text(&self) -> Result<&str> {
+    Ok("secrets>")
+  }
+
+  fn dispatch(self: Box<Self>, params: &[&str])
+    -> Result<Option<Box<dyn Mode>>>
+  {
+    if params.len() > 0 {
+      if let Some(command) = self.command_map.get(params[0]) {
+        (command.implementation)(self, &params[1..])
+      } else {
+        println!("No command named {}. Type help if you need help.",
+                 params[0]);
+        Ok(Some(self))
+      }
+    } else {
+      default_empty_command()?;
+
+      Ok(Some(self))
+    }
+  }
+}
+
+
+fn default_empty_command() -> Result<()> {
+  println!("No command? Type help if you need help.");
+
+  Ok(())
+}
+
+
+fn main() -> Result<()> {
+  help();
+
+  let mut current_mode: Option<Box<dyn Mode>>
+    = Some(Box::new(TopLevelMode::new()?));
+
+  while let Some(mode) = current_mode {
+    if let Some(input) = prompt(mode.prompt_text()?)? {
+      let words: Vec<&str> = input.split_whitespace().collect();
+
+      current_mode = mode.dispatch(&words[..])?;
+    } else {
+      current_mode = None;
+    }
+  }
+
+  Ok(())
+}
+
+
+fn help() {
+  println!("Type a command (there are none yet)");
+}
+
+
+fn prompt(raw: &str) -> Result<Option<String>> {
+  let mut stdout = std::io::stdout();
+  stdout.write_all(format!("\n{} ", raw).as_bytes())?;
+  stdout.flush()?;
+
+  Ok(std::io::stdin().lines().next().transpose()?)
 }