summary refs log tree commit diff
path: root/src/terminal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/terminal.rs')
-rw-r--r--src/terminal.rs32
1 files changed, 32 insertions, 0 deletions
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<()>