From 6f334395f7d32741bec518eddc66e2f49d273892 Mon Sep 17 00:00:00 2001 From: pagedmov Date: Fri, 20 Feb 2026 14:15:25 -0500 Subject: [PATCH] line editor now sends bell on no-op edits --- src/prompt/readline/mod.rs | 13 +++++++++---- src/prompt/readline/term.rs | 18 ++++++++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/prompt/readline/mod.rs b/src/prompt/readline/mod.rs index f61a7e4..f823662 100644 --- a/src/prompt/readline/mod.rs +++ b/src/prompt/readline/mod.rs @@ -8,6 +8,7 @@ use vimode::{CmdReplay, ModeReport, ViInsert, ViMode, ViNormal, ViReplace, ViVis use crate::libsh::sys::TTY_FILENO; use crate::prelude::*; +use crate::state::read_shopts; use crate::{ libsh::{ error::ShResult, @@ -222,9 +223,9 @@ impl FernVi { let hint = self.history.get_hint(); self.editor.set_hint(hint); } - None => match crate::state::read_shopts(|s| s.core.bell_style) { + None => match read_shopts(|s| s.core.bell_style) { crate::shopt::FernBellStyle::Audible => { - self.writer.flush_write("\x07")?; + self.writer.send_bell().ok(); } crate::shopt::FernBellStyle::Visible | crate::shopt::FernBellStyle::Disable => {} }, @@ -255,7 +256,7 @@ impl FernVi { self.writer.flush_write("\n")?; let buf = self.editor.take_buf(); // Save command to history if auto_hist is enabled - if crate::state::read_shopts(|s| s.core.auto_hist) && !buf.is_empty() { + if read_shopts(|s| s.core.auto_hist) && !buf.is_empty() { self.history.push(buf.clone()); if let Err(e) = self.history.save() { eprintln!("Failed to save history: {e}"); @@ -276,6 +277,8 @@ impl FernVi { } } + let has_edit_verb = cmd.verb().is_some_and(|v| v.1.is_edit()); + let before = self.editor.buffer.clone(); self.exec_cmd(cmd)?; let after = self.editor.as_str(); @@ -284,7 +287,9 @@ impl FernVi { self .history .update_pending_cmd((self.editor.as_str(), self.editor.cursor.get())); - } + } else if before == after && has_edit_verb { + self.writer.send_bell().ok(); // bell on no-op commands with a verb (e.g., 'x' on empty line) + } let hint = self.history.get_hint(); self.editor.set_hint(hint); diff --git a/src/prompt/readline/term.rs b/src/prompt/readline/term.rs index d455a35..eb63886 100644 --- a/src/prompt/readline/term.rs +++ b/src/prompt/readline/term.rs @@ -18,8 +18,7 @@ use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use vte::{Parser, Perform}; use crate::{ - libsh::{error::{ShErr, ShErrKind, ShResult}, sys::TTY_FILENO}, - prompt::readline::keys::{KeyCode, ModKeys}, + libsh::{error::{ShErr, ShErrKind, ShResult}, sys::TTY_FILENO}, prompt::readline::keys::{KeyCode, ModKeys}, shopt::FernBellStyle, state::read_shopts }; use crate::{ prelude::*, @@ -185,6 +184,7 @@ pub trait LineWriter { fn clear_rows(&mut self, layout: &Layout) -> ShResult<()>; fn redraw(&mut self, prompt: &str, line: &str, new_layout: &Layout) -> ShResult<()>; fn flush_write(&mut self, buf: &str) -> ShResult<()>; + fn send_bell(&mut self) -> ShResult<()>; } #[derive(Clone, Copy, Debug)] @@ -975,4 +975,18 @@ impl LineWriter for TermWriter { write_all(self.out, buf)?; Ok(()) } + + fn send_bell(&mut self) -> ShResult<()> { + match read_shopts(|o| o.core.bell_style) { + FernBellStyle::Audible => { + self.flush_write("\x07")?; + } + FernBellStyle::Visible => { + log::warn!("Visual bell is not supported in fern shell yet"); + } + FernBellStyle::Disable => { /* Do nothing */ } + } + Ok(()) + } + }