+27
-1
Cargo.lock
+27
-1
Cargo.lock
···
408
408
]
409
409
410
410
[[package]]
411
+
name = "bstr"
412
+
version = "1.12.1"
413
+
source = "registry+https://github.com/rust-lang/crates.io-index"
414
+
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
415
+
dependencies = [
416
+
"memchr",
417
+
"serde",
418
+
]
419
+
420
+
[[package]]
411
421
name = "btree-range-map"
412
422
version = "0.7.2"
413
423
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1404
1414
"nu-protocol",
1405
1415
"rapidhash",
1406
1416
"reqwest",
1417
+
"rust-embed",
1407
1418
"scc",
1408
1419
"serde",
1409
1420
"serde_ipld_dagcbor",
···
1734
1745
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
1735
1746
1736
1747
[[package]]
1748
+
name = "globset"
1749
+
version = "0.4.18"
1750
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1751
+
checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
1752
+
dependencies = [
1753
+
"aho-corasick",
1754
+
"bstr",
1755
+
"log",
1756
+
"regex-automata",
1757
+
"regex-syntax",
1758
+
]
1759
+
1760
+
[[package]]
1737
1761
name = "gloo-storage"
1738
1762
version = "0.3.0"
1739
1763
source = "registry+https://github.com/rust-lang/crates.io-index"
···
4407
4431
source = "registry+https://github.com/rust-lang/crates.io-index"
4408
4432
checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475"
4409
4433
dependencies = [
4434
+
"globset",
4410
4435
"sha2",
4411
4436
"walkdir",
4412
4437
]
···
5784
5809
[[package]]
5785
5810
name = "vfs"
5786
5811
version = "0.12.1"
5787
-
source = "git+https://github.com/landaire/rust-vfs?branch=fix%2Fwasm#c4341e8e7c16a019c1a1415fc8a413bf883a08d5"
5812
+
source = "git+https://github.com/90-008/rust-vfs?branch=fix%2Fwasm#547b30641d8f329614fb29e44c1c7360ef57ded9"
5788
5813
dependencies = [
5789
5814
"filetime",
5815
+
"rust-embed",
5790
5816
]
5791
5817
5792
5818
[[package]]
+3
-2
Cargo.toml
+3
-2
Cargo.toml
···
11
11
wasm-bindgen-futures = "0.4"
12
12
getrandom = { version = "0.3", features = ["wasm_js"] }
13
13
web-sys = { version = "0.3", features = ["console", "Window"] }
14
-
vfs = { version = "0.12" }
14
+
vfs = { version = "0.12", features = ["embedded-fs"] }
15
15
nu-command = { git = "https://github.com/90-008/nushell", default-features = false }
16
16
nu-engine = { git = "https://github.com/90-008/nushell", default-features = false }
17
17
nu-parser = { git = "https://github.com/90-008/nushell", default-features = false }
···
39
39
rapidhash = { version = "4", features = ["unsafe"] }
40
40
async-lock = "3.4.1"
41
41
compile-time = "0.2.0"
42
+
rust-embed = { version = "8.9.0", features = ["debug-embed", "include-exclude"] }
42
43
43
44
[patch.crates-io]
44
-
vfs = { git = "https://github.com/landaire/rust-vfs", branch = "fix/wasm" }
45
+
vfs = { git = "https://github.com/90-008/rust-vfs", branch = "fix/wasm" }
45
46
46
47
[profile.release]
47
48
opt-level = 3
embedded/.gitkeep
embedded/.gitkeep
This is a binary file and will not be displayed.
+6
src/cmd/ls.rs
+6
src/cmd/ls.rs
···
11
11
Category, ListStream, PipelineData, Record, ShellError, Signature, SyntaxShape, Type, Value,
12
12
engine::{Command, EngineState, Stack},
13
13
};
14
+
use wasm_bindgen::JsValue;
14
15
15
16
#[derive(Clone)]
16
17
pub struct Ls;
···
55
56
let full_paths = call.has_flag(engine_state, stack, "full-paths")?;
56
57
57
58
let pwd = get_pwd();
59
+
// web_sys::console::log_1(&JsValue::from_str(&format!("{pwd:?}")));
60
+
// web_sys::console::log_1(&JsValue::from_str(&format!(
61
+
// "{:?}",
62
+
// pwd.read_dir().map(|a| a.collect::<Vec<_>>())
63
+
// )));
58
64
let mut target_dir = pwd.clone();
59
65
if let Some(path) = path_arg {
60
66
target_dir = Arc::new(
-2
src/cmd/mod.rs
-2
src/cmd/mod.rs
+6
src/cmd/sys.rs
+6
src/cmd/sys.rs
···
180
180
);
181
181
}
182
182
183
+
let date = compile_time::unix!();
184
+
let rustc = compile_time::rustc_version_str!();
185
+
186
+
rec.push("build_time", Value::int(date, head));
187
+
rec.push("rustc_version", Value::string(rustc, head));
188
+
183
189
Ok(Value::record(rec, head).into_pipeline_data())
184
190
}
185
191
}
-40
src/cmd/version.rs
-40
src/cmd/version.rs
···
1
-
use nu_protocol::Type;
2
-
use nu_protocol::engine::Call;
3
-
use nu_protocol::{
4
-
Category, IntoPipelineData, PipelineData, ShellError, Signature, Value,
5
-
engine::{Command, EngineState, Stack},
6
-
};
7
-
8
-
#[derive(Clone)]
9
-
pub struct Version;
10
-
11
-
impl Command for Version {
12
-
fn name(&self) -> &str {
13
-
"version"
14
-
}
15
-
16
-
fn signature(&self) -> Signature {
17
-
Signature::build(self.name())
18
-
.input_output_type(Type::Nothing, Type::String)
19
-
.category(Category::System)
20
-
}
21
-
22
-
fn description(&self) -> &str {
23
-
"print the version of dysnomia."
24
-
}
25
-
26
-
fn run(
27
-
&self,
28
-
_engine_state: &EngineState,
29
-
_stack: &mut Stack,
30
-
call: &Call,
31
-
_input: PipelineData,
32
-
) -> Result<PipelineData, ShellError> {
33
-
let date = compile_time::unix!();
34
-
let rustc = compile_time::rustc_version_str!();
35
-
Ok(
36
-
Value::string(format!("dysnomia.v099.t{date} (rustc {rustc})"), call.head)
37
-
.into_pipeline_data(),
38
-
)
39
-
}
40
-
}
-3
src/completion/suggestions.rs
-3
src/completion/suggestions.rs
···
193
193
pub fn generate_command_argument_suggestions(
194
194
input: &str,
195
195
engine_guard: &EngineState,
196
-
working_set: &StateWorkingSet,
197
196
prefix: String,
198
197
span: Span,
199
198
command_name: String,
···
299
298
// Get positional arguments from signature
300
299
// Check if argument is in required or optional positional
301
300
let required_count = signature.required_positional.len();
302
-
let is_optional = arg_index >= required_count;
303
301
304
302
// Find the argument at the given index
305
303
let arg = if arg_index < signature.required_positional.len() {
···
546
544
} => generate_command_argument_suggestions(
547
545
input,
548
546
engine_guard,
549
-
working_set,
550
547
prefix,
551
548
span,
552
549
command_name,
+15
-3
src/globals.rs
+15
-3
src/globals.rs
···
3
3
ShellError, Signal, Span,
4
4
engine::{EngineState, StateDelta},
5
5
};
6
+
use rust_embed::RustEmbed;
6
7
use std::{
7
8
collections::HashMap,
8
9
sync::{
···
11
12
},
12
13
time::{Duration, SystemTime, UNIX_EPOCH},
13
14
};
14
-
use vfs::{VfsError, VfsPath, error::VfsErrorKind};
15
+
use vfs::{EmbeddedFS, OverlayFS, VfsError, VfsPath, error::VfsErrorKind};
15
16
use wasm_bindgen::prelude::*;
16
17
17
18
use crate::memory_fs::MemoryFS;
18
19
19
20
static ROOT: OnceLock<Arc<VfsPath>> = OnceLock::new();
20
21
22
+
fn init_vfs() -> Arc<VfsPath> {
23
+
let memory_fs = VfsPath::new(MemoryFS::new());
24
+
let embedded_fs = VfsPath::new(EmbeddedFS::<EmbeddedFiles>::new());
25
+
let overlaid_fs = VfsPath::new(OverlayFS::new(&[memory_fs, embedded_fs]));
26
+
Arc::new(overlaid_fs)
27
+
}
28
+
21
29
pub fn get_vfs() -> Arc<VfsPath> {
22
-
ROOT.get_or_init(|| Arc::new(VfsPath::new(MemoryFS::new())))
23
-
.clone()
30
+
ROOT.get_or_init(init_vfs).clone()
24
31
}
32
+
33
+
#[derive(RustEmbed, Debug)]
34
+
#[folder = "embedded/"]
35
+
#[exclude = ".gitkeep"]
36
+
pub struct EmbeddedFiles;
25
37
26
38
static PWD: OnceLock<RwLock<Arc<VfsPath>>> = OnceLock::new();
27
39
+2
-42
src/lib.rs
+2
-42
src/lib.rs
···
32
32
use crate::{
33
33
cmd::{
34
34
Cd, Fetch, Job, JobKill, JobList, Ls, Mkdir, Mv, Open, Pwd, Random, Rm, Save, Source, Sys,
35
-
Version,
36
35
},
37
36
default_context::add_shell_command_context,
38
37
error::format_error,
···
94
93
engine_state = add_shell_command_context(engine_state);
95
94
engine_state = add_extra_command_context(engine_state);
96
95
97
-
let write_file = |name: &str, contents: &str| {
98
-
get_vfs()
99
-
.join(name)
100
-
.and_then(|p| p.create_file())
101
-
.and_then(|mut f| f.write_all(contents.as_bytes()).map_err(VfsError::from))
102
-
.map_err(|e| miette::miette!(e.to_string()))
103
-
};
104
-
105
-
let access_log = format!(
106
-
r#"/dysnomia.v000 /user: 90008/ /ip: [REDACTED]/ /time: [REDACTED]//
107
-
/dysnomia.v002 /user: 90008/ /ip: [REDACTED]/ /time: [REDACTED]//
108
-
/dysnomia.v011 /user: 90008/ /ip: [REDACTED]/ /time: [REDACTED]//
109
-
[...ENTRIES TRUNCATED...]
110
-
/dysnomia.v099 /user: anonymous/ /ip: [REDACTED]/ /time: {time}//"#,
111
-
time = current_time()
112
-
.and_then(|t| t.duration_since(UNIX_EPOCH).ok())
113
-
.map_or_else(
114
-
|| "unknown".to_string(),
115
-
|time| chrono::DateTime::from_timestamp_nanos(time.as_nanos() as i64)
116
-
.format("%Y-%m-%dT%H:%M:%SZ")
117
-
.to_string()
118
-
)
119
-
);
120
-
write_file(".access.log", &access_log)?;
121
-
122
-
let welcome_txt = r#"welcome anonymous !
123
-
124
-
125
-
you are interfacing with dysnomia.v099
126
-
using the nu shell.
127
-
128
-
129
-
a few commands you can try:
130
-
131
-
"hello, user!" | save message.txt
132
-
fetch at://ptr.pet
133
-
ls --help"#;
134
-
write_file("welcome.txt", &welcome_txt)?;
135
-
136
96
let mut working_set = StateWorkingSet::new(&engine_state);
137
-
let decls: [Box<dyn Command>; 16] = [
97
+
let decls: [Box<dyn Command>; 15] = [
138
98
Box::new(Ls),
139
99
Box::new(Open),
140
100
Box::new(Save),
···
150
110
Box::new(JobKill),
151
111
Box::new(Sys),
152
112
Box::new(Random),
153
-
Box::new(Version),
154
113
];
155
114
for decl in decls {
156
115
working_set.add_decl(decl);
···
161
120
config.use_ansi_coloring = true.into();
162
121
config.show_banner = nu_protocol::BannerKind::Full;
163
122
config.hooks.display_output = Some("table".into_value(Span::unknown()));
123
+
config.table.show_empty = false;
164
124
engine_state.config = Arc::new(config);
165
125
166
126
engine_state.set_signals(Signals::new(Arc::new(InterruptBool)));
+10
-10
www/index.html
+10
-10
www/index.html
···
1
1
<!doctype html>
2
2
<html lang="en">
3
-
<head>
4
-
<meta charset="UTF-8" />
5
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
-
<title>dysnomia</title>
8
-
</head>
9
-
<body>
10
-
<div id="app"></div>
11
-
<script type="module" src="/src/main.ts"></script>
12
-
</body>
3
+
<head>
4
+
<meta charset="UTF-8" />
5
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+
<title>faunu</title>
8
+
</head>
9
+
<body>
10
+
<div id="app"></div>
11
+
<script type="module" src="/src/main.ts"></script>
12
+
</body>
13
13
</html>