# Host files File path: `out/dir/api.rs` ```rust // Host code /* Rust API */ #[derive(Debug)] pub enum Commands { Trinitrix(trinitrix::Trinitrix), } pub mod trinitrix { #[derive(Debug)] pub enum Trinitrix { Stdi(stdi::Stdi), Api(api::Api), } /// Language specific functions, which mirror the `trinitrix.api` namespace. /// That is, if you have to choose between a `std` and a `api` function choose the `std` /// one as it will most likely be more high-level and easier to use (as it isn't abstracted /// over multiple languages). Feel free to drop down to the lower level api, if you feel /// like that more, it should be as stable and user-oriented as the `std` functions pub mod stdi { #[derive(Debug)] pub enum Stdi {} } /// General API to change stuff in Trinitrix pub mod api { #[derive(Debug)] pub enum Api { /// Closes the application #[allow(non_camel_case_types)] exit, /// Send a message to the current room /// The send message is interpreted literally. #[allow(non_camel_case_types)] room_message_send { message: trixy::types::newtypes::String }, Ui(ui::Ui), Keymaps(keymaps::Keymaps), Raw(raw::Raw), } /// Function that change the UI, or UI state pub mod ui { #[allow(non_camel_case_types)] #[derive(Debug)] pub enum Mode { /// Default mode (navigation mode) Normal, /// Allows you to insert things Insert, /// actives the command line Command, } impl From for Mode { fn from(value: crate::trinitrix_c::api_c::ui_c::Mode_c) -> Self { match value { crate::trinitrix_c::api_c::ui_c::Mode_c::Normal => Self::Normal, crate::trinitrix_c::api_c::ui_c::Mode_c::Insert => Self::Insert, crate::trinitrix_c::api_c::ui_c::Mode_c::Command => Self::Command, } } } #[derive(Debug)] pub enum Ui { /// Change the active mode #[allow(non_camel_case_types)] set_mode { mode: crate::trinitrix::api::ui::Mode }, /// Go to the next plane #[allow(non_camel_case_types)] cycle_planes, /// Go to the previous plane #[allow(non_camel_case_types)] cycle_planes_rev, } } /// Manipulate keymappings, the mode is specified as a String build up of all mode /// the keymapping should be active in. The mapping works as follows: /// n => normal Mode /// c => command Mode /// i => insert Mode /// /// The key works in a similar matter, specifying the required keypresses to trigger the /// callback. For example "aba" for require the user to press "a" then "b" then "a" again /// to trigger the mapping. Special characters are encoded as follows: /// "ba" => "Ctrl+a" then "b" then "a" /// "" => "A" or "Shift+a" /// "A" => "A" /// " " => "Alt+a" () or "Meta+a"() (most terminals can't really differentiate between these characters) /// "a" => "a" then "Ctrl+b" then "Ctrl+a" (also works for Shift, Alt and Super) /// "" => "Ctrl+Shift+Alt+b" (the ordering doesn't matter) /// "a " => "a" then a literal space (" ") /// "å🙂" => "å" then "🙂" (full Unicode support!) /// "" => escape key /// "" => F3 key /// "" => backspace key (and so forth) /// "" => a literal "-" /// "" or "" => a literal "<" /// "" or "" => a literal ">" /// /// The callback MUST be registered first by calling /// `trinitrix.api.register_function()` the returned value can than be used to /// set the keymap. pub mod keymaps { #[derive(Debug)] pub enum Keymaps { /// Add a new keymapping #[allow(non_camel_case_types)] add { mode: trixy::types::newtypes::String, key: trixy::types::newtypes::String, callback: extern "C" fn(), }, /// Remove a keymapping /// /// Does nothing, if the keymapping doesn't exists yet #[allow(non_camel_case_types)] remove { mode: trixy::types::newtypes::String, key: trixy::types::newtypes::String, }, /// List declared keymappings #[allow(non_camel_case_types)] get { mode: trixy::types::newtypes::String }, } } /// Functions only used internally within Trinitrix pub mod raw { #[derive(Debug)] pub enum Raw { /// Send an error to the default error output #[allow(non_camel_case_types)] raise_error { error_message: trixy::types::newtypes::String }, /// Send output to the default output /// This is mainly used to display the final /// output of evaluated lua commands. #[allow(non_camel_case_types)] display_output { output_message: trixy::types::newtypes::String }, /// Input a character without checking for possible keymaps /// If the current state does not expect input, this character is ignored /// The encoding is the same as in the `trinitrix.api.keymaps` commands #[allow(non_camel_case_types)] send_input_unprocessed { input: trixy::types::newtypes::String }, Private(__private::Private), } /// This namespace is used to store some command specific data (like functions, as /// ensuring memory locations stay allocated in garbage collected language is hard) /// /// Treat it as an implementation detail pub mod __private { #[derive(Debug)] pub enum Private {} } } } } /* C API */ pub mod trinitrix_c { #[allow(unused_imports)] use crate::callback_function; pub mod stdi_c { #[allow(unused_imports)] use crate::callback_function; } pub mod api_c { #[allow(unused_imports)] use crate::callback_function; pub mod ui_c { #[allow(unused_imports)] use crate::callback_function; #[allow(non_camel_case_types)] #[repr(C)] #[derive(Debug)] pub enum Mode_c { /// Default mode (navigation mode) Normal, /// Allows you to insert things Insert, /// actives the command line Command, } impl From for Mode_c { fn from(value: crate::trinitrix::api::ui::Mode) -> Self { match value { crate::trinitrix::api::ui::Mode::Normal => Self::Normal, crate::trinitrix::api::ui::Mode::Insert => Self::Insert, crate::trinitrix::api::ui::Mode::Command => Self::Command, } } } } #[no_mangle] pub extern "C" fn trinitrix_api_ui_set_mode( mode: crate::trinitrix_c::api_c::ui_c::Mode_c, ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Ui(crate::trinitrix::api::ui::Ui::set_mode { mode: match mode.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ), ); return 1; } #[no_mangle] pub extern "C" fn trinitrix_api_ui_cycle_planes() -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Ui( crate::trinitrix::api::ui::Ui::cycle_planes, ), ), ), ); return 1; } #[no_mangle] pub extern "C" fn trinitrix_api_ui_cycle_planes_rev() -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Ui( crate::trinitrix::api::ui::Ui::cycle_planes_rev, ), ), ), ); return 1; } pub mod keymaps_c { #[allow(unused_imports)] use crate::callback_function; } #[no_mangle] pub extern "C" fn trinitrix_api_keymaps_add( mode: trixy::types::String, key: trixy::types::String, callback: extern "C" fn(), ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Keymaps(crate::trinitrix::api::keymaps::Keymaps::add { mode: match mode.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, key: match key.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, callback: match callback.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ), ); return 1; } #[no_mangle] pub extern "C" fn trinitrix_api_keymaps_remove( mode: trixy::types::String, key: trixy::types::String, ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Keymaps(crate::trinitrix::api::keymaps::Keymaps::remove { mode: match mode.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, key: match key.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ), ); return 1; } #[no_mangle] pub extern "C" fn trinitrix_api_keymaps_get( mode: trixy::types::String, ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Keymaps(crate::trinitrix::api::keymaps::Keymaps::get { mode: match mode.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ), ); return 1; } pub mod raw_c { #[allow(unused_imports)] use crate::callback_function; pub mod __private_c { #[allow(unused_imports)] use crate::callback_function; } } #[no_mangle] pub extern "C" fn trinitrix_api_raw_raise_error( error_message: trixy::types::String, ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Raw(crate::trinitrix::api::raw::Raw::raise_error { error_message: match error_message.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ), ); return 1; } #[no_mangle] pub extern "C" fn trinitrix_api_raw_display_output( output_message: trixy::types::String, ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Raw(crate::trinitrix::api::raw::Raw::display_output { output_message: match output_message.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ), ); return 1; } #[no_mangle] pub extern "C" fn trinitrix_api_raw_send_input_unprocessed( input: trixy::types::String, ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api( crate::trinitrix::api::Api::Raw(crate::trinitrix::api::raw::Raw::send_input_unprocessed { input: match input.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ), ); return 1; } } #[no_mangle] pub extern "C" fn trinitrix_api_exit() -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api(crate::trinitrix::api::Api::exit), ), ); return 1; } #[no_mangle] pub extern "C" fn trinitrix_api_room_message_send( message: trixy::types::String, ) -> core::ffi::c_int { callback_function( crate::Commands::Trinitrix( crate::trinitrix::Trinitrix::Api(crate::trinitrix::api::Api::room_message_send { message: match message.try_into() { Ok(ok) => ok, Err(err) => { trixy::types::traits::errno::set(err.into()); return 0; } }, }), ), ); return 1; } } // vim: filetype=rust ``` # Auxiliary files File path: `dist/interface.h` ```c #if !defined TRIXY_MAIN_HEADER #define TRIXY_MAIN_HEADER #include "errno.h" #include "string.h" #include "vec.h" /** * Closes the application */ extern int trinitrix_api_exit (); /** * Send a message to the current room * The send message is interpreted literally. */ extern int trinitrix_api_room_message_send (const char *message); enum Mode { /** * Default mode (navigation mode) */ Normal, /** * Allows you to insert things */ Insert, /** * actives the command line */ Command, }; /** * Change the active mode */ extern int trinitrix_api_ui_set_mode (enum Mode mode); /** * Go to the next plane */ extern int trinitrix_api_ui_cycle_planes (); /** * Go to the previous plane */ extern int trinitrix_api_ui_cycle_planes_rev (); /** * Add a new keymapping */ extern int trinitrix_api_keymaps_add (const char *mode, const char *key, void (*callback) ()); /** * Remove a keymapping * * Does nothing, if the keymapping doesn't exists yet */ extern int trinitrix_api_keymaps_remove (const char *mode, const char *key); /** * List declared keymappings */ extern int trinitrix_api_keymaps_get (const char *mode); /** * Send an error to the default error output */ extern int trinitrix_api_raw_raise_error (const char *error_message); /** * Send output to the default output * This is mainly used to display the final * output of evaluated lua commands. */ extern int trinitrix_api_raw_display_output (const char *output_message); /** * Input a character without checking for possible keymaps * If the current state does not expect input, this character is ignored * The encoding is the same as in the `trinitrix.api.keymaps` commands */ extern int trinitrix_api_raw_send_input_unprocessed (const char *input); /** * Language specific functions, which mirror the `trinitrix.api` namespace. * That is, if you have to choose between a `std` and a `api` function choose * the `std` one as it will most likely be more high-level and easier to use * (as it isn't abstracted over multiple languages). Feel free to drop down to * the lower level api, if you feel like that more, it should be as stable and * user-oriented as the `std` functions */ struct stdi { }; /** * Function that change the UI, or UI state */ struct ui { int (*set_mode) (enum Mode); int (*cycle_planes) (void); int (*cycle_planes_rev) (void); }; /** * Manipulate keymappings, the mode is specified as a String build up of all * mode the keymapping should be active in. The mapping works as follows: n => * normal Mode c => command Mode i => insert Mode * * The key works in a similar matter, specifying the required keypresses to * trigger the callback. For example "aba" for require the user to press "a" * then "b" then "a" again to trigger the mapping. Special characters are * encoded as follows: * "ba" => "Ctrl+a" then "b" then "a" * "" => "A" or "Shift+a" * "A" => "A" * " " => "Alt+a" () or "Meta+a"() (most terminals can't * really differentiate between these characters) "a" => "a" then * "Ctrl+b" then "Ctrl+a" (also works for Shift, Alt and Super) * "" => "Ctrl+Shift+Alt+b" (the ordering doesn't matter) * "a " => "a" then a literal space (" ") * "å🙂" => "å" then "🙂" (full Unicode support!) * "" => escape key * "" => F3 key * "" => backspace key (and so forth) * "" => a literal "-" * "" or "" => a literal "<" * "" or "" => a literal ">" * * The callback MUST be registered first by calling * `trinitrix.api.register_function()` the returned value can than be used to * set the keymap. */ struct keymaps { int (*add) (const char *, const char *, void (*callback) ()); int (*remove) (const char *, const char *); int (*get) (const char *); }; /** * This namespace is used to store some command specific data (like functions, * as ensuring memory locations stay allocated in garbage collected language is * hard) * * Treat it as an implementation detail */ struct __private { }; /** * Functions only used internally within Trinitrix */ struct raw { int (*raise_error) (const char *); int (*display_output) (const char *); int (*send_input_unprocessed) (const char *); struct __private __private; }; /** * General API to change stuff in Trinitrix */ struct api { int (*exit) (void); int (*room_message_send) (const char *); struct ui ui; struct keymaps keymaps; struct raw raw; }; struct trinitrix { struct stdi stdi; struct api api; }; const struct stdi stdi = {}; const struct ui ui = { .set_mode = trinitrix_api_ui_set_mode, .cycle_planes = trinitrix_api_ui_cycle_planes, .cycle_planes_rev = trinitrix_api_ui_cycle_planes_rev, }; const struct keymaps keymaps = { .add = trinitrix_api_keymaps_add, .remove = trinitrix_api_keymaps_remove, .get = trinitrix_api_keymaps_get, }; const struct __private __private = {}; const struct raw raw = { .raise_error = trinitrix_api_raw_raise_error, .display_output = trinitrix_api_raw_display_output, .send_input_unprocessed = trinitrix_api_raw_send_input_unprocessed, .__private = __private, }; const struct api api = { .exit = trinitrix_api_exit, .room_message_send = trinitrix_api_room_message_send, .ui = ui, .keymaps = keymaps, .raw = raw, }; const struct trinitrix trinitrix = { .stdi = stdi, .api = api, }; #endif // if !defined TRIXY_MAIN_HEADER // vim: filetype=c ```