From 7f3e1cfceed9843aac5c8d28192c11b60931c40e Mon Sep 17 00:00:00 2001 From: pagedmov Date: Wed, 28 Jan 2026 19:57:14 -0500 Subject: [PATCH] renamed fern.rs back to main.rs --- Cargo.toml | 1 - src/expand.rs | 11 ++-- src/jobs.rs | 2 + src/libsh/sys.rs | 4 +- src/{fern.rs => main.rs} | 0 src/parse/execute.rs | 7 +-- src/parse/lex.rs | 7 ++- src/prompt/mod.rs | 4 +- src/prompt/readline/linebuf.rs | 20 +++---- src/prompt/readline/mod.rs | 2 +- src/prompt/readline/term.rs | 2 - src/prompt/readline/vicmd.rs | 5 +- src/prompt/readline/vimode.rs | 1 - src/signal.rs | 7 ++- src/state.rs | 98 +++++++++------------------------- 15 files changed, 52 insertions(+), 119 deletions(-) rename src/{fern.rs => main.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 5948418..2a3c9f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,4 +24,3 @@ pretty_assertions = "1.4.1" [[bin]] name = "fern" -path = "src/fern.rs" diff --git a/src/expand.rs b/src/expand.rs index 16fb476..d26618d 100644 --- a/src/expand.rs +++ b/src/expand.rs @@ -1,6 +1,5 @@ use std::collections::HashSet; use std::iter::Peekable; -use std::mem::take; use std::str::{Chars, FromStr}; use glob::Pattern; @@ -68,11 +67,10 @@ impl Expander { pub fn expand(&mut self) -> ShResult> { let mut chars = self.raw.chars().peekable(); self.raw = expand_raw(&mut chars)?; - if let Ok(glob_exp) = expand_glob(&self.raw) { - if !glob_exp.is_empty() { + if let Ok(glob_exp) = expand_glob(&self.raw) + && !glob_exp.is_empty() { self.raw = glob_exp; } - } Ok(self.split_words()) } pub fn split_words(&mut self) -> Vec { @@ -776,11 +774,10 @@ pub fn expand_proc_sub(raw: &str, is_input: bool) -> ShResult { pub fn expand_cmd_sub(raw: &str) -> ShResult { flog!(DEBUG, "in expand_cmd_sub"); flog!(DEBUG, raw); - if raw.starts_with('(') && raw.ends_with(')') { - if let Ok(output) = expand_arithmetic(raw) { + if raw.starts_with('(') && raw.ends_with(')') + && let Ok(output) = expand_arithmetic(raw) { return Ok(output); // It's actually an arithmetic sub } - } let (rpipe, wpipe) = IoMode::get_pipes(); let cmd_sub_redir = Redir::new(wpipe, RedirType::Output); let cmd_sub_io_frame = IoFrame::from_redir(cmd_sub_redir); diff --git a/src/jobs.rs b/src/jobs.rs index 391f301..88f2df4 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -507,6 +507,8 @@ impl Job { flog!(TRACE, "waiting on children"); flog!(TRACE, self.children); for child in self.children.iter_mut() { + flog!(TRACE, "shell pid {}", Pid::this()); + flog!(TRACE, "child pid {}", child.pid); if child.pid == Pid::this() { // TODO: figure out some way to get the exit code of builtins let code = state::get_status(); diff --git a/src/libsh/sys.rs b/src/libsh/sys.rs index 01b7b04..b0bcc31 100644 --- a/src/libsh/sys.rs +++ b/src/libsh/sys.rs @@ -55,12 +55,12 @@ pub fn save_termios() { ///This function is unsafe because it accesses a public mutable static value. /// This function should only ever be called after save_termios() has already /// been called. -pub unsafe fn get_saved_termios() -> Option { +pub unsafe fn get_saved_termios() -> Option { unsafe { // SAVED_TERMIOS should *only ever* be set once and accessed once // Set at the start of the program, and accessed during the exit of the program // to reset the termios. Do not use this variable anywhere else SAVED_TERMIOS.clone().flatten() -} +}} /// Set termios to not echo control characters, like ^Z for instance pub fn set_termios() { diff --git a/src/fern.rs b/src/main.rs similarity index 100% rename from src/fern.rs rename to src/main.rs diff --git a/src/parse/execute.rs b/src/parse/execute.rs index 01d993d..0e4dd31 100644 --- a/src/parse/execute.rs +++ b/src/parse/execute.rs @@ -118,12 +118,7 @@ impl ExecArgs { pub fn exec_input(input: String, io_stack: Option) -> ShResult<()> { write_meta(|m| m.start_timer()); - let log_tab = { - let fern = FERN.read().unwrap(); - // TODO: Is there a better way to do this? - // The goal is mainly to not be holding a lock while executing input - fern.read_logic().clone() - }; + let log_tab = read_logic(|l| l.clone()); let input = expand_aliases(input, HashSet::new(), &log_tab); let mut parser = ParsedSrc::new(Arc::new(input)); if let Err(errors) = parser.parse_src() { diff --git a/src/parse/lex.rs b/src/parse/lex.rs index cdacf8f..c7a7646 100644 --- a/src/parse/lex.rs +++ b/src/parse/lex.rs @@ -317,17 +317,16 @@ impl LexStream { let slice = self.slice_from_cursor().unwrap().to_string(); let mut pos = self.cursor; let mut chars = slice.chars().peekable(); - let mut can_be_subshell = chars.peek() == Some(&'('); + let can_be_subshell = chars.peek() == Some(&'('); - if self.flags.contains(LexFlags::IN_CASE) { - if let Some(count) = case_pat_lookahead(chars.clone()) { + if self.flags.contains(LexFlags::IN_CASE) + && let Some(count) = case_pat_lookahead(chars.clone()) { pos += count; let casepat_tk = self.get_token(self.cursor..pos, TkRule::CasePattern); self.cursor = pos; self.set_next_is_cmd(true); return Ok(casepat_tk); } - } while let Some(ch) = chars.next() { match ch { diff --git a/src/prompt/mod.rs b/src/prompt/mod.rs index 82eb5e2..be58813 100644 --- a/src/prompt/mod.rs +++ b/src/prompt/mod.rs @@ -1,13 +1,11 @@ pub mod highlight; pub mod readline; -use std::path::Path; use readline::{FernVi, Readline}; use crate::{ expand::expand_prompt, libsh::error::ShResult, prelude::*, shopt::FernEditMode, - state::read_shopts, }; /// Initialize the line editor @@ -32,7 +30,7 @@ pub fn readline(edit_mode: FernEditMode, initial: Option<&str>) -> ShResult { let mut fern_vi = FernVi::new(Some(prompt))?; if let Some(input) = initial { - fern_vi = fern_vi.with_initial(&input) + fern_vi = fern_vi.with_initial(input) } Box::new(fern_vi) as Box } diff --git a/src/prompt/readline/linebuf.rs b/src/prompt/readline/linebuf.rs index 658f14b..ac4a273 100644 --- a/src/prompt/readline/linebuf.rs +++ b/src/prompt/readline/linebuf.rs @@ -953,11 +953,10 @@ impl LineBuf { } let start = start.unwrap_or(0); - if count > 1 { - if let Some((_, new_end)) = self.text_obj_sentence(end, count - 1, bound) { + if count > 1 + && let Some((_, new_end)) = self.text_obj_sentence(end, count - 1, bound) { end = new_end; } - } Some((start, end)) } @@ -2590,8 +2589,8 @@ impl LineBuf { self.cursor.add(content.len().saturating_sub(1)); } Verb::SwapVisualAnchor => { - if let Some((start, end)) = self.select_range() { - if let Some(mut mode) = self.select_mode { + if let Some((start, end)) = self.select_range() + && let Some(mut mode) = self.select_mode { mode.invert_anchor(); let new_cursor_pos = match mode.anchor() { SelectAnchor::Start => start, @@ -2600,7 +2599,6 @@ impl LineBuf { self.cursor.set(new_cursor_pos); self.select_mode = Some(mode) } - } } Verb::JoinLines => { let start = self.start_of_line(); @@ -2748,11 +2746,10 @@ impl LineBuf { let edit_is_merging = self.undo_stack.last().is_some_and(|edit| edit.merging); // Merge character inserts into one edit - if edit_is_merging && cmd.verb.as_ref().is_none_or(|v| !v.1.is_char_insert()) { - if let Some(edit) = self.undo_stack.last_mut() { + if edit_is_merging && cmd.verb.as_ref().is_none_or(|v| !v.1.is_char_insert()) + && let Some(edit) = self.undo_stack.last_mut() { edit.stop_merge(); } - } let ViCmd { register, @@ -2839,11 +2836,10 @@ impl LineBuf { self.saved_col = None; } - if is_char_insert { - if let Some(edit) = self.undo_stack.last_mut() { + if is_char_insert + && let Some(edit) = self.undo_stack.last_mut() { edit.start_merge(); } - } Ok(()) } diff --git a/src/prompt/readline/mod.rs b/src/prompt/readline/mod.rs index 4bd1d56..da6f30b 100644 --- a/src/prompt/readline/mod.rs +++ b/src/prompt/readline/mod.rs @@ -1,4 +1,4 @@ -use history::{History, SearchConstraint, SearchKind}; +use history::History; use keys::{KeyCode, KeyEvent, ModKeys}; use linebuf::{LineBuf, SelectAnchor, SelectMode}; use nix::libc::STDOUT_FILENO; diff --git a/src/prompt/readline/term.rs b/src/prompt/readline/term.rs index 7de5648..b1d5909 100644 --- a/src/prompt/readline/term.rs +++ b/src/prompt/readline/term.rs @@ -2,9 +2,7 @@ use std::{ env, fmt::{Debug, Write}, io::{BufRead, BufReader, Read}, - iter::Peekable, os::fd::{AsFd, BorrowedFd, RawFd}, - str::Chars, }; use nix::{ diff --git a/src/prompt/readline/vicmd.rs b/src/prompt/readline/vicmd.rs index bed70d1..7f22612 100644 --- a/src/prompt/readline/vicmd.rs +++ b/src/prompt/readline/vicmd.rs @@ -161,15 +161,14 @@ impl ViCmd { } /// If a ViCmd has a linewise motion, but no verb, we change it to charwise pub fn alter_line_motion_if_no_verb(&mut self) { - if self.is_line_motion() && self.verb.is_none() { - if let Some(motion) = self.motion.as_mut() { + if self.is_line_motion() && self.verb.is_none() + && let Some(motion) = self.motion.as_mut() { match motion.1 { Motion::LineUp => motion.1 = Motion::LineUpCharwise, Motion::LineDown => motion.1 = Motion::LineDownCharwise, _ => unreachable!(), } } - } } pub fn is_mode_transition(&self) -> bool { self.verb.as_ref().is_some_and(|v| { diff --git a/src/prompt/readline/vimode.rs b/src/prompt/readline/vimode.rs index 19e60a4..976fdae 100644 --- a/src/prompt/readline/vimode.rs +++ b/src/prompt/readline/vimode.rs @@ -5,7 +5,6 @@ use nix::NixPath; use unicode_segmentation::UnicodeSegmentation; use super::keys::{KeyCode as K, KeyEvent as E, ModKeys as M}; -use super::linebuf::CharClass; use super::vicmd::{ Anchor, Bound, CmdFlags, Dest, Direction, Motion, MotionCmd, RegisterName, TextObj, To, Verb, VerbCmd, ViCmd, Word, diff --git a/src/signal.rs b/src/signal.rs index 5853457..31e9ef6 100644 --- a/src/signal.rs +++ b/src/signal.rs @@ -4,7 +4,7 @@ use nix::sys::signal::{SaFlags, SigAction, sigaction}; use crate::{ jobs::{JobCmdFlags, JobID, take_term}, - libsh::{error::{ShErr, ShErrKind, ShResult}, sys::sh_quit}, + libsh::error::{ShErr, ShErrKind, ShResult}, prelude::*, state::{read_jobs, write_jobs}, }; @@ -249,8 +249,8 @@ pub fn child_exited(pid: Pid, status: WtStat) -> ShResult<()> { } else { None } - }) { - if is_finished { + }) + && is_finished { if is_fg { take_term()?; } else { @@ -262,6 +262,5 @@ pub fn child_exited(pid: Pid, status: WtStat) -> ShResult<()> { } } } - } Ok(()) } diff --git a/src/state.rs b/src/state.rs index 99b8c6e..e490412 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap, VecDeque}, fmt::Display, ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Deref}, str::FromStr, sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard}, time::Duration + cell::RefCell, collections::{HashMap, VecDeque}, fmt::Display, ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Deref}, str::FromStr, time::Duration }; use nix::unistd::{gethostname, getppid, User}; @@ -17,53 +17,23 @@ use crate::{ }; pub struct Fern { - pub jobs: JobTab, - pub var_scopes: ScopeStack, - pub meta: MetaTab, - pub logic: LogTab, - pub shopts: ShOpts, + pub jobs: RefCell, + pub var_scopes: RefCell, + pub meta: RefCell, + pub logic: RefCell, + pub shopts: RefCell, } impl Fern { pub fn new() -> Self { Self { - jobs: JobTab::new(), - var_scopes: ScopeStack::new(), - meta: MetaTab::new(), - logic: LogTab::new(), - shopts: ShOpts::default(), + jobs: RefCell::new(JobTab::new()), + var_scopes: RefCell::new(ScopeStack::new()), + meta: RefCell::new(MetaTab::new()), + logic: RefCell::new(LogTab::new()), + shopts: RefCell::new(ShOpts::default()), } } - pub fn write_jobs(&mut self) -> &mut JobTab { - &mut self.jobs - } - pub fn write_vars(&mut self) -> &mut ScopeStack { - &mut self.var_scopes - } - pub fn write_meta(&mut self) -> &mut MetaTab { - &mut self.meta - } - pub fn write_logic(&mut self) -> &mut LogTab { - &mut self.logic - } - pub fn write_shopts(&mut self) -> &mut ShOpts { - &mut self.shopts - } - pub fn read_jobs(&self) -> &JobTab { - &self.jobs - } - pub fn read_vars(&self) -> &ScopeStack { - &self.var_scopes - } - pub fn read_meta(&self) -> &MetaTab { - &self.meta - } - pub fn read_logic(&self) -> &LogTab { - &self.logic - } - pub fn read_shopts(&self) -> &ShOpts { - &self.shopts - } } impl Default for Fern { @@ -257,7 +227,9 @@ impl ScopeStack { } } -pub static FERN: LazyLock> = LazyLock::new(|| RwLock::new(Fern::new())); +thread_local! { + pub static FERN: Fern = Fern::new(); +} /// A shell function /// @@ -721,69 +693,49 @@ impl MetaTab { /// Read from the job table pub fn read_jobs T>(f: F) -> T { - let fern = FERN.read().unwrap(); - let jobs = fern.read_jobs(); - f(jobs) + FERN.with(|fern| f(&fern.jobs.borrow())) } /// Write to the job table pub fn write_jobs T>(f: F) -> T { - let mut fern = FERN.write().unwrap(); - let jobs = &mut fern.jobs; - f(jobs) + FERN.with(|fern| f(&mut fern.jobs.borrow_mut())) } /// Read from the var scope stack pub fn read_vars T>(f: F) -> T { - let fern = FERN.read().unwrap(); - let vars = fern.read_vars(); - f(vars) + FERN.with(|fern| f(&fern.var_scopes.borrow())) } /// Write to the variable table pub fn write_vars T>(f: F) -> T { - let mut fern = FERN.write().unwrap(); - let vars = fern.write_vars(); - f(vars) + FERN.with(|fern| f(&mut fern.var_scopes.borrow_mut())) } pub fn read_meta T>(f: F) -> T { - let fern = FERN.read().unwrap(); - let meta = fern.read_meta(); - f(meta) + FERN.with(|fern| f(&fern.meta.borrow())) } -/// Write to the variable table +/// Write to the meta table pub fn write_meta T>(f: F) -> T { - let mut fern = FERN.write().unwrap(); - let meta = fern.write_meta(); - f(meta) + FERN.with(|fern| f(&mut fern.meta.borrow_mut())) } /// Read from the logic table pub fn read_logic T>(f: F) -> T { - let fern = FERN.read().unwrap(); - let logic = fern.read_logic(); - f(logic) + FERN.with(|fern| f(&fern.logic.borrow())) } /// Write to the logic table pub fn write_logic T>(f: F) -> T { - let mut fern = FERN.write().unwrap(); - let logic = &mut fern.logic; - f(logic) + FERN.with(|fern| f(&mut fern.logic.borrow_mut())) } pub fn read_shopts T>(f: F) -> T { - let fern = FERN.read().unwrap(); - let shopts = fern.read_shopts(); - f(shopts) + FERN.with(|fern| f(&fern.shopts.borrow())) } pub fn write_shopts T>(f: F) -> T { - let mut fern = FERN.write().unwrap(); - let shopts = &mut fern.shopts; - f(shopts) + FERN.with(|fern| f(&mut fern.shopts.borrow_mut())) } pub fn descend_scope(argv: Option>) {