parent
5ace6fbdfb
commit
f12e1ffc8f
18
Cargo.toml
18
Cargo.toml
|
@ -1,12 +1,10 @@
|
|||
[package]
|
||||
name = "vanten-s"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.22"
|
||||
wasm-logger = "0.2.0"
|
||||
web-sys = "0.3.76"
|
||||
# this is the development version of Yew
|
||||
yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
resolver = "2"
|
||||
|
||||
default-members = [ "backend" ]
|
||||
|
||||
members = [
|
||||
"backend",
|
||||
"frontend"
|
||||
]
|
||||
|
|
10
backend/Cargo.toml
Normal file
10
backend/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "backend"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
actix-files = "0.6.6"
|
||||
actix-web = "4.9.0"
|
||||
env_logger = "0.11.6"
|
||||
tokio = { version = "1.42.0", features = ["full"] }
|
16
backend/src/main.rs
Normal file
16
backend/src/main.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use actix_files::Files;
|
||||
use actix_web::{middleware::Logger, App, HttpServer};
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.wrap(Logger::default())
|
||||
.service(Files::new("/fs", "fs").index_file("index.html"))
|
||||
.service(Files::new("/", "dist").index_file("index.html"))
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
}
|
14
frontend/Cargo.toml
Normal file
14
frontend/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "vanten-s"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.22"
|
||||
wasm-logger = "0.2.0"
|
||||
web-sys = "0.3.76"
|
||||
yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
wasm-bindgen-futures = "0.4.49"
|
||||
futures = "0.3.31"
|
||||
|
|
@ -16,6 +16,7 @@ body {
|
|||
font: inherit;
|
||||
padding: 0;
|
||||
border: none;
|
||||
width: max;
|
||||
}
|
||||
|
||||
.input:focus {
|
78
frontend/src/commands/cat.rs
Normal file
78
frontend/src/commands/cat.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use wasm_bindgen_futures::{spawn_local, JsFuture};
|
||||
use web_sys::{console, wasm_bindgen::UnwrapThrowExt, window, Response};
|
||||
use super::{Environment, Handle, Rader};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Fetcher {
|
||||
next: Option<Arc<Fetcher>>,
|
||||
filename: String,
|
||||
previous_text: String,
|
||||
rader: Rader,
|
||||
handle: Handle
|
||||
}
|
||||
|
||||
pub fn cat(mut env: Environment) {
|
||||
if env.arguments.len() == 1 {
|
||||
env.rader.push("cat: no filename provided\n".to_string());
|
||||
env.handle.set(env.rader);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut previous_fetcher = None;
|
||||
for filename in env.arguments[1..].iter().rev() {
|
||||
let next_fetcher = Fetcher {
|
||||
next: previous_fetcher,
|
||||
filename: filename.to_string(),
|
||||
previous_text: String::new(),
|
||||
rader: env.rader.clone(),
|
||||
handle: env.handle.clone(),
|
||||
};
|
||||
previous_fetcher = Some(Arc::new(next_fetcher));
|
||||
}
|
||||
|
||||
spawn_local(fetch((*previous_fetcher.unwrap_throw()).clone()));
|
||||
|
||||
}
|
||||
|
||||
async fn fetch(mut fetcher: Fetcher) {
|
||||
let text = fetch_single_file(fetcher.filename).await;
|
||||
|
||||
let text = fetcher.previous_text + &text;
|
||||
|
||||
if let Some(fetcher) = fetcher.next {
|
||||
let mut fetcher = (*fetcher).clone();
|
||||
fetcher.previous_text = text;
|
||||
Box::pin(fetch(fetcher.clone())).await
|
||||
} else {
|
||||
fetcher.rader.push(text.clone());
|
||||
fetcher.handle.set(fetcher.rader);
|
||||
}
|
||||
}
|
||||
|
||||
async fn fetch_single_file(filename: String) -> String {
|
||||
let resource = format!("/fs/{filename}");
|
||||
|
||||
let window = window().unwrap_throw();
|
||||
|
||||
console::log_1(&"Got Window".into());
|
||||
|
||||
let future: JsFuture = window.fetch_with_str(&resource).into();
|
||||
let response = future.await.unwrap_throw();
|
||||
let response = Response::from(response);
|
||||
|
||||
if response.status() == 404 {
|
||||
return format!("cat: {filename}: No such file or directory\n");
|
||||
}
|
||||
|
||||
console::log_1(&"Got Response".into());
|
||||
|
||||
let text: JsFuture = response.text().unwrap_throw().into();
|
||||
let text = text.await.unwrap_throw();
|
||||
let text = text.as_string().unwrap_throw();
|
||||
|
||||
console::log_1(&"Got Text".into());
|
||||
|
||||
text
|
||||
}
|
5
frontend/src/commands/clear.rs
Normal file
5
frontend/src/commands/clear.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use super::Environment;
|
||||
|
||||
pub fn clear(env: Environment) {
|
||||
env.handle.set(vec![]);
|
||||
}
|
12
frontend/src/commands/echo.rs
Normal file
12
frontend/src/commands/echo.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use super::Environment;
|
||||
|
||||
pub fn echo(mut env: Environment) {
|
||||
let mut text = "".to_string();
|
||||
for argument in &env.arguments[1..] {
|
||||
text += argument;
|
||||
text += " ";
|
||||
};
|
||||
text += "\n";
|
||||
env.rader.push(text);
|
||||
env.handle.set(env.rader);
|
||||
}
|
45
frontend/src/commands/mod.rs
Normal file
45
frontend/src/commands/mod.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use log::{error, info};
|
||||
use yew::UseStateHandle;
|
||||
|
||||
mod clear;
|
||||
mod cat;
|
||||
mod echo;
|
||||
|
||||
pub type Rader = Vec<String>;
|
||||
pub type Handle = UseStateHandle<Rader>;
|
||||
|
||||
struct Environment<'a> {
|
||||
pub rader: Rader,
|
||||
pub handle: Handle,
|
||||
pub arguments: Vec<&'a str>,
|
||||
}
|
||||
|
||||
pub fn run(command: String, rader: Rader, handle: Handle) {
|
||||
let arguments = command.trim().split_whitespace().collect::<Vec<_>>();
|
||||
|
||||
info!("{:?}", arguments);
|
||||
|
||||
if arguments.len() == 0 {
|
||||
handle.set(rader);
|
||||
return;
|
||||
}
|
||||
|
||||
let environment = Environment {
|
||||
rader,
|
||||
handle,
|
||||
arguments,
|
||||
};
|
||||
|
||||
match environment.arguments[0] {
|
||||
"clear" => clear::clear(environment),
|
||||
"cat" => cat::cat(environment),
|
||||
"echo" => echo::echo(environment),
|
||||
_ => unrecognized_command(environment),
|
||||
}
|
||||
}
|
||||
|
||||
fn unrecognized_command(mut env: Environment) {
|
||||
env.rader.push(format!("vsh: {}: command not found\n", env.arguments[0]));
|
||||
env.handle.set(env.rader);
|
||||
error!("Unrecognized Command");
|
||||
}
|
|
@ -20,9 +20,8 @@ fn App() -> Html {
|
|||
info!("{}", rad);
|
||||
let handle = rader_handle.clone();
|
||||
let mut val = (*handle).clone();
|
||||
val.push(get_prompt() + &rad);
|
||||
val = commands::run(rad, val);
|
||||
rader_handle.set(val);
|
||||
val.push(get_prompt() + &rad + "\n");
|
||||
commands::run(rad, val, handle);
|
||||
};
|
||||
|
||||
html! {
|
||||
|
@ -73,8 +72,7 @@ fn Terminal(props: &TerminalProps) -> Html {
|
|||
.map(|rad| {
|
||||
html! {
|
||||
<>
|
||||
<code><wbr /> { rad } </code>
|
||||
<br />
|
||||
<code> { rad } </code>
|
||||
</>
|
||||
}
|
||||
})
|
1
fs/hihi.txt
Normal file
1
fs/hihi.txt
Normal file
|
@ -0,0 +1 @@
|
|||
:3
|
|
@ -3,7 +3,10 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Yew App</title>
|
||||
<link data-trunk rel="css" href="main.css"/>
|
||||
<link data-trunk rel="css" href="frontend/main.css"/>
|
||||
</head>
|
||||
<body></body>
|
||||
<body>
|
||||
<link data-trunk rel="rust" data-type="main" href="frontend/Cargo.toml"/>
|
||||
<link data-trunk rel="copy-dir" href="fs/"/>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
pub fn clear(_rader: Vec<String>) -> Vec<String> {
|
||||
return vec![];
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
use log::error;
|
||||
|
||||
mod clear;
|
||||
|
||||
pub fn run(command: String, rader: Vec<String>) -> Vec<String> {
|
||||
match command.as_str() {
|
||||
"" => rader,
|
||||
"clear" => clear::clear(rader),
|
||||
unrecognized => unrecognized_command(unrecognized, rader),
|
||||
}
|
||||
}
|
||||
|
||||
fn unrecognized_command(command: &str, mut rader: Vec<String>) -> Vec<String> {
|
||||
rader.push(format!("Unrecognized Command \"{command}\""));
|
||||
error!("Unrecognized Command");
|
||||
rader
|
||||
}
|
Loading…
Reference in a new issue