mirror of
https://github.com/Xyverle/neutuino.git
synced 2026-06-26 22:23:14 -04:00
Finish stuff up
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
16
src/input.rs
16
src/input.rs
@@ -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::*;
|
||||
|
||||
|
||||
89
src/unix.rs
89
src/unix.rs
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user