aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJonas Maier <>2026-03-04 16:47:34 +0100
committerJonas Maier <>2026-03-04 16:47:34 +0100
commit15182b740d9d3d3b7e263b1690051aa06334ab0c (patch)
tree198f73df725bce910f5df9229833756f12e1bb60 /src
downloadpish-15182b740d9d3d3b7e263b1690051aa06334ab0c.tar.gz
initial commit
Diffstat (limited to 'src')
-rw-r--r--src/main.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..7f372c1
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,100 @@
+use std::io::{self, Read, Write, IsTerminal};
+use std::os::unix::io::AsRawFd;
+use termios::*;
+
+struct ScopedRawMode {
+ fd: i32,
+ settings: Termios,
+}
+
+impl Drop for ScopedRawMode {
+ fn drop(&mut self) {
+ self.disable();
+ }
+}
+
+impl ScopedRawMode {
+ fn on_fd(fd: i32) -> Self {
+ let mut termios = Termios::from_fd(fd).unwrap();
+ let settings = termios.clone();
+ cfmakeraw(&mut termios);
+ tcsetattr(fd, TCSANOW, &termios).unwrap();
+ Self { fd, settings }
+ }
+
+ fn disable(&self) {
+ tcsetattr(self.fd, TCSANOW, &self.settings).unwrap();
+ }
+}
+
+macro_rules! print {
+ ($($x:tt)*) => {{
+ write!(io::stdout(), $($x)*).unwrap();
+ io::stdout().flush().unwrap();
+ }}
+}
+
+fn main() {
+ let stdin = io::stdin();
+ let stdout = io::stdout();
+
+ if !stdin.is_terminal() {
+ println!("need to run in a tty");
+ return;
+ }
+
+ let fd = stdin.as_raw_fd();
+ let _scoped_raw = ScopedRawMode::on_fd(fd); // needs to be a var, gets dropped on scope exit,
+ // even if something panics
+
+ let mut stdin = stdin.lock();
+ let mut stdout = stdout.lock();
+
+ let mut buffer = [0u8; 1];
+
+ loop {
+ let Ok(_) = stdin.read_exact(&mut buffer) else {
+ break;
+ };
+
+ match buffer[0] {
+ // EOF
+ 4 => {
+ break;
+ }
+
+ // Enter
+ b'\r' => {
+ println!("\r");
+ }
+
+ // Backspace (127 on most systems)
+ 127 => {
+ write!(stdout, "\x08 \x08").unwrap();
+ stdout.flush().unwrap();
+ }
+
+ // Escape sequence
+ 27 => {
+ let mut seq = [0u8; 2];
+ stdin.read_exact(&mut seq).unwrap();
+
+ if seq[0] == b'[' {
+ match seq[1] {
+ b'A' => print!("Up"),
+ b'B' => print!("Down"),
+ b'C' => print!("Right"),
+ b'D' => print!("Left"),
+ _ => {}
+ }
+ }
+ }
+
+ // Normal character
+ x => {
+ stdout.write(&[x]).unwrap();
+ stdout.flush().unwrap();
+ }
+ }
+ }
+}