diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-03-27 03:42:32 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-03-27 03:42:32 -0700 |
| commit | 10327d770eb19764d1e272d2f32a4f0e3edd9062 (patch) | |
| tree | cc70187f69116b4fb48aef1569e3dece2b05027a /src | |
| parent | 4997c2a4e4856b49668a3d1257e967597c7dfb92 (diff) | |
add a loop that reads a character of user input
(right now it exits after the first time, doing nothing) Force-Push: yes Change-Id: I89f8d3d298e6a42e373e536121e6b434e30ef66f
Diffstat (limited to 'src')
| -rw-r--r-- | src/encoding.rs | 28 | ||||
| -rw-r--r-- | src/main.rs | 53 | ||||
| -rw-r--r-- | src/terminal.rs | 32 | ||||
| -rw-r--r-- | src/types.rs | 1 |
4 files changed, 100 insertions, 14 deletions
diff --git a/src/encoding.rs b/src/encoding.rs new file mode 100644 index 0000000..7d5326e --- /dev/null +++ b/src/encoding.rs @@ -0,0 +1,28 @@ +#![forbid(unsafe_code)] + + +#[derive(Clone, Copy, Debug)] +pub enum UTF8ByteType { + Single, + Introducer(u8), + Continuation, + Invalid, +} + + +pub fn get_utf8_byte_type(b: u8) -> UTF8ByteType { + if b & 0x80 == 0 { + UTF8ByteType::Single + } else if b & 0xC0 == 0x80 { + UTF8ByteType::Continuation + } else if b & 0xE0 == 0xC0 { + UTF8ByteType::Introducer(2) + } else if b & 0xF0 == 0xE0 { + UTF8ByteType::Introducer(3) + } else if b & 0xF8 == 0xF0 { + UTF8ByteType::Introducer(4) + } else { + UTF8ByteType::Invalid + } +} + diff --git a/src/main.rs b/src/main.rs index d0c07e9..1753688 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,14 +2,13 @@ use crate::types::*; use smol::prelude::*; -use smol::Timer; use smol::fs::File; use smol::lock::RwLock; use std::path::PathBuf; use std::process::ExitCode; use std::ops::Range; -use std::time::Duration; +mod encoding; mod terminal; mod types; @@ -50,24 +49,39 @@ impl Ivy { } async fn run(mut self) -> Result<()> { + /* The awkward structure here is because it's important that cleanup still + * happen even if something fails in the middle. + */ let mut error = None; - error = error.or(self.init_arguments().await.err()); - error = error.or(self.init_editor().await.err()); + error = error.or(self.init().await.err()); + error = error.or(self.interact().await.err()); + error = error.or(self.zap().await.err()); - error = error.or(self.terminal.write().await - .init_termios().await.err()); - error = error.or(self.terminal.write().await - .init_full_screen().await.err()); + if let Some(error) = error { + Err(error) + } else { + Ok(()) + } + } - error = error.or(self.draw().await.err()); + async fn init(&mut self) -> Result<()> { + self.init_arguments().await?; + self.init_editor().await?; - Timer::after(Duration::from_millis(1000)).await; + self.terminal.write().await.init_termios().await?; + self.terminal.write().await.init_full_screen().await?; - error = error.or(self.terminal.write().await - .zap_full_screen().await.err()); - error = error.or(self.terminal.write().await - .zap_termios().await.err()); + Ok(()) + } + + async fn zap(&mut self) -> Result<()> { + let mut error = None; + + error = error.or( + self.terminal.write().await.zap_full_screen().await.err()); + error = error.or( + self.terminal.write().await.zap_termios().await.err()); if let Some(error) = error { Err(error) @@ -100,6 +114,17 @@ impl Ivy { Ok(()) } + async fn interact(&mut self) -> Result<()> { + self.draw().await?; + + loop { + let c = self.terminal.write().await.read_char().await; + println!("c {:?}", c); + smol::Timer::after(std::time::Duration::from_millis(1000)).await; + return Ok(()); + } + } + async fn draw(&mut self) -> Result<()> { let mut terminal = self.terminal.write().await; let buffer = self.buffer.read().await; diff --git a/src/terminal.rs b/src/terminal.rs index 78727c8..d812069 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -2,6 +2,8 @@ use crate::types::*; use smol::prelude::*; +use crate::encoding; + use smol::{ unblock, Unblock }; use smol::lock::{ OnceCell, RwLock }; use std::fmt::Display; @@ -88,6 +90,36 @@ impl Terminal { Ok(()) } + pub async fn read_char(&mut self) -> Result<char> { + let mut buf = vec![0; 4]; + + loop { + self.stdin.read_exact(&mut buf[0 .. 1]).await?; + + match encoding::get_utf8_byte_type(buf[0]) { + UTF8ByteType::Single => { }, + UTF8ByteType::Introducer(2) => { + self.stdin.read_exact(&mut buf[1 .. 2]).await?; + }, + UTF8ByteType::Introducer(3) => { + self.stdin.read_exact(&mut buf[1 .. 3]).await?; + }, + UTF8ByteType::Introducer(4) => { + self.stdin.read_exact(&mut buf[1 .. 4]).await?; + }, + + /* If it's not the start of a valid character, ignore it. */ + _ => continue, + } + + if let Ok(string) = std::str::from_utf8(&buf) + && let Some(c) = string.chars().next() + { + return Ok(c); + } + } + } + pub async fn do_escape(&mut self, escape_type: EscapeType, code: &str, parameters: &[impl Display]) -> Result<()> diff --git a/src/types.rs b/src/types.rs index ef45492..1f74216 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,4 +1,5 @@ #![forbid(unsafe_code)] +pub use crate::encoding::UTF8ByteType; pub use crate::terminal::Terminal; pub type Error = std::io::Error; |