From fba8bbd369f36f3dba348201dd608e162f4a2286 Mon Sep 17 00:00:00 2001 From: Hanz Po Date: Tue, 21 Apr 2026 13:15:28 -0400 Subject: [PATCH 1/3] feat(config): add configurable input_prompt setting Add an optional `input_prompt` string under [settings] that overrides the default lock/unlock emoji prompt in the input area. When unset, preserve existing behaviour (U+1F512 green for encrypted, U+1F513 red for unencrypted, `> ` red for unknown). When set, use the provided string for all three states. The default emoji prompt can produce stray characters in the input line when iamb runs inside tmux, because ratatui's unicode-width, tmux's internal width tables, and the outer terminal's emoji rendering do not always agree on the width of the lock glyph plus variation selector. An ASCII override avoids the width mismatch without changing defaults. --- config.example.toml | 1 + src/config.rs | 4 ++++ src/windows/room/chat.rs | 32 ++++++++++++++++++++++---------- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/config.example.toml b/config.example.toml index c4ebd653..4937a33d 100644 --- a/config.example.toml +++ b/config.example.toml @@ -7,6 +7,7 @@ url = "https://matrix.org" [settings] default_room = "#iamb-users:0x.badd.cafe" external_edit_file_suffix = ".md" +# input_prompt = "❯ " # Overrides the input-area prompt. Unset = default 🔒/🔓/> based on encryption state. log_level = "warn" message_shortcode_display = false open_command = ["my-open", "--file"] diff --git a/src/config.rs b/src/config.rs index 39853ecb..1c27d615 100644 --- a/src/config.rs +++ b/src/config.rs @@ -540,6 +540,7 @@ pub struct TunableValues { pub user_gutter_width: usize, pub external_edit_file_suffix: String, pub tabstop: usize, + pub input_prompt: Option, } #[derive(Clone, Default, Deserialize)] @@ -569,6 +570,7 @@ pub struct Tunables { pub user_gutter_width: Option, pub external_edit_file_suffix: Option, pub tabstop: Option, + pub input_prompt: Option, } impl Tunables { @@ -604,6 +606,7 @@ impl Tunables { .external_edit_file_suffix .or(other.external_edit_file_suffix), tabstop: self.tabstop.or(other.tabstop), + input_prompt: self.input_prompt.or(other.input_prompt), } } @@ -635,6 +638,7 @@ impl Tunables { .external_edit_file_suffix .unwrap_or_else(|| ".md".to_string()), tabstop: self.tabstop.unwrap_or(4), + input_prompt: self.input_prompt, } } } diff --git a/src/windows/room/chat.rs b/src/windows/room/chat.rs index 7d26a1fe..b2e0909d 100644 --- a/src/windows/room/chat.rs +++ b/src/windows/room/chat.rs @@ -9,7 +9,6 @@ use edit::edit_with_builder as external_edit; use edit::Builder; use matrix_sdk::EncryptionState; use modalkit::editing::store::RegisterError; -use ratatui::style::{Color, Style}; use std::process::Command; use tokio; use url::Url; @@ -41,6 +40,7 @@ use matrix_sdk::{ use ratatui::{ buffer::Buffer, layout::Rect, + style::{Color, Style}, text::{Line, Span}, widgets::{Paragraph, StatefulWidget, Widget}, }; @@ -992,15 +992,27 @@ impl StatefulWidget for Chat<'_> { Paragraph::new(desc_spans).render(descarea, buf); } - let prompt = match (self.focused, state.room().encryption_state()) { - (false, _) => Span::raw(" "), - (_, EncryptionState::Encrypted) => { - Span::styled("\u{1F512}\u{FE0E} ", Style::new().fg(Color::LightGreen)) - }, - (_, EncryptionState::NotEncrypted) => { - Span::styled("\u{1F513}\u{FE0E} ", Style::new().fg(Color::Red)) - }, - (_, EncryptionState::Unknown) => Span::styled("> ", Style::new().fg(Color::Red)), + let prompt = if !self.focused { + Span::raw(" ") + } else if let Some(custom) = self + .store + .application + .settings + .tunables + .input_prompt + .as_deref() + { + Span::raw(custom) + } else { + match state.room().encryption_state() { + EncryptionState::Encrypted => { + Span::styled("\u{1F512}\u{FE0E} ", Style::new().fg(Color::LightGreen)) + }, + EncryptionState::NotEncrypted => { + Span::styled("\u{1F513}\u{FE0E} ", Style::new().fg(Color::Red)) + }, + EncryptionState::Unknown => Span::styled("> ", Style::new().fg(Color::Red)), + } }; let tbox = TextBox::new().prompt(prompt); From cc0335969b4b9f35a93d508741035223d4ca97c5 Mon Sep 17 00:00:00 2001 From: Ulyssa Date: Fri, 4 Sep 2026 20:41:13 -0400 Subject: [PATCH 2/3] update `tests.rs` --- src/tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests.rs b/src/tests.rs index dcf8533f..7a733132 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -170,6 +170,7 @@ pub fn mock_tunables() -> TunableValues { ignorecase: false, default_room: None, encryption: Encryption::default().values(), + input_prompt: None, log_level: "warn".into(), max_log_files: 7, message_shortcode_display: false, From 114eedef8d8269c2949500bc0af61a140147fe51 Mon Sep 17 00:00:00 2001 From: Ulyssa Date: Fri, 4 Sep 2026 20:45:43 -0400 Subject: [PATCH 3/3] Update manual page --- config.example.toml | 2 +- docs/iamb.5 | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config.example.toml b/config.example.toml index 4495c370..64ede336 100644 --- a/config.example.toml +++ b/config.example.toml @@ -10,8 +10,8 @@ default_markup = "html" default_room = "#iamb-users:0x.badd.cafe" default_split = "vertical" external_edit_file_suffix = ".md" -# input_prompt = "❯ " # Overrides the input-area prompt. Unset = default 🔒/🔓/> based on encryption state. ignorecase = false +input_prompt = "❯ " log_level = "warn" members_split = "vertical" message_shortcode_display = false diff --git a/docs/iamb.5 b/docs/iamb.5 index 9873a539..46cd8970 100644 --- a/docs/iamb.5 +++ b/docs/iamb.5 @@ -166,6 +166,8 @@ Subsection for configuring image previews. See for more details. .It Sy ignorecase Defines whether searches ignore case. Defaults to false. +.It Sy input_prompt +Override the default message bar prompt. .It Sy log_level Specifies the lowest log level that should be shown. Possible values are: