all: remove yggdrasil_rt dependency
This commit is contained in:
parent
6c8ae720d0
commit
6da1dbecc7
119
Cargo.lock
generated
119
Cargo.lock
generated
@ -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",
|
||||||
]
|
]
|
||||||
|
@ -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" }
|
|
||||||
|
@ -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
|
||||||
|
@ -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
76
red/src/keymap/key.rs
Normal 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>"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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()))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {
|
||||||
|
@ -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> {
|
||||||
|
@ -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"
|
||||||
|
@ -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!();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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(),
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user