Fix(app::command_interface): Provide pre-generated file, to check syntax
This commit is contained in:
parent
ebb16a20de
commit
189ae509f8
|
@ -0,0 +1,54 @@
|
||||||
|
// FIXME: This file needs documentation with examples of how the proc macros work.
|
||||||
|
// for now use `cargo expand app::command_interface` for an overview
|
||||||
|
|
||||||
|
use std::{io::{Error, ErrorKind}, sync::Arc};
|
||||||
|
|
||||||
|
use lua_macros::{ci_command, turn_struct_to_ci_command_enum};
|
||||||
|
|
||||||
|
use crate::app::event_types::Event;
|
||||||
|
/// This struct is here to guarantee, 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.
|
||||||
|
///
|
||||||
|
/// What it does:
|
||||||
|
/// - Generates a `generate_ci_functions` function, which wraps the specified rust in functions
|
||||||
|
/// in lua and exports them to the globals in the context provided as argument.
|
||||||
|
/// - Generates a Commands enum, which contains every Camel cased version of the fields.
|
||||||
|
///
|
||||||
|
/// Every command specified here should have a function named $command_name, where $command_name is the snake cased name of the field.
|
||||||
|
///
|
||||||
|
/// This function is exported to the lua context, thus it's signature must be:
|
||||||
|
/// ```rust
|
||||||
|
/// fn $command_name(context: Context, input_string: String) -> Result<$return_type, rlua::Error> {}
|
||||||
|
/// ```
|
||||||
|
/// where $return_type is the type returned by the function (the only supported ones are right now
|
||||||
|
/// `String` and `()`).
|
||||||
|
|
||||||
|
#[turn_struct_to_ci_command_enum]
|
||||||
|
struct Commands {
|
||||||
|
/// Greets the user
|
||||||
|
greet: fn(String) -> String,
|
||||||
|
|
||||||
|
/// Closes the application
|
||||||
|
//#[expose(lua)]
|
||||||
|
exit: fn(),
|
||||||
|
|
||||||
|
/// Shows the command line
|
||||||
|
command_line_show: fn(),
|
||||||
|
|
||||||
|
/// Hides the command line
|
||||||
|
command_line_hide: fn(),
|
||||||
|
|
||||||
|
/// Go to the next plane
|
||||||
|
cycle_planes: fn(),
|
||||||
|
/// Go to the previous plane
|
||||||
|
cycle_planes_rev: fn(),
|
||||||
|
|
||||||
|
/// Sets the current app mode to Normal / navigation mode
|
||||||
|
set_mode_normal: fn(),
|
||||||
|
/// Sets the current app mode to Insert / editing mode
|
||||||
|
set_mode_insert: fn(),
|
||||||
|
|
||||||
|
/// Send a message to the current room
|
||||||
|
/// The send message is interpreted literally.
|
||||||
|
room_message_send: fn(String) -> String,
|
||||||
|
}
|
|
@ -1,57 +1,63 @@
|
||||||
// FIXME: This file needs documentation with examples of how the proc macros work.
|
use cli_log::debug;
|
||||||
// for now use `cargo expand app::command_interface` for an overview
|
|
||||||
|
|
||||||
use std::{
|
#[derive(Debug)]
|
||||||
io::{Error, ErrorKind},
|
pub enum Command {
|
||||||
sync::Arc,
|
Greet(String),
|
||||||
};
|
Exit,
|
||||||
|
CommandLineShow,
|
||||||
use lua_macros::{ci_command, turn_struct_to_ci_command_enum};
|
CommandLineHide,
|
||||||
|
CyclePlanes,
|
||||||
use crate::app::event_types::Event;
|
CyclePlanesRev,
|
||||||
/// This struct is here to guarantee, that all functions actually end up in the lua context.
|
RoomMessageSend(String),
|
||||||
/// I.e. Rust should throw a compile error, when one field is added, but not a matching function.
|
Help(Option<String>),
|
||||||
///
|
}
|
||||||
/// What it does:
|
|
||||||
/// - Generates a `generate_ci_functions` function, which wraps the specified rust in functions
|
pub fn generate_ci_functions(
|
||||||
/// in lua and exports them to the globals in the context provided as argument.
|
lua: mlua::Lua,
|
||||||
/// - Generates a Commands enum, which contains every Camel cased version of the fields.
|
tx: tokio::sync::mpsc::Sender<crate::app::events::event_types::Event>,
|
||||||
///
|
) -> mlua::Lua {
|
||||||
/// Every command specified here should have a function named $command_name, where $command_name is the snake cased name of the field.
|
lua.set_app_data(tx);
|
||||||
///
|
let globals = lua.globals();
|
||||||
/// This function is exported to the lua context, thus it's signature must be:
|
let fun_greet = lua.create_async_function(greet).expect(&{
|
||||||
/// ```rust
|
let res = format!("The function: `{}` should be defined", "greet");
|
||||||
/// fn $command_name(context: Context, input_string: String) -> Result<$return_type, rlua::Error> {}
|
res
|
||||||
/// ```
|
});
|
||||||
/// where $return_type is the type returned by the function (the only supported ones are right now
|
globals.set("greet", fun_greet).expect(&{
|
||||||
/// `String` and `()`).
|
let res = format!(
|
||||||
|
"Setting a static global value ({}, fun_{}) should work",
|
||||||
#[turn_struct_to_ci_command_enum]
|
"greet", "greet",
|
||||||
struct Commands {
|
);
|
||||||
/// Greets the user
|
res
|
||||||
greet: fn(String) -> String,
|
});
|
||||||
|
|
||||||
/// Closes the application
|
drop(globals);
|
||||||
//#[expose(lua)]
|
lua
|
||||||
exit: fn(),
|
}
|
||||||
|
|
||||||
/// Shows the command line
|
async fn greet(lua: &mlua::Lua, input: String) -> Result<String, mlua::Error> {
|
||||||
command_line_show: fn(),
|
let (callback_tx, mut callback_rx) = tokio::sync::mpsc::channel::<String>(256);
|
||||||
|
let tx: core::cell::Ref<tokio::sync::mpsc::Sender<crate::app::events::event_types::Event>> =
|
||||||
/// Hides the command line
|
lua.app_data_ref().expect("This exists, it was set before");
|
||||||
command_line_hide: fn(),
|
|
||||||
|
debug!("Got tx");
|
||||||
/// Go to the next plane
|
(*tx)
|
||||||
cycle_planes: fn(),
|
.try_send(crate::app::events::event_types::Event::CommandEvent(
|
||||||
/// Go to the previous plane
|
Command::Greet(input.clone()),
|
||||||
cycle_planes_rev: fn(),
|
Some(callback_tx),
|
||||||
|
))
|
||||||
/// Sets the current app mode to Normal / navigation mode
|
.expect("This should work, as the reciever is not dropped");
|
||||||
set_mode_normal: fn(),
|
|
||||||
/// Sets the current app mode to Insert / editing mode
|
debug!("Sent CommandEvent");
|
||||||
set_mode_insert: fn(),
|
|
||||||
|
debug!("Returning output...");
|
||||||
/// Send a message to the current room
|
if let Some(output) = callback_rx.recv().await {
|
||||||
/// The send message is interpreted literally.
|
callback_rx.close();
|
||||||
room_message_send: fn(String) -> String,
|
debug!("returned output");
|
||||||
|
return Ok(output);
|
||||||
|
} else {
|
||||||
|
debug!("Not returning output...");
|
||||||
|
return Err(mlua::Error::ExternalError(std::sync::Arc::new(
|
||||||
|
std::io::Error::new(std::io::ErrorKind::Other, "Callback reciever dropped"),
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue