Various bugfixes

This commit is contained in:
2026-01-29 19:47:12 -05:00
parent 8933153c2b
commit d04dd4bc1e
7 changed files with 54 additions and 13 deletions

View File

@@ -1,5 +1,6 @@
pub mod highlight;
pub mod readline;
pub mod statusline;
use readline::{FernVi, Readline};

View File

@@ -1,4 +1,5 @@
use std::{
collections::HashSet,
env,
fmt::{Display, Write},
fs::{self, OpenOptions},
@@ -194,6 +195,22 @@ fn read_hist_file(path: &Path) -> ShResult<Vec<HistEntry>> {
Ok(raw.parse::<HistEntries>()?.0)
}
/// Deduplicate entries, keeping only the most recent occurrence of each command.
/// Preserves chronological order (oldest to newest).
fn dedupe_entries(entries: &[HistEntry]) -> Vec<HistEntry> {
let mut seen = HashSet::new();
// Iterate backwards (newest first), keeping first occurrence of each command
entries
.iter()
.rev()
.filter(|ent| seen.insert(ent.command.clone()))
.cloned()
.collect::<Vec<_>>()
.into_iter()
.rev() // Restore chronological order
.collect()
}
pub struct History {
path: PathBuf,
entries: Vec<HistEntry>,
@@ -222,7 +239,7 @@ impl History {
new: true,
})
}
let search_mask = entries.clone();
let search_mask = dedupe_entries(&entries);
let cursor = entries.len() - 1;
let mut new = Self {
path,
@@ -288,15 +305,16 @@ impl History {
match kind {
SearchKind::Prefix => {
if term.is_empty() {
self.search_mask = self.entries.clone();
self.search_mask = dedupe_entries(&self.entries);
} else {
let filtered = self
let filtered: Vec<_> = self
.entries
.clone()
.into_iter()
.filter(|ent| ent.command().starts_with(&term));
.iter()
.filter(|ent| ent.command().starts_with(&term))
.cloned()
.collect();
self.search_mask = filtered.collect();
self.search_mask = dedupe_entries(&filtered);
}
self.cursor = self.search_mask.len().saturating_sub(1);
}

View File

@@ -362,6 +362,8 @@ impl LineBuf {
let hint = hint.strip_prefix(&self.buffer).unwrap(); // If this ever panics, I will eat my hat
if !hint.is_empty() {
self.hint = Some(hint.to_string())
} else {
self.hint = None
}
} else {
self.hint = None

View File

@@ -57,7 +57,6 @@ impl Readline for FernVi {
Err(_) | Ok(None) => {
flog!(DEBUG, "EOF detected");
raw_mode_guard.disable_for(|| self.writer.flush_write("\n"))?;
std::mem::drop(raw_mode_guard);
return Err(ShErr::simple(ShErrKind::ReadlineErr, "EOF"));
}
@@ -68,7 +67,6 @@ impl Readline for FernVi {
if self.should_accept_hint(&key) {
self.editor.accept_hint();
self.history.update_pending_cmd(self.editor.as_str());
self.print_line()?;
continue;
}
@@ -81,19 +79,22 @@ impl Readline for FernVi {
if self.should_grab_history(&cmd) {
self.scroll_history(cmd);
self.print_line()?;
continue;
}
if cmd.should_submit() {
raw_mode_guard.disable_for(|| self.writer.flush_write("\n"))?;
std::mem::drop(raw_mode_guard);
return Ok(self.editor.take_buf());
let buf = self.editor.take_buf();
// Save command to history
self.history.push(buf.clone());
if let Err(e) = self.history.save() {
eprintln!("Failed to save history: {e}");
}
return Ok(buf);
}
if cmd.verb().is_some_and(|v| v.1 == Verb::EndOfFile) {
if self.editor.buffer.is_empty() {
std::mem::drop(raw_mode_guard);
return Err(ShErr::simple(ShErrKind::CleanExit(0), "exit"));
} else {
self.editor.buffer.clear();

View File

@@ -36,6 +36,9 @@ pub fn raw_mode() -> RawModeGuard {
&raw,
)
.expect("Failed to set terminal to raw mode");
let (cols, rows) = get_win_size(STDIN_FILENO);
RawModeGuard {
orig,
fd: STDIN_FILENO,

1
src/prompt/statusline.rs Normal file
View File

@@ -0,0 +1 @@