Start help system.
This commit is contained in:
parent
43a4a4f4d2
commit
5895e2508a
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -781,9 +781,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.70"
|
version = "0.3.72"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
|
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
@ -1443,9 +1443,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -1454,9 +1454,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
@ -1481,9 +1481,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@ -1491,9 +1491,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1504,15 +1504,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.69"
|
version = "0.3.72"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
@ -13,7 +13,7 @@ piccolo = { git = "https://github.com/kyren/piccolo.git", rev = "fcbaabc92429217
|
|||||||
unicode-segmentation = "1.11.0"
|
unicode-segmentation = "1.11.0"
|
||||||
unicode-width = "0.1.13"
|
unicode-width = "0.1.13"
|
||||||
wasm-bindgen = "0.2.92"
|
wasm-bindgen = "0.2.92"
|
||||||
web-sys = { version = "0.3.69", features = ["ResizeObserver", "DomRect", "CssStyleDeclaration", "HtmlAnchorElement"] }
|
web-sys = { version = "0.3.72", features = ["ResizeObserver", "DomRect", "CssStyleDeclaration", "HtmlAnchorElement", "XmlHttpRequest"] }
|
||||||
yew = { version = "0.21.0", features = ["csr"] }
|
yew = { version = "0.21.0", features = ["csr"] }
|
||||||
minicrossterm = { git = "https://git.blastmud.org/blasthavers/minicrossterm.git", rev = "0c8c6d4f0cf445adf7bb957811081a1b710bd933" }
|
minicrossterm = { git = "https://git.blastmud.org/blasthavers/minicrossterm.git", rev = "0c8c6d4f0cf445adf7bb957811081a1b710bd933" }
|
||||||
thiserror = "1.0.63"
|
thiserror = "1.0.63"
|
||||||
|
26
help.json
Normal file
26
help.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"_index": "Try #help command_name (leave off the # from command names) for command help.\r\n\r\n\"#help getting started\" has tips to get started.",
|
||||||
|
"act": "Use #act to set a trigger that will automatically run commands based on a match to the MUD's output. Example: #act {^The (.*) attacks you.} {\"Hey $1, you're going to wish you hadn't done that!\"}.\r\nUse #act by itself to list triggers. See #unact for info on how to remove triggers.",
|
||||||
|
"alias": "Use #alias to set a command alias.\r\nFor example, #alias {^hi} {#echo Hello} will make typing 'hi' run the echo command.\r\nUse #alias by itself to list aliases. See also: #unalias",
|
||||||
|
"connect_mud": "Use #connect_mud to connect to a MUD. Provide a name for the connection and the WebSocket server URL, e.g. #connect_mud ex wss://example.com/ws.",
|
||||||
|
"copy_paste": "Use Ctrl Insert to copy and Shift Insert to paste in most browsers.",
|
||||||
|
"create_script": "Use the '+' icon in the script browser to create a new script. You will need to name it first.",
|
||||||
|
"delay": "Use #delay to schedule a command to run after a specified time (in seconds).\r\nFor example, #delay 5 {#echo Ding!} will run the echo command after 5 seconds.\r\nOptionally give it a name with a third argument.\r\nUse #delay by itself to list delays.\r\nSee also: #undelay",
|
||||||
|
"deletelogs": "Use #deletelogs to permanently delete logs.\r\nExample: #deletelogs mylog 2024-10-01 2024-10-10\r\nThe first argument is the log name. Optionally, follow with a second and third argument to give the date range - or just one date to only specify the end of the date range.\r\nSee also: #downloadlogs",
|
||||||
|
"downloadlogs": "Use #downloadlogs to download logs within a date range. Example: #downloadlogs mylog 2024-10-01 2024-10-10.",
|
||||||
|
"editor": "Use #editor to open the script editor where you can manage Lua scripts.",
|
||||||
|
"getting started": "Use #help connect_mud to learn how to connect if you aren't already.\r\nSend basic commands to the current MUD just by typing them in. Use a number like #5 n to repeat a command. Use semicolons to send commands in sequence, e.g. n;#4 e\r\nCopy and paste using Ctrl+Insert and Shift+Insert",
|
||||||
|
"hsplit": "Use #hsplit to split the screen horizontally. For example, #hsplit {} 2 will create a horizontal split with frame 2.",
|
||||||
|
"include": "To run a script, use #include scriptname. Example: #include myscript.lua.",
|
||||||
|
"listlogs": "Use #listlogs to list stored logs and the number of entries for each logname.",
|
||||||
|
"log": "Use #log to start logging a MUD's output. Example: #log mymud mylog will start logging for the 'mymud' connection.",
|
||||||
|
"lua_scripting": "Scripts use Lua code. Use commands like 'commands.command(\"command to send\")' to execute MUD commands. For example, to set an alias, use 'commands.alias(\"^hi\", \"#echo Hello\")'.",
|
||||||
|
"panel_merge": "Use #panel_merge followed by the frame path to merge panels. For example, #panel_merge {} will merge the current panel with the top-level split.",
|
||||||
|
"send_multiple_commands": "To send several commands in quick succession, separate them with a semicolon. For example, use 'n;e' to go north and then east.",
|
||||||
|
"tick": "Use #tick to set a recurring command to run at a specified time interval (in seconds).\r\nFor example, #tick 60 {#echo Cockadoodledoo!} will repeat every 60 seconds.\r\nOptionally give it a name with a third argument.\r\nUse #tick by itself to list active ticks.\r\nSee also: #untick",
|
||||||
|
"unact": "Use #unact followed by the trigger pattern to delete a trigger. Example: #unact {^The (.*) attacks you.}.",
|
||||||
|
"unalias": "Use #unalias followed by the alias pattern to delete it. For example, #unalias {^hi}.",
|
||||||
|
"undelay": "Use #undelay followed by the delay name to cancel it. Example: #undelay ding to cancel a delay named 'ding'.",
|
||||||
|
"untick": "Use #untick followed by the tick name to cancel it. Example: #untick rooster to cancel a tick named 'rooster'.",
|
||||||
|
"vsplit": "Use #vsplit to split the screen vertically. For example, #vsplit {} 2 will create a vertical split with frame 2."
|
||||||
|
}
|
@ -27,6 +27,7 @@
|
|||||||
<script data-trunk src="node_modules/@xterm/xterm/lib/xterm.js"></script>
|
<script data-trunk src="node_modules/@xterm/xterm/lib/xterm.js"></script>
|
||||||
<script data-trunk src="node_modules/@xterm/addon-fit/lib/addon-fit.js"></script>
|
<script data-trunk src="node_modules/@xterm/addon-fit/lib/addon-fit.js"></script>
|
||||||
<link data-trunk rel="css" href="styles.css"/>
|
<link data-trunk rel="css" href="styles.css"/>
|
||||||
|
<link data-trunk rel="copy-file" href="help.json"/>
|
||||||
<link data-trunk rel="copy-file" href="assets/fonts/JetBrainsMono-Regular.woff2"/>
|
<link data-trunk rel="copy-file" href="assets/fonts/JetBrainsMono-Regular.woff2"/>
|
||||||
<link data-trunk rel="copy-file" href="node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff" data-target-path="fonts"/>
|
<link data-trunk rel="copy-file" href="node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff" data-target-path="fonts"/>
|
||||||
<link data-trunk rel="copy-file" href="node_modules/@codemirror/view/dist/index.js" data-target-path="@codemirror/view"></link>
|
<link data-trunk rel="copy-file" href="node_modules/@codemirror/view/dist/index.js" data-target-path="@codemirror/view"></link>
|
||||||
|
@ -377,8 +377,8 @@ async fn immediate_download_logs_refutable(
|
|||||||
let buf_bytes = buf.as_bytes();
|
let buf_bytes = buf.as_bytes();
|
||||||
let buf_array = Uint8Array::new_with_length(buf_bytes.len() as u32);
|
let buf_array = Uint8Array::new_with_length(buf_bytes.len() as u32);
|
||||||
buf_array.copy_from(buf_bytes);
|
buf_array.copy_from(buf_bytes);
|
||||||
let mut blobprops: BlobPropertyBag = Default::default();
|
let blobprops: BlobPropertyBag = Default::default();
|
||||||
blobprops.type_("text/plain");
|
blobprops.set_type("text/plain");
|
||||||
let blob = Blob::new_with_u8_array_sequence_and_options(
|
let blob = Blob::new_with_u8_array_sequence_and_options(
|
||||||
&[&buf_array].into_iter().collect::<Array>(),
|
&[&buf_array].into_iter().collect::<Array>(),
|
||||||
&blobprops,
|
&blobprops,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use self::{frameroutes::*, frames::*, muds::*, storage::*};
|
use self::{frameroutes::*, frames::*, muds::*, storage::*};
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use help::{cmd_help, load_help};
|
||||||
use muds::telopt::configure_telopt_table;
|
use muds::telopt::configure_telopt_table;
|
||||||
use piccolo::{
|
use piccolo::{
|
||||||
async_callback::{AsyncSequence, Locals},
|
async_callback::{AsyncSequence, Locals},
|
||||||
@ -29,7 +30,9 @@ pub struct LuaState {
|
|||||||
|
|
||||||
mod frameroutes;
|
mod frameroutes;
|
||||||
pub mod frames;
|
pub mod frames;
|
||||||
|
pub mod help;
|
||||||
pub mod muds;
|
pub mod muds;
|
||||||
|
pub mod named_closure;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
|
|
||||||
impl LuaState {
|
impl LuaState {
|
||||||
@ -217,6 +220,7 @@ pub fn install_lua_globals(
|
|||||||
register_command!(echo_frame);
|
register_command!(echo_frame);
|
||||||
register_command!(echo_frame_raw);
|
register_command!(echo_frame_raw);
|
||||||
register_command!(editor);
|
register_command!(editor);
|
||||||
|
register_stateless_command!(cmd_help, "help");
|
||||||
register_command!(hsplit);
|
register_command!(hsplit);
|
||||||
register_stateless_command!(cmd_include, "include");
|
register_stateless_command!(cmd_include, "include");
|
||||||
register_command!(cmd_list_logs, "listlogs");
|
register_command!(cmd_list_logs, "listlogs");
|
||||||
@ -387,6 +391,7 @@ fn lua_global_initialisation(global_memo: &GlobalMemoCell) -> Result<(), String>
|
|||||||
Function::Callback(ensure_frame_instance(ctx, &FrameId(1))),
|
Function::Callback(ensure_frame_instance(ctx, &FrameId(1))),
|
||||||
(),
|
(),
|
||||||
);
|
);
|
||||||
|
let _ = load_help(global_memo, ctx, "help.json");
|
||||||
});
|
});
|
||||||
lua_engine_ref
|
lua_engine_ref
|
||||||
.interp
|
.interp
|
||||||
|
90
src/lua_engine/help.rs
Normal file
90
src/lua_engine/help.rs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use crate::GlobalMemoCell;
|
||||||
|
use anyhow::Result;
|
||||||
|
use piccolo::{Callback, CallbackReturn, Context, FromValue, Function, Table, Value, Variadic};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
|
||||||
|
use web_sys::{console, XmlHttpRequest};
|
||||||
|
|
||||||
|
use super::named_closure::{release_named_global_closure, store_named_global_closure};
|
||||||
|
|
||||||
|
pub fn load_help(global_memo: &GlobalMemoCell, ctx: Context, url: &str) -> Result<()> {
|
||||||
|
let xhr: Rc<XmlHttpRequest> = XmlHttpRequest::new()
|
||||||
|
.map_err(|_e| anyhow::Error::msg("Error creating XmlHttpRequest"))?
|
||||||
|
.into();
|
||||||
|
let global_memo = global_memo.clone();
|
||||||
|
let xhr_cb = xhr.clone();
|
||||||
|
let load_callback: Closure<dyn Fn()> = Closure::new(move || {
|
||||||
|
let _ = global_memo.lua_engine.borrow_mut().interp.try_enter(|ctx| {
|
||||||
|
release_named_global_closure(ctx, "_help_load_callback");
|
||||||
|
if let Ok(Some(txt)) = xhr_cb.response_text() {
|
||||||
|
match serde_json::from_str::<BTreeMap<String, String>>(&txt) {
|
||||||
|
Err(_) => console::log_1(&JsValue::from_str(
|
||||||
|
"Loading help failed because result wasn't a String -> String map",
|
||||||
|
)),
|
||||||
|
Ok(d) => {
|
||||||
|
let help_tbl: Value = ctx.get_global("help")?;
|
||||||
|
let help_tbl = if help_tbl.is_nil() {
|
||||||
|
let tbl = Table::new(&ctx);
|
||||||
|
ctx.set_global("help", tbl);
|
||||||
|
tbl
|
||||||
|
} else {
|
||||||
|
Table::from_value(ctx, help_tbl)?
|
||||||
|
};
|
||||||
|
for (k, v) in d.iter() {
|
||||||
|
help_tbl.set(ctx, k.clone(), v.clone())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
xhr.set_onload(Some(load_callback.as_ref().unchecked_ref()));
|
||||||
|
store_named_global_closure(ctx, "_help_load_callback", load_callback);
|
||||||
|
xhr.open("GET", url)
|
||||||
|
.map_err(|_e| anyhow::Error::msg("Error opening XmlHttpRequest"))?;
|
||||||
|
xhr.send()
|
||||||
|
.map_err(|_e| anyhow::Error::msg("Error sending XmlHttpRequest"))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn cmd_help<'gc>(ctx: Context<'gc>) -> Callback<'gc> {
|
||||||
|
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
|
||||||
|
let help: Value = ctx.get_global("help")?;
|
||||||
|
let echo: Function = ctx.get_global::<Table>("commands")?.get(ctx, "echo")?;
|
||||||
|
let args: Variadic<Vec<String>> = stack.consume(ctx)?;
|
||||||
|
let mut path: String = args.join(" ");
|
||||||
|
if let Some(p) = path.strip_prefix('#') {
|
||||||
|
path = p.to_owned();
|
||||||
|
}
|
||||||
|
path = path.trim().to_lowercase();
|
||||||
|
|
||||||
|
if path.is_empty() {
|
||||||
|
path = "_index".to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
if help.is_nil() {
|
||||||
|
stack.into_back(ctx, "Help has not (yet) loaded successfully");
|
||||||
|
return Ok(CallbackReturn::Call {
|
||||||
|
function: echo,
|
||||||
|
then: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let help: Table = Table::from_value(ctx, help)?;
|
||||||
|
let help_value: Value = help.get(ctx, path)?;
|
||||||
|
let help_value = if help_value.is_nil() {
|
||||||
|
"No help available on that.".to_owned()
|
||||||
|
} else {
|
||||||
|
String::from_value(ctx, help_value)?
|
||||||
|
};
|
||||||
|
stack.into_back(ctx, help_value);
|
||||||
|
|
||||||
|
Ok(CallbackReturn::Call {
|
||||||
|
function: echo,
|
||||||
|
then: None,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
35
src/lua_engine/named_closure.rs
Normal file
35
src/lua_engine/named_closure.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use gc_arena::Collect;
|
||||||
|
use gc_arena::Gc;
|
||||||
|
use gc_arena::Rootable;
|
||||||
|
use piccolo::{Context, UserData, Value};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use wasm_bindgen::prelude::Closure;
|
||||||
|
|
||||||
|
#[derive(Collect)]
|
||||||
|
#[collect(require_static)]
|
||||||
|
struct ClosureCollect<F: ?Sized> {
|
||||||
|
#[allow(unused)]
|
||||||
|
inner: Rc<Closure<F>>,
|
||||||
|
}
|
||||||
|
pub fn store_named_global_closure<'gc, F: 'static + ?Sized>(
|
||||||
|
ctx: Context<'gc>,
|
||||||
|
name: &'static str,
|
||||||
|
closure: Closure<F>,
|
||||||
|
) {
|
||||||
|
ctx.set_global(
|
||||||
|
name,
|
||||||
|
UserData::new::<Rootable![Gc<'_, ClosureCollect<F>>]>(
|
||||||
|
&ctx,
|
||||||
|
Gc::new(
|
||||||
|
&ctx,
|
||||||
|
ClosureCollect {
|
||||||
|
inner: Rc::new(closure),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn release_named_global_closure(ctx: Context, name: &'static str) {
|
||||||
|
ctx.set_global(name, Value::Nil);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user