mirror of
https://github.com/Xyverle/neutuino.git
synced 2026-06-26 22:23:14 -04:00
add convenience constants & example
This commit is contained in:
46
examples/test.rs
Normal file
46
examples/test.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
|
|
||||||
|
use std::{time::Duration, io};
|
||||||
|
use neutuino::ansi::{COLORS_BG, COLORS_FG, STYLE_BOLD, STYLE_ITALIC, STYLE_RESET, STYLE_UNDERLINE, move_cursor_to_column, set_window_title};
|
||||||
|
use neutuino::os::{enable_ansi, get_terminal_size};
|
||||||
|
use neutuino::input::{poll_input, Event, KeyEvent};
|
||||||
|
|
||||||
|
|
||||||
|
fn print_line_style_reset(string: &str) {
|
||||||
|
println!("{}{}{}", string, STYLE_RESET, move_cursor_to_column(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let all_styles = format!("{STYLE_BOLD}{STYLE_ITALIC}{STYLE_UNDERLINE}");
|
||||||
|
let _raw_terminal = neutuino::os::RawTerminal::new()?;
|
||||||
|
enable_ansi()?;
|
||||||
|
|
||||||
|
println!("q to quit{}", move_cursor_to_column(0));
|
||||||
|
let next = |x: usize| (x + 1) % COLORS_FG.len();
|
||||||
|
|
||||||
|
let terminal_size = get_terminal_size()?;
|
||||||
|
let terminal_size_str = format!("{terminal_size:?}");
|
||||||
|
print!("{}", set_window_title(terminal_size_str).unwrap());
|
||||||
|
|
||||||
|
let mut counter = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut input = Err(io::ErrorKind::Other.into());
|
||||||
|
while input.is_err() {
|
||||||
|
input = poll_input(Duration::new(1, 0));
|
||||||
|
}
|
||||||
|
let input = input.unwrap();
|
||||||
|
let string = format!("{input:?}");
|
||||||
|
print_line_style_reset(&format!(
|
||||||
|
"{all_styles}{}{}{string}",
|
||||||
|
COLORS_FG[counter],
|
||||||
|
COLORS_BG[next(counter)]
|
||||||
|
));
|
||||||
|
// q to quit
|
||||||
|
if input == Event::Key(KeyEvent::Char('q')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter = next(counter);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
36
src/ansi.rs
36
src/ansi.rs
@@ -208,3 +208,39 @@ pub const COLOR_WHITE_BG: &str = "\x1b[47m";
|
|||||||
pub const COLOR_DEFAULT_FG: &str = "\x1b[39m";
|
pub const COLOR_DEFAULT_FG: &str = "\x1b[39m";
|
||||||
/// Makes characters sent to the screen have a default background
|
/// Makes characters sent to the screen have a default background
|
||||||
pub const COLOR_DEFAULT_BG: &str = "\x1b[49m";
|
pub const COLOR_DEFAULT_BG: &str = "\x1b[49m";
|
||||||
|
|
||||||
|
pub const COLORS_FG: [&str; 9] = [
|
||||||
|
COLOR_BLACK_FG,
|
||||||
|
COLOR_RED_FG,
|
||||||
|
COLOR_GREEN_FG,
|
||||||
|
COLOR_YELLOW_FG,
|
||||||
|
COLOR_BLUE_FG,
|
||||||
|
COLOR_MAGENTA_FG,
|
||||||
|
COLOR_CYAN_FG,
|
||||||
|
COLOR_WHITE_FG,
|
||||||
|
COLOR_DEFAULT_FG,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub const COLORS_BG: [&str; 9] = [
|
||||||
|
COLOR_BLACK_BG,
|
||||||
|
COLOR_RED_BG,
|
||||||
|
COLOR_GREEN_BG,
|
||||||
|
COLOR_YELLOW_BG,
|
||||||
|
COLOR_BLUE_BG,
|
||||||
|
COLOR_MAGENTA_BG,
|
||||||
|
COLOR_CYAN_BG,
|
||||||
|
COLOR_WHITE_BG,
|
||||||
|
COLOR_DEFAULT_BG,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub const COLORS: [(&str, &str); 9] = [
|
||||||
|
(COLOR_BLACK_FG, COLOR_BLACK_BG),
|
||||||
|
(COLOR_RED_FG, COLOR_RED_BG),
|
||||||
|
(COLOR_GREEN_FG, COLOR_GREEN_BG),
|
||||||
|
(COLOR_YELLOW_FG, COLOR_YELLOW_BG),
|
||||||
|
(COLOR_BLUE_FG, COLOR_BLUE_BG),
|
||||||
|
(COLOR_MAGENTA_FG, COLOR_MAGENTA_BG),
|
||||||
|
(COLOR_CYAN_FG, COLOR_CYAN_BG),
|
||||||
|
(COLOR_WHITE_FG, COLOR_WHITE_BG),
|
||||||
|
(COLOR_DEFAULT_FG, COLOR_DEFAULT_BG),
|
||||||
|
];
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ mod windows_input;
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use windows_input::*;
|
pub use windows_input::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Key(KeyEvent),
|
Key(KeyEvent),
|
||||||
Mouse(MouseEvent),
|
Mouse(MouseEvent),
|
||||||
@@ -23,6 +24,7 @@ pub enum Event {
|
|||||||
FocusLost,
|
FocusLost,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum KeyEvent {
|
pub enum KeyEvent {
|
||||||
Backspace,
|
Backspace,
|
||||||
Up,
|
Up,
|
||||||
@@ -44,12 +46,14 @@ pub enum KeyEvent {
|
|||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum MouseEvent {
|
pub enum MouseEvent {
|
||||||
Press(MouseButton, u16, u16),
|
Press(MouseButton, u16, u16),
|
||||||
Release(u16, u16),
|
Release(u16, u16),
|
||||||
Hold(u16, u16),
|
Hold(u16, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum MouseButton {
|
pub enum MouseButton {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
|||||||
@@ -32,18 +32,21 @@ impl Iterator for ReadIterator {
|
|||||||
type Item = io::Result<u8>;
|
type Item = io::Result<u8>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let bytes_read = unsafe { read(self.fd, &raw mut self.buf as *mut c_void, 1) };
|
let bytes_read = unsafe { read(self.fd, (&raw mut self.buf).cast::<c_void>(), 1) };
|
||||||
|
|
||||||
if bytes_read > 0 {
|
match bytes_read {
|
||||||
Some(Ok(self.buf))
|
1.. => Some(Ok(self.buf)),
|
||||||
} else if bytes_read == 0 {
|
0 => None,
|
||||||
None
|
_ => Some(Err(io::Error::last_os_error())),
|
||||||
} else {
|
|
||||||
Some(Err(io::Error::last_os_error()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to fetch input from stdin
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// If the timeout has expired or
|
||||||
|
/// there was an error getting the data
|
||||||
pub fn poll_input(timeout: Duration) -> io::Result<Event> {
|
pub fn poll_input(timeout: Duration) -> io::Result<Event> {
|
||||||
let mut fds = [PollFD {
|
let mut fds = [PollFD {
|
||||||
fd: STDIN_FILENO,
|
fd: STDIN_FILENO,
|
||||||
@@ -51,6 +54,7 @@ pub fn poll_input(timeout: Duration) -> io::Result<Event> {
|
|||||||
revents: 0,
|
revents: 0,
|
||||||
}];
|
}];
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
poll(
|
poll(
|
||||||
fds.as_mut_ptr(),
|
fds.as_mut_ptr(),
|
||||||
fds.len() as c_ulong,
|
fds.len() as c_ulong,
|
||||||
@@ -59,14 +63,15 @@ pub fn poll_input(timeout: Duration) -> io::Result<Event> {
|
|||||||
};
|
};
|
||||||
let mut read_iter = ReadIterator::new(STDIN_FILENO);
|
let mut read_iter = ReadIterator::new(STDIN_FILENO);
|
||||||
|
|
||||||
if result > 0 {
|
let timed_out: io::Error = io::ErrorKind::TimedOut.into();
|
||||||
let item = read_iter.next().ok_or(io::ErrorKind::InvalidData)??;
|
|
||||||
try_parse_event(item, &mut read_iter)
|
match result {
|
||||||
} else if result == 0 {
|
1.. => {
|
||||||
// The function timed out.
|
let item = read_iter.next().ok_or(timed_out)??;
|
||||||
Err(io::ErrorKind::TimedOut.into())
|
try_parse_event(item, &mut read_iter)
|
||||||
} else {
|
}
|
||||||
Err(io::Error::last_os_error())
|
0 => Err(timed_out),
|
||||||
|
_ => Err(io::Error::last_os_error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user