mirror of
https://github.com/Xyverle/neutuino.git
synced 2026-09-03 05:20:03 -04:00
make clippy happy, add docs, add asserts, etc.
This commit is contained in:
35
src/ansi.rs
35
src/ansi.rs
@@ -2,9 +2,10 @@
|
|||||||
//!
|
//!
|
||||||
//! These should work on *most* terminals (i.e. Xterm compatible terminals)
|
//! These should work on *most* terminals (i.e. Xterm compatible terminals)
|
||||||
//!
|
//!
|
||||||
//! For these to work on Windows you need to run the enable_ansi function in the os module
|
//! For these to work on Windows you need to run the `enable_ansi` function in the os module
|
||||||
|
|
||||||
/// Sets the terminal to an arbitrary 12-bit/truecolor color
|
/// Sets the terminal to an arbitrary 12-bit/truecolor color
|
||||||
|
#[must_use]
|
||||||
pub fn rgb_color_code(red: u8, green: u8, blue: u8) -> String {
|
pub fn rgb_color_code(red: u8, green: u8, blue: u8) -> String {
|
||||||
format!("\x1b[38;2;{red};{green};{blue}m")
|
format!("\x1b[38;2;{red};{green};{blue}m")
|
||||||
}
|
}
|
||||||
@@ -13,10 +14,11 @@ pub fn rgb_color_code(red: u8, green: u8, blue: u8) -> String {
|
|||||||
///
|
///
|
||||||
/// The title must be only in ASCII characters or **weird** things will happen
|
/// The title must be only in ASCII characters or **weird** things will happen
|
||||||
///
|
///
|
||||||
/// Panics:
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// When the title is more than 255 characters
|
/// When the title is more than 255 characters
|
||||||
pub fn set_window_title(title: String) -> String {
|
#[must_use]
|
||||||
|
pub fn set_window_title(title: &str) -> String {
|
||||||
assert!(
|
assert!(
|
||||||
title.len() <= 255,
|
title.len() <= 255,
|
||||||
"Title length longer than maximum of 255"
|
"Title length longer than maximum of 255"
|
||||||
@@ -25,21 +27,25 @@ pub fn set_window_title(title: String) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the cursor up {num} characters
|
/// Moves the cursor up {num} characters
|
||||||
|
#[must_use]
|
||||||
pub fn move_cursor_up(num: u16) -> String {
|
pub fn move_cursor_up(num: u16) -> String {
|
||||||
format!("\x1b[{num}A")
|
format!("\x1b[{num}A")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the cursor down {num} characters
|
/// Moves the cursor down {num} characters
|
||||||
|
#[must_use]
|
||||||
pub fn move_cursor_down(num: u16) -> String {
|
pub fn move_cursor_down(num: u16) -> String {
|
||||||
format!("\x1b[{num}B")
|
format!("\x1b[{num}B")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the cursor right {num} characters
|
/// Moves the cursor right {num} characters
|
||||||
|
#[must_use]
|
||||||
pub fn move_cursor_right(num: u16) -> String {
|
pub fn move_cursor_right(num: u16) -> String {
|
||||||
format!("\x1b[{num}C")
|
format!("\x1b[{num}C")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the cursor left {num} characters
|
/// Moves the cursor left {num} characters
|
||||||
|
#[must_use]
|
||||||
pub fn move_cursor_left(num: u16) -> String {
|
pub fn move_cursor_left(num: u16) -> String {
|
||||||
format!("\x1b[{num}A")
|
format!("\x1b[{num}A")
|
||||||
}
|
}
|
||||||
@@ -47,21 +53,40 @@ pub fn move_cursor_left(num: u16) -> String {
|
|||||||
/// Moves the cursor to {row}
|
/// Moves the cursor to {row}
|
||||||
///
|
///
|
||||||
/// Origin is 1, 1
|
/// Origin is 1, 1
|
||||||
pub fn move_cursor_to_row(row: u16) -> String {
|
#[must_use]
|
||||||
format!("\x1b[{row}d")
|
pub fn move_cursor_to_row(line: u16) -> String {
|
||||||
|
debug_assert!(
|
||||||
|
line != 0,
|
||||||
|
"Tried to go to line 0, when position is (1, 1)-based"
|
||||||
|
);
|
||||||
|
format!("\x1b[{line}d")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the cursor to {column}
|
/// Moves the cursor to {column}
|
||||||
///
|
///
|
||||||
/// Origin is 1, 1
|
/// Origin is 1, 1
|
||||||
|
#[must_use]
|
||||||
pub fn move_cursor_to_column(column: u16) -> String {
|
pub fn move_cursor_to_column(column: u16) -> String {
|
||||||
|
debug_assert!(
|
||||||
|
column != 0,
|
||||||
|
"Tried to go to column 0, when position is (1, 1)-based"
|
||||||
|
);
|
||||||
format!("\x1b[{column}G")
|
format!("\x1b[{column}G")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves the cursor to Position {x}, {y}
|
/// Moves the cursor to Position {x}, {y}
|
||||||
///
|
///
|
||||||
/// Origin is 1, 1
|
/// Origin is 1, 1
|
||||||
|
#[must_use]
|
||||||
pub fn move_cursor_to_position(column: u16, line: u16) -> String {
|
pub fn move_cursor_to_position(column: u16, line: u16) -> String {
|
||||||
|
debug_assert!(
|
||||||
|
line != 0,
|
||||||
|
"Tried to go to line 0, when position is (1, 1)-based"
|
||||||
|
);
|
||||||
|
debug_assert!(
|
||||||
|
column != 0,
|
||||||
|
"Tried to go to column 0, when position is (1, 1)-based"
|
||||||
|
);
|
||||||
format!("\x1b[{line};{column}H")
|
format!("\x1b[{line};{column}H")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
//! Various input functions, structs, etc.
|
||||||
|
//!
|
||||||
|
//! Very incomplete currently
|
||||||
|
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@@ -6,6 +10,8 @@ use std::thread;
|
|||||||
///
|
///
|
||||||
/// This acts as any other stream, with the exception that reading from it won't block. Instead,
|
/// This acts as any other stream, with the exception that reading from it won't block. Instead,
|
||||||
/// the buffer will only be partially updated based on how much the internal buffer holds.
|
/// the buffer will only be partially updated based on how much the internal buffer holds.
|
||||||
|
///
|
||||||
|
/// Taken from the Termion crate
|
||||||
pub struct AsyncReader {
|
pub struct AsyncReader {
|
||||||
recv: mpsc::Receiver<io::Result<u8>>,
|
recv: mpsc::Receiver<io::Result<u8>>,
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/os.rs
34
src/os.rs
@@ -1,36 +1,18 @@
|
|||||||
|
//! Collection of functions that help control the terminal
|
||||||
|
//!
|
||||||
|
//! These are built to work at least on these platforms:
|
||||||
|
//! Windows, Linux, and Mac, but are likely to work on more
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[path = "unix.rs"]
|
#[path = "unix.rs"]
|
||||||
mod unix;
|
mod unix;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use unix as os;
|
pub use unix::*;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
#[path = "windows.rs"]
|
#[path = "windows.rs"]
|
||||||
mod windows;
|
mod unix;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use windows as os;
|
pub use windows::*;
|
||||||
|
|
||||||
/// Checks if stdout is a terminal
|
|
||||||
pub use os::is_terminal;
|
|
||||||
|
|
||||||
/// Enables ANSI support on Windows terminals
|
|
||||||
///
|
|
||||||
/// ANSI is on by default on *nix machines but still exists on them for simpler usage
|
|
||||||
pub use os::enable_ansi;
|
|
||||||
|
|
||||||
/// Gets the size of the terminal
|
|
||||||
///
|
|
||||||
/// Returns in (width, height) format
|
|
||||||
pub use os::get_terminal_size;
|
|
||||||
|
|
||||||
/// Enables raw mode
|
|
||||||
///
|
|
||||||
/// Disables input echoing, line feeding, etc.
|
|
||||||
pub use os::enable_raw_mode;
|
|
||||||
|
|
||||||
/// Disables raw mode
|
|
||||||
///
|
|
||||||
/// Enables input echoing, line feeding, etc.
|
|
||||||
pub use os::disable_raw_mode;
|
|
||||||
|
|||||||
39
src/unix.rs
39
src/unix.rs
@@ -46,17 +46,38 @@ struct Termios {
|
|||||||
cc: [u8; NCCS],
|
cc: [u8; NCCS],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if stdout is a terminal
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_terminal() -> bool {
|
pub fn is_terminal() -> bool {
|
||||||
unsafe { isatty(1) != 0 }
|
unsafe { isatty(1) != 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enables ANSI support on Windows terminals
|
||||||
|
///
|
||||||
|
/// ANSI is on by default on *nix machines but still exists on them for simpler usage
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Never on *nix
|
||||||
|
///
|
||||||
|
/// If There is no stdout,
|
||||||
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it cannot change terminal properties on Windows
|
||||||
pub fn enable_ansi() -> io::Result<()> {
|
pub fn enable_ansi() -> io::Result<()> {
|
||||||
// ANSI is on by default on unix platforms
|
// ANSI is on by default on unix platforms
|
||||||
// This is here for compatibility with the windows version of this API
|
// This is here for compatibility with the windows version of this API
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the size of the terminal
|
||||||
|
///
|
||||||
|
/// Returns in (width, height) format
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If there is no stdout,
|
||||||
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it fails to retrieve the terminal size
|
||||||
pub fn get_terminal_size() -> io::Result<(u16, u16)> {
|
pub fn get_terminal_size() -> io::Result<(u16, u16)> {
|
||||||
let mut winsize = unsafe { std::mem::zeroed::<Winsize>() };
|
let mut winsize = unsafe { std::mem::zeroed::<Winsize>() };
|
||||||
let ioctl_result = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ, (&raw mut winsize).cast::<u8>()) };
|
let ioctl_result = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ, (&raw mut winsize).cast::<u8>()) };
|
||||||
@@ -68,6 +89,15 @@ pub fn get_terminal_size() -> io::Result<(u16, u16)> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enables raw mode
|
||||||
|
///
|
||||||
|
/// Disables input echoing, line feeding, etc.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If there is no stdout,
|
||||||
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it fails to get or set terminal settings
|
||||||
pub fn enable_raw_mode() -> io::Result<()> {
|
pub fn enable_raw_mode() -> io::Result<()> {
|
||||||
let mut termios = unsafe { std::mem::zeroed::<Termios>() };
|
let mut termios = unsafe { std::mem::zeroed::<Termios>() };
|
||||||
get_attributes(STDIN_FILENO, &mut termios)?;
|
get_attributes(STDIN_FILENO, &mut termios)?;
|
||||||
@@ -76,6 +106,15 @@ pub fn enable_raw_mode() -> io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Disables raw mode
|
||||||
|
///
|
||||||
|
/// Enables input echoing, line feeding, etc.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If there is no stdout,
|
||||||
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it fails to get or set terminal settings
|
||||||
pub fn disable_raw_mode() -> io::Result<()> {
|
pub fn disable_raw_mode() -> io::Result<()> {
|
||||||
let mut termios = unsafe { std::mem::zeroed::<Termios>() };
|
let mut termios = unsafe { std::mem::zeroed::<Termios>() };
|
||||||
get_attributes(STDIN_FILENO, &mut termios)?;
|
get_attributes(STDIN_FILENO, &mut termios)?;
|
||||||
|
|||||||
@@ -2,14 +2,6 @@
|
|||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
const STD_INPUT_HANDLE: u32 = 0xFFFF_FFF6;
|
|
||||||
const STD_OUTPUT_HANDLE: u32 = 0xFFFF_FFF5;
|
|
||||||
const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 4;
|
|
||||||
const ENABLE_ECHO_INPUT: u32 = 4;
|
|
||||||
const ENABLE_LINE_INPUT: u32 = 2;
|
|
||||||
const ENABLE_PROCESSED_INPUT: u32 = 1;
|
|
||||||
const INVALID_HANDLE_VALUE: usize = usize::MAX - 1;
|
|
||||||
|
|
||||||
unsafe extern "system" {
|
unsafe extern "system" {
|
||||||
fn GetStdHandle(nStdHandle: u32) -> usize;
|
fn GetStdHandle(nStdHandle: u32) -> usize;
|
||||||
fn GetConsoleMode(hConsoleHandle: usize, dwMode: *mut u32) -> u32;
|
fn GetConsoleMode(hConsoleHandle: usize, dwMode: *mut u32) -> u32;
|
||||||
@@ -20,6 +12,14 @@ unsafe extern "system" {
|
|||||||
) -> u32;
|
) -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const STD_INPUT_HANDLE: u32 = 0xFFFF_FFF6;
|
||||||
|
const STD_OUTPUT_HANDLE: u32 = 0xFFFF_FFF5;
|
||||||
|
const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 4;
|
||||||
|
const ENABLE_ECHO_INPUT: u32 = 4;
|
||||||
|
const ENABLE_LINE_INPUT: u32 = 2;
|
||||||
|
const ENABLE_PROCESSED_INPUT: u32 = 1;
|
||||||
|
const INVALID_HANDLE_VALUE: usize = usize::MAX - 1;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ConsoleScreenBufferInfo {
|
struct ConsoleScreenBufferInfo {
|
||||||
@@ -36,6 +36,7 @@ struct ConsoleScreenBufferInfo {
|
|||||||
dwMaximumWindowSizeY: u16,
|
dwMaximumWindowSizeY: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if stdout is a terminal
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_terminal() -> bool {
|
pub fn is_terminal() -> bool {
|
||||||
let handle = get_std_handle(STD_OUTPUT_HANDLE);
|
let handle = get_std_handle(STD_OUTPUT_HANDLE);
|
||||||
@@ -48,6 +49,35 @@ pub fn is_terminal() -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enables ANSI support on Windows terminals
|
||||||
|
///
|
||||||
|
/// ANSI is on by default on *nix machines but still exists on them for simpler usage
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Never on *nix
|
||||||
|
///
|
||||||
|
/// On Windows, if There is no stdout,
|
||||||
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it cannot change terminal properties
|
||||||
|
pub fn enable_ansi() -> io::Result<()> {
|
||||||
|
let handle = get_std_handle(STD_OUTPUT_HANDLE)?;
|
||||||
|
let mut dwMode = 0;
|
||||||
|
get_console_mode(handle, &raw mut dwMode)?;
|
||||||
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
set_console_mode(handle, &raw mut dwMode)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the size of the terminal
|
||||||
|
///
|
||||||
|
/// Returns in (width, height) format
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If there is no stdout,
|
||||||
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it fails to retrieve the terminal size
|
||||||
pub fn get_terminal_size() -> io::Result<(u16, u16)> {
|
pub fn get_terminal_size() -> io::Result<(u16, u16)> {
|
||||||
let handle = get_std_handle(STD_OUTPUT_HANDLE)?;
|
let handle = get_std_handle(STD_OUTPUT_HANDLE)?;
|
||||||
let mut csbi = ConsoleScreenBufferInfo::default();
|
let mut csbi = ConsoleScreenBufferInfo::default();
|
||||||
@@ -59,15 +89,15 @@ pub fn get_terminal_size() -> io::Result<(u16, u16)> {
|
|||||||
Err(io::Error::last_os_error())
|
Err(io::Error::last_os_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_ansi() -> io::Result<()> {
|
/// Enables raw mode
|
||||||
let handle = get_std_handle(STD_OUTPUT_HANDLE)?;
|
///
|
||||||
let mut dwMode = 0;
|
/// Disables input echoing, line feeding, etc.
|
||||||
get_console_mode(handle, &raw mut dwMode)?;
|
///
|
||||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
/// # Errors
|
||||||
set_console_mode(handle, &raw mut dwMode)?;
|
///
|
||||||
Ok(())
|
/// If there is no stdout,
|
||||||
}
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it fails to get or set terminal settings
|
||||||
pub fn enable_raw_mode() -> io::Result<()> {
|
pub fn enable_raw_mode() -> io::Result<()> {
|
||||||
let handle = get_std_handle(STD_INPUT_HANDLE)?;
|
let handle = get_std_handle(STD_INPUT_HANDLE)?;
|
||||||
let mut dwMode = 0;
|
let mut dwMode = 0;
|
||||||
@@ -77,6 +107,15 @@ pub fn enable_raw_mode() -> io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Disables raw mode
|
||||||
|
///
|
||||||
|
/// Enables input echoing, line feeding, etc.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If there is no stdout,
|
||||||
|
/// if stdout isn't a TTY, or
|
||||||
|
/// if it fails to get or set terminal settings
|
||||||
pub fn disable_raw_mode() -> io::Result<()> {
|
pub fn disable_raw_mode() -> io::Result<()> {
|
||||||
let handle = get_std_handle(STD_INPUT_HANDLE)?;
|
let handle = get_std_handle(STD_INPUT_HANDLE)?;
|
||||||
let mut dwMode = 0;
|
let mut dwMode = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user