Skip to content
Open
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
2 changes: 2 additions & 0 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 @@ -61,6 +61,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
22 changes: 22 additions & 0 deletions docs/iamb.1
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,29 @@ View a list of rooms with mentions of the current user.
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"
.Bl -tag -width Ds
.It Sy ":keys export [path] [passphrase]"
Expand Down
43 changes: 39 additions & 4 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use std::collections::hash_map::{Entry, IntoIter};
use std::collections::{BTreeSet, HashSet};
use std::path::PathBuf;

use emojis::Emoji;
use matrix_sdk::Client;
Expand Down Expand Up @@ -41,8 +42,10 @@ use modalkit::keybindings::SequenceStatus;
use serde::de::Error as SerdeError;
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use strum::VariantNames;
use tokio::sync::Mutex as AsyncMutex;

use crate::config::{ReloadError, TunablesUpdate};
use crate::notifications::NotificationHandle;
use crate::prelude::*;

Expand Down Expand Up @@ -190,7 +193,8 @@ bitflags::bitflags! {
}

/// Fields that rooms and spaces can be sorted by.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq, VariantNames)]
#[strum(serialize_all = "lowercase")]
pub enum SortFieldRoom {
/// Sort rooms by whether they have the Favorite tag.
Favorite,
Expand All @@ -205,6 +209,7 @@ pub enum SortFieldRoom {
Alias,

/// Sort rooms by their Matrix room identifier.
#[strum(serialize = "id")]
RoomId,

/// Sort rooms by the server portion of their canonical room alias.
Expand All @@ -225,9 +230,12 @@ pub enum SortFieldRoom {
}

/// Fields that users can be sorted by.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq, VariantNames)]
#[strum(serialize_all = "lowercase")]
pub enum SortFieldUser {
#[strum(serialize = "power")]
PowerLevel,
#[strum(serialize = "id")]
UserId,
LocalPart,
Server,
Expand Down Expand Up @@ -256,7 +264,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 @@ -310,7 +318,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 @@ -566,6 +574,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 @@ -583,6 +601,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 @@ -630,6 +651,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 @@ -653,6 +680,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 @@ -669,6 +697,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 @@ -685,6 +714,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 @@ -700,6 +730,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 @@ -883,6 +914,10 @@ pub enum IambError {
/// A generic error that doesn't need a specific error type.
#[error("{0}")]
Custom(String),

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

impl From<IambError> for UIError<IambInfo> {
Expand Down
49 changes: 49 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ use crate::base::{
ProgramCommand,
ProgramCommands,
RoomField,
SettingsAction,
VerifyAction,
};
use crate::config::TunablesUpdate;
use crate::prelude::*;

type ProgContext = CommandContext;
Expand Down Expand Up @@ -995,6 +997,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);
}

pub fn add_iamb_commands(cmds: &mut ProgramCommands) {
cmds.add_command(ProgramCommand {
name: "cancel".into(),
Expand Down Expand Up @@ -1128,6 +1167,16 @@ pub 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