sysutils: add a showkey program

This commit is contained in:
2026-01-08 14:45:14 +02:00
parent 7abb950a8f
commit e44b616998
5 changed files with 94 additions and 22 deletions
+39 -12
View File
@@ -84,21 +84,23 @@ impl TerminalInput {
self.buffer_len -= count;
}
fn parse_utf8_from_buffer(&mut self) -> Option<TermKey> {
fn parse_utf8_from_buffer(&mut self, output: &mut [u8]) -> Option<(TermKey, usize)> {
for count in 1..=4 {
if count > self.buffer_len {
break;
}
if let Ok(utf8) = std::str::from_utf8(&self.buffer[..count]) {
let ch = utf8.chars().next().unwrap();
let output_len = output.len().min(count);
output[..output_len].copy_from_slice(&self.buffer[..output_len]);
self.take(count);
return Some(TermKey::Char(ch));
return Some((TermKey::Char(ch), output_len));
}
}
None
}
fn parse_escape(&mut self) -> Option<TermKey> {
fn parse_escape(&mut self, output: &mut [u8]) -> Option<(TermKey, usize)> {
const MATCH_TABLE: &[(&[u8], TermKey)] = &[
(b"\x04", TermKey::Eof),
//
@@ -159,6 +161,9 @@ impl TerminalInput {
return None;
}
let output_len = output.len().min(self.buffer_len);
output[..output_len].copy_from_slice(&data[..output_len]);
if data.len() >= 6 {
let x = mouse_event_coord(data[4]);
let y = mouse_event_coord(data[5]);
@@ -175,25 +180,25 @@ impl TerminalInput {
if let Some(event) = event {
self.take(6);
return Some(event(x, y));
return Some((event(x, y), output_len));
}
}
for &(m, key) in MATCH_TABLE {
if data.starts_with(m) {
self.take(m.len());
return Some(key);
return Some((key, output_len));
}
}
None
}
fn parse_from_buffer(&mut self) -> Option<TermKey> {
if let Some(key) = self.parse_escape() {
return Some(key);
fn parse_from_buffer(&mut self, output: &mut [u8]) -> Option<(TermKey, usize)> {
if let Some((key, len)) = self.parse_escape(output) {
return Some((key, len));
}
self.parse_utf8_from_buffer()
self.parse_utf8_from_buffer(output)
}
pub fn read_cursor_position_report(&mut self) -> io::Result<Option<(u32, u32)>> {
@@ -245,9 +250,9 @@ impl TerminalInput {
}
}
pub fn read_key(&mut self) -> io::Result<TermKey> {
pub fn read_key_with_bytes(&mut self, bytes: &mut [u8]) -> io::Result<(TermKey, usize)> {
while self.buffer_len < self.buffer.len() {
if let Some(key) = self.parse_from_buffer() {
if let Some(key) = self.parse_from_buffer(bytes) {
return Ok(key);
}
if self.buffer_len > 0 && self.buffer[0] != b'\x1B' {
@@ -260,7 +265,29 @@ impl TerminalInput {
self.buffer_len += count;
}
if let Some(key) = self.parse_from_buffer() {
if let Some(key) = self.parse_from_buffer(bytes) {
return Ok(key);
}
todo!("Buffer full, but no key read")
}
pub fn read_key(&mut self) -> io::Result<TermKey> {
while self.buffer_len < self.buffer.len() {
if let Some((key, _)) = self.parse_from_buffer(&mut []) {
return Ok(key);
}
if self.buffer_len > 0 && self.buffer[0] != b'\x1B' {
break;
}
if self.buffer_len != 0 && self.poll.wait(Some(Duration::from_millis(10)))?.is_none() {
break;
}
let count = self.stdin.read(&mut self.buffer[self.buffer_len..])?;
self.buffer_len += count;
}
if let Some((key, _)) = self.parse_from_buffer(&mut []) {
return Ok(key);
}
+4
View File
@@ -122,6 +122,10 @@ path = "src/cat.rs"
name = "hexd"
path = "src/hexd.rs"
[[bin]]
name = "showkey"
path = "src/showkey.rs"
[[bin]]
name = "random"
path = "src/random.rs"
+9 -8
View File
@@ -1,7 +1,7 @@
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os))]
use std::{
io::{self, stdout, Read, Write},
io::{self, Read, Write, stdout},
os::fd::AsRawFd,
path::PathBuf,
process::ExitCode,
@@ -28,7 +28,7 @@ fn run(args: Args) -> io::Result<()> {
let mut stdin = RawStdin::open()?;
let mut buffer = [0; 1];
let mut ctrl_a = false;
let mut ctrl_x = false;
poll.add(&serial)?;
poll.add(&stdin)?;
@@ -41,14 +41,15 @@ fn run(args: Args) -> io::Result<()> {
break;
}
if ctrl_a {
if ctrl_x {
match buffer[0] {
b'x' => break,
_ => ctrl_a = false,
// c
b'c' => break,
_ => ctrl_x = false,
}
} else if buffer[0] == 0x01 {
// Ctrl+A
ctrl_a = true;
} else if buffer[0] == 0x18 {
// Ctrl+X
ctrl_x = true;
} else {
serial.write_all(&buffer)?;
}
+39
View File
@@ -0,0 +1,39 @@
use cross::term::TerminalInput;
use libterm::TermKey;
fn main() {
println!("Press Ctrl+D to exit");
let mut input = TerminalInput::open().expect("Couldn't open terminal input");
let mut buffer = [0; 64];
loop {
let (key, len) = input.read_key_with_bytes(&mut buffer).unwrap();
if len == 1 {
println!(
"{key:?}\t{}\t0o{:04o}\t0x{:02x}",
buffer[0], buffer[0], buffer[0]
);
} else {
println!("{key:?}");
print!("\t");
for &byte in &buffer[..len] {
match byte {
b'\x1B' => print!(" ^["),
_ => print!(" {:?}", byte as char),
}
}
println!();
print!("\t");
for &byte in &buffer[..len] {
print!(" {byte:02x}");
}
println!();
}
if key == TermKey::Eof {
break;
}
}
}
+3 -2
View File
@@ -30,7 +30,6 @@ const PROGRAMS: &[(&str, &str)] = &[
("shell", "bin/sh"),
// sysutils
("cat", "bin/cat"),
("tar", "bin/tar"),
("chmod", "bin/chmod"),
("chroot", "sbin/chroot"),
("date", "bin/date"),
@@ -52,17 +51,19 @@ const PROGRAMS: &[(&str, &str)] = &[
("random", "bin/random"),
("reboot", "sbin/reboot"),
("rm", "bin/rm"),
("serial", "bin/serial"),
("sha256sum", "bin/sha256sum"),
("showkey", "bin/showkey"),
("sleep", "bin/sleep"),
("strace", "bin/strace"),
("sync", "bin/sync"),
("sysmon", "bin/sysmon"),
("tar", "bin/tar"),
("top", "bin/top"),
("touch", "bin/touch"),
("tree", "bin/tree"),
("tst", "bin/tst"),
("view", "bin/view"),
("serial", "bin/serial"),
// netutils
("netconf", "sbin/netconf"),
("dhcp-client", "sbin/dhcp-client"),