sysutils: add a showkey program
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)?;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"),
|
||||
|
||||
Reference in New Issue
Block a user