init - implement raw mode
This commit is contained in:
commit
6ffb32c543
7 changed files with 210 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/Cargo.lock
|
1
.rustfmt.toml
Normal file
1
.rustfmt.toml
Normal file
|
@ -0,0 +1 @@
|
|||
hard_tabs = true
|
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "ants"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
[[example]]
|
||||
name = "print"
|
23
examples/print.rs
Normal file
23
examples/print.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use ants::{event::Events, raw_mode};
|
||||
use std::{
|
||||
io::{stdin, Read},
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
raw_mode::enter().unwrap();
|
||||
|
||||
let start_time = SystemTime::now();
|
||||
|
||||
let mut buf = Vec::new();
|
||||
while start_time.elapsed().unwrap() < Duration::from_secs(5) {
|
||||
let mut b = [0u8];
|
||||
if let Ok(_n) = stdin().read(&mut b) {
|
||||
if b[0] != 0 {
|
||||
buf.push(b[0]);
|
||||
print!("[{}]:{}\n\r", b[0], String::from_utf8_lossy(&buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
raw_mode::exit().unwrap();
|
||||
}
|
11
src/event.rs
Normal file
11
src/event.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
use std::io::{stdin, Stdin};
|
||||
|
||||
pub struct Events {
|
||||
bytes: Stdin,
|
||||
}
|
||||
|
||||
impl Events {
|
||||
pub fn new() -> Self {
|
||||
Self { bytes: stdin() }
|
||||
}
|
||||
}
|
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod event;
|
||||
pub mod raw_mode;
|
160
src/raw_mode.rs
Normal file
160
src/raw_mode.rs
Normal file
|
@ -0,0 +1,160 @@
|
|||
use std::{
|
||||
ffi::{c_char, c_int, c_uint},
|
||||
io::{self, Result},
|
||||
os::fd::{self, AsFd},
|
||||
};
|
||||
|
||||
static mut PREV_TERMINAL_STATE: Option<Termios> = None;
|
||||
|
||||
pub fn enter() -> Result<()> {
|
||||
if unsafe { PREV_TERMINAL_STATE.is_some() } {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut state = Termios::default();
|
||||
let stdin = io::stdin();
|
||||
|
||||
unsafe {
|
||||
// save current terminal state
|
||||
check_err(tcgetattr(stdin.as_fd(), &mut state))?;
|
||||
PREV_TERMINAL_STATE = Some(state.clone());
|
||||
}
|
||||
// https://man7.org/linux/man-pages/man3/termios.3.html
|
||||
// termios.c_iflag &= !(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||||
// termios.c_oflag &= !OPOST;
|
||||
// termios.c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||||
// termios.c_cflag &= !(CSIZE | PARENB);
|
||||
// termios.c_cflag |= CS8;
|
||||
unsafe {
|
||||
// set to raw mode
|
||||
cfmakeraw(&state);
|
||||
check_err(tcsetattr(stdin.as_fd(), 0, &state))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn exit() -> Result<()> {
|
||||
unsafe {
|
||||
if let Some(termios) = PREV_TERMINAL_STATE.as_ref() {
|
||||
let stdin = io::stdin();
|
||||
check_err(tcsetattr(stdin.as_fd(), 0, termios))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_err(val: c_int) -> Result<()> {
|
||||
if val == -1 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[repr(C)]
|
||||
struct Termios {
|
||||
pub c_iflag: c_uint,
|
||||
pub c_oflag: c_uint,
|
||||
pub c_cflag: c_uint,
|
||||
pub c_lflag: c_uint,
|
||||
pub c_line: c_char,
|
||||
pub c_cc: [c_char; 32],
|
||||
// these two seem to be platform specific and don't need to be used
|
||||
// pub c_ispeed: c_int,
|
||||
// pub c_ospeed: c_int,
|
||||
}
|
||||
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
/// get terminal flags for fd
|
||||
fn tcgetattr(fd: fd::BorrowedFd, termios_p: *mut Termios) -> c_int;
|
||||
/// set terminal flags for fd
|
||||
fn tcsetattr(fd: fd::BorrowedFd, optional_actions: c_int, termios_p: *const Termios) -> c_int;
|
||||
/// set terminal flags to raw mode
|
||||
fn cfmakeraw(termios_p: *const Termios);
|
||||
}
|
||||
/*
|
||||
const TCIOFF: c_int = 2;
|
||||
const TCION: c_int = 3;
|
||||
const TCOOFF: c_int = 0;
|
||||
const TCOON: c_int = 1;
|
||||
const TCIFLUSH: c_int = 0;
|
||||
const TCOFLUSH: c_int = 1;
|
||||
const TCIOFLUSH: c_int = 2;
|
||||
const NL0: c_uint = 0x00000000;
|
||||
const NL1: c_uint = 0x00000100;
|
||||
const TAB0: c_uint = 0x00000000;
|
||||
const CR0: c_uint = 0x00000000;
|
||||
const FF0: c_uint = 0x00000000;
|
||||
const BS0: c_uint = 0x00000000;
|
||||
const VT0: c_uint = 0x00000000;
|
||||
const VERASE: usize = 2;
|
||||
const VKILL: usize = 3;
|
||||
const VINTR: usize = 0;
|
||||
const VQUIT: usize = 1;
|
||||
const VLNEXT: usize = 15;
|
||||
const IGNBRK: c_uint = 0x00000001;
|
||||
const BRKINT: c_uint = 0x00000002;
|
||||
const IGNPAR: c_uint = 0x00000004;
|
||||
const PARMRK: c_uint = 0x00000008;
|
||||
const INPCK: c_uint = 0x00000010;
|
||||
const ISTRIP: c_uint = 0x00000020;
|
||||
const INLCR: c_uint = 0x00000040;
|
||||
const IGNCR: c_uint = 0x00000080;
|
||||
const ICRNL: c_uint = 0x00000100;
|
||||
const IXANY: c_uint = 0x00000800;
|
||||
const IMAXBEL: c_uint = 0x00002000;
|
||||
const OPOST: c_uint = 0x1;
|
||||
const CS5: c_uint = 0x00000000;
|
||||
const CRTSCTS: c_uint = 0x80000000;
|
||||
const ECHO: c_uint = 0x00000008;
|
||||
const OCRNL: c_uint = 0o000010;
|
||||
const ONOCR: c_uint = 0o000020;
|
||||
const ONLRET: c_uint = 0o000040;
|
||||
const OFILL: c_uint = 0o000100;
|
||||
const OFDEL: c_uint = 0o000200;
|
||||
|
||||
const IXON: c_uint = 0x00000400;
|
||||
const IXOFF: c_uint = 0x00001000;
|
||||
const ONLCR: c_uint = 0x4;
|
||||
const CSIZE: c_uint = 0x00000030;
|
||||
const CS6: c_uint = 0x00000010;
|
||||
const CS7: c_uint = 0x00000020;
|
||||
const CS8: c_uint = 0x00000030;
|
||||
const CSTOPB: c_uint = 0x00000040;
|
||||
const CREAD: c_uint = 0x00000080;
|
||||
const PARENB: c_uint = 0x00000100;
|
||||
const PARODD: c_uint = 0x00000200;
|
||||
const HUPCL: c_uint = 0x00000400;
|
||||
const CLOCAL: c_uint = 0x00000800;
|
||||
const ECHOKE: c_uint = 0x00000800;
|
||||
const ECHOE: c_uint = 0x00000010;
|
||||
const ECHOK: c_uint = 0x00000020;
|
||||
const ECHONL: c_uint = 0x00000040;
|
||||
const ECHOPRT: c_uint = 0x00000400;
|
||||
const ECHOCTL: c_uint = 0x00000200;
|
||||
const ISIG: c_uint = 0x00000001;
|
||||
const ICANON: c_uint = 0x00000002;
|
||||
const PENDIN: c_uint = 0x00004000;
|
||||
const NOFLSH: c_uint = 0x00000080;
|
||||
const CIBAUD: c_uint = 0o02003600000;
|
||||
const CBAUDEX: c_uint = 0o010000;
|
||||
const VSWTC: usize = 7;
|
||||
const OLCUC: c_uint = 0o000002;
|
||||
const NLDLY: c_uint = 0o000400;
|
||||
const CRDLY: c_uint = 0o003000;
|
||||
const TABDLY: c_uint = 0o014000;
|
||||
const BSDLY: c_uint = 0o020000;
|
||||
const FFDLY: c_uint = 0o100000;
|
||||
const VTDLY: c_uint = 0o040000;
|
||||
const XTABS: c_uint = 0o014000;
|
||||
|
||||
const VEOL: usize = 11;
|
||||
const VEOL2: usize = 16;
|
||||
const VMIN: usize = 6;
|
||||
const IEXTEN: c_uint = 0x00008000;
|
||||
const TOSTOP: c_uint = 0x00000100;
|
||||
const FLUSHO: c_uint = 0x00001000;
|
||||
const EXTPROC: c_uint = 0x00010000;
|
||||
// */
|
Loading…
Reference in a new issue