forked from trinitrix/core
fix(src): Ensure that the new c api can actually be used
This commit is contained in:
parent
a39a0875a3
commit
c233b30a52
|
@ -1,2 +1,5 @@
|
|||
[target.x86_64-unknown-linux-gnu]
|
||||
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
|
||||
# [target.x86_64-unknown-linux-gnu]
|
||||
# rustflags = ["-C", "link-arg=-fuse-ld=mold"]
|
||||
|
||||
[build]
|
||||
rustflags = ["-C", "link-args=-rdynamic -fuse-ld=mold"]
|
||||
|
|
|
@ -211,9 +211,9 @@ checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
|
|||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "backoff"
|
||||
|
@ -1696,9 +1696,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.18"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
@ -2863,9 +2863,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "trixy"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84becfd882a68c35ec1c2bc23aac6a0b0e10021d74b8675250c048621d633c1"
|
||||
checksum = "73eef2c0a310a228e44c0d5aa8b264381407f221975bb909646edb08d3b722ab"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"libc",
|
||||
|
|
|
@ -24,7 +24,7 @@ keymaps = {version = "0.1.1", features = ["crossterm"] }
|
|||
|
||||
# c api
|
||||
libloading = "0.8.3"
|
||||
trixy = {version = "0.1.0"}
|
||||
trixy = {version = "0.1.1"}
|
||||
|
||||
# lua stuff
|
||||
mlua = { version = "0.9.7", features = ["lua54", "async", "send", "serialize"] }
|
||||
|
@ -43,7 +43,7 @@ directories = "5.0.1"
|
|||
pretty_assertions = "1.4.0"
|
||||
|
||||
[build-dependencies]
|
||||
trixy = { version = "0.1.0" }
|
||||
trixy = { version = "0.1.1" }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
|
|
@ -1,14 +1,58 @@
|
|||
// Run the `api` bin to see the generated api
|
||||
|
||||
use std::{panic::catch_unwind, process, thread};
|
||||
|
||||
use cli_log::{debug, info};
|
||||
|
||||
use crate::app::{events::Event, COMMAND_TRANSMITTER};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/api.rs"));
|
||||
|
||||
pub fn handle_cmd(cmd: Commands) {
|
||||
let tx = COMMAND_TRANSMITTER
|
||||
.get()
|
||||
.expect("The cell should always be populated, at this point");
|
||||
// Unwinding into the c code implicitly calling this function would be UB. Besides, rust would
|
||||
// probably just abort the process, giving us a weird shutdown without an error message.
|
||||
// Thus we catch the panic before the ffi boundary. This could also be moved to trixy.
|
||||
let error = catch_unwind(|| {
|
||||
let tx = COMMAND_TRANSMITTER
|
||||
.get()
|
||||
.expect("The cell should always be populated, at this point");
|
||||
|
||||
// FIXME: The None here is definitely wrong <2024-05-03>
|
||||
tx.send(Event::CommandEvent(cmd, None));
|
||||
info!("Received command: {:#?}", cmd);
|
||||
|
||||
// NOTE: The extra future and tokio runtime here is necessary to have a sync api. Which is imho
|
||||
// better than expecting c to work with a async one. <2024-05-04>
|
||||
let future = async move {
|
||||
debug!("Asyncly started to send cmd");
|
||||
|
||||
// FIXME: The None here is definitely wrong <2024-05-03>
|
||||
tx.send(Event::CommandEvent(cmd, None))
|
||||
.await
|
||||
.expect("I hope that this does not fail");
|
||||
|
||||
debug!("Done with the async send");
|
||||
};
|
||||
|
||||
debug!("Starting runtime");
|
||||
let handle = thread::spawn(|| {
|
||||
// run the task a separate thread to avoid tokio having problems with the currently
|
||||
// running runtime.
|
||||
|
||||
// PERFORMANCE(@soispha): Stating a new thread for each command is very bad. <2024-05-04>
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(future);
|
||||
});
|
||||
handle.join().expect("Shall never error");
|
||||
debug!("Handled command");
|
||||
});
|
||||
|
||||
if let Err(err) = error {
|
||||
eprintln!("Catched a panic just before the c ffi: {:#?}", err);
|
||||
|
||||
// This will leave the terminal in a horrendous shape (as no destructors are run), but what
|
||||
// can we do at this point beside that?
|
||||
process::abort();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{mem, str::FromStr};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
|
@ -84,11 +84,12 @@ pub async fn handle(
|
|||
Trinitrix::Api(api) => match api {
|
||||
Api::exit => {
|
||||
send_status_output!("Terminating the application..");
|
||||
warn!("Terminating the application");
|
||||
EventStatus::Terminate
|
||||
}
|
||||
Api::room_message_send { message } => {
|
||||
if let Some(room) = app.status.room_mut() {
|
||||
room.send(message.clone()).await?;
|
||||
room.send(message.to_string()).await?;
|
||||
send_status_output!("Sent message: `{}`", message);
|
||||
} else {
|
||||
// FIXME(@soispha): This should raise an error within lua, as it would
|
||||
|
@ -99,8 +100,6 @@ pub async fn handle(
|
|||
);
|
||||
}
|
||||
|
||||
// NOTE(@soispha): This is temporary, until trixy can do it automatically <2024-05-03>
|
||||
mem::forget(message);
|
||||
EventStatus::Ok
|
||||
}
|
||||
Api::Ui(ui) => match ui {
|
||||
|
@ -140,9 +139,11 @@ pub async fn handle(
|
|||
key,
|
||||
callback,
|
||||
} => {
|
||||
mode.chars().for_each(|char| {
|
||||
info!("Will add a keymapping for '{}' in mode '{}'", key, mode);
|
||||
mode.as_str().chars().for_each(|char| {
|
||||
info!("Setting keymaping ('{}') for mode '{}'", key, char);
|
||||
let parsed_keys = key
|
||||
.as_str()
|
||||
.parse::<Keys>()
|
||||
.map_err(|err| {
|
||||
send_error_output!(err.to_string());
|
||||
|
@ -172,8 +173,6 @@ pub async fn handle(
|
|||
};
|
||||
});
|
||||
|
||||
mem::forget(key);
|
||||
mem::forget(mode);
|
||||
EventStatus::Ok
|
||||
}
|
||||
// FIXME(@soispha): It would be nice to have these functions, but well..
|
||||
|
@ -183,22 +182,20 @@ pub async fn handle(
|
|||
},
|
||||
Api::Raw(raw) => match raw {
|
||||
Raw::raise_error { error_message } => {
|
||||
send_error_output!(error_message);
|
||||
mem::forget(error_message);
|
||||
send_error_output!(error_message.to_string());
|
||||
EventStatus::Ok
|
||||
}
|
||||
Raw::display_output { output_message } => {
|
||||
// TODO(@Soispha): This is only used to show the Lua command output to the user.
|
||||
// Lua commands already receive the output. This should probably be communicated
|
||||
// better, should it?
|
||||
send_status_output!(output_message);
|
||||
mem::forget(output_message);
|
||||
send_status_output!(output_message.to_string());
|
||||
EventStatus::Ok
|
||||
}
|
||||
Raw::send_input_unprocessed { input } => {
|
||||
let output = match app.status.state() {
|
||||
State::Insert => {
|
||||
let key = Key::from_str(&input)?;
|
||||
let key = Key::from_str(input.as_str())?;
|
||||
let cross_input: Event = key.try_into()?;
|
||||
app.ui
|
||||
.message_compose
|
||||
|
@ -206,7 +203,7 @@ pub async fn handle(
|
|||
EventStatus::Ok
|
||||
}
|
||||
State::Command => {
|
||||
let key = Key::from_str(&input)?;
|
||||
let key = Key::from_str(input.as_str())?;
|
||||
let cross_input: Event = key.try_into()?;
|
||||
app.ui
|
||||
.cli
|
||||
|
@ -222,7 +219,6 @@ pub async fn handle(
|
|||
pending_keys: _,
|
||||
} => EventStatus::Ok,
|
||||
};
|
||||
mem::forget(input);
|
||||
output
|
||||
}
|
||||
Raw::Private(private) => {
|
||||
|
|
|
@ -32,7 +32,7 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
|
|||
.send(Event::CommandEvent(
|
||||
Commands::Trinitrix(Trinitrix::Api(Api::Raw(
|
||||
Raw::send_input_unprocessed {
|
||||
input: key.to_string_repr(),
|
||||
input: key.to_string_repr().into(),
|
||||
},
|
||||
))),
|
||||
None,
|
||||
|
@ -45,7 +45,7 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
|
|||
app.tx
|
||||
.send(Event::CommandEvent(
|
||||
Commands::Trinitrix(Trinitrix::Api(Api::Raw(Raw::send_input_unprocessed {
|
||||
input: converted_key.to_string_repr(),
|
||||
input: converted_key.to_string_repr().into(),
|
||||
}))),
|
||||
None,
|
||||
))
|
||||
|
|
|
@ -4,7 +4,7 @@ pub mod listeners;
|
|||
use anyhow::{Context, Result};
|
||||
|
||||
use crate::app::{command_interface::Commands, status::State, App};
|
||||
use cli_log::trace;
|
||||
use cli_log::{trace, warn};
|
||||
use crossterm::event::Event as CrosstermEvent;
|
||||
use handlers::{command, input, lua_command, matrix, setup};
|
||||
|
||||
|
@ -29,7 +29,13 @@ impl Event {
|
|||
.await
|
||||
.with_context(|| format!("Failed to handle command event: `{:#?}`", event)),
|
||||
|
||||
Event::LuaCommand(lua_code) => Ok(EventStatus::Terminate),
|
||||
Event::LuaCommand(lua_code) => {
|
||||
warn!(
|
||||
"Got lua code to execute, but no exectuter is available:\n{}",
|
||||
lua_code
|
||||
);
|
||||
Ok(EventStatus::Ok)
|
||||
}
|
||||
// lua_command::handle(app, lua_code.to_owned())
|
||||
// .await
|
||||
// .with_context(|| format!("Failed to handle lua code: `{}`", lua_code)),
|
||||
|
|
|
@ -5,14 +5,21 @@ pub mod status;
|
|||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::c_int,
|
||||
path::{Path, PathBuf},
|
||||
sync::OnceLock,
|
||||
};
|
||||
|
||||
use anyhow::{Context, Error, Result};
|
||||
use cli_log::{info, warn};
|
||||
use crossterm::{
|
||||
event::DisableMouseCapture,
|
||||
execute,
|
||||
terminal::{disable_raw_mode, LeaveAlternateScreen},
|
||||
};
|
||||
use directories::ProjectDirs;
|
||||
use keymaps::trie::Node;
|
||||
use libloading::{Library, Symbol};
|
||||
use matrix_sdk::Client;
|
||||
use tokio::sync::mpsc::{self, Sender};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
@ -86,7 +93,11 @@ impl App<'_> {
|
|||
})
|
||||
}
|
||||
|
||||
pub async fn run(&mut self, cli_lua_config_file: Option<PathBuf>) -> Result<()> {
|
||||
pub async fn run(
|
||||
&mut self,
|
||||
cli_lua_config_file: Option<PathBuf>,
|
||||
plugin_path: Option<PathBuf>,
|
||||
) -> Result<()> {
|
||||
// Spawn input event listener
|
||||
tokio::task::spawn(events::listeners::input::poll(
|
||||
self.tx.clone(),
|
||||
|
@ -121,6 +132,21 @@ impl App<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(plugin) = plugin_path {
|
||||
info!("Loading plugin_main() from {}", plugin.display());
|
||||
|
||||
unsafe {
|
||||
let lib = Library::new(plugin).context("Failed to load plugin")?;
|
||||
let func: Symbol<unsafe fn() -> c_int> = lib
|
||||
.get(b"plugin_main")
|
||||
.context("Plugin does not have a 'plugin_main' symbol")?;
|
||||
|
||||
info!("Starting plugin");
|
||||
let out = func();
|
||||
info!("Plugin finished with: {}", out);
|
||||
}
|
||||
}
|
||||
|
||||
if self.account().is_err() {
|
||||
info!("No saved sessions found -> jumping into setup");
|
||||
self.setup().await?;
|
||||
|
|
|
@ -12,9 +12,12 @@ pub struct Args {
|
|||
/// The subcommand to execute, default is start
|
||||
pub subcommand: Option<Command>,
|
||||
|
||||
// #[arg(long, short)]
|
||||
// /// Path to the Lua config file, executed instead of the normal one
|
||||
// pub lua_config_file: Option<PathBuf>,
|
||||
#[arg(long, short)]
|
||||
/// Path to the Lua config file, executed instead of the normal one
|
||||
pub lua_config_file: Option<PathBuf>,
|
||||
/// Path to a plugin to load. It must be a shared-object (.so)
|
||||
pub plugin_path: Option<PathBuf>,
|
||||
}
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Command {
|
||||
|
|
|
@ -16,7 +16,9 @@ async fn main() -> anyhow::Result<()> {
|
|||
match command {
|
||||
Command::Start {} => {
|
||||
let mut app = app::App::new()?;
|
||||
app.run(args.lua_config_file).await?;
|
||||
|
||||
// NOTE(@soispha): The `None` is temporary <2024-05-03>
|
||||
app.run(None, args.plugin_path).await?;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,6 +26,4 @@ async fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
|
||||
// FIXME(@soispha): Re-exports for trixy, this should be configurable <2024-05-03>
|
||||
pub use crate::app::command_interface::handle_cmd;
|
||||
pub use crate::app::command_interface::Commands;
|
||||
pub use crate::app::command_interface::*;
|
||||
|
|
Loading…
Reference in New Issue