Feat(command_interface): Add basic lua support
This commit is contained in:
parent
ef5afcda02
commit
327450c64b
|
@ -140,7 +140,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -151,7 +151,7 @@ checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -269,6 +269,15 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.13.0"
|
||||
|
@ -642,7 +651,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -841,7 +850,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1278,6 +1287,15 @@ dependencies = [
|
|||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lua_macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
|
@ -1586,7 +1604,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1701,7 +1719,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2097,6 +2115,30 @@ dependencies = [
|
|||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlua"
|
||||
version = "0.19.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d33e5ba15c3d43178f283ed5863d4531e292fc0e56fb773f3bea45f18e3a42a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bstr",
|
||||
"libc",
|
||||
"num-traits",
|
||||
"rlua-lua54-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlua-lua54-sys"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7aafabafe1895cb4a2be81a56d7ff3d46bf4b5d2f9cfdbea2ed404cdabe96474"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.7.4"
|
||||
|
@ -2286,7 +2328,7 @@ checksum = "27738cfea0d944ab72c3ed01f3d5f23ec4322af8a1431e40ce630e4c01ea74fd"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2458,9 +2500,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.24"
|
||||
version = "2.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36ccaf716a23c35ff908f91c971a86a9a71af5998c1d8f10e828d9f55f68ac00"
|
||||
checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
|
@ -2498,7 +2540,7 @@ checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2553,7 +2595,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2632,7 +2674,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2652,7 +2694,9 @@ dependencies = [
|
|||
"cli-log",
|
||||
"crossterm",
|
||||
"indexmap 2.0.0",
|
||||
"lua_macros",
|
||||
"matrix-sdk",
|
||||
"rlua",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
|
@ -2870,7 +2914,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -2904,7 +2948,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -3090,5 +3134,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
|||
dependencies = [
|
||||
"proc-macro2 1.0.64",
|
||||
"quote 1.0.29",
|
||||
"syn 2.0.24",
|
||||
"syn 2.0.25",
|
||||
]
|
||||
|
|
|
@ -7,6 +7,7 @@ license = "MIT"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lua_macros = { path = "./lua_macros" }
|
||||
tui = "0.19"
|
||||
tui-textarea = { version = "0.2", features = ["crossterm"] }
|
||||
crossterm = "0.25"
|
||||
|
@ -17,3 +18,4 @@ tokio-util = "0.7"
|
|||
serde = "1.0"
|
||||
cli-log = "2.0"
|
||||
indexmap = "2.0.0"
|
||||
rlua = "0.19.7"
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
rust-stable
|
||||
rust-analyzer
|
||||
cargo-edit
|
||||
cargo-expand
|
||||
];
|
||||
inherit nativeBuildInputs buildInputs;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# build
|
||||
/target
|
||||
/result
|
||||
|
||||
# lua_macros is a library
|
||||
Cargo.lock
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "lua_macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate_type = ["proc-macro"]
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.64"
|
||||
quote = "1.0.29"
|
||||
syn = "2.0.25"
|
|
@ -0,0 +1,59 @@
|
|||
use proc_macro::TokenStream;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::{format_ident, quote};
|
||||
use syn;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn generate_ci_functions(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
// Construct a representation of Rust code as a syntax tree
|
||||
// that we can manipulate
|
||||
let input = syn::parse(input)
|
||||
.expect("This should always be valid rust code, as it's extracted from direct code");
|
||||
|
||||
// Build the trait implementation
|
||||
generate_generate_ci_functions(&input)
|
||||
}
|
||||
|
||||
fn generate_generate_ci_functions(input: &syn::DeriveInput) -> TokenStream {
|
||||
let input_tokens: TokenStream2 = match &input.data {
|
||||
syn::Data::Struct(input) => match &input.fields {
|
||||
syn::Fields::Named(named_fields) => named_fields
|
||||
.named
|
||||
.iter()
|
||||
.map(|field| -> TokenStream2 {
|
||||
let field_ident = field.ident.as_ref().expect(
|
||||
"These are only the named field, thus they all should have a name.",
|
||||
);
|
||||
let function_name_ident = format_ident!("fun_{}", field_ident);
|
||||
let function_name = format!("{}", field_ident);
|
||||
quote! {
|
||||
let #function_name_ident = context.create_function(#field_ident).expect(
|
||||
&format!(
|
||||
"The function: `{}` should be defined",
|
||||
#function_name
|
||||
)
|
||||
);
|
||||
globals.set(#function_name, #function_name_ident).expect(
|
||||
&format!(
|
||||
"Setting a static global value ({}, fun_{}) should work",
|
||||
#function_name,
|
||||
#function_name
|
||||
)
|
||||
);
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.collect(),
|
||||
_ => unimplemented!("Only implemented for named fileds"),
|
||||
},
|
||||
_ => unimplemented!("Only for implemented for structs"),
|
||||
};
|
||||
|
||||
let gen = quote! {
|
||||
pub fn generate_ci_functions(context: &mut Context) {
|
||||
let globals = context.globals();
|
||||
#input_tokens
|
||||
}
|
||||
};
|
||||
gen.into()
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
use lua_macros::generate_ci_functions;
|
||||
use rlua::Context;
|
||||
|
||||
// This struct is here to gurantee, that all functions actually end up in the lua context.
|
||||
// I. e. rust should throw a compile error, when one field is added, but not a matching function.
|
||||
#[generate_ci_functions()]
|
||||
struct Commands<'lua> {
|
||||
greet: Function<'lua>,
|
||||
}
|
||||
|
||||
fn greet(context: Context, name: String) -> Result<String, rlua::Error> {
|
||||
Ok(format!("Name is {}", name))
|
||||
}
|
|
@ -136,7 +136,42 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
|
|||
};
|
||||
}
|
||||
ui::MainInputPosition::CLI => {
|
||||
todo!();
|
||||
if let Some(_) = app.ui.cli {
|
||||
match input {
|
||||
CrosstermEvent::Key(KeyEvent {
|
||||
code: KeyCode::Enter,
|
||||
..
|
||||
}) => {
|
||||
let cli_event = app.ui
|
||||
.cli
|
||||
.as_mut()
|
||||
.expect("This is already checked")
|
||||
.lines()
|
||||
.get(0)
|
||||
.expect(
|
||||
"There can only be one line in the buffer, as we collect it on enter being inputted"
|
||||
)
|
||||
.to_owned();
|
||||
let output = app.handle_ci_event(&cli_event).await?;
|
||||
|
||||
// delete the old text:
|
||||
|
||||
// We can use a mutable borrow now, as we should only need one
|
||||
let cli = app.ui.cli.as_mut().expect("Checked above");
|
||||
cli.move_cursor(tui_textarea::CursorMove::Jump(0, 0));
|
||||
cli.delete_str(0, cli_event.chars().count());
|
||||
assert!(cli.is_empty());
|
||||
cli.insert_str(output);
|
||||
}
|
||||
_ => {
|
||||
app.ui
|
||||
.cli
|
||||
.as_mut()
|
||||
.expect("This is already checked")
|
||||
.input(tui_textarea::Input::from(input.to_owned()));
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
|
|
|
@ -26,10 +26,21 @@ pub struct App<'ui> {
|
|||
channel_rx: mpsc::Receiver<event_types::Event>,
|
||||
input_listener_killer: CancellationToken,
|
||||
matrix_listener_killer: CancellationToken,
|
||||
|
||||
lua: Lua,
|
||||
}
|
||||
|
||||
impl App<'_> {
|
||||
pub fn new() -> Result<Self> {
|
||||
fn set_up_lua() -> Lua {
|
||||
let lua = Lua::new();
|
||||
|
||||
lua.context(|mut lua_context| {
|
||||
generate_ci_functions(&mut lua_context);
|
||||
});
|
||||
lua
|
||||
}
|
||||
|
||||
let path: &std::path::Path = Path::new("userdata/accounts.json");
|
||||
let config = if path.exists() {
|
||||
info!("Reading account config (userdata/accounts.json)");
|
||||
|
@ -49,9 +60,26 @@ impl App<'_> {
|
|||
channel_rx,
|
||||
input_listener_killer: CancellationToken::new(),
|
||||
matrix_listener_killer: CancellationToken::new(),
|
||||
|
||||
lua: set_up_lua(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn handle_ci_event(&self, event: &str) -> Result<String> {
|
||||
info!("Recieved ci event: `{event}`; executing..");
|
||||
|
||||
// TODO: Should the ci support more than strings?
|
||||
let output = self.lua.context(|context| -> Result<String> {
|
||||
let output = context
|
||||
.load(&event)
|
||||
.eval::<String>()
|
||||
.with_context(|| format!("Failed to execute: `{event}`"))?;
|
||||
info!("Function evaluated to: `{output}`");
|
||||
Ok(output)
|
||||
})?;
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Result<()> {
|
||||
// Spawn input event listener
|
||||
tokio::task::spawn(events::poll_input_events(
|
||||
|
|
Reference in New Issue