diff options
| author | Jonas Maier <> | 2026-03-04 17:46:36 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-04 17:46:36 +0100 |
| commit | 7c46116456ebddba482d9f5c25d0e5d9c38e5c37 (patch) | |
| tree | 3064239328e81c6f405b598ccd5bd42fcd7e1e71 | |
| parent | 3c880475148d770ed39918fb0344faaed43299d0 (diff) | |
| download | pish-7c46116456ebddba482d9f5c25d0e5d9c38e5c37.tar.gz | |
lets you run commands
| -rw-r--r-- | src/main.rs | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs index bb74b2d..8747d85 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,8 @@ use std::io::{self, Read, Write, IsTerminal}; use std::os::unix::io::AsRawFd; +use std::process::Command; +use std::ffi::OsStr; +use std::os::unix::ffi::OsStrExt; use termios::*; struct ScopedRawMode { @@ -15,13 +18,16 @@ impl Drop for ScopedRawMode { 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(); + let settings = Termios::from_fd(fd).unwrap(); Self { fd, settings } } + fn enable(&self) { + let mut settings = self.settings.clone(); + cfmakeraw(&mut settings); + tcsetattr(self.fd, TCSANOW, &settings).unwrap(); + } + fn disable(&self) { tcsetattr(self.fd, TCSANOW, &self.settings).unwrap(); } @@ -113,6 +119,13 @@ pub fn move_cursor(direction: Direction, n: usize) { print!("\x1b[{n}{code}"); } +/// Represents a cursor position +#[derive(Debug, Clone, Copy)] +pub struct CursorPos { + pub row: usize, + pub col: usize, +} + fn main() { let stdin = io::stdin(); let stdout = io::stdout(); @@ -123,14 +136,17 @@ fn main() { } 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 raw = ScopedRawMode::on_fd(fd); + raw.enable(); let mut stdin = stdin.lock(); let mut stdout = stdout.lock(); let mut buffer = [0u8; 1]; let mut line = LineBuffer::new(); + let prompt = "> "; + + print!("{prompt}"); loop { let Ok(_) = stdin.read_exact(&mut buffer) else { @@ -146,14 +162,36 @@ fn main() { // Enter b'\r' => { print!("\r\n"); - stdout.write_all(&line.dump()).unwrap(); - print!("\r\n"); + let line = line.dump(); + let words: Vec<&[u8]> = line.split(|x| *x == b' ').collect(); + if words.is_empty() { + print!("{prompt}"); + continue; + } + + let mut cmd = Command::new(OsStr::from_bytes(words[0])); + for arg in words[1..].iter() { + cmd.arg(OsStr::from_bytes(arg)); + } + + raw.disable(); + let status = cmd.status(); + raw.enable(); + + let status_string = match status { + Ok(ec) if ec.success() => String::new(), + Ok(ec) => format!("{ec} "), + Err(_) => String::from("IO ERROR "), + }; + //ensure_newline(); + print!("{status_string}{prompt}"); } // Backspace (127 on most systems) 127 => { - line.del_left(); - print!("\x08 \x08"); + if line.del_left().is_some() { + print!("\x08 \x08"); + } } // Escape sequence |
