fixed the $0 parameter not being populated correctly

This commit is contained in:
2026-02-19 14:24:55 -05:00
parent 8cb8f20a35
commit 9483477edd
12 changed files with 210 additions and 99 deletions

View File

@@ -87,8 +87,8 @@ impl Completer {
ctx.push(markers::VAR_SUB);
}
}
markers::ARG => {
log::debug!("Found argument marker at position {}", pos);
markers::ARG | markers::ASSIGNMENT => {
log::debug!("Found argument/assignment marker at position {}", pos);
if last_priority < 1 {
ctx_start = pos;
ctx.push(markers::ARG);
@@ -328,6 +328,8 @@ impl Completer {
})
.collect();
let limit = crate::state::read_shopts(|s| s.prompt.comp_limit);
candidates.truncate(limit);
Ok(CompResult::from_candidates(candidates))
}

View File

@@ -1,6 +1,6 @@
use std::{env, path::{Path, PathBuf}};
use std::{env, os::unix::fs::PermissionsExt, path::{Path, PathBuf}};
use crate::{libsh::term::{Style, StyleSet, Styled}, prompt::readline::{annotate_input, markers}, state::read_logic};
use crate::{libsh::term::{Style, StyleSet, Styled}, prompt::readline::{annotate_input, markers}, state::{read_logic, read_shopts}};
/// Syntax highlighter for shell input using Unicode marker-based annotation
///
@@ -214,16 +214,31 @@ impl Highlighter {
fn is_valid(command: &str) -> bool {
let path = env::var("PATH").unwrap_or_default();
let paths = path.split(':');
if PathBuf::from(&command).exists() {
return true;
let cmd_path = PathBuf::from(&command);
if cmd_path.exists() {
// the user has given us an absolute path
if cmd_path.is_dir() && read_shopts(|o| o.core.autocd) {
// this is a directory and autocd is enabled
return true;
} else {
let Ok(meta) = cmd_path.metadata() else { return false };
// this is a file that is executable by someone
return meta.permissions().mode() & 0o111 == 0
}
} else {
// they gave us a command name
// now we must traverse the PATH env var
// and see if we find any matches
for path in paths {
let path = PathBuf::from(path).join(command);
if path.exists() {
return true;
let Ok(meta) = path.metadata() else { continue };
return meta.permissions().mode() & 0o111 != 0;
}
}
// also check shell functions and aliases for any matches
let found = read_logic(|l| l.get_func(command).is_some() || l.get_alias(command).is_some());
if found {
return true;

View File

@@ -217,11 +217,17 @@ pub struct History {
impl History {
pub fn new() -> ShResult<Self> {
let ignore_dups = crate::state::read_shopts(|s| s.core.hist_ignore_dupes);
let max_hist = crate::state::read_shopts(|s| s.core.max_hist);
let path = PathBuf::from(env::var("FERNHIST").unwrap_or({
let home = env::var("HOME").unwrap();
format!("{home}/.fern_history")
}));
let mut entries = read_hist_file(&path)?;
// Enforce max_hist limit on loaded entries
if entries.len() > max_hist {
entries = entries.split_off(entries.len() - max_hist);
}
// Create pending entry for current input
let id = entries.last().map(|ent| ent.id + 1).unwrap_or(0);
entries.push(HistEntry {
@@ -238,8 +244,8 @@ impl History {
search_mask,
cursor,
search_direction: Direction::Backward,
ignore_dups: true,
max_size: None,
ignore_dups,
max_size: Some(max_hist as u32),
})
}

View File

@@ -212,7 +212,10 @@ impl FernVi {
self.editor.set_hint(hint);
}
None => {
self.writer.flush_write("\x07")?; // Bell character
match crate::state::read_shopts(|s| s.core.bell_style) {
crate::shopt::FernBellStyle::Audible => { self.writer.flush_write("\x07")?; }
crate::shopt::FernBellStyle::Visible | crate::shopt::FernBellStyle::Disable => {}
}
}
}
@@ -240,10 +243,12 @@ impl FernVi {
self.print_line()?;
self.writer.flush_write("\n")?;
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}");
// Save command to history if auto_hist is enabled
if crate::state::read_shopts(|s| s.core.auto_hist) {
self.history.push(buf.clone());
if let Err(e) = self.history.save() {
eprintln!("Failed to save history: {e}");
}
}
return Ok(ReadlineEvent::Line(buf));
}
@@ -283,7 +288,8 @@ impl FernVi {
pub fn get_layout(&mut self, line: &str) -> Layout {
let to_cursor = self.editor.slice_to_cursor().unwrap_or_default();
let (cols, _) = get_win_size(STDIN_FILENO);
Layout::from_parts(/* tab_stop: */ 8, cols, &self.prompt, to_cursor, line)
let tab_stop = crate::state::read_shopts(|s| s.prompt.tab_stop) as u16;
Layout::from_parts(tab_stop, cols, &self.prompt, to_cursor, line)
}
pub fn scroll_history(&mut self, cmd: ViCmd) {
/*
@@ -360,15 +366,16 @@ impl FernVi {
}
pub fn line_text(&mut self) -> String {
let start = Instant::now();
let line = self.editor.to_string();
self.highlighter.load_input(&line);
self.highlighter.highlight();
let highlighted = self.highlighter.take();
let hint = self.editor.get_hint_text();
let complete = format!("{highlighted}{hint}");
let end = start.elapsed();
complete
if crate::state::read_shopts(|s| s.prompt.highlight) {
self.highlighter.load_input(&line);
self.highlighter.highlight();
let highlighted = self.highlighter.take();
format!("{highlighted}{hint}")
} else {
format!("{line}{hint}")
}
}
pub fn print_line(&mut self) -> ShResult<()> {