Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ serde = "1.0"
serde_json = "1.0"
shellexpand = "3.1"
sled = "0.34.7"
strum = "0.28.0"
strum_macros = "0.28.0"
temp-dir = "0.2"
thiserror = "2.0"
toml = "1.1"
Expand Down
21 changes: 21 additions & 0 deletions docs/iamb.1
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@ Mark all rooms as read.
View the startup Welcome window.
.It Sy ":forget"
Remove all left rooms from the internal database.
.Id Sy ":reload"
Reload the config.
.It Sy ":se[t] {options}"
Change config options at runtime.
Use
.Dq {option}
and
.Dq no{option}
for booleans and
.Dq {option}={value}
for other settings.

.Ss Example 1: Disable notifications
.Bd -literal -offset indent
:set notifications.noenabled
.Ed
.El
.Ss Example 2: Remove a username override
.Bd -literal -offset indent
:set users.@username:example.org.name=
.Ed
.El

.Sh "E2EE COMMANDS"
Expand Down
64 changes: 60 additions & 4 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use std::collections::{BTreeSet, HashMap, HashSet};
use std::convert::TryFrom;
use std::fmt::{self, Display};
use std::hash::Hash;
use std::ops::Deref;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::{Duration, Instant};
Expand All @@ -28,6 +30,7 @@ use serde::{
Serialize,
Serializer,
};
use strum::{EnumProperty, VariantArray};
use tokio::sync::Mutex as AsyncMutex;
use url::Url;

Expand Down Expand Up @@ -89,7 +92,12 @@ use modalkit::{
prelude::{CommandType, WordStyle},
};

use crate::config::ImagePreviewProtocolValues;
use crate::config::{
ImagePreviewProtocolValues,
ReloadError,
TunablesUpdate,
TunablesUpdateDiscriminants,
};
use crate::message::ImageStatus;
use crate::notifications::NotificationHandle;
use crate::preview::{source_from_event, spawn_insert_preview};
Expand Down Expand Up @@ -296,7 +304,7 @@ impl<'de> Deserialize<'de> for SortColumn<SortFieldRoom> {
}

/// [serde] visitor for deserializing [SortColumn] for rooms and spaces.
struct SortRoomVisitor;
pub(crate) struct SortRoomVisitor;

impl Visitor<'_> for SortRoomVisitor {
type Value = SortColumn<SortFieldRoom>;
Expand Down Expand Up @@ -349,7 +357,7 @@ impl<'de> Deserialize<'de> for SortColumn<SortFieldUser> {
}

/// [serde] visitor for deserializing [SortColumn] for users.
struct SortUserVisitor;
pub(crate) struct SortUserVisitor;

impl Visitor<'_> for SortUserVisitor {
type Value = SortColumn<SortFieldUser>;
Expand Down Expand Up @@ -506,6 +514,16 @@ pub enum KeysAction {
Import(String, String),
}

/// An action performed on the application settings.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SettingsAction {
/// Change some settings.
Set(Vec<TunablesUpdate>),

/// Reload the (specified) config file.
Reload(Option<PathBuf>),
}

/// An action that the main program loop should.
///
/// See [the commands module][super::commands] for where these are usually created.
Expand All @@ -523,6 +541,9 @@ pub enum IambAction {
/// Perform an action on the current space.
Space(SpaceAction),

/// Perform an action on the application settings.
Settings(SettingsAction),

/// Open a URL.
OpenLink(String),

Expand Down Expand Up @@ -570,6 +591,12 @@ impl From<SpaceAction> for IambAction {
}
}

impl From<SettingsAction> for IambAction {
fn from(act: SettingsAction) -> Self {
IambAction::Settings(act)
}
}

impl From<RoomAction> for IambAction {
fn from(act: RoomAction) -> Self {
IambAction::Room(act)
Expand All @@ -593,6 +620,7 @@ impl ApplicationAction for IambAction {
IambAction::Room(..) => SequenceStatus::Break,
IambAction::OpenLink(..) => SequenceStatus::Break,
IambAction::Send(..) => SequenceStatus::Break,
IambAction::Settings(..) => SequenceStatus::Break,
IambAction::ToggleScrollbackFocus => SequenceStatus::Break,
IambAction::Verify(..) => SequenceStatus::Break,
IambAction::VerifyRequest(..) => SequenceStatus::Break,
Expand All @@ -609,6 +637,7 @@ impl ApplicationAction for IambAction {
IambAction::OpenLink(..) => SequenceStatus::Atom,
IambAction::Room(..) => SequenceStatus::Atom,
IambAction::Send(..) => SequenceStatus::Atom,
IambAction::Settings(..) => SequenceStatus::Atom,
IambAction::ToggleScrollbackFocus => SequenceStatus::Atom,
IambAction::Verify(..) => SequenceStatus::Atom,
IambAction::VerifyRequest(..) => SequenceStatus::Atom,
Expand All @@ -625,6 +654,7 @@ impl ApplicationAction for IambAction {
IambAction::Room(..) => SequenceStatus::Ignore,
IambAction::OpenLink(..) => SequenceStatus::Ignore,
IambAction::Send(..) => SequenceStatus::Ignore,
IambAction::Settings(..) => SequenceStatus::Ignore,
IambAction::ToggleScrollbackFocus => SequenceStatus::Ignore,
IambAction::Verify(..) => SequenceStatus::Ignore,
IambAction::VerifyRequest(..) => SequenceStatus::Ignore,
Expand All @@ -640,6 +670,7 @@ impl ApplicationAction for IambAction {
IambAction::Room(..) => false,
IambAction::Keys(..) => false,
IambAction::Send(..) => false,
IambAction::Settings(..) => false,
IambAction::OpenLink(..) => false,
IambAction::ToggleScrollbackFocus => false,
IambAction::Verify(..) => false,
Expand Down Expand Up @@ -813,6 +844,10 @@ pub enum IambError {
/// A failure while trying to show an image preview.
#[error("Preview error: {0}")]
Preview(String),

/// Config couldn't be reloaded
#[error("Reload error: {0}")]
ConfigReload(#[from] ReloadError),
}

impl From<IambError> for UIError<IambInfo> {
Expand Down Expand Up @@ -2129,7 +2164,7 @@ fn complete_cmdarg(
match cmd.name.as_str() {
"cancel" | "dms" | "edit" | "redact" | "reply" => vec![],
"members" | "rooms" | "spaces" | "welcome" => vec![],
"download" | "keys" | "open" | "upload" => complete_path(text, cursor),
"download" | "keys" | "open" | "upload" | "reload" => complete_path(text, cursor),
"react" | "unreact" => complete_emoji(text, cursor, store),

"invite" => complete_users(text, cursor, store),
Expand All @@ -2139,6 +2174,27 @@ fn complete_cmdarg(
"vertical" | "horizontal" | "aboveleft" | "belowright" | "tab" => {
complete_cmd(desc.arg.text.as_str(), text, cursor, store)
},
"set" => {
// TODO: improve once #520 is merged
let word = text
.get_prefix_word_mut(cursor, &MATRIX_ID_WORD)
.unwrap_or_else(EditRope::empty);
let word = Cow::from(&word);

TunablesUpdateDiscriminants::VARIANTS
.iter()
.flat_map(|variant| {
let name = <_ as Into<&'static str>>::into(variant).to_lowercase();
if variant.get_bool("is_bool") == Some(true) {
vec![format!("no{name}"), name]
} else {
vec![name]
}
})
.filter(|option| option.starts_with(word.deref()))
.map(|option| option.to_string())
.collect()
},
_ => vec![],
}
}
Expand Down
49 changes: 49 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ use crate::base::{
RoomAction,
RoomField,
SendAction,
SettingsAction,
SpaceAction,
VerifyAction,
};
use crate::config::TunablesUpdate;

type ProgContext = CommandContext;
type ProgResult = CommandResult<ProgramCommand>;
Expand Down Expand Up @@ -717,6 +719,43 @@ fn iamb_logout(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
return Ok(step);
}

fn iamb_set(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
let args = desc.arg.strings()?;

let mut updates = vec![];

for arg in args {
let (option, value) = if let Some((option, value)) = arg.split_once('=') {
(option.to_string(), Some(value))
} else {
(arg.clone(), None)
};

match TunablesUpdate::new(option, value) {
Ok(update) => updates.push(update),
Err(err) => return Result::Err(CommandError::ParseFailed(format!("{err}: {arg}"))),
}
}

let iact = IambAction::from(SettingsAction::Set(updates));
let step = CommandStep::Continue(iact.into(), ctx.context.clone());

return Ok(step);
}

fn iamb_reload(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
let mut args = desc.arg.strings()?;

if args.len() > 1 {
return Result::Err(CommandError::InvalidArgument);
}

let iact = IambAction::from(SettingsAction::Reload(args.pop().map(Into::into)));
let step = CommandStep::Continue(iact.into(), ctx.context.clone());

return Ok(step);
}

fn add_iamb_commands(cmds: &mut ProgramCommands) {
cmds.add_command(ProgramCommand {
name: "cancel".into(),
Expand Down Expand Up @@ -834,6 +873,16 @@ fn add_iamb_commands(cmds: &mut ProgramCommands) {
aliases: vec![],
f: iamb_logout,
});
cmds.add_command(ProgramCommand {
name: "set".into(),
aliases: vec!["se".into()],
f: iamb_set,
});
cmds.add_command(ProgramCommand {
name: "reload".into(),
aliases: vec![],
f: iamb_reload,
});
}

/// Initialize the default command state.
Expand Down
Loading
Loading