forked from trinitrix/core
fix(src): Adapt the code to compile with trixy
The term "to compile" was specifically chosen, as this code does nothing more. I would honestly be surprised if it worked in this state.
This commit is contained in:
parent
6ef6bea61c
commit
a39a0875a3
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//// Prints to the output, with a newline.
|
||||
// HACK(@soispha): The stdlib Lua `print()` function has stdout as output hardcoded,
|
||||
// redirecting stdout seems too much like a hack thus we are just redefining the print function
|
||||
// to output to a controlled output. <2023-09-09>
|
||||
// This is implemented only for lua
|
||||
/* fn print(CommandTransferValue); */
|
||||
|
||||
mod trinitrix {
|
||||
/// 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
|
||||
mod stdi {}
|
||||
|
||||
/// General API to change stuff in Trinitrix
|
||||
mod api {
|
||||
/// Closes the application
|
||||
fn exit();
|
||||
|
||||
/// Send a message to the current room
|
||||
/// The send message is interpreted literally.
|
||||
fn room_message_send(message: String);
|
||||
|
||||
//// Open the help pages at the first occurrence of
|
||||
//// the input string if it is Some, otherwise open
|
||||
//// the help pages at the start
|
||||
// TODO(@soispha): To be implemented <2024-03-09>
|
||||
// fn help(Option<String>);
|
||||
|
||||
//// Register a function to be used with the Trinitrix api
|
||||
// (This function is not actually implemented here)
|
||||
/* declare register_function: false, */
|
||||
|
||||
/// Function that change the UI, or UI state
|
||||
mod ui {
|
||||
enum Mode {
|
||||
/// Default mode (navigation mode)
|
||||
Normal,
|
||||
/// Allows you to insert things
|
||||
Insert,
|
||||
/// actives the command line
|
||||
Command,
|
||||
}
|
||||
|
||||
/// Change the active mode
|
||||
fn set_mode(mode: Mode);
|
||||
|
||||
/// Go to the next plane
|
||||
fn cycle_planes();
|
||||
/// Go to the previous plane
|
||||
fn 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:
|
||||
/// "<C-a>ba" => "Ctrl+a" then "b" then "a"
|
||||
/// "<S-a>" => "A" or "Shift+a"
|
||||
/// "A" => "A"
|
||||
/// "<M-a> " => "Alt+a" (<A-a>) or "Meta+a"(<M-a>) (most terminals can't really differentiate between these characters)
|
||||
/// "a<C-b><C-a>" => "a" then "Ctrl+b" then "Ctrl+a" (also works for Shift, Alt and Super)
|
||||
/// "<CSM-b>" => "Ctrl+Shift+Alt+b" (the ordering doesn't matter)
|
||||
/// "a " => "a" then a literal space (" ")
|
||||
/// "å🙂" => "å" then "🙂" (full Unicode support!)
|
||||
/// "<ESC>" => escape key
|
||||
/// "<F3>" => F3 key
|
||||
/// "<BACKSPACE>" => backspace key (and so forth)
|
||||
/// "<DASH>" => a literal "-"
|
||||
/// "<ANGULAR_BRACKET_OPEN>" or "<ABO>" => a literal "<"
|
||||
/// "<ANGULAR_BRACKET_CLOSE>" or "<ABC>" => 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.
|
||||
mod keymaps {
|
||||
/// Add a new keymapping
|
||||
fn add(mode: String, key: String, callback: fn());
|
||||
|
||||
/// Remove a keymapping
|
||||
///
|
||||
/// Does nothing, if the keymapping doesn't exists yet
|
||||
fn remove(mode: String, key: String);
|
||||
|
||||
/// List declared keymappings
|
||||
fn get(mode: String);
|
||||
}
|
||||
|
||||
/// Functions only used internally within Trinitrix
|
||||
mod raw {
|
||||
/// Send an error to the default error output
|
||||
fn raise_error(error_message: String);
|
||||
|
||||
/// Send output to the default output
|
||||
/// This is mainly used to display the final
|
||||
/// output of evaluated lua commands.
|
||||
fn display_output(output_message: 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
|
||||
fn send_input_unprocessed(input: String);
|
||||
|
||||
/// 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
|
||||
mod __private {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trixy is sort of a subset of rust
|
||||
// vim: syntax=rust
|
|
@ -1,150 +1,14 @@
|
|||
// Use `cargo expand app::command_interface::command_list` for an overview of the file contents
|
||||
// Run the `api` bin to see the generated api
|
||||
|
||||
use language_macros::parse_command_enum;
|
||||
use crate::app::{events::Event, COMMAND_TRANSMITTER};
|
||||
|
||||
// TODO(@soispha): Should these paths be moved to the proc macro?
|
||||
// As they are not static, it could be easier for other people,
|
||||
// if they stay here.
|
||||
use crate::app::command_interface::command_transfer_value::{
|
||||
support_types::Function, CommandTransferValue,
|
||||
};
|
||||
use crate::app::Event;
|
||||
use mlua::IntoLua;
|
||||
include!(concat!(env!("OUT_DIR"), "/api.rs"));
|
||||
|
||||
parse_command_enum! {
|
||||
commands {
|
||||
/// Prints to the output, with a newline.
|
||||
// HACK(@soispha): The stdlib Lua `print()` function has stdout as output hardcoded,
|
||||
// redirecting stdout seems too much like a hack thus we are just redefining the print function
|
||||
// to output to a controlled output. <2023-09-09>
|
||||
declare print: fn(CommandTransferValue),
|
||||
pub fn handle_cmd(cmd: Commands) {
|
||||
let tx = COMMAND_TRANSMITTER
|
||||
.get()
|
||||
.expect("The cell should always be populated, at this point");
|
||||
|
||||
namespace trinitrix {
|
||||
/// 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
|
||||
namespace std {
|
||||
/// This command is a no-op, it's just here to ensure that the 'std'
|
||||
/// namespace get actually created
|
||||
// FIXME(@soispha): Add an attribute to namespaces to avoid having to use
|
||||
// empty functions <2023-10-14>
|
||||
declare private_initializer_std: fn(),
|
||||
},
|
||||
|
||||
/// Debug only functions, these are effectively useless
|
||||
namespace debug {
|
||||
/// Greets the user
|
||||
declare greet: fn(String) -> String,
|
||||
|
||||
/// Returns a table of greeted users
|
||||
declare greet_multiple: fn() -> Table,
|
||||
},
|
||||
|
||||
/// General API to change stuff in Name
|
||||
namespace api {
|
||||
/// Closes the application
|
||||
declare exit: fn(),
|
||||
/// Send a message to the current room
|
||||
/// The send message is interpreted literally.
|
||||
declare room_message_send: fn(String),
|
||||
/// Open the help pages at the first occurrence of
|
||||
/// the input string if it is Some, otherwise open
|
||||
/// the help pages at the start
|
||||
declare help: fn(Option<String>),
|
||||
|
||||
// Register a function to be used with the Trinitrix api
|
||||
// (This function is not actually implemented here)
|
||||
/* declare register_function: false, */
|
||||
|
||||
/// Function that change the UI, or UI state
|
||||
namespace ui {
|
||||
/// Shows the command line
|
||||
declare command_line_show: fn(),
|
||||
|
||||
/// Hides the command line
|
||||
declare command_line_hide: fn(),
|
||||
|
||||
/// Go to the next plane
|
||||
declare cycle_planes: fn(),
|
||||
/// Go to the previous plane
|
||||
declare cycle_planes_rev: fn(),
|
||||
|
||||
/// Sets the current app mode to Normal / navigation mode
|
||||
declare set_mode_normal: fn(),
|
||||
/// Sets the current app mode to Insert / editing mode
|
||||
declare set_mode_insert: fn(),
|
||||
},
|
||||
|
||||
/// 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:
|
||||
/// "<C-a>ba" => "Ctrl+a" then "b" then "a"
|
||||
/// "<S-a>" => "A" or "Shift+a"
|
||||
/// "A" => "A"
|
||||
/// "<M-a> " => "Alt+a" (<A-a>) or "Meta+a"(<M-a>) (most terminals can't really differentiate between these characters)
|
||||
/// "a<C-b><C-a>" => "a" then "Ctrl+b" then "Ctrl+a" (also works for Shift, Alt and Super)
|
||||
/// "<CSM-b>" => "Ctrl+Shift+Alt+b" (the ordering doesn't matter)
|
||||
/// "a " => "a" then a literal space (" ")
|
||||
/// "å🙂" => "å" then "🙂" (full Unicode support!)
|
||||
/// "<ESC>" => escape key
|
||||
/// "<F3>" => F3 key
|
||||
/// "<BACKSPACE>" => backspace key (and so forth)
|
||||
/// "<DASH>" => a literal "-"
|
||||
/// "<ANGULAR_BRACKET_OPEN>" or "<ABO>" => a literal "<"
|
||||
/// "<ANGULAR_BRACKET_CLOSE>" or "<ABC>" => 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.
|
||||
namespace keymaps {
|
||||
/// Add a new keymapping
|
||||
declare add: fn((/* mode: */ String, /* key: */ String, /* callback: */ Function)),
|
||||
|
||||
/// Remove a keymapping
|
||||
///
|
||||
/// Does nothing, if the keymapping doesn't exists
|
||||
declare remove: fn((/* mode: */ String, /* key: */ String)),
|
||||
|
||||
/// List declared keymappings
|
||||
declare get: fn(/* mode: */ String),
|
||||
},
|
||||
|
||||
/// Functions only used internally within Trinitrix
|
||||
namespace raw {
|
||||
/// Send an error to the default error output
|
||||
declare raise_error: fn(String),
|
||||
|
||||
/// Send output to the default output
|
||||
/// This is mainly used to display the final
|
||||
/// output of evaluated lua commands.
|
||||
declare display_output: fn(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
|
||||
declare send_input_unprocessed: fn(String),
|
||||
|
||||
/// 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
|
||||
namespace __private {
|
||||
/// This command is a no-op, it's just here to ensure that the '__private'
|
||||
/// namespace get actually created
|
||||
// FIXME(@soispha): Add an attribute to namespaces to avoid having to use
|
||||
// empty functions <2023-10-14>
|
||||
declare private_initializer_private: fn(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
// FIXME: The None here is definitely wrong <2024-05-03>
|
||||
tx.send(Event::CommandEvent(cmd, None));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pub mod command_list;
|
||||
pub mod command_transfer_value;
|
||||
pub mod lua_command_manager;
|
||||
// pub mod command_transfer_value;
|
||||
// pub mod lua_command_manager;
|
||||
|
||||
pub use command_list::*;
|
||||
|
|
|
@ -1,31 +1,36 @@
|
|||
use std::{collections::HashMap, str::FromStr};
|
||||
use std::{mem, str::FromStr};
|
||||
|
||||
use anyhow::{Error, Result};
|
||||
use crate::{
|
||||
app::{
|
||||
command_interface::{
|
||||
trinitrix::{
|
||||
api::{keymaps::Keymaps, raw::Raw, ui::Ui, Api},
|
||||
Trinitrix,
|
||||
},
|
||||
Commands,
|
||||
},
|
||||
events::EventStatus,
|
||||
status::State,
|
||||
App,
|
||||
},
|
||||
trinitrix::api::ui::Mode,
|
||||
ui::central::InputPosition,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use cli_log::{info, trace, warn};
|
||||
use crossterm::event::Event;
|
||||
use keymaps::{
|
||||
key_repr::{Key, Keys},
|
||||
trie::Node,
|
||||
};
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
command_interface::{
|
||||
command_transfer_value::{CommandTransferValue, Table},
|
||||
Api, Command, Debug, Keymaps, Raw, Trinitrix, Ui,
|
||||
},
|
||||
events::EventStatus,
|
||||
status::State,
|
||||
App,
|
||||
},
|
||||
ui::central::InputPosition,
|
||||
};
|
||||
use trixy::oneshot;
|
||||
|
||||
pub async fn handle(
|
||||
app: &mut App<'_>,
|
||||
command: &Command,
|
||||
output_callback: Option<oneshot::Sender<CommandTransferValue>>,
|
||||
command: &Commands,
|
||||
|
||||
// FIXME(@soispha): The `String` is temporary <2024-05-03>
|
||||
output_callback: Option<oneshot::Sender<String>>,
|
||||
) -> Result<EventStatus> {
|
||||
// A command can both return _status output_ (what you would normally print to stderr)
|
||||
// and _main output_ (the output which is normally printed to stdout).
|
||||
|
@ -51,110 +56,90 @@ pub async fn handle(
|
|||
app.status.add_error_message(format!($str, $($args),+))
|
||||
};
|
||||
}
|
||||
macro_rules! send_main_output {
|
||||
($str:expr) => {
|
||||
if let Some(sender) = output_callback {
|
||||
sender
|
||||
.send(CommandTransferValue::from($str))
|
||||
.map_err(|e| Error::msg(format!("Failed to send command main output: `{}`", e)))?;
|
||||
}
|
||||
};
|
||||
($str:expr, $($args:ident),+) => {
|
||||
if let Some(sender) = output_callback {
|
||||
sender
|
||||
.send(CommandTransferValue::from(format!($str, $($args),+)))
|
||||
.map_err(|e| Error::msg(format!("Failed to send command main output: `{}`", e)))?;
|
||||
}
|
||||
};
|
||||
}
|
||||
// macro_rules! send_main_output {
|
||||
// ($str:expr) => {
|
||||
// if let Some(sender) = output_callback {
|
||||
// sender
|
||||
// .send(CommandTransferValue::from($str))
|
||||
// .map_err(|e| Error::msg(format!("Failed to send command main output: `{}`", e)))?;
|
||||
// }
|
||||
// };
|
||||
// ($str:expr, $($args:ident),+) => {
|
||||
// if let Some(sender) = output_callback {
|
||||
// sender
|
||||
// .send(CommandTransferValue::from(format!($str, $($args),+)))
|
||||
// .map_err(|e| Error::msg(format!("Failed to send command main output: `{}`", e)))?;
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
trace!("Handling command: {:#?}", command);
|
||||
|
||||
Ok(match command {
|
||||
Command::Print(output) => {
|
||||
let output_str: String = output.to_string();
|
||||
send_status_output!(output_str);
|
||||
EventStatus::Ok
|
||||
}
|
||||
|
||||
Command::Trinitrix(trinitrix) => match trinitrix {
|
||||
Trinitrix::Debug(debug) => match debug {
|
||||
Debug::Greet(msg) => {
|
||||
send_main_output!("Greeting, {}!", msg);
|
||||
EventStatus::Ok
|
||||
}
|
||||
Debug::GreetMultiple => {
|
||||
let mut table: Table = HashMap::new();
|
||||
table.insert("UserId".to_owned(), CommandTransferValue::Integer(2));
|
||||
table.insert(
|
||||
"UserName".to_owned(),
|
||||
CommandTransferValue::String("James".to_owned()),
|
||||
);
|
||||
|
||||
let mut second_table: Table = HashMap::new();
|
||||
second_table.insert("interface".to_owned(), CommandTransferValue::Integer(3));
|
||||
second_table.insert("api".to_owned(), CommandTransferValue::Boolean(true));
|
||||
table.insert(
|
||||
"Versions".to_owned(),
|
||||
CommandTransferValue::Table(second_table),
|
||||
);
|
||||
send_main_output!(table);
|
||||
EventStatus::Ok
|
||||
}
|
||||
},
|
||||
Commands::Trinitrix(trinitrix) => match trinitrix {
|
||||
Trinitrix::Stdi(_) => {
|
||||
// No-op I guess
|
||||
EventStatus::Ok
|
||||
}
|
||||
Trinitrix::Api(api) => match api {
|
||||
Api::Exit => {
|
||||
Api::exit => {
|
||||
send_status_output!("Terminating the application..");
|
||||
EventStatus::Terminate
|
||||
}
|
||||
Api::RoomMessageSend(msg) => {
|
||||
Api::room_message_send { message } => {
|
||||
if let Some(room) = app.status.room_mut() {
|
||||
room.send(msg.clone()).await?;
|
||||
send_status_output!("Sent message: `{}`", msg);
|
||||
room.send(message.clone()).await?;
|
||||
send_status_output!("Sent message: `{}`", message);
|
||||
} else {
|
||||
// FIXME(@soispha): This should raise an error within lua, as it would
|
||||
// otherwise be very confusing <2023-09-20>
|
||||
warn!("Can't send message: `{}`, as there is no open room!", &msg);
|
||||
warn!(
|
||||
"Can't send message: `{}`, as there is no open room!",
|
||||
&message
|
||||
);
|
||||
}
|
||||
|
||||
// NOTE(@soispha): This is temporary, until trixy can do it automatically <2024-05-03>
|
||||
mem::forget(message);
|
||||
EventStatus::Ok
|
||||
}
|
||||
Api::Help(_) => todo!(),
|
||||
Api::Ui(ui) => match ui {
|
||||
Ui::CommandLineShow => {
|
||||
app.ui.cli_enable();
|
||||
app.status.set_state(State::Command);
|
||||
send_status_output!("CLI online");
|
||||
EventStatus::Ok
|
||||
}
|
||||
Ui::CommandLineHide => {
|
||||
app.ui.cli_disable();
|
||||
send_status_output!("CLI offline");
|
||||
EventStatus::Ok
|
||||
}
|
||||
Ui::CyclePlanes => {
|
||||
Ui::set_mode { mode } => match mode {
|
||||
Mode::Normal => {
|
||||
app.status.set_state(State::Normal);
|
||||
send_status_output!("Set input mode to Normal");
|
||||
EventStatus::Ok
|
||||
}
|
||||
Mode::Insert => {
|
||||
app.status.set_state(State::Insert);
|
||||
app.ui.set_input_position(InputPosition::MessageCompose);
|
||||
send_status_output!("Set input mode to Insert");
|
||||
EventStatus::Ok
|
||||
}
|
||||
Mode::Command => {
|
||||
app.ui.cli_enable();
|
||||
app.status.set_state(State::Command);
|
||||
send_status_output!("Set input mode to CLI");
|
||||
EventStatus::Ok
|
||||
}
|
||||
},
|
||||
Ui::cycle_planes => {
|
||||
app.ui.cycle_main_input_position();
|
||||
send_status_output!("Switched main input position");
|
||||
EventStatus::Ok
|
||||
}
|
||||
Ui::CyclePlanesRev => {
|
||||
Ui::cycle_planes_rev => {
|
||||
app.ui.cycle_main_input_position_rev();
|
||||
send_status_output!("Switched main input position; reversed");
|
||||
EventStatus::Ok
|
||||
}
|
||||
Ui::SetModeNormal => {
|
||||
app.status.set_state(State::Normal);
|
||||
send_status_output!("Set input mode to Normal");
|
||||
EventStatus::Ok
|
||||
}
|
||||
Ui::SetModeInsert => {
|
||||
app.status.set_state(State::Insert);
|
||||
app.ui.set_input_position(InputPosition::MessageCompose);
|
||||
send_status_output!("Set input mode to Insert");
|
||||
EventStatus::Ok
|
||||
}
|
||||
},
|
||||
Api::Keymaps(keymaps) => match keymaps {
|
||||
Keymaps::Add((mode, key, callback)) => {
|
||||
Keymaps::add {
|
||||
mode,
|
||||
key,
|
||||
callback,
|
||||
} => {
|
||||
mode.chars().for_each(|char| {
|
||||
info!("Setting keymaping ('{}') for mode '{}'", key, char);
|
||||
let parsed_keys = key
|
||||
|
@ -179,7 +164,7 @@ pub async fn handle(
|
|||
}
|
||||
trie.insert(&parsed_keys, callback.to_owned())
|
||||
.map_err(|err| {
|
||||
send_error_output!(err.to_string());
|
||||
send_error_output!(format!("{:#?}", err));
|
||||
})
|
||||
.expect("We already dealt with the error")
|
||||
}
|
||||
|
@ -187,60 +172,140 @@ pub async fn handle(
|
|||
};
|
||||
});
|
||||
|
||||
mem::forget(key);
|
||||
mem::forget(mode);
|
||||
EventStatus::Ok
|
||||
}
|
||||
// TODO(@soispha): Well.., we should probably add these functions: <2023-10-15>
|
||||
Keymaps::Remove((mode, key)) => todo!(),
|
||||
Keymaps::Get(mode) => todo!(),
|
||||
// FIXME(@soispha): It would be nice to have these functions, but well..
|
||||
// someone needs to write them <2024-05-03>
|
||||
Keymaps::remove { mode, key } => todo!(),
|
||||
Keymaps::get { mode } => todo!(),
|
||||
},
|
||||
Api::Raw(raw) => match raw {
|
||||
Raw::RaiseError(err) => {
|
||||
send_error_output!(err);
|
||||
Raw::raise_error { error_message } => {
|
||||
send_error_output!(error_message);
|
||||
mem::forget(error_message);
|
||||
EventStatus::Ok
|
||||
}
|
||||
Raw::DisplayOutput(output) => {
|
||||
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);
|
||||
send_status_output!(output_message);
|
||||
mem::forget(output_message);
|
||||
EventStatus::Ok
|
||||
}
|
||||
Raw::Private(_) => {
|
||||
// no-op, read the comment about it in the `command_list`
|
||||
Raw::send_input_unprocessed { input } => {
|
||||
let output = match app.status.state() {
|
||||
State::Insert => {
|
||||
let key = Key::from_str(&input)?;
|
||||
let cross_input: Event = key.try_into()?;
|
||||
app.ui
|
||||
.message_compose
|
||||
.input(tui_textarea::Input::from(cross_input));
|
||||
EventStatus::Ok
|
||||
}
|
||||
State::Command => {
|
||||
let key = Key::from_str(&input)?;
|
||||
let cross_input: Event = key.try_into()?;
|
||||
app.ui
|
||||
.cli
|
||||
.as_mut()
|
||||
.expect("This should exist, when the state is 'Command'")
|
||||
.input(tui_textarea::Input::from(cross_input));
|
||||
EventStatus::Ok
|
||||
}
|
||||
State::Normal
|
||||
| State::Setup
|
||||
| State::KeyInputPending {
|
||||
old_state: _,
|
||||
pending_keys: _,
|
||||
} => EventStatus::Ok,
|
||||
};
|
||||
mem::forget(input);
|
||||
output
|
||||
}
|
||||
Raw::Private(private) => {
|
||||
// no-op, this was used to store functions (not so sure, if we need it
|
||||
// any longer)
|
||||
EventStatus::Ok
|
||||
}
|
||||
Raw::SendInputUnprocessed(char) => match app.status.state() {
|
||||
State::Insert => {
|
||||
let key = Key::from_str(char)?;
|
||||
let cross_input: Event = key.try_into()?;
|
||||
app.ui
|
||||
.message_compose
|
||||
.input(tui_textarea::Input::from(cross_input));
|
||||
EventStatus::Ok
|
||||
}
|
||||
State::Command => {
|
||||
let key = Key::from_str(char)?;
|
||||
let cross_input: Event = key.try_into()?;
|
||||
app.ui
|
||||
.cli
|
||||
.as_mut()
|
||||
.expect("This should exist, when the state is 'Command'")
|
||||
.input(tui_textarea::Input::from(cross_input));
|
||||
EventStatus::Ok
|
||||
}
|
||||
State::Normal
|
||||
| State::Setup
|
||||
| State::KeyInputPending {
|
||||
old_state: _,
|
||||
pending_keys: _,
|
||||
} => EventStatus::Ok,
|
||||
},
|
||||
},
|
||||
},
|
||||
Trinitrix::Std(_) => {
|
||||
// no-op, read the comment about it in the `command_list`
|
||||
EventStatus::Ok
|
||||
}
|
||||
},
|
||||
// Command::Print(output) => {
|
||||
// let output_str: String = output.to_string();
|
||||
// send_status_output!(output_str);
|
||||
// EventStatus::Ok
|
||||
// }
|
||||
//
|
||||
// Command::Trinitrix(trinitrix) => match trinitrix {
|
||||
// Trinitrix::Debug(debug) => match debug {
|
||||
// Debug::Greet(msg) => {
|
||||
// send_main_output!("Greeting, {}!", msg);
|
||||
// EventStatus::Ok
|
||||
// }
|
||||
// Debug::GreetMultiple => {
|
||||
// let mut table: Table = HashMap::new();
|
||||
// table.insert("UserId".to_owned(), CommandTransferValue::Integer(2));
|
||||
// table.insert(
|
||||
// "UserName".to_owned(),
|
||||
// CommandTransferValue::String("James".to_owned()),
|
||||
// );
|
||||
//
|
||||
// let mut second_table: Table = HashMap::new();
|
||||
// second_table.insert("interface".to_owned(), CommandTransferValue::Integer(3));
|
||||
// second_table.insert("api".to_owned(), CommandTransferValue::Boolean(true));
|
||||
// table.insert(
|
||||
// "Versions".to_owned(),
|
||||
// CommandTransferValue::Table(second_table),
|
||||
// );
|
||||
// send_main_output!(table);
|
||||
// EventStatus::Ok
|
||||
// }
|
||||
// },
|
||||
// Trinitrix::Api(api) => match api {
|
||||
// Api::RoomMessageSend(msg) => {
|
||||
// }
|
||||
// Api::Help(_) => todo!(),
|
||||
// Api::Ui(ui) => match ui {
|
||||
// Ui::CommandLineShow => {
|
||||
// }
|
||||
// Ui::CommandLineHide => {
|
||||
// app.ui.cli_disable();
|
||||
// send_status_output!("CLI offline");
|
||||
// EventStatus::Ok
|
||||
// }
|
||||
// Ui::CyclePlanes => {
|
||||
// }
|
||||
// Ui::CyclePlanesRev => {
|
||||
// }
|
||||
// Ui::SetModeNormal => {
|
||||
// }
|
||||
// Ui::SetModeInsert => {
|
||||
// }
|
||||
// },
|
||||
// Api::Keymaps(keymaps) => match keymaps {
|
||||
// Keymaps::Add((mode, key, callback)) => {
|
||||
// }
|
||||
// // TODO(@soispha): Well.., we should probably add these functions: <2023-10-15>
|
||||
// Keymaps::Remove((mode, key)) => todo!(),
|
||||
// Keymaps::Get(mode) => todo!(),
|
||||
// },
|
||||
// Api::Raw(raw) => match raw {
|
||||
// Raw::RaiseError(err) => {
|
||||
// }
|
||||
// Raw::DisplayOutput(output) => {
|
||||
// }
|
||||
// Raw::Private(_) => {
|
||||
// }
|
||||
// Raw::SendInputUnprocessed(char) =>
|
||||
// },
|
||||
// },
|
||||
// Trinitrix::Std(_) => {
|
||||
// // no-op, read the comment about it in the `command_list`
|
||||
// EventStatus::Ok
|
||||
// }
|
||||
// },
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use anyhow::Result;
|
||||
|
||||
use crate::app::{
|
||||
command_interface::command_transfer_value::support_types::Function, events::EventStatus, App,
|
||||
};
|
||||
|
||||
// TODO(@soispha): We just assume for now that all functions originate in lua. This module will in
|
||||
// future versions house check for the language the function came from <2023-10-15>
|
||||
pub async fn handle(app: &mut App<'_>, function: Function) -> Result<EventStatus> {
|
||||
app.lua.execute_function(function).await;
|
||||
|
||||
Ok(EventStatus::Ok)
|
||||
}
|
||||
// use anyhow::Result;
|
||||
//
|
||||
// use crate::app::{
|
||||
// command_interface::command_transfer_value::support_types::Function, events::EventStatus, App,
|
||||
// };
|
||||
//
|
||||
// // TODO(@soispha): We just assume for now that all functions originate in lua. This module will in
|
||||
// // future versions house check for the language the function came from <2023-10-15>
|
||||
// pub async fn handle(app: &mut App<'_>, function: Function) -> Result<EventStatus> {
|
||||
// app.lua.execute_function(function).await;
|
||||
//
|
||||
// Ok(EventStatus::Ok)
|
||||
// }
|
||||
|
|
|
@ -4,7 +4,13 @@ use crossterm::event::Event as CrosstermEvent;
|
|||
use keymaps::key_repr::{Key, Keys};
|
||||
|
||||
use crate::app::{
|
||||
command_interface::{Api::Raw, Command, Raw::SendInputUnprocessed, Trinitrix::Api},
|
||||
command_interface::{
|
||||
trinitrix::{
|
||||
api::{raw::Raw, Api},
|
||||
Trinitrix,
|
||||
},
|
||||
Commands,
|
||||
},
|
||||
events::{Event, EventStatus},
|
||||
status::State,
|
||||
App,
|
||||
|
@ -24,7 +30,11 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
|
|||
for key in pending_keys {
|
||||
app.tx
|
||||
.send(Event::CommandEvent(
|
||||
Command::Trinitrix(Api(Raw(SendInputUnprocessed(key.to_string_repr())))),
|
||||
Commands::Trinitrix(Trinitrix::Api(Api::Raw(
|
||||
Raw::send_input_unprocessed {
|
||||
input: key.to_string_repr(),
|
||||
},
|
||||
))),
|
||||
None,
|
||||
))
|
||||
.await?;
|
||||
|
@ -34,9 +44,9 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
|
|||
// Just let the input event slip through if no keymap matches
|
||||
app.tx
|
||||
.send(Event::CommandEvent(
|
||||
Command::Trinitrix(Api(Raw(SendInputUnprocessed(
|
||||
converted_key.to_string_repr(),
|
||||
)))),
|
||||
Commands::Trinitrix(Trinitrix::Api(Api::Raw(Raw::send_input_unprocessed {
|
||||
input: converted_key.to_string_repr(),
|
||||
}))),
|
||||
None,
|
||||
))
|
||||
.await?;
|
||||
|
@ -88,7 +98,9 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
|
|||
let function = possible_key_map
|
||||
.value()
|
||||
.expect("This node is terminal and a child, it should have a value");
|
||||
app.tx.send(Event::Function(*function)).await?;
|
||||
|
||||
function();
|
||||
// app.tx.send(Event::Function(*function)).await?;
|
||||
app.status.set_state(old_state.to_owned());
|
||||
} else {
|
||||
// The choice does not have a value attached to it (might be a waypoint)
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use anyhow::Result;
|
||||
use cli_log::trace;
|
||||
|
||||
use crate::app::{events::EventStatus, App};
|
||||
|
||||
// This function is here mainly to reserve this spot for further processing of the lua command.
|
||||
// TODO(@Soispha): Move the lua executor thread code from app to this module
|
||||
pub async fn handle(app: &mut App<'_>, command: String) -> Result<EventStatus> {
|
||||
trace!("Recieved ci command: `{command}`; executing..");
|
||||
|
||||
app.lua.execute_code(command).await;
|
||||
|
||||
Ok(EventStatus::Ok)
|
||||
}
|
||||
// use anyhow::Result;
|
||||
// use cli_log::trace;
|
||||
//
|
||||
// use crate::app::{events::EventStatus, App};
|
||||
//
|
||||
// // This function is here mainly to reserve this spot for further processing of the lua command.
|
||||
// // TODO(@Soispha): Move the lua executor thread code from app to this module
|
||||
// pub async fn handle(app: &mut App<'_>, command: String) -> Result<EventStatus> {
|
||||
// trace!("Recieved ci command: `{command}`; executing..");
|
||||
//
|
||||
// app.lua.execute_code(command).await;
|
||||
//
|
||||
// Ok(EventStatus::Ok)
|
||||
// }
|
||||
|
|
|
@ -8,4 +8,4 @@ pub mod matrix;
|
|||
// ci
|
||||
pub mod command;
|
||||
pub mod lua_command;
|
||||
pub mod function;
|
||||
// pub mod function;
|
||||
|
|
|
@ -3,26 +3,18 @@ pub mod listeners;
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use crate::app::{
|
||||
command_interface::{
|
||||
command_transfer_value::{support_types::Function, CommandTransferValue},
|
||||
Command,
|
||||
},
|
||||
status::State,
|
||||
App,
|
||||
};
|
||||
use crate::app::{command_interface::Commands, status::State, App};
|
||||
use cli_log::trace;
|
||||
use crossterm::event::Event as CrosstermEvent;
|
||||
use handlers::{command, function, input, lua_command, matrix, setup};
|
||||
use tokio::sync::oneshot;
|
||||
use handlers::{command, input, lua_command, matrix, setup};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Event {
|
||||
InputEvent(CrosstermEvent),
|
||||
MatrixEvent(matrix_sdk::deserialized_responses::SyncResponse),
|
||||
CommandEvent(Command, Option<oneshot::Sender<CommandTransferValue>>),
|
||||
// FIXME(@soispha): The `String` is also wrong <2024-05-03>
|
||||
CommandEvent(Commands, Option<trixy::oneshot::Sender<String>>),
|
||||
LuaCommand(String),
|
||||
Function(Function),
|
||||
}
|
||||
|
||||
impl Event {
|
||||
|
@ -37,13 +29,13 @@ impl Event {
|
|||
.await
|
||||
.with_context(|| format!("Failed to handle command event: `{:#?}`", event)),
|
||||
|
||||
Event::LuaCommand(lua_code) => lua_command::handle(app, lua_code.to_owned())
|
||||
.await
|
||||
.with_context(|| format!("Failed to handle lua code: `{}`", lua_code)),
|
||||
Event::Function(function) => function::handle(app, function.to_owned())
|
||||
.await
|
||||
.with_context(|| format!("Failed to handle function: `{}`", function)),
|
||||
|
||||
Event::LuaCommand(lua_code) => Ok(EventStatus::Terminate),
|
||||
// lua_command::handle(app, lua_code.to_owned())
|
||||
// .await
|
||||
// .with_context(|| format!("Failed to handle lua code: `{}`", lua_code)),
|
||||
// Event::Function(function) => function::handle(app, function.to_owned())
|
||||
// .await
|
||||
// .with_context(|| format!("Failed to handle function: `{}`", function)),
|
||||
Event::InputEvent(event) => match app.status.state() {
|
||||
State::Setup => setup::handle(app, &event).await.with_context(|| {
|
||||
format!("Failed to handle input (setup) event: `{:#?}`", event)
|
||||
|
|
|
@ -6,6 +6,7 @@ pub mod status;
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
sync::OnceLock,
|
||||
};
|
||||
|
||||
use anyhow::{Context, Error, Result};
|
||||
|
@ -13,12 +14,12 @@ use cli_log::{info, warn};
|
|||
use directories::ProjectDirs;
|
||||
use keymaps::trie::Node;
|
||||
use matrix_sdk::Client;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::mpsc::{self, Sender};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use self::command_interface::{
|
||||
command_transfer_value::support_types::Function, lua_command_manager::LuaCommandManager,
|
||||
};
|
||||
// use self::command_interface::{
|
||||
// lua_command_manager::LuaCommandManager,
|
||||
// };
|
||||
|
||||
use crate::{
|
||||
accounts::{Account, AccountsManager},
|
||||
|
@ -40,13 +41,14 @@ pub struct App<'runtime> {
|
|||
input_listener_killer: CancellationToken,
|
||||
matrix_listener_killer: CancellationToken,
|
||||
|
||||
lua: LuaCommandManager,
|
||||
|
||||
// lua: LuaCommandManager,
|
||||
project_dirs: ProjectDirs,
|
||||
|
||||
key_mappings: HashMap<State, Node<Function>>,
|
||||
key_mappings: HashMap<State, Node<extern "C" fn()>>,
|
||||
}
|
||||
|
||||
pub static COMMAND_TRANSMITTER: OnceLock<Sender<Event>> = OnceLock::new();
|
||||
|
||||
impl App<'_> {
|
||||
pub fn new() -> Result<Self> {
|
||||
let path: &std::path::Path = Path::new("userdata/accounts.json");
|
||||
|
@ -58,6 +60,11 @@ impl App<'_> {
|
|||
};
|
||||
|
||||
let (tx, rx) = mpsc::channel(256);
|
||||
|
||||
COMMAND_TRANSMITTER
|
||||
.set(tx.clone())
|
||||
.expect("The cell should always be empty at this point");
|
||||
|
||||
Ok(Self {
|
||||
ui: central::UI::new()?,
|
||||
accounts_manager: AccountsManager::new(config)?,
|
||||
|
@ -68,7 +75,7 @@ impl App<'_> {
|
|||
input_listener_killer: CancellationToken::new(),
|
||||
matrix_listener_killer: CancellationToken::new(),
|
||||
|
||||
lua: LuaCommandManager::new(tx),
|
||||
// lua: LuaCommandManager::new(tx),
|
||||
|
||||
// TODO: We probably want to populate the strings below a bit more <2023-09-09>
|
||||
project_dirs: ProjectDirs::from("", "", "trinitrix").context(
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
fn main() {
|
||||
let output = include_str!(concat!(env!("OUT_DIR"), "/api.rs"));
|
||||
println!("{}", output);
|
||||
}
|
|
@ -2,22 +2,22 @@ use std::path::PathBuf;
|
|||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
// TODO: The description could be better
|
||||
// TODO: The description is wrong
|
||||
|
||||
/// A terminal client for the matrix chat protocol
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
#[command(subcommand)]
|
||||
/// The subcommand to execute, default is start
|
||||
pub subcommand: Option<Command>,
|
||||
|
||||
#[clap(value_parser, long, short)]
|
||||
#[arg(long, short)]
|
||||
/// Path to the Lua config file, executed instead of the normal one
|
||||
pub lua_config_file: Option<PathBuf>,
|
||||
}
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Command {
|
||||
#[clap(value_parser)]
|
||||
/// Starts the main TUI client
|
||||
Start {},
|
||||
}
|
||||
|
|
|
@ -22,3 +22,8 @@ async fn main() -> anyhow::Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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