]> git.sondrewold.no Git - octo.git/commitdiff
Editor and Terminal basics
authorSondre Wold <[email protected]>
Sun, 21 Apr 2024 05:21:15 +0000 (07:21 +0200)
committerSondre Wold <[email protected]>
Sun, 21 Apr 2024 05:21:15 +0000 (07:21 +0200)
octo/Cargo.toml
octo/src/.editor.rs.swp [new file with mode: 0644]
octo/src/.terminal.rs.swp [new file with mode: 0644]
octo/src/editor.rs [new file with mode: 0644]
octo/src/main.rs
octo/src/terminal.rs [new file with mode: 0644]

index 17e593bccc81ec264bfff5adc09cf401f9e32c53..bc088c14a3dff29e3cdf5810f2f33d42b191e5d1 100644 (file)
@@ -6,3 +6,5 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+crossterm = "0.27.0"
+termion = "3.0.0"
diff --git a/octo/src/.editor.rs.swp b/octo/src/.editor.rs.swp
new file mode 100644 (file)
index 0000000..e95abb7
Binary files /dev/null and b/octo/src/.editor.rs.swp differ
diff --git a/octo/src/.terminal.rs.swp b/octo/src/.terminal.rs.swp
new file mode 100644 (file)
index 0000000..58f6258
Binary files /dev/null and b/octo/src/.terminal.rs.swp differ
diff --git a/octo/src/editor.rs b/octo/src/editor.rs
new file mode 100644 (file)
index 0000000..bef7795
--- /dev/null
@@ -0,0 +1,60 @@
+use crate::Terminal;
+use termion::event::Key;
+
+fn die(e: std::io::Error) {
+    Terminal::clear_screen();
+    panic!("{:?}", e);
+}
+
+pub struct Editor {
+    should_quit: bool,
+    terminal: Terminal,
+}
+
+impl Editor {
+    pub fn run(&mut self) {
+        loop {
+            if let Err(error) = self.refresh_screen() {
+                die(error);
+            }
+            if self.should_quit {
+                break;
+            }
+            if let Err(error) = self.process_keypress() {
+                die(error);
+            }
+        }
+    }
+    pub fn default() -> Self {
+        Self {
+            should_quit: false,
+            terminal: Terminal::default().expect("Failed to create terminal"),
+        }
+    }
+
+    fn refresh_screen(&self) -> Result<(), std::io::Error> {
+        Terminal::clear_screen();
+        Terminal::cursor_position(0, 0);
+        if self.should_quit {
+            println!("Goodbye.\r");
+        } else {
+            self.draw_rows();
+            Terminal::cursor_position(0, 0);
+        }
+        Terminal::flush()
+    }
+
+    fn process_keypress(&mut self) -> Result<(), std::io::Error> {
+        let pressed_key = Terminal::read_key()?;
+        match pressed_key {
+            Key::Ctrl('q') => self.should_quit = true,
+            _ => (),
+        };
+        Ok(())
+    }
+    fn draw_rows(&self) {
+        for _ in 0..self.terminal.size().height {
+            println!("~\r");
+        }
+    }
+}
index e7a11a969c037e00a796aafeff6258501ec15e9a..06376819a73a557d54c5a549c8c6ac30ef93d646 100644 (file)
@@ -1,3 +1,9 @@
+#![warn(clippy::all, clippy::pedantic)]
+mod editor;
+mod terminal;
+use editor::Editor;
+pub use terminal::Terminal;
+
 fn main() {
-    println!("Hello, world!");
+    Editor::default().run();
 }
diff --git a/octo/src/terminal.rs b/octo/src/terminal.rs
new file mode 100644 (file)
index 0000000..599d873
--- /dev/null
@@ -0,0 +1,52 @@
+use std::io::{self, stdout, Write};
+use termion::event::Key;
+use termion::input::TermRead;
+use termion::raw::{IntoRawMode, RawTerminal};
+
+pub struct Size {
+    pub width: u16,
+    pub height: u16,
+}
+
+pub struct Terminal {
+    size: Size,
+    _stdout: RawTerminal<std::io::Stdout>,
+}
+
+impl Terminal {
+    pub fn default() -> Result<Self, std::io::Error> {
+        let size = termion::terminal_size()?;
+        Ok(Self {
+            size: Size {
+                width: size.0,
+                height: size.1,
+            },
+            _stdout: stdout().into_raw_mode()?,
+        })
+    }
+    pub fn size(&self) -> &Size {
+        &self.size
+    }
+
+    pub fn clear_screen() {
+        print!("{}", termion::clear::All);
+    }
+
+    pub fn cursor_position(x: u16, y: u16) {
+        let x = x.saturating_add(1);
+        let y = y.saturating_add(1);
+        print!("{}", termion::cursor::Goto(x, y));
+    }
+
+    pub fn flush() -> Result<(), std::io::Error> {
+        io::stdout().flush()
+    }
+
+    pub fn read_key() -> Result<Key, std::io::Error> {
+        loop {
+            if let Some(key) = io::stdin().lock().keys().next() {
+                return key;
+            }
+        }
+    }
+}