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