1pub mod command_line;
2pub mod editor;
3pub mod theme;
4
5use std::error;
6
7use strum_macros::{Display, EnumString};
8
9use crate::commands::Command;
10
11use self::{command_line::CommandLine, editor::EditorBuffer, theme::Theme};
12
13pub type AppResult<T> = std::result::Result<T, Box<dyn error::Error>>;
15
16#[derive(Display, Debug, EnumString, PartialEq, Clone, Copy)]
18pub enum InputMode {
19 Normal,
20 Insert,
21 Command,
22}
23
24#[derive(Debug)]
26pub struct App {
27 pub running: bool,
29 pub mode: InputMode,
31 pub command_line: CommandLine,
33 pub theme: Theme,
35 pub editor: EditorBuffer,
37}
38
39impl Default for App {
40 fn default() -> Self {
41 Self {
42 running: true,
43 mode: InputMode::Normal,
44 command_line: CommandLine::default(),
45 theme: Theme::default(),
46 editor: EditorBuffer::default(),
47 }
48 }
49}
50
51impl App {
52 pub fn new(file: String) -> Self {
54 Self {
55 running: true,
56 mode: InputMode::Normal,
57 command_line: CommandLine::default(),
58 theme: Theme::default(),
59 editor: EditorBuffer::from_file(file),
60 }
61 }
62
63 pub fn tick(&self) {}
65
66 pub fn execute(&mut self, commands: Vec<Command>) -> AppResult<()> {
68 for command in commands {
69 self.execute_single_command(command)?;
70 }
71 Ok(())
72 }
73
74 fn execute_single_command(&mut self, command: Command) -> AppResult<()> {
76 match command {
77 Command::Quit => self.quit(),
78 Command::CommandLineStop => self.command_line.deactivate(),
79 Command::CommandLineInsertChar(ch) => self.command_line.enter_char(ch),
80 Command::CommandLineDelete => self.command_line.delete_char(),
81 Command::CommandLineLeft => self.command_line.move_cursor_left(),
82 Command::CommandLineRight => self.command_line.move_cursor_right(),
83 Command::CommandLineEnter => {
84 self.execute(self.command_line.get_commands())?;
85 }
86 Command::ChangeInputMode(mode) => self.change_input_mode(mode),
87 Command::EditorInsert(to_insert) => self.editor.insert(to_insert, self.mode),
88 Command::EditorDelete(motion) => self.editor.delete(motion, self.mode),
89 Command::EditorMove(motion) => self.editor.move_cursor(&motion, self.mode),
90 Command::EditorSave => self.editor.save()?,
91 };
92 Ok(())
93 }
94
95 fn quit(&mut self) {
97 self.running = false;
98 }
99
100 fn change_input_mode(&mut self, input_mode: InputMode) {
102 self.mode = input_mode
103 }
104}