Finish stuff up

This commit is contained in:
2025-06-22 12:13:03 -04:00
parent 6e4039bba6
commit 160414819e
5 changed files with 61 additions and 97 deletions

View File

@@ -9,7 +9,8 @@ This project is still highly work in progress and it will be a decent while unti
- [x] Output (Unix)
- [x] Output (Windows)
- [x] Input (Unix) (Appears to work, more testing needed)
- [ ] Input (Windows) (WIP)
- [x] Input (Windows) (Appears to work, more testing needed)
- [ ] Input (Kitty)
- [ ] Events (Focus reporting, Bracketed-paste) (Unix)
- [ ] Events (Focus reporting, Bracketed-paste) (Windows)
- [ ] Mouse input (Unix)

View File

@@ -1,8 +1,8 @@
#![warn(clippy::all, clippy::pedantic)]
use neutuino::prelude::*;
use std::{io, time::Duration};
use std::io::IsTerminal;
use std::{io, time::Duration};
fn print_line_style_reset(string: &str) {
println!("{}{}{}", string, STYLE_RESET, move_cursor_to_column(0));
@@ -38,7 +38,7 @@ fn main() -> io::Result<()> {
COLORS_BG[next(counter)]
));
// q to quit
if input == Event::Key(KeyEvent::Char('q')) {
if input == Event::Key(Key::Char('q'), KeyType::Press, KeyModifiers::none()) {
break;
}
counter = next(counter);

View File

@@ -12,18 +12,14 @@
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Event {
/// An event that happens upon a key being pressed
Key(KeyEvent),
Key(Key, KeyType, KeyModifiers),
/// An event that happens upon focus to the terminal window being gained
FocusGained,
/// An event that happens upon focus to the terminal window being lost
FocusLost,
}
/// An event that happens upon a key being pressed
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct KeyEvent(pub Key, pub KeyType, pub KeyModifiers);
/// An event that happens upon a key being pressed
/// The base key that was pressed
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
/// The Backspace key
@@ -46,8 +42,6 @@ pub enum Key {
PageDown,
/// The Tab key
Tab,
/// Shift + Tab key
ShiftTab,
/// The delete key
Delete,
/// The insert key
@@ -119,12 +113,6 @@ pub enum KeyType {
Release,
}
impl From<KeyEvent> for Event {
fn from(value: KeyEvent) -> Self {
Self::Key(value)
}
}
#[cfg(unix)]
pub use crate::unix::input::*;

View File

@@ -11,7 +11,6 @@ unsafe extern "C" {
const STDIN_FILENO: c_int = 0;
const STDOUT_FILENO: c_int = 1;
const POLLIN: c_short = 1;
const ICRNL: c_uint = 0x40;
#[cfg(not(target_os = "macos"))]
const TIOCGWINSZ: c_ulong = 0x5413;
@@ -146,7 +145,7 @@ pub mod os {
pub mod input {
use super::{POLLIN, STDIN_FILENO};
use crate::input::{Event, Key, KeyEvent, KeyModifiers, KeyType};
use crate::input::{Event, Key, KeyModifiers, KeyType};
use std::ffi::{c_int, c_short, c_ulong, c_void};
use std::io;
use std::time::Duration;
@@ -228,44 +227,40 @@ pub mod input {
{
match item {
b'\x1b' => try_parse_ansi_sequence(iter),
b'\r' => Ok(Event::Key(KeyEvent(
b'\r' => Ok(Event::Key(
Key::Char('\n'),
KeyType::Press,
KeyModifiers::none(),
))),
b'\n' => Ok(Event::Key(KeyEvent(
)),
b'\n' => Ok(Event::Key(
Key::Char('j'),
KeyType::Press,
KeyModifiers::none().ctrl(),
))),
b'\t' => Ok(Event::Key(KeyEvent(
)),
b'\t' => Ok(Event::Key(
Key::Char('\t'),
KeyType::Press,
KeyModifiers::none(),
))),
b'\x7f' => Ok(Event::Key(KeyEvent(
)),
b'\x7f' => Ok(Event::Key(
Key::Backspace,
KeyType::Press,
KeyModifiers::none(),
))),
b'\0' => Ok(Event::Key(KeyEvent(
Key::Null,
KeyType::Press,
KeyModifiers::none(),
))),
c @ b'\x01'..=b'\x1a' => Ok(Event::Key(KeyEvent(
)),
b'\0' => Ok(Event::Key(Key::Null, KeyType::Press, KeyModifiers::none())),
c @ b'\x01'..=b'\x1a' => Ok(Event::Key(
Key::Char((c + 96) as char),
KeyType::Press,
KeyModifiers::none().ctrl(),
))),
c @ b'\x1c'..=b'\x1f' => Ok(Event::Key(KeyEvent(
)),
c @ b'\x1c'..=b'\x1f' => Ok(Event::Key(
Key::Char((c + 24) as char),
KeyType::Press,
KeyModifiers::none().ctrl(),
))),
)),
c => {
let character = parse_utf8_char(c, iter)?;
Ok(Event::Key(KeyEvent(
Ok(Event::Key(
Key::Char(parse_utf8_char(c, iter)?),
KeyType::Press,
KeyModifiers {
@@ -274,7 +269,7 @@ pub mod input {
ctrl: false,
meta: false,
},
)))
))
}
}
}
@@ -302,11 +297,11 @@ pub mod input {
let error = io::Error::other("Could not parse event");
match iter.next() {
Some(Ok(b'O')) => match iter.next() {
Some(Ok(val @ b'P'..=b's')) => Ok(Event::Key(KeyEvent(
Some(Ok(val @ b'P'..=b's')) => Ok(Event::Key(
Key::F(1 + val - b'P'),
KeyType::Press,
KeyModifiers::none(),
))),
)),
_ => Err(error),
},
Some(Ok(b'[')) => try_parse_csi_sequence(iter).ok_or(error),
@@ -320,48 +315,24 @@ pub mod input {
{
match iter.next() {
Some(Ok(b'[')) => match iter.next() {
Some(Ok(val @ b'A'..=b'E')) => Some(Event::Key(KeyEvent(
Some(Ok(val @ b'A'..=b'E')) => Some(Event::Key(
Key::F(1 + val - b'A'),
KeyType::Press,
KeyModifiers::none(),
))),
)),
_ => None,
},
Some(Ok(b'D')) => Some(Event::Key(KeyEvent(
Key::Left,
Some(Ok(b'D')) => Some(Event::Key(Key::Left, KeyType::Press, KeyModifiers::none())),
Some(Ok(b'C')) => Some(Event::Key(Key::Right, KeyType::Press, KeyModifiers::none())),
Some(Ok(b'A')) => Some(Event::Key(Key::Up, KeyType::Press, KeyModifiers::none())),
Some(Ok(b'B')) => Some(Event::Key(Key::Down, KeyType::Press, KeyModifiers::none())),
Some(Ok(b'H')) => Some(Event::Key(Key::Home, KeyType::Press, KeyModifiers::none())),
Some(Ok(b'F')) => Some(Event::Key(Key::End, KeyType::Press, KeyModifiers::none())),
Some(Ok(b'Z')) => Some(Event::Key(
Key::Tab,
KeyType::Press,
KeyModifiers::none(),
))),
Some(Ok(b'C')) => Some(Event::Key(KeyEvent(
Key::Right,
KeyType::Press,
KeyModifiers::none(),
))),
Some(Ok(b'A')) => Some(Event::Key(KeyEvent(
Key::Up,
KeyType::Press,
KeyModifiers::none(),
))),
Some(Ok(b'B')) => Some(Event::Key(KeyEvent(
Key::Down,
KeyType::Press,
KeyModifiers::none(),
))),
Some(Ok(b'H')) => Some(Event::Key(KeyEvent(
Key::Home,
KeyType::Press,
KeyModifiers::none(),
))),
Some(Ok(b'F')) => Some(Event::Key(KeyEvent(
Key::End,
KeyType::Press,
KeyModifiers::none(),
))),
Some(Ok(b'Z')) => Some(Event::Key(KeyEvent(
Key::ShiftTab,
KeyType::Press,
KeyModifiers::none(),
))),
KeyModifiers::none().shift(),
)),
_ => None,
}
}

View File

@@ -148,7 +148,7 @@ pub mod os {
pub mod input {
use super::get_stdin_handle;
use crate::input::{Event, KeyEvent, Key, KeyModifiers, KeyType};
use crate::input::{Event, Key, KeyModifiers, KeyType};
use std::os::windows::raw::HANDLE;
use std::{io, mem, time::Duration};
@@ -241,7 +241,7 @@ pub mod input {
// more this will have to do
return Err(io::ErrorKind::Other.into());
}
Ok(Event::Key(parse_key_event(&key_event)))
Ok(parse_key_event(&key_event))
}
_ => {
//TODO Make this better
@@ -250,41 +250,45 @@ pub mod input {
}
}
fn parse_key_event(event: &KeyEventRecord) -> KeyEvent {
fn parse_key_event(event: &KeyEventRecord) -> Event {
let ctrl = event.control_key_state & (0x0008 | 0x0004) != 0; // LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED
let shift = event.control_key_state & 0x0010 != 0; // SHIFT_PRESSED
match event.virtual_key_code {
0x08 => KeyEvent(Key::Backspace, KeyType::Press, KeyModifiers::none()),
0x08 => Event::Key(Key::Backspace, KeyType::Press, KeyModifiers::none()),
0x09 => {
if shift {
KeyEvent(Key::ShiftTab, KeyType::Press, KeyModifiers::none().shift())
Event::Key(Key::Tab, KeyType::Press, KeyModifiers::none().shift())
} else {
KeyEvent(Key::Tab, KeyType::Press, KeyModifiers::none())
Event::Key(Key::Tab, KeyType::Press, KeyModifiers::none())
}
}
0x0D => KeyEvent(Key::Char('\n'), KeyType::Press, KeyModifiers::none()),
0x1B => KeyEvent(Key::Escape, KeyType::Press, KeyModifiers::none()),
0x21 => KeyEvent(Key::PageUp, KeyType::Press, KeyModifiers::none()),
0x22 => KeyEvent(Key::PageDown, KeyType::Press, KeyModifiers::none()),
0x23 => KeyEvent(Key::End, KeyType::Press, KeyModifiers::none()),
0x24 => KeyEvent(Key::Home, KeyType::Press, KeyModifiers::none()),
0x25 => KeyEvent(Key::Left, KeyType::Press, KeyModifiers::none()),
0x26 => KeyEvent(Key::Up, KeyType::Press, KeyModifiers::none()),
0x27 => KeyEvent(Key::Right, KeyType::Press, KeyModifiers::none()),
0x28 => KeyEvent(Key::Down, KeyType::Press, KeyModifiers::none()),
0x2D => KeyEvent(Key::Insert, KeyType::Press, KeyModifiers::none()),
0x2E => KeyEvent(Key::Delete, KeyType::Press, KeyModifiers::none()),
0x0D => Event::Key(Key::Char('\n'), KeyType::Press, KeyModifiers::none()),
0x1B => Event::Key(Key::Escape, KeyType::Press, KeyModifiers::none()),
0x21 => Event::Key(Key::PageUp, KeyType::Press, KeyModifiers::none()),
0x22 => Event::Key(Key::PageDown, KeyType::Press, KeyModifiers::none()),
0x23 => Event::Key(Key::End, KeyType::Press, KeyModifiers::none()),
0x24 => Event::Key(Key::Home, KeyType::Press, KeyModifiers::none()),
0x25 => Event::Key(Key::Left, KeyType::Press, KeyModifiers::none()),
0x26 => Event::Key(Key::Up, KeyType::Press, KeyModifiers::none()),
0x27 => Event::Key(Key::Right, KeyType::Press, KeyModifiers::none()),
0x28 => Event::Key(Key::Down, KeyType::Press, KeyModifiers::none()),
0x2D => Event::Key(Key::Insert, KeyType::Press, KeyModifiers::none()),
0x2E => Event::Key(Key::Delete, KeyType::Press, KeyModifiers::none()),
// I don't think anybody is going to try to press F256 clippy
#[allow(clippy::cast_possible_truncation)]
0x70..=0x87 => KeyEvent(Key::F((event.virtual_key_code - 0x6F) as u8), KeyType::Press, KeyModifiers::none()), // F1-F24
0x70..=0x87 => Event::Key(
Key::F((event.virtual_key_code - 0x6F) as u8),
KeyType::Press,
KeyModifiers::none(),
), // F1-F24
_ => {
let c =
char::from_u32(u32::from(unsafe { event.u_char.unicode_char })).unwrap_or(' ');
if ctrl && c.is_ascii_alphabetic() {
KeyEvent(Key::Char(c), KeyType::Press, KeyModifiers::none().ctrl())
Event::Key(Key::Char(c), KeyType::Press, KeyModifiers::none().ctrl())
} else {
KeyEvent(Key::Char(c), KeyType::Press, KeyModifiers::none())
Event::Key(Key::Char(c), KeyType::Press, KeyModifiers::none())
}
}
}