make clippy happy, add docs, add asserts, etc.

This commit is contained in:
2025-03-15 20:36:10 -04:00
parent 956921185f
commit 9618ac7957
5 changed files with 139 additions and 48 deletions

View File

@@ -2,9 +2,10 @@
//!
//! 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
#[must_use]
pub fn rgb_color_code(red: u8, green: u8, blue: u8) -> String {
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
///
/// Panics:
/// # Panics
///
/// 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!(
title.len() <= 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
#[must_use]
pub fn move_cursor_up(num: u16) -> String {
format!("\x1b[{num}A")
}
/// Moves the cursor down {num} characters
#[must_use]
pub fn move_cursor_down(num: u16) -> String {
format!("\x1b[{num}B")
}
/// Moves the cursor right {num} characters
#[must_use]
pub fn move_cursor_right(num: u16) -> String {
format!("\x1b[{num}C")
}
/// Moves the cursor left {num} characters
#[must_use]
pub fn move_cursor_left(num: u16) -> String {
format!("\x1b[{num}A")
}
@@ -47,21 +53,40 @@ pub fn move_cursor_left(num: u16) -> String {
/// Moves the cursor to {row}
///
/// Origin is 1, 1
pub fn move_cursor_to_row(row: u16) -> String {
format!("\x1b[{row}d")
#[must_use]
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}
///
/// Origin is 1, 1
#[must_use]
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")
}
/// Moves the cursor to Position {x}, {y}
///
/// Origin is 1, 1
#[must_use]
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")
}

View File

@@ -1,3 +1,7 @@
//! Various input functions, structs, etc.
//!
//! Very incomplete currently
use std::io::{self, Read};
use std::sync::mpsc;
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,
/// the buffer will only be partially updated based on how much the internal buffer holds.
///
/// Taken from the Termion crate
pub struct AsyncReader {
recv: mpsc::Receiver<io::Result<u8>>,
}

View File

@@ -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)]
#[path = "unix.rs"]
mod unix;
#[cfg(unix)]
use unix as os;
pub use unix::*;
#[cfg(windows)]
#[path = "windows.rs"]
mod windows;
mod unix;
#[cfg(windows)]
use windows as os;
/// 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;
pub use windows::*;

View File

@@ -46,17 +46,38 @@ struct Termios {
cc: [u8; NCCS],
}
/// Checks if stdout is a terminal
#[must_use]
pub fn is_terminal() -> bool {
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<()> {
// ANSI is on by default on unix platforms
// This is here for compatibility with the windows version of this API
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)> {
let mut winsize = unsafe { std::mem::zeroed::<Winsize>() };
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<()> {
let mut termios = unsafe { std::mem::zeroed::<Termios>() };
get_attributes(STDIN_FILENO, &mut termios)?;
@@ -76,6 +106,15 @@ pub fn enable_raw_mode() -> io::Result<()> {
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<()> {
let mut termios = unsafe { std::mem::zeroed::<Termios>() };
get_attributes(STDIN_FILENO, &mut termios)?;

View File

@@ -2,14 +2,6 @@
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" {
fn GetStdHandle(nStdHandle: u32) -> usize;
fn GetConsoleMode(hConsoleHandle: usize, dwMode: *mut u32) -> u32;
@@ -20,6 +12,14 @@ unsafe extern "system" {
) -> 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)]
#[derive(Default)]
struct ConsoleScreenBufferInfo {
@@ -36,6 +36,7 @@ struct ConsoleScreenBufferInfo {
dwMaximumWindowSizeY: u16,
}
/// Checks if stdout is a terminal
#[must_use]
pub fn is_terminal() -> bool {
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)> {
let handle = get_std_handle(STD_OUTPUT_HANDLE)?;
let mut csbi = ConsoleScreenBufferInfo::default();
@@ -59,15 +89,15 @@ pub fn get_terminal_size() -> io::Result<(u16, u16)> {
Err(io::Error::last_os_error())
}
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(())
}
/// 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<()> {
let handle = get_std_handle(STD_INPUT_HANDLE)?;
let mut dwMode = 0;
@@ -77,6 +107,15 @@ pub fn enable_raw_mode() -> io::Result<()> {
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<()> {
let handle = get_std_handle(STD_INPUT_HANDLE)?;
let mut dwMode = 0;