Compare commits

..

No commits in common. "7aea23f3b650820453970a625b92626f72042a34" and "d93b00484eea27f1ff853877012e6fc31f8d5004" have entirely different histories.

14 changed files with 766 additions and 713 deletions

652
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,15 +11,15 @@ default = ["tui"]
tui = ["dep:tui", "dep:tui-textarea", "dep:crossterm", "dep:tokio-util", "dep:serde", "dep:indexmap"]
[dependencies]
clap = { version = "4.4.2", features = ["derive"] }
clap = { version = "4.3.19", features = ["derive"] }
cli-log = "2.0"
anyhow = "1.0"
matrix-sdk = "0.6"
tokio = { version = "1.32", features = ["macros", "rt-multi-thread"] }
tokio = { version = "1.29", features = ["macros", "rt-multi-thread"] }
# lua stuff
language_macros = { path = "./language_macros" }
mlua = { version = "0.9.1", features = ["lua54", "async", "send", "serialize"] }
mlua = { version = "0.8.9", features = ["lua54", "async", "send", "serialize"] }
once_cell = "1.18.0"
# tui feature specific parts

View File

@ -16,11 +16,11 @@
]
},
"locked": {
"lastModified": 1693762390,
"narHash": "sha256-IzmbGqrzVUzyc1IxgH62nQ9l6Dz7hq6JWIeyZiDZqKw=",
"lastModified": 1688772518,
"narHash": "sha256-ol7gZxwvgLnxNSZwFTDJJ49xVY5teaSvF7lzlo3YQfM=",
"owner": "ipetkov",
"repo": "crane",
"rev": "7b92b595c947b3c82ba04f78e58446faac20c4cb",
"rev": "8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e",
"type": "github"
},
"original": {
@ -50,11 +50,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1692799911,
"narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=",
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
@ -65,11 +65,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1693654884,
"narHash": "sha256-EqKKEl+IOS8TSjkt+xn1qGpsjnx5/ag33YNQ1+c7OuM=",
"lastModified": 1690327932,
"narHash": "sha256-Fv7PYZxN4eo0K6zXhHG/vOc+e2iuqQ5ywDrh0yeRjP0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e7f35e03abd06a2faef6684d0de813370e13bda8",
"rev": "a9b47d85504bdd199e90846622c76aa0bfeabfac",
"type": "github"
},
"original": {
@ -100,11 +100,11 @@
]
},
"locked": {
"lastModified": 1693707092,
"narHash": "sha256-HR1EnynBSPqbt+04/yxxqsG1E3n6uXrOl7SPco/UnYo=",
"lastModified": 1690338181,
"narHash": "sha256-Sz2oQ9aNS3MVncnCMndr0302G26UrFUfPynoH2iLjsg=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "98ccb73e6eefc481da6039ee57ad8818d1ca8d56",
"rev": "b7f0b7b58b3c6f14a1377ec31a3d78b23ab843ec",
"type": "github"
},
"original": {
@ -116,11 +116,11 @@
"rustc_cranelift_backend": {
"flake": false,
"locked": {
"lastModified": 1693573696,
"narHash": "sha256-9V2JGtm7tiAAxaIMXzHLliS7rRyuogMxCmP8u9VRjBE=",
"lastModified": 1690205271,
"narHash": "sha256-mMj1dSlGzM+jCgtVX/KNxdYPXohS22RyU/uWmhR7EA0=",
"owner": "bjorn3",
"repo": "rustc_codegen_cranelift",
"rev": "0559de65672243a97d6cd6e6ee6a8e8c291ef4ce",
"rev": "6641b3a548a425eae518b675e43b986094daf609",
"type": "github"
},
"original": {
@ -133,7 +133,7 @@
"rustc_cranelift_backend_src": {
"flake": false,
"locked": {
"narHash": "sha256-h7VLPtyiXg5KpbQKPo3RKl/+AnTWqimKqAXc1VngYEo=",
"narHash": "sha256-E4n1Dqne8/9XHVKFqApdp2baxXun0DMl+oHfo4+oq3Q=",
"type": "tarball",
"url": "https://github.com/bjorn3/rustc_codegen_cranelift/releases/download/dev/cg_clif-x86_64-unknown-linux-gnu.tar.xz"
},

View File

@ -52,28 +52,6 @@
...
}:
flake-utils.lib.eachDefaultSystem (system: let
inherit (pkgs) lib;
bintools-wrapper = "${nixpkgs}/pkgs/build-support/bintools-wrapper";
mold' = pkgs.symlinkJoin {
name = "mold";
paths = [pkgs.mold];
nativeBuildInputs = [pkgs.makeWrapper];
suffixSalt = lib.replaceStrings ["-" "."] ["_" "_"] pkgs.targetPlatform.config;
postBuild = ''
for bin in ${pkgs.mold}/bin/*; do
rm $out/bin/"$(basename "$bin")"
export prog="$bin"
substituteAll "${bintools-wrapper}/ld-wrapper.sh" $out/bin/"$(basename "$bin")"
chmod +x $out/bin/"$(basename "$bin")"
mkdir -p $out/nix-support
substituteAll "${bintools-wrapper}/add-flags.sh" $out/nix-support/add-flags.sh
substituteAll "${bintools-wrapper}/add-hardening.sh" $out/nix-support/add-hardening.sh
substituteAll "${bintools-wrapper}/../wrapper-common/utils.bash" $out/nix-support/utils.bash
done
'';
};
c_rust = pkgs.rust-bin.fromRustupToolchainFile "${rustc_cranelift_backend}/rust-toolchain";
rcb = pkgs.stdenv.mkDerivation {
pname = "rustc_cranelift_backend";
@ -168,7 +146,7 @@
nativeBuildInputs = with pkgs; [
pkg-config
mold'
mold
rcb
];
buildInputs = with pkgs; [

View File

@ -126,7 +126,67 @@ fn get_function_body(field: &Field, has_input: bool, output_type: &Option<Type>)
let function_return = if let Some(_) = output_type {
quote! {
return Ok(output.into_lua(lua).expect("This conversion should always work"));
let converted_output = lua
.to_value(&output)
.expect("This conversion should (indirectely) be checked at compile time");
if let mlua::Value::Table(table) = converted_output {
let real_output: mlua::Value = match output {
CommandTransferValue::Nil => table
.get("Nil")
.expect("This should exist"),
CommandTransferValue::Boolean(_) => table
.get("Boolean")
.expect("This should exist"),
CommandTransferValue::Integer(_) => table
.get("Integer")
.expect("This should exist"),
CommandTransferValue::Number(_) => table
.get("Number")
.expect("This should exist"),
CommandTransferValue::String(_) => table
.get("String")
.expect("This should exist"),
CommandTransferValue::Table(_) => {
todo!()
// FIXME(@Soispha): This returns a table with the values wrapped the
// same way the values above are wrapped. That is (from the greet_multiple
// function):
// ```json
// {
// "Table": {
// "UserName1": {
// "Integer": 2
// }
// }
// }
// ```
// whilst the output should be:
// ```json
// {
// "UserName1": 2
// }
// ```
// That table would need to be unpacked, but this requires some recursive
// function, which seems not very performance oriented.
//
// My first (quick) attempt:
//let mut output_table = lua.create_table().expect("This should work?");
//let initial_table: mlua::Value = table
// .get("Table")
// .expect("This should exist");
//while let mlua::Value::Table(table) = initial_table {
// for pair in table.pairs() {
// let (key, value) = pair.expect("This should also work?");
// output_table.set(key, value);
// }
//}
},
};
return Ok(real_output);
} else {
unreachable!("Lua serializes these things always in a table");
}
}
} else {
quote! {
@ -136,7 +196,7 @@ fn get_function_body(field: &Field, has_input: bool, output_type: &Option<Type>)
let does_function_expect_output = if output_type.is_some() {
quote! {
// We didn't receive output but expected output. Raise an error to notify the lua code
// about it.
// about it
return Err(mlua::Error::ExternalError(std::sync::Arc::new(
err
)));
@ -150,7 +210,7 @@ fn get_function_body(field: &Field, has_input: bool, output_type: &Option<Type>)
quote! {
let (callback_tx, callback_rx) = tokio::sync::oneshot::channel::<CommandTransferValue>();
let tx: mlua::AppDataRef<tokio::sync::mpsc::Sender<Event>> =
let tx: core::cell::Ref<tokio::sync::mpsc::Sender<Event>> =
lua.app_data_ref().expect("This should exist, it was set before");
(*tx)

View File

@ -1,94 +0,0 @@
use cli_log::{debug, info};
use mlua::{IntoLua, LuaSerdeExt, Table, Value};
use super::CommandTransferValue;
impl<'lua> IntoLua<'lua> for CommandTransferValue {
fn into_lua(self, lua: &'lua mlua::Lua) -> mlua::Result<mlua::Value<'lua>> {
let converted_output = lua.to_value(&self)?;
return unwrap(converted_output, lua);
}
}
fn unwrap<'lua>(
value_to_unwrap: Value<'lua>,
lua: &'lua mlua::Lua,
) -> mlua::Result<mlua::Value<'lua>> {
fn unwrap_first_level<'lua>(table: Table<'lua>) -> mlua::Result<Value<'lua>> {
let (_, value): (Value, Value) = table
.pairs()
.next()
.expect("Exactly one item should extist")?;
Ok(value)
}
// That converted value looks somewhat like this (e.g. a String):
// ```
// {
// ["String"] = "hi",
// }
// ```
// or like this (e.g. a table):
// ```
// {
// ["Table"] = {
// ["UserId"] = {
// ["Integer"] = 2,
// },
// ["UserName"] = {
// ["String"] = "James",
// },
// },
// }
// ```
if let Value::Table(table) = value_to_unwrap {
let value = unwrap_first_level(table)?;
if let Value::Table(wrapped_table) = value {
info!("We've got a wtable! wtable: \n{:#?}", wrapped_table);
// we now have a wrapped table value for example like this:
// ```
// {
// ["UserId"] = {
// ["Integer"] = 2,
// },
// ["UserName"] = {
// ["String"] = "James",
// },
// ["Versions"] = {
// ["Table"] = {
// ["api"] = {
// ["Boolean"] = true,
// },
// ["interface"] = {
// ["Integer"] = 3,
// },
// },
// },
// }
// ```
let output_table: Table = lua
.load("{}")
.eval()
.expect("This is static, it should always work");
// FIXME(@soispha): This still fails for nested tables (i.e. the table above), as it
// unpacks too much. While unpacking the while loop should stop, when a key is not from
// the CommandTransferValue family (i.e. ["Integer", "Boolean", "String", "Table",
// etc.]) <2023-09-09>
for pair in wrapped_table.pairs::<Value, Value>() {
let (key, mut raw_value) = pair?;
while let Value::Table(raw_table) = raw_value {
raw_value = unwrap_first_level(raw_table)?;
}
output_table.set(key, raw_value)?;
}
return Ok(output_table.into_lua(lua)?);
} else {
info!("We've got a normal output! output: {:#?}", value);
// we had a simple wrapped value, which is already unwrapped, thus it can be
// returned directly
return Ok(value);
}
} else {
unreachable!("The returned table should always only contain one element");
}
}

View File

@ -1,60 +0,0 @@
use std::{collections::HashMap, fmt::Display};
use serde::{Deserialize, Serialize};
pub mod type_conversions;
// language support
pub mod lua;
pub type Table = HashMap<String, CommandTransferValue>;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum CommandTransferValue {
/// `nil` or `null` or `undefined`; anything which goes in that group of types.
Nil,
/// `true` or `false`.
Boolean(bool),
// A “light userdata” object, equivalent to a raw pointer.
// /* TODO */ LightUserData(LightUserData),
/// An integer number.
Integer(i64),
/// A floating point number.
Number(f64),
/// A string
String(String),
/// A table, dictionary or HashMap
Table(HashMap<String, CommandTransferValue>),
// Reference to a Lua function (or closure).
// /* TODO */ Function(Function),
// Reference to a Lua thread (or coroutine).
// /* TODO */ Thread(Thread<'lua>),
// Reference to an userdata object that holds a custom type which implements `UserData`.
// Special builtin userdata types will be represented as other `Value` variants.
// /* TODO */ UserData(AnyUserData),
// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned.
// /* TODO */ Error(Error),
}
impl Display for CommandTransferValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CommandTransferValue::Nil => f.write_str("Nil"),
CommandTransferValue::Boolean(bool) => f.write_str(&format!("{}", bool)),
CommandTransferValue::Integer(int) => f.write_str(&format!("{}", int)),
CommandTransferValue::Number(num) => f.write_str(&format!("{}", num)),
CommandTransferValue::String(str) => f.write_str(&format!("{}", str)),
// TODO(@Soispha): The following line should be a real display call, but how do you
// format a HashMap?
CommandTransferValue::Table(table) => f.write_str(&format!("{:#?}", table)),
}
}
}

View File

@ -1,34 +0,0 @@
use std::collections::HashMap;
use super::CommandTransferValue;
impl From<String> for CommandTransferValue {
fn from(s: String) -> Self {
Self::String(s.to_owned())
}
}
impl From<f64> for CommandTransferValue {
fn from(s: f64) -> Self {
Self::Number(s.to_owned())
}
}
impl From<i64> for CommandTransferValue {
fn from(s: i64) -> Self {
Self::Integer(s.to_owned())
}
}
impl From<HashMap<String, CommandTransferValue>> for CommandTransferValue {
fn from(s: HashMap<String, CommandTransferValue>) -> Self {
Self::Table(s.to_owned())
}
}
impl From<bool> for CommandTransferValue {
fn from(s: bool) -> Self {
Self::Boolean(s.to_owned())
}
}
impl From<()> for CommandTransferValue {
fn from(_: ()) -> Self {
Self::Nil
}
}

View File

@ -1,9 +1,10 @@
use std::thread;
use std::{collections::HashMap, fmt::Display, thread};
use anyhow::{Context, Result};
use cli_log::{debug, error, info};
use cli_log::{error, info, debug};
use mlua::{Function, Value};
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};
use tokio::{
runtime::Builder,
sync::{mpsc, Mutex},
@ -16,13 +17,95 @@ use crate::app::{
};
static LUA: OnceCell<Mutex<mlua::Lua>> = OnceCell::new();
pub type Table = HashMap<String, CommandTransferValue>;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum CommandTransferValue {
/// `nil` or `null` or `undefined`; anything which goes in that group of types.
Nil,
/// `true` or `false`.
Boolean(bool),
// A "light userdata" object, equivalent to a raw pointer.
// /*TODO*/ LightUserData(LightUserData),
/// An integer number.
Integer(i64),
/// A floating point number.
Number(f64),
/// A string
String(String),
/// A table, directory or HashMap
Table(HashMap<String, CommandTransferValue>),
// Reference to a Lua function (or closure).
// /* TODO */ Function(Function),
// Reference to a Lua thread (or coroutine).
// /* TODO */ Thread(Thread<'lua>),
// Reference to a userdata object that holds a custom type which implements `UserData`.
// Special builtin userdata types will be represented as other `Value` variants.
// /* TODO */ UserData(AnyUserData),
// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned.
// /* TODO */ Error(Error),
}
impl Display for CommandTransferValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CommandTransferValue::Nil => f.write_str("Nil"),
CommandTransferValue::Boolean(bool) => f.write_str(&format!("{}", bool)),
CommandTransferValue::Integer(int) => f.write_str(&format!("{}", int)),
CommandTransferValue::Number(num) => f.write_str(&format!("{}", num)),
CommandTransferValue::String(str) => f.write_str(&format!("{}", str)),
// TODO(@Soispha): The following line should be a real display call, but how do you
// format a HashMap?
CommandTransferValue::Table(table) => f.write_str(&format!("{:#?}", table)),
}
}
}
/// This structure contains the necessary state for running an embedded Lua runtime (i.e.
/// the tread, the Lua memory, etc.).
pub struct LuaCommandManager {
lua_command_tx: mpsc::Sender<String>,
}
impl From<String> for CommandTransferValue {
fn from(s: String) -> Self {
Self::String(s.to_owned())
}
}
impl From<f64> for CommandTransferValue {
fn from(s: f64) -> Self {
Self::Number(s.to_owned())
}
}
impl From<i64> for CommandTransferValue {
fn from(s: i64) -> Self {
Self::Integer(s.to_owned())
}
}
impl From<HashMap<String, CommandTransferValue>> for CommandTransferValue {
fn from(s: HashMap<String, CommandTransferValue>) -> Self {
Self::Table(s.to_owned())
}
}
impl From<bool> for CommandTransferValue {
fn from(s: bool) -> Self {
Self::Boolean(s.to_owned())
}
}
impl From<()> for CommandTransferValue {
fn from(_: ()) -> Self {
Self::Nil
}
}
impl LuaCommandManager {
pub async fn execute_code(&self, code: String) {
self.lua_command_tx
@ -46,11 +129,13 @@ impl LuaCommandManager {
waiting for commands.."
);
while let Some(command) = lua_command_rx.recv().await {
debug!("Recieved lua code (in LuaCommandHandler): {}", &command);
debug!("Recieved lua code: {}", &command);
let local_event_call_tx = event_call_tx.clone();
task::spawn_local(async move {
exec_lua(&command, local_event_call_tx).await.expect(
exec_lua_command(&command, local_event_call_tx)
.await
.expect(
"This should return all relevent errors \
by other messages, \
this should never error",
@ -65,7 +150,7 @@ impl LuaCommandManager {
}
}
async fn exec_lua(lua_code: &str, event_call_tx: mpsc::Sender<Event>) -> Result<()> {
async fn exec_lua_command(command: &str, event_call_tx: mpsc::Sender<Event>) -> Result<()> {
let second_event_call_tx = event_call_tx.clone();
let lua = LUA
.get_or_init(|| {
@ -77,23 +162,21 @@ async fn exec_lua(lua_code: &str, event_call_tx: mpsc::Sender<Event>) -> Result<
.lock()
.await;
info!("Recieved code to execute: `{}`, executing...", &lua_code);
let output = lua.load(lua_code).eval_async::<Value>().await;
info!("Recieved code to execute: `{}`, executing...", &command);
let output = lua.load(command).eval_async::<Value>().await;
match output {
Ok(out) => {
let to_string_fn: Function = lua.globals().get("tostring").expect("This always exists");
let output: String = to_string_fn.call(out).expect("tostring should not error");
info!("Lua code `{}` evaluated to: `{}`", lua_code, &output);
info!("Function `{}` returned: `{}`", command, &output);
if output != "nil" {
event_call_tx
.send(Event::CommandEvent(Command::DisplayOutput(output), None))
.await
.context("Failed to send lua output command")?
}
}
Err(err) => {
error!("Lua code `{}` returned error: `{}`", lua_code, err);
error!("Function `{}` returned error: `{}`", command, err);
event_call_tx
.send(Event::CommandEvent(
Command::RaiseError(err.to_string()),

View File

@ -1,15 +1,14 @@
// Use `cargo expand app::command_interface` for an overview of the file contents
pub mod command_transfer_value;
pub mod lua_command_manager;
use language_macros::ci_command_enum;
// 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::CommandTransferValue;
use mlua::IntoLua;
// if they stay here
use lua_command_manager::CommandTransferValue;
use mlua::LuaSerdeExt;
use crate::app::Event;
#[ci_command_enum]
@ -26,6 +25,7 @@ struct Commands {
/// Returns a table of greeted users
greet_multiple: fn() -> Table,
// End debug functions
/// Closes the application
exit: fn(),
@ -46,7 +46,7 @@ struct Commands {
set_mode_insert: fn(),
/// Send a message to the current room
/// The send message is interpreted literally.
/// The sent message is interpreted literally.
room_message_send: fn(String),
/// Open the help pages at the first occurrence of

View File

@ -4,18 +4,14 @@ use anyhow::{Error, Result};
use cli_log::{trace, warn};
use tokio::sync::oneshot;
use crate::{
app::{
use crate::{app::{
command_interface::{
command_transfer_value::{CommandTransferValue, Table},
lua_command_manager::{CommandTransferValue, Table},
Command,
},
events::event_types::EventStatus,
status::State,
App,
},
ui::central::InputPosition,
};
App, status::State,
}, ui::central::InputPosition};
pub async fn handle(
app: &mut App<'_>,
@ -24,8 +20,8 @@ pub async fn handle(
) -> 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).
// We simulate these by returning the main output to the Lua function, and printing the
// status output to a status UI field.
// We simulate these by returning the main output to the lua function, and printing the
// status output to a status ui field.
//
// Every function should return some status output to show the user, that something is
// happening, while only some functions return some value to the main output, as this
@ -72,7 +68,7 @@ pub async fn handle(
}
Command::DisplayOutput(output) => {
// TODO(@Soispha): This is only used to show the Lua command output to the user.
// 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);
@ -81,7 +77,6 @@ pub async fn handle(
Command::CommandLineShow => {
app.ui.cli_enable();
app.status.set_state(State::Command);
send_status_output!("CLI online");
EventStatus::Ok
}
@ -119,7 +114,7 @@ pub async fn handle(
room.send(msg.clone()).await?;
send_status_output!("Sent message: `{}`", msg);
} else {
// TODO(@Soispha): Should this raise a Lua error? It could be very confusing,
// TODO(@Soispha): Should this raise a lua error? It could be very confusing,
// when a user doesn't read the log.
warn!("Can't send message: `{}`, as there is no open room!", &msg);
}
@ -131,25 +126,13 @@ pub async fn handle(
}
Command::Print(output) => {
// FIXME(@Soispha): This only works with strings, which is a clear downside to the
// original print function. Find a way to just use the original one.
// original print function. Find a way to just use the original one
send_main_output!("{}", output);
EventStatus::Ok
}
Command::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),
);
table.insert("UserName1".to_owned(), CommandTransferValue::Integer(2));
send_main_output!(table);
EventStatus::Ok
}

View File

@ -10,56 +10,13 @@ use crate::{
ui::central,
};
pub async fn handle_command(
pub async fn handle_normal(
app: &mut App<'_>,
input_event: &CrosstermEvent,
) -> Result<EventStatus> {
if let Some(cli) = &app.ui.cli {
match input_event {
CrosstermEvent::Key(KeyEvent {
code: KeyCode::Esc, ..
}) => {
app.tx
.send(Event::CommandEvent(Command::SetModeNormal, None))
.await?;
}
CrosstermEvent::Key(KeyEvent {
code: KeyCode::Enter,
..
}) => {
let ci_event = cli
.lines()
.get(0)
.expect(
"One line always exists,
and others can't exists
because we collect on
enter",
)
.to_owned();
app.tx
.send(Event::LuaCommand(ci_event))
.await
.context("Failed to send lua command to internal event stream")?;
}
_ => {
app.ui
.cli
.as_mut()
.expect("This is already checked")
.input(tui_textarea::Input::from(input_event.to_owned()));
}
}
} else {
unreachable!("The cli should not be active while no cli is defined");
}
Ok(EventStatus::Ok)
}
pub async fn handle_normal(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<EventStatus> {
match input_event {
CrosstermEvent::Key(KeyEvent {
code: KeyCode::Char('q'),
..
}) => {
app.tx
.send(Event::CommandEvent(Command::Exit, None))
@ -180,7 +137,38 @@ pub async fn handle_normal(app: &mut App<'_>, input_event: &CrosstermEvent) -> R
_ => (),
};
}
central::InputPosition::CLI => {
if let Some(cli) = &app.ui.cli {
match input {
CrosstermEvent::Key(KeyEvent {
code: KeyCode::Enter,
..
}) => {
let ci_event = cli
.lines()
.get(0)
.expect(
"One line always exists,
and others can't exists
because we collect on
enter",
)
.to_owned();
app.tx
.send(Event::LuaCommand(ci_event))
.await
.context("Failed to send lua command to internal event stream")?;
}
_ => {
app.ui
.cli
.as_mut()
.expect("This is already checked")
.input(tui_textarea::Input::from(input.to_owned()));
}
};
};
}
_ => (),
},
};

View File

@ -6,7 +6,7 @@ use crossterm::event::Event as CrosstermEvent;
use tokio::sync::oneshot;
use crate::app::{
command_interface::{command_transfer_value::CommandTransferValue, Command},
command_interface::{lua_command_manager::CommandTransferValue, Command},
status::State,
App,
};
@ -45,9 +45,6 @@ impl Event {
State::Insert => main::handle_insert(app, &event).await.with_context(|| {
format!("Failed to handle input (insert) event: `{:#?}`", event)
}),
State::Command => main::handle_command(app, &event).await.with_context(|| {
format!("Failed to handle input (command) event: `{:#?}`", event)
}),
State::Setup => setup::handle(app, &event).await.with_context(|| {
format!("Failed to handle input (setup) event: `{:#?}`", event)
}),

View File

@ -15,7 +15,6 @@ use matrix_sdk::{
pub enum State {
Normal,
Insert,
Command,
/// Temporary workaround until command based login is working
Setup,
}
@ -58,7 +57,6 @@ impl fmt::Display for State {
match self {
Self::Normal => write!(f, "Normal"),
Self::Insert => write!(f, "Insert"),
Self::Command => write!(f, "Command"),
Self::Setup => write!(f, "Setup (!! workaround !!)"),
}
}