all: remove yggdrasil_rt dependency

This commit is contained in:
Mark Poliakov 2023-11-24 13:29:53 +02:00
parent 6c8ae720d0
commit 6da1dbecc7
15 changed files with 362 additions and 203 deletions

119
Cargo.lock generated
View File

@ -4,9 +4,9 @@ version = 3
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.1" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
@ -34,20 +34,19 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.3.19" version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
"once_cell",
] ]
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.3.19" version = "4.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"clap_lex", "clap_lex",
@ -55,9 +54,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.3.12" version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -67,9 +66,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.5.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]] [[package]]
name = "crossterm" name = "crossterm"
@ -114,6 +113,43 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "futures-core"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-macro"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-task"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-core",
"futures-macro",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
@ -230,12 +266,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.1" version = "0.12.1"
@ -259,6 +289,18 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -267,18 +309,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.66" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.32" version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -311,18 +353,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.192" version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.192" version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -369,6 +411,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.11.2" version = "1.11.2"
@ -377,9 +428,9 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.32" version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -405,7 +456,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"humansize", "humansize",
"yggdrasil-rt",
] ]
[[package]] [[package]]
@ -461,9 +511,9 @@ dependencies = [
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.11" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
@ -571,13 +621,22 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "yasync"
version = "0.1.0"
dependencies = [
"futures-util",
]
[[package]] [[package]]
name = "yggdrasil-abi" name = "yggdrasil-abi"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.alnyan.me/yggdrasil/yggdrasil-abi.git#c957a433c73bd704ca0c64c16477638ababe2432"
[[package]] [[package]]
name = "yggdrasil-rt" name = "yggdrasil-rt"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.alnyan.me/yggdrasil/yggdrasil-rt.git#f00ecdb926c2f912d658589f9f631100e41ad6c5"
dependencies = [ dependencies = [
"yggdrasil-abi", "yggdrasil-abi",
] ]

View File

@ -6,9 +6,3 @@ members = [
"sysutils", "sysutils",
"red" "red"
] ]
[patch.'https://git.alnyan.me/yggdrasil/yggdrasil-abi.git']
yggdrasil-abi = { path = "../abi" }
[patch.'https://git.alnyan.me/yggdrasil/yggdrasil-rt.git']
yggdrasil-rt = { path = "rt" }

View File

@ -1,3 +1,3 @@
init:1:wait:/sbin/rc default init:1:wait:/sbin/rc default
user:1:once:/sbin/login /dev/tty0 user:1:once:/sbin/login /dev/ttyS0

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
buffer::Mode, buffer::Mode,
command::Action, command::Action,
keymap::{bind, KeyMap, PrefixNode}, keymap::{bindn, bind1, KeyMap, KeySeq, PrefixNode},
}; };
pub struct Config { pub struct Config {
@ -18,30 +18,30 @@ impl Default for Config {
use Action::*; use Action::*;
let nmap = KeyMap::from_iter([ let nmap = KeyMap::from_iter([
bind('i', [InsertBefore]), bind1('i', [InsertBefore]),
bind('a', [InsertAfter]), bind1('a', [InsertAfter]),
bind('h', [MoveCharPrev]), bind1('h', [MoveCharPrev]),
bind('l', [MoveCharNext]), bind1('l', [MoveCharNext]),
bind('j', [MoveLineForward(1)]), bind1('j', [MoveLineForward(1)]),
bind("J", [MoveLineForward(25)]), bind1('J', [MoveLineForward(25)]),
bind('k', [MoveLineBack(1)]), bind1('k', [MoveLineBack(1)]),
bind("K", [MoveLineBack(25)]), bind1('K', [MoveLineBack(25)]),
bind("gg", [MoveFirstLine]), bindn(['g', 'g'], [MoveFirstLine]),
bind("G", [MoveLastLine]), bind1('G', [MoveLastLine]),
bind('I', [MoveLineStart, InsertBefore]), bind1('I', [MoveLineStart, InsertBefore]),
bind('A', [MoveLineEnd, InsertAfter]), bind1('A', [MoveLineEnd, InsertAfter]),
bind('o', [NewlineAfter, MoveLineForward(1), InsertBefore]), bind1('o', [NewlineAfter, MoveLineForward(1), InsertBefore]),
bind('O', [NewlineBefore, MoveLineBack(1), InsertBefore]), bind1('O', [NewlineBefore, MoveLineBack(1), InsertBefore]),
bind("dd", [KillLine]), bindn(['d', 'd'], [KillLine]),
]); ]);
let imap = KeyMap::from_iter([ let imap = KeyMap::from_iter([
bind('\x7F', [EraseBackward]), bind1('\x7F', [EraseBackward]),
bind( bind1(
'\n', '\n',
[BreakLine, MoveLineForward(1), MoveLineStart, InsertBefore], [BreakLine, MoveLineForward(1), MoveLineStart, InsertBefore],
), ),
bind( bind1(
'\x0D', '\x0D',
[BreakLine, MoveLineForward(1), MoveLineStart, InsertBefore], [BreakLine, MoveLineForward(1), MoveLineStart, InsertBefore],
), ),
@ -57,10 +57,10 @@ impl Default for Config {
} }
impl Config { impl Config {
pub fn key(&self, mode: Mode, key: &str) -> Option<&PrefixNode<String, Vec<Action>>> { pub fn key_seq(&self, mode: Mode, seq: &KeySeq) -> Option<&PrefixNode<KeySeq, Vec<Action>>> {
match mode { match mode {
Mode::Normal => self.nmap.get(key), Mode::Normal => self.nmap.get(seq),
Mode::Insert => self.imap.get(key), Mode::Insert => self.imap.get(seq),
} }
} }
} }

76
red/src/keymap/key.rs Normal file
View File

@ -0,0 +1,76 @@
use std::fmt::{self, Write};
use super::map::Prefix;
#[derive(Clone, Copy, PartialEq, Debug, Hash, Eq)]
pub enum Key {
Char(char),
Escape,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct KeySeq(Vec<Key>);
impl KeySeq {
pub fn one<I: Into<Key>>(k: I) -> Self {
Self(vec![k.into()])
}
pub fn empty() -> Self {
Self(vec![])
}
pub fn push<I: Into<Key>>(&mut self, k: I) {
self.0.push(k.into());
}
pub fn clear(&mut self) {
self.0.clear();
}
}
impl Prefix for KeySeq {
fn prefix(&self) -> Option<Self> {
self.0.split_last().map(|(_, vs)| vs.iter().copied().collect()).map(Self)
}
}
impl<K: Into<Key>, I: IntoIterator<Item = K>> From<I> for KeySeq {
fn from(value: I) -> Self {
Self(value.into_iter().map(Into::into).collect())
}
}
impl From<Key> for KeySeq {
fn from(value: Key) -> Self {
Self::one(value)
}
}
impl fmt::Display for KeySeq {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, key) in self.0.iter().enumerate() {
if i != 0 {
f.write_char('+')?;
}
fmt::Display::fmt(key, f)?;
}
Ok(())
}
}
impl From<char> for Key {
fn from(value: char) -> Self {
Self::Char(value)
}
}
impl fmt::Display for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Char('\t') => f.write_str("<tab>"),
Self::Char(key) => fmt::Display::fmt(key, f),
Self::Escape => f.write_str("<esc>"),
}
}
}

View File

@ -1,18 +1,18 @@
use std::{ use std::{borrow::Borrow, hash::Hash};
borrow::Borrow,
hash::Hash,
};
use crate::command::Action; use crate::command::Action;
use self::map::{PrefixMap, Prefix}; use self::map::PrefixMap;
pub use self::map::PrefixNode; pub use self::map::PrefixNode;
mod key;
mod map; mod map;
#[derive(Debug, Default)] pub use key::{Key, KeySeq};
#[derive(Debug)]
pub struct KeyMap { pub struct KeyMap {
map: PrefixMap<String, Vec<Action>>, map: PrefixMap<KeySeq, Vec<Action>>,
} }
impl KeyMap { impl KeyMap {
@ -22,64 +22,37 @@ impl KeyMap {
} }
} }
pub fn get<N>(&self, key: &N) -> Option<&PrefixNode<String, Vec<Action>>> pub fn get<N>(&self, key: &N) -> Option<&PrefixNode<KeySeq, Vec<Action>>>
where where
String: Borrow<N>, KeySeq: Borrow<N>,
N: Eq + Hash + ?Sized, N: Eq + Hash + ?Sized,
{ {
self.map.get(key) self.map.get(key)
} }
} }
impl FromIterator<(String, Vec<Action>)> for KeyMap { impl FromIterator<(KeySeq, Vec<Action>)> for KeyMap {
fn from_iter<T: IntoIterator<Item = (String, Vec<Action>)>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = (KeySeq, Vec<Action>)>>(iter: T) -> Self {
Self { Self {
map: PrefixMap::from_iter(iter), map: PrefixMap::from_iter(iter),
} }
} }
} }
impl Prefix for String { pub fn bindn<I: Into<KeySeq>, V: IntoIterator<Item = Action>>(
fn prefix(&self) -> Option<Self> {
if self.is_empty() {
None
} else {
let mut res = self.clone();
res.remove(res.len() - 1);
Some(res)
}
}
}
pub fn bind<I: Into<String>, V: IntoIterator<Item = Action>>(
key: I, key: I,
actions: V, actions: V,
) -> (String, Vec<Action>) { ) -> (KeySeq, Vec<Action>) {
(key.into(), actions.into_iter().collect()) (key.into(), actions.into_iter().collect())
} }
pub fn bind1<I: Into<Key>, V: IntoIterator<Item = Action>>(key: I, actions: V) -> (KeySeq, Vec<Action>) {
(KeySeq::one(key), actions.into_iter().collect())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::HashSet;
use crate::{command::Action, keymap::PrefixNode};
use super::{bind, KeyMap};
#[test] #[test]
fn from_iter() { fn from_iter() {
let map = KeyMap::from_iter([
bind("aa", [Action::InsertBefore, Action::MoveLineEnd]),
]);
assert_eq!(
map.get("a"),
Some(&PrefixNode::Prefix(HashSet::from_iter(["aa".to_owned()])))
);
assert_eq!(
map.get("aa"),
Some(&PrefixNode::Leaf([Action::InsertBefore, Action::MoveLineEnd].to_vec()))
);
} }
} }

View File

@ -1,4 +1,4 @@
#![feature(let_chains, rustc_private)] #![feature(let_chains, rustc_private, async_fn_in_trait)]
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_raw_fd, yggdrasil_os))] #![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_raw_fd, yggdrasil_os))]
use std::{env, fmt::Write, path::Path}; use std::{env, fmt::Write, path::Path};
@ -6,7 +6,7 @@ use std::{env, fmt::Write, path::Path};
use buffer::{Buffer, Mode, SetMode}; use buffer::{Buffer, Mode, SetMode};
use config::Config; use config::Config;
use error::Error; use error::Error;
use keymap::PrefixNode; use keymap::{PrefixNode, KeySeq, Key};
use term::{Clear, Color, Term}; use term::{Clear, Color, Term};
pub mod buffer; pub mod buffer;
@ -29,7 +29,7 @@ pub struct State {
command: String, command: String,
message: Option<String>, message: Option<String>,
status: Option<String>, status: Option<String>,
key: String, key_seq: KeySeq,
top_mode: TopMode, top_mode: TopMode,
config: Config, config: Config,
running: bool, running: bool,
@ -59,7 +59,7 @@ impl State {
message: None, message: None,
status: None, status: None,
command: String::new(), command: String::new(),
key: String::new(), key_seq: KeySeq::empty(),
running: true, running: true,
buffer, buffer,
term, term,
@ -157,7 +157,7 @@ impl State {
self.term self.term
.set_cursor_position(self.buffer.height(), self.buffer.width() - 10)?; .set_cursor_position(self.buffer.height(), self.buffer.width() - 10)?;
self.term.set_foreground(Color::White)?; self.term.set_foreground(Color::White)?;
write!(self.term, "{}", self.key).map_err(Error::TerminalFmtError)?; write!(self.term, "{}", self.key_seq).map_err(Error::TerminalFmtError)?;
self.term.reset_style()?; self.term.reset_style()?;
@ -213,38 +213,37 @@ impl State {
command::execute(self, cmd) command::execute(self, cmd)
} }
fn handle_command_key(&mut self, key: char) -> Result<(), Error> { fn handle_command_key(&mut self, key: Key) -> Result<(), Error> {
match key { match key {
'\n' | '\x0D' => { Key::Char('\n') | Key::Char('\x0D') => {
self.top_mode = TopMode::Normal; self.top_mode = TopMode::Normal;
self.handle_command()?; self.handle_command()?;
} }
'\x7F' => { Key::Char('\x7F') => {
if self.command.is_empty() { if self.command.is_empty() {
self.top_mode = TopMode::Normal; self.top_mode = TopMode::Normal;
} else { } else {
self.command.pop(); self.command.pop();
} }
} }
'\x1B' => { Key::Escape => {
self.top_mode = TopMode::Normal; self.top_mode = TopMode::Normal;
} }
c if c.is_ascii_graphic() => self.command.push(c), Key::Char(c) if c.is_ascii_graphic() || c == ' ' => self.command.push(c),
' ' => self.command.push(' '),
_ => (), _ => (),
} }
Ok(()) Ok(())
} }
fn handle_mode_key(&mut self, mode: Mode, key: char) -> Result<(), Error> { fn handle_mode_key(&mut self, mode: Mode, key: Key) -> Result<(), Error> {
let buffer = &mut self.buffer; let buffer = &mut self.buffer;
self.key.push(key); self.key_seq.push(key);
match self.config.key(mode, &self.key) { match self.config.key_seq(mode, &self.key_seq) {
Some(PrefixNode::Leaf(actions)) => { Some(PrefixNode::Leaf(actions)) => {
self.key.clear(); self.key_seq.clear();
for &action in actions { for &action in actions {
command::perform(buffer, &self.config, action)?; command::perform(buffer, &self.config, action)?;
@ -252,7 +251,7 @@ impl State {
} }
Some(PrefixNode::Prefix(_)) => {} Some(PrefixNode::Prefix(_)) => {}
None => { None => {
self.key.clear(); self.key_seq.clear();
} }
} }
@ -263,15 +262,15 @@ impl State {
Ok(()) Ok(())
} }
fn handle_normal_key(&mut self, key: char) -> Result<(), Error> { fn handle_normal_key(&mut self, key: Key) -> Result<(), Error> {
match key { match key {
'\x1B' => { Key::Escape => {
self.key.clear(); self.key_seq.clear();
self.buffer.set_mode(&self.config, SetMode::Normal); self.buffer.set_mode(&self.config, SetMode::Normal);
Ok(()) Ok(())
} }
':' => { Key::Char(':') => {
self.key.clear(); self.key_seq.clear();
self.command.clear(); self.command.clear();
self.status = None; self.status = None;
self.top_mode = TopMode::Command; self.top_mode = TopMode::Command;
@ -281,13 +280,13 @@ impl State {
} }
} }
fn handle_insert_key(&mut self, key: char) -> Result<(), Error> { fn handle_insert_key(&mut self, key: Key) -> Result<(), Error> {
match key { match key {
'\x1B' => { Key::Escape => {
self.buffer.set_mode(&self.config, SetMode::Normal); self.buffer.set_mode(&self.config, SetMode::Normal);
Ok(()) Ok(())
} }
key if !key.is_ascii() || key == ' ' || key == '\t' || key.is_ascii_graphic() => { Key::Char(key) if !key.is_ascii() || key == ' ' || key == '\t' || key.is_ascii_graphic() => {
self.buffer.insert(&self.config, key); self.buffer.insert(&self.config, key);
Ok(()) Ok(())
} }
@ -312,7 +311,7 @@ impl State {
if self.message.is_some() { if self.message.is_some() {
self.message = None; self.message = None;
if key != ':' { if key != Key::Char(':') {
return Ok(()); return Ok(());
} }
} }

View File

@ -1,9 +1,10 @@
use std::io::{Read, Stdin}; use std::{io::{Read, Stdin}, future::{Future, self}};
use crate::error::InputError; use crate::error::InputError;
pub trait ReadChar { pub trait ReadChar {
fn read_char(&mut self) -> Result<char, InputError>; fn read_char(&mut self) -> Result<char, InputError>;
async fn read_byte_delay(&mut self);
} }
impl ReadChar for Stdin { impl ReadChar for Stdin {
@ -23,6 +24,10 @@ impl ReadChar for Stdin {
let s = core::str::from_utf8(&buf[..len + 1]).map_err(InputError::DecodeError)?; let s = core::str::from_utf8(&buf[..len + 1]).map_err(InputError::DecodeError)?;
Ok(s.chars().next().unwrap()) Ok(s.chars().next().unwrap())
} }
async fn read_byte_delay(&mut self) {
todo!();
}
} }
const fn utf8_len_prefix(l: u8) -> Option<usize> { const fn utf8_len_prefix(l: u8) -> Option<usize> {

View File

@ -1,6 +1,6 @@
use std::{io::{Stdout, Write, Stdin, stdin, stdout, self}, fmt}; use std::{io::{Stdout, Write, Stdin, stdin, stdout, self}, fmt};
use crate::{error::Error, term::input::ReadChar}; use crate::{error::Error, term::input::ReadChar, keymap::Key};
use self::sys::RawMode; use self::sys::RawMode;
@ -161,8 +161,14 @@ impl Term {
}.map_err(Error::TerminalError) }.map_err(Error::TerminalError)
} }
pub fn read_key(&mut self) -> Result<char, Error> { pub fn read_key(&mut self) -> Result<Key, Error> {
self.stdin.read_char().map_err(Error::InputError) let ch = self.stdin.read_char().map_err(Error::InputError)?;
if ch == '\x1B' {
return Ok(Key::Escape);
}
Ok(Key::Char(ch))
} }
pub fn flush(&mut self) -> Result<(), Error> { pub fn flush(&mut self) -> Result<(), Error> {

View File

@ -9,7 +9,6 @@ edition = "2021"
clap = { version = "4.3.19", features = ["std", "derive"], default-features = false } clap = { version = "4.3.19", features = ["std", "derive"], default-features = false }
# TODO own impl # TODO own impl
humansize = { version = "2.1.3", features = ["impl_style"] } humansize = { version = "2.1.3", features = ["impl_style"] }
yggdrasil-rt = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-rt.git" }
[lib] [lib]
path = "src/lib.rs" path = "src/lib.rs"

View File

@ -1,11 +1,12 @@
fn main() { fn main() {
for bg in 40..=49 { loop {}
if bg == 48 { continue; } // for bg in 40..=49 {
for fg in 30..=39 { // if bg == 48 { continue; }
if fg == 48 { continue; } // for fg in 30..=39 {
print!("\x1B[{}m\x1B[{}m@\x1B[0m", bg, fg); // if fg == 48 { continue; }
} // print!("\x1B[{}m\x1B[{}m@\x1B[0m", bg, fg);
println!(); // }
} // println!();
// }
} }

View File

@ -1,4 +1,50 @@
use std::{io::{self, Read}, fs::File}; use std::{
fs::File,
io::{self, Read},
};
#[cfg(unix)]
pub mod unix {
use std::fmt;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct FileMode(u32);
impl From<u32> for FileMode {
fn from(value: u32) -> Self {
Self(value)
}
}
impl fmt::Display for FileMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
macro_rules! print_bit {
($res:expr, $val:expr, $self:expr, $bit:expr) => {
if $self.0 & $bit == $bit {
$res = $val;
}
};
}
let mut buf = ['-'; 9];
print_bit!(buf[0], 'r', self, 0o400);
print_bit!(buf[1], 'w', self, 0o200);
print_bit!(buf[2], 'x', self, 0o100);
print_bit!(buf[3], 'r', self, 0o040);
print_bit!(buf[4], 'w', self, 0o020);
print_bit!(buf[5], 'x', self, 0o010);
print_bit!(buf[6], 'r', self, 0o004);
print_bit!(buf[7], 'w', self, 0o002);
print_bit!(buf[8], 'x', self, 0o001);
for ch in buf.iter() {
fmt::Display::fmt(ch, f)?;
}
Ok(())
}
}
}
// TODO replace this // TODO replace this
pub trait ToExitCode { pub trait ToExitCode {
@ -9,14 +55,14 @@ impl<T> ToExitCode for io::Result<T> {
fn to_exit_code(&self) -> i32 { fn to_exit_code(&self) -> i32 {
match self { match self {
Ok(_) => 0, Ok(_) => 0,
_ => 1 _ => 1,
} }
} }
} }
pub enum Input { pub enum Input {
Stdin(io::Stdin), Stdin(io::Stdin),
File(io::BufReader<File>) File(io::BufReader<File>),
} }
impl Input { impl Input {
@ -47,7 +93,7 @@ impl Read for Input {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self { match self {
Self::Stdin(value) => value.read(buf), Self::Stdin(value) => value.read(buf),
Self::File(value) => value.read(buf) Self::File(value) => value.read(buf),
} }
} }
} }

View File

@ -2,18 +2,15 @@
use std::{ use std::{
env, env,
io::{stdin, stdout, BufRead, Write}, io::{self, stdin, stdout, BufRead, Write},
os::{ os::{
fd::AsRawFd, fd::AsRawFd,
yggdrasil::signal::{set_signal_handler, Signal, SignalHandler}, yggdrasil::{
io::{start_terminal_session, DeviceRequest, FdDeviceRequest},
signal::{set_signal_handler, Signal, SignalHandler},
},
}, },
process::{ExitCode, Command}, process::{self, Command, ExitCode},
};
use yggdrasil_rt::{
debug_trace,
io::{DeviceRequest, FileMode, OpenOptions, RawFd},
sys,
}; };
fn handler(_signal: Signal) {} fn handler(_signal: Signal) {}
@ -22,18 +19,18 @@ fn login_readline<R: BufRead + AsRawFd>(
reader: &mut R, reader: &mut R,
buf: &mut String, buf: &mut String,
_secret: bool, _secret: bool,
) -> Result<usize, std::io::Error> { ) -> Result<usize, io::Error> {
reader.read_line(buf) reader.read_line(buf)
} }
fn login_as(username: &str, _password: &str) -> Result<(), std::io::Error> { fn login_as(username: &str, _password: &str) -> Result<(), io::Error> {
let mut shell = Command::new("/bin/sh").arg("-l").spawn()?; let mut shell = Command::new("/bin/sh").arg("-l").spawn()?;
println!("Hello {:?}", username); println!("Hello {:?}", username);
shell.wait()?; shell.wait()?;
Ok(()) Ok(())
} }
fn login_attempt(erase: bool) -> Result<(), std::io::Error> { fn login_attempt(erase: bool) -> Result<(), io::Error> {
let mut stdin = stdin().lock(); let mut stdin = stdin().lock();
let mut stdout = stdout(); let mut stdout = stdout();
@ -53,20 +50,6 @@ fn login_attempt(erase: bool) -> Result<(), std::io::Error> {
login_as(username.trim(), "") login_as(username.trim(), "")
} }
fn setup_session(terminal: &str) -> Result<(), yggdrasil_rt::Error> {
// This will close the file descriptors associated with the old terminal
unsafe { sys::start_session()? };
unsafe {
// File descriptors 0, 1, 2 are now free, need to reopen them with a new terminal
sys::open(None, terminal, OpenOptions::READ, FileMode::empty())?;
sys::open(None, terminal, OpenOptions::WRITE, FileMode::empty())?;
sys::open(None, terminal, OpenOptions::WRITE, FileMode::empty())?;
}
Ok(())
}
fn main() -> ExitCode { fn main() -> ExitCode {
let args: Vec<_> = env::args().skip(1).collect(); let args: Vec<_> = env::args().skip(1).collect();
if args.len() != 1 { if args.len() != 1 {
@ -76,21 +59,22 @@ fn main() -> ExitCode {
let terminal = args[0].as_str(); let terminal = args[0].as_str();
// TODO check that `terminal` is a terminal // TODO check that `terminal` is a terminal
debug_trace!("Starting a session at {}", terminal); debug_trace!("Starting a session at {}", terminal);
if let Err(err) = setup_session(terminal) { if let Err(err) = unsafe { start_terminal_session(terminal) } {
debug_trace!("Failed: {:?}", err); debug_trace!("Error: {:?}", err);
eprintln!("Could not setup session at {}: {:?}", terminal, err); eprintln!("Could not setup a session at {}: {:?}", terminal, err);
return ExitCode::FAILURE; return ExitCode::FAILURE;
} }
let mut attempt_number = 0; let mut attempt_number = 0;
loop { loop {
debug_trace!("Login attempt {}", attempt_number); debug_trace!("Login attempt {}", attempt_number);
// "Attach" the terminal // "Attach" the terminal
unsafe { unsafe {
let mut req = DeviceRequest::SetTerminalGroup(sys::get_pid()); stdin()
sys::device_request(RawFd::STDIN, &mut req).unwrap(); .device_request(&mut DeviceRequest::SetTerminalGroup(process::id()))
.expect("Could not attach the terminal");
} }
if let Err(err) = login_attempt(attempt_number % 3 == 0) { if let Err(err) = login_attempt(attempt_number % 3 == 0) {

View File

@ -1,14 +1,20 @@
#![cfg_attr(target_os = "yggdrasil", feature(yggdrasil_os))]
use std::{ use std::{
fmt, fmt,
fs::{read_dir, FileType}, fs::{read_dir, FileType, Metadata},
io, io,
mem::MaybeUninit, mem::MaybeUninit,
path::Path, path::Path,
}; };
#[cfg(target_os = "yggdrasil")]
use std::os::yggdrasil::fs::MetadataExt;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
use clap::Parser; use clap::Parser;
use humansize::{FormatSize, BINARY}; use humansize::{FormatSize, BINARY};
use yggdrasil_rt::io::FileAttr;
#[derive(Parser)] #[derive(Parser)]
pub struct Args { pub struct Args {
@ -74,7 +80,7 @@ impl<T: DisplaySizeBit + Copy> fmt::Display for DisplaySizeWith<'_, T> {
struct Entry { struct Entry {
name: String, name: String,
ty: Option<FileType>, ty: Option<FileType>,
attrs: Option<FileAttr>, attrs: Option<Metadata>,
} }
impl DisplayBit for Option<FileType> { impl DisplayBit for Option<FileType> {
@ -93,13 +99,29 @@ impl DisplayBit for Option<FileType> {
} }
} }
impl DisplayBit for Option<FileAttr> { #[cfg(target_os = "yggdrasil")]
impl DisplayBit for Option<Metadata> {
fn display_bit(&self, opts: &Args, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn display_bit(&self, opts: &Args, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Some(attrs) = self else { let Some(attrs) = self else {
return write!(f, "--------- {:<8}", "???"); return write!(f, "--------- {:<8}", "???");
}; };
write!(f, "{} {:>8}", attrs.mode, attrs.size.display_size_with(opts)) let mode = attrs.mode_ext();
write!(f, "{} {:>8}", mode, attrs.len().display_size_with(opts))
}
}
#[cfg(unix)]
impl DisplayBit for Option<Metadata> {
fn display_bit(&self, opts: &Args, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use sysutils::unix::FileMode;
let Some(attrs) = self else {
return write!(f, "--------- {:<8}", "???");
};
let mode = FileMode::from(attrs.mode());
write!(f, "{} {:>8}", mode, attrs.len().display_size_with(opts))
} }
} }
@ -119,15 +141,6 @@ impl DisplayBit for Entry {
} }
} }
fn fetch_entry<P: AsRef<Path>>(path: P) -> Option<FileAttr> {
let mut attrs = MaybeUninit::uninit();
let attrs = unsafe {
yggdrasil_rt::sys::get_metadata(None, path.as_ref().to_str()?, &mut attrs, false).ok()?;
attrs.assume_init()
};
Some(attrs)
}
impl Entry { impl Entry {
fn invalid() -> Self { fn invalid() -> Self {
Self { Self {
@ -148,7 +161,7 @@ fn list_directory(path: &Path) -> io::Result<Vec<Entry>> {
let os_filename = entry.file_name(); let os_filename = entry.file_name();
let ty = entry.file_type().ok(); let ty = entry.file_type().ok();
let attrs = fetch_entry(entry.path()); let attrs = entry.path().metadata().ok();
entries.push(Entry { entries.push(Entry {
name: os_filename.to_string_lossy().to_string(), name: os_filename.to_string_lossy().to_string(),

View File

@ -1,7 +1,7 @@
use std::process::ExitCode; #![feature(rustc_private, yggdrasil_os)]
use std::{process::ExitCode, os::yggdrasil::io::{MountOptions, mount_raw}};
use clap::Parser; use clap::Parser;
use yggdrasil_rt::{io::MountOptions, sys::mount};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Args { struct Args {
@ -14,19 +14,23 @@ struct Args {
fn main() -> ExitCode { fn main() -> ExitCode {
let args = Args::parse(); let args = Args::parse();
let source = if args.target.is_some() { Some(args.source.as_str()) } else { None }; let source = if args.target.is_some() {
Some(args.source.as_str())
} else {
None
};
let target = args.target.as_deref().unwrap_or(args.source.as_str()); let target = args.target.as_deref().unwrap_or(args.source.as_str());
let filesystem = args.ty.as_deref(); let filesystem = args.ty.as_deref();
// Permissions are not yet implemented, lol // Permissions are not yet implemented, lol
let result = unsafe { let result = unsafe {
let options = MountOptions { let options = MountOptions {
source, source,
filesystem, filesystem,
target target,
}; };
mount(&options) mount_raw(&options)
}; };
match result { match result {