diff --git a/src/builtin/help.rs b/src/builtin/help.rs index 4789fac..17c0c41 100644 --- a/src/builtin/help.rs +++ b/src/builtin/help.rs @@ -121,11 +121,7 @@ pub fn help(node: Node) -> ShResult<()> { } pub fn open_help(content: &str, line: Option, file_name: Option) -> ShResult<()> { - let pager = env::var("SHED_HPAGER") - .unwrap_or( - env::var("PAGER") - .unwrap_or("less -R".into()), - ); + let pager = env::var("SHED_HPAGER").unwrap_or(env::var("PAGER").unwrap_or("less -R".into())); let line_arg = line.map(|ln| format!("+{ln}")).unwrap_or_default(); let prompt_arg = file_name .map(|name| format!("-Ps'{name}'")) diff --git a/src/jobs.rs b/src/jobs.rs index 743eea8..d4f18d0 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -873,12 +873,12 @@ pub fn wait_fg(job: Job, interactive: bool) -> ShResult<()> { write_jobs(|j| j.fg_to_bg(*status))?; } WtStat::Signaled(_, sig, _) => { - if *sig == Signal::SIGINT { - // interrupt propagates to the shell - // necessary for interrupting stuff like - // while/for loops - kill(getpid(), Signal::SIGINT)?; - } else if *sig == Signal::SIGTSTP { + if *sig == Signal::SIGINT { + // interrupt propagates to the shell + // necessary for interrupting stuff like + // while/for loops + kill(getpid(), Signal::SIGINT)?; + } else if *sig == Signal::SIGTSTP { was_stopped = true; write_jobs(|j| j.fg_to_bg(*status))?; } diff --git a/src/main.rs b/src/main.rs index cc0e362..39f32d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,7 +38,9 @@ use crate::prelude::*; use crate::procio::borrow_fd; use crate::readline::term::{LineWriter, RawModeGuard, raw_mode}; use crate::readline::{Prompt, ReadlineEvent, ShedVi}; -use crate::signal::{GOT_SIGUSR1, GOT_SIGWINCH, JOB_DONE, QUIT_CODE, check_signals, sig_setup, signals_pending}; +use crate::signal::{ + GOT_SIGUSR1, GOT_SIGWINCH, JOB_DONE, QUIT_CODE, check_signals, sig_setup, signals_pending, +}; use crate::state::{ AutoCmdKind, read_logic, read_shopts, source_env, source_login, source_rc, write_jobs, write_meta, write_shopts, @@ -285,16 +287,16 @@ fn shed_interactive(args: ShedArgs) -> ShResult<()> { readline.prompt_mut().refresh(); } - if GOT_SIGUSR1.swap(false, Ordering::SeqCst) { - log::info!("SIGUSR1 received: refreshing readline state"); - readline.mark_dirty(); - readline.prompt_mut().refresh(); - } + if GOT_SIGUSR1.swap(false, Ordering::SeqCst) { + log::info!("SIGUSR1 received: refreshing readline state"); + readline.mark_dirty(); + readline.prompt_mut().refresh(); + } readline.print_line(false)?; // Poll for - // stdin input + // stdin input let mut fds = [PollFd::new( unsafe { BorrowedFd::borrow_raw(*TTY_FILENO) }, PollFlags::POLLIN, @@ -442,10 +444,10 @@ fn handle_readline_event(readline: &mut ShedVi, event: ShResult) }) { // CleanExit signals an intentional shell exit; any other error is printed. match e.kind() { - ShErrKind::Interrupt => { - // We got Ctrl+C during command execution - // Just fall through here - } + ShErrKind::Interrupt => { + // We got Ctrl+C during command execution + // Just fall through here + } ShErrKind::CleanExit(code) => { QUIT_CODE.store(*code, Ordering::SeqCst); return Ok(true); diff --git a/src/parse/execute.rs b/src/parse/execute.rs index de4a1a3..40b458f 100644 --- a/src/parse/execute.rs +++ b/src/parse/execute.rs @@ -32,13 +32,20 @@ use crate::{ test::double_bracket_test, trap::{TrapTarget, trap}, varcmds::{export, local, readonly, unset}, - }, expand::{expand_aliases, expand_case_pattern, glob_to_regex}, jobs::{ChildProc, JobStack, attach_tty, dispatch_job}, libsh::{ + }, + expand::{expand_aliases, expand_case_pattern, glob_to_regex}, + jobs::{ChildProc, JobStack, attach_tty, dispatch_job}, + libsh::{ error::{ShErr, ShErrKind, ShResult, ShResultExt, next_color}, guards::{scope_guard, var_ctx_guard}, utils::RedirVecUtils, - }, prelude::*, procio::{IoMode, IoStack, PipeGenerator}, signal::{check_signals, signals_pending}, state::{ + }, + prelude::*, + procio::{IoMode, IoStack, PipeGenerator}, + signal::{check_signals, signals_pending}, + state::{ self, ShFunc, VarFlags, VarKind, read_logic, read_shopts, write_jobs, write_logic, write_vars, - } + }, }; use super::{ @@ -268,10 +275,10 @@ impl Dispatcher { } pub fn dispatch_node(&mut self, node: Node) -> ShResult<()> { while signals_pending() { - // If we have received SIGINT, - // this will stop the execution here - // and propagate back to the functions in main.rs - check_signals()?; + // If we have received SIGINT, + // this will stop the execution here + // and propagate back to the functions in main.rs + check_signals()?; } match node.class { diff --git a/src/readline/linebuf.rs b/src/readline/linebuf.rs index 92f962b..62b738c 100644 --- a/src/readline/linebuf.rs +++ b/src/readline/linebuf.rs @@ -12,15 +12,23 @@ use super::vicmd::{ ViCmd, Word, }; use crate::{ - expand::expand_cmd_sub, libsh::{error::ShResult, guards::var_ctx_guard}, parse::{ - Redir, RedirType, execute::exec_input, lex::{LexFlags, LexStream, QuoteState, Tk, TkFlags, TkRule} - }, prelude::*, procio::{IoFrame, IoMode, IoStack}, readline::{ + expand::expand_cmd_sub, + libsh::{error::ShResult, guards::var_ctx_guard}, + parse::{ + Redir, RedirType, + execute::exec_input, + lex::{LexFlags, LexStream, QuoteState, Tk, TkFlags, TkRule}, + }, + prelude::*, + procio::{IoFrame, IoMode, IoStack}, + readline::{ history::History, markers, register::{RegisterContent, write_register}, - term::RawModeGuard, + term::{RawModeGuard, get_win_size}, vicmd::{ReadSrc, WriteDest}, - }, state::{VarFlags, VarKind, read_shopts, write_meta, write_vars} + }, + state::{VarFlags, VarKind, read_shopts, write_meta, write_vars}, }; const PUNCTUATION: [&str; 3] = ["?", "!", "."]; @@ -1012,12 +1020,31 @@ impl LineBuf { if self.end_of_line() == self.cursor.max { return None; } - let target_line = self.cursor_line_number() + n; + let target_line = self.cursor_line_number() + n - 1; let start = self.start_of_line(); let (_, end) = self.line_bounds(target_line); Some((start, end)) } + pub fn lines_in_range(&mut self, range: Range) -> Vec<(usize, usize)> { + let mut ranges = vec![]; + + let mut first_line = self.pos_line_number(range.start); + let mut last_line = self.pos_line_number(range.end); + + (first_line, last_line) = ordered(first_line, last_line); + + if first_line == last_line { + return vec![self.line_bounds(first_line)]; + } + + for line_no in first_line..last_line { + let (s, e) = self.line_bounds(line_no); + ranges.push((s, e)); + } + + ranges + } pub fn line_bounds(&self, n: usize) -> (usize, usize) { if n > self.total_lines() { panic!( @@ -2129,12 +2156,16 @@ impl LineBuf { self.buffer.replace_range(start..end, new); } pub fn calc_indent_level(&mut self) -> usize { - let to_cursor = self - .slice_to_cursor() + self.calc_indent_level_for_pos(self.cursor.get()) + } + + pub fn calc_indent_level_for_pos(&mut self, pos: usize) -> usize { + let slice = self + .slice_to(pos) .map(|s| s.to_string()) .unwrap_or(self.buffer.clone()); - self.indent_ctx.calculate(&to_cursor) + self.indent_ctx.calculate(&slice) } pub fn eval_motion(&mut self, verb: Option<&Verb>, motion: MotionCmd) -> MotionKind { let buffer = self.buffer.clone(); @@ -2338,7 +2369,7 @@ impl LineBuf { let pos = if count == 1 { self.end_of_line_exclusive() } else if let Some((_, end)) = self.select_lines_down(count) { - end + end.saturating_sub(1) } else { self.end_of_line_exclusive() }; @@ -2455,14 +2486,6 @@ impl LineBuf { MotionKind::On(target_pos) } - MotionCmd(_count, Motion::ScreenLineUp) => todo!(), - MotionCmd(_count, Motion::ScreenLineUpCharwise) => todo!(), - MotionCmd(_count, Motion::ScreenLineDown) => todo!(), - MotionCmd(_count, Motion::ScreenLineDownCharwise) => todo!(), - MotionCmd(_count, Motion::BeginningOfScreenLine) => todo!(), - MotionCmd(_count, Motion::FirstGraphicalOnScreenLine) => todo!(), - MotionCmd(_count, Motion::HalfOfScreen) => todo!(), - MotionCmd(_count, Motion::HalfOfScreenLineText) => todo!(), MotionCmd(_count, Motion::WholeBuffer) => { MotionKind::Exclusive((0, self.grapheme_indices().len())) } @@ -2503,8 +2526,9 @@ impl LineBuf { final_end = final_end.min(self.cursor.max); MotionKind::Exclusive((start, final_end)) } - MotionCmd(_count, Motion::RepeatMotion) => todo!(), - MotionCmd(_count, Motion::RepeatMotionRev) => todo!(), + MotionCmd(_count, Motion::RepeatMotion) | MotionCmd(_count, Motion::RepeatMotionRev) => { + unreachable!("already handled in readline/mod.rs") + } MotionCmd(_count, Motion::Null) | MotionCmd(_count, Motion::Global(_)) | MotionCmd(_count, Motion::NotGlobal(_)) => MotionKind::Null, @@ -3058,28 +3082,34 @@ impl LineBuf { } #[allow(clippy::unnecessary_to_owned)] fn verb_dedent(&mut self, motion: MotionKind) -> ShResult<()> { - let Some((start, mut end)) = self.range_from_motion(&motion) else { + let Some((start, end)) = self.range_from_motion(&motion) else { return Ok(()); }; + let end = end.min(self.grapheme_indices().len().saturating_sub(1)); + + // Collect tab positions to remove, then remove in reverse so indices stay valid + let mut to_remove = Vec::new(); if self.grapheme_at(start) == Some("\t") { - self.remove(start); + to_remove.push(start); } - end = end.min(self.grapheme_indices().len().saturating_sub(1)); - let mut range_indices = self.grapheme_indices()[start..end].to_vec().into_iter(); - while let Some(idx) = range_indices.next() { - let gr = self.grapheme_at(idx).unwrap(); - if gr == "\n" { - let Some(idx) = range_indices.next() else { - if self.grapheme_at(self.grapheme_indices().len().saturating_sub(1)) == Some("\t") { - self.remove(self.grapheme_indices().len().saturating_sub(1)); - } - break; - }; - if self.grapheme_at(idx) == Some("\t") { - self.remove(idx); + let range_indices = self.grapheme_indices()[start..end].to_vec(); + let mut i = 0; + while i < range_indices.len() { + let idx = range_indices[i]; + if self.grapheme_at(idx) == Some("\n") && i + 1 < range_indices.len() { + let next_idx = range_indices[i + 1]; + if self.grapheme_at(next_idx) == Some("\t") { + to_remove.push(next_idx); + i += 1; } } + i += 1; } + + for idx in to_remove.into_iter().rev() { + self.remove(idx); + } + match motion { MotionKind::ExclusiveWithTargetCol((_, _), pos) | MotionKind::InclusiveWithTargetCol((_, _), pos) => { @@ -3091,6 +3121,29 @@ impl LineBuf { } Ok(()) } + fn verb_equalize(&mut self, motion: MotionKind) -> ShResult<()> { + let Some((s, e)) = self.range_from_motion(&motion) else { + return Ok(()); + }; + let lines = self.lines_in_range(s..e); + let target_col = self.cursor_col(); + + // reverse the list of line spans so that the spans stay valid + for (s, _) in lines.into_iter().rev() { + let indent_level = self.calc_indent_level_for_pos(s); + while self.grapheme_at(s).is_some_and(|c| c == "\t") { + self.remove(s) + } + for _ in 0..indent_level { + self.insert_at(s, '\t'); + } + } + + self.cursor.set(s); + self.cursor.add(target_col); + + Ok(()) + } fn verb_insert_mode_line_break(&mut self, anchor: Anchor) -> ShResult<()> { let (mut start, end) = self.this_line_exclusive(); let auto_indent = read_shopts(|o| o.prompt.auto_indent); @@ -3296,7 +3349,7 @@ impl LineBuf { Verb::ToLower => self.verb_case_transform(motion, CaseTransform::Lower)?, Verb::ToUpper => self.verb_case_transform(motion, CaseTransform::Upper)?, Verb::Redo | Verb::Undo => self.verb_undo_redo(verb)?, - Verb::RepeatLast => todo!(), + Verb::RepeatLast => unreachable!("already handled in readline.rs"), Verb::Put(anchor) => self.verb_put(anchor, register)?, Verb::SwapVisualAnchor => self.verb_swap_visual_anchor(), Verb::JoinLines => self.verb_join_lines()?, @@ -3304,7 +3357,7 @@ impl LineBuf { Verb::Insert(string) => self.verb_insert(string), Verb::Indent => self.verb_indent(motion)?, Verb::Dedent => self.verb_dedent(motion)?, - Verb::Equalize => todo!(), + Verb::Equalize => self.verb_equalize(motion)?, Verb::InsertModeLineBreak(anchor) => self.verb_insert_mode_line_break(anchor)?, Verb::AcceptLineOrNewline => self.verb_accept_line_or_newline()?, Verb::IncrementNumber(n) => self.verb_adjust_number(n as i64)?, @@ -3352,54 +3405,51 @@ impl LineBuf { self.cursor.add(grapheme_count); } }, - Verb::Write(dest) => { - match dest { - WriteDest::FileAppend(ref path_buf) | - WriteDest::File(ref path_buf) => { - let Ok(mut file) = (if matches!(dest, WriteDest::File(_)) { - OpenOptions::new() - .create(true) - .truncate(true) - .write(true) - .open(path_buf) - } else { - OpenOptions::new() - .create(true) - .append(true) - .open(path_buf) - }) else { - write_meta(|m| { - m.post_system_message(format!("Failed to open file {}", path_buf.display())) - }); - return Ok(()); - }; - if let Err(e) = file.write_all(self.as_str().as_bytes()) { - write_meta(|m| { - m.post_system_message(format!("Failed to write to file {}: {e}", path_buf.display())) - }); - } - return Ok(()); - } - WriteDest::Cmd(cmd) => { - let buf = self.as_str().to_string(); - let io_mode = IoMode::Buffer { - tgt_fd: STDIN_FILENO, - buf, - flags: TkFlags::IS_HEREDOC | TkFlags::LIT_HEREDOC, - }; - let redir = Redir::new(io_mode, RedirType::Input); - let mut frame = IoFrame::new(); - frame.push(redir); - let mut stack = IoStack::new(); - stack.push_frame(frame); - exec_input(cmd, Some(stack), false, Some("ex write".into()))?; - } - } - } + Verb::Write(dest) => match dest { + WriteDest::FileAppend(ref path_buf) | WriteDest::File(ref path_buf) => { + let Ok(mut file) = (if matches!(dest, WriteDest::File(_)) { + OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(path_buf) + } else { + OpenOptions::new().create(true).append(true).open(path_buf) + }) else { + write_meta(|m| { + m.post_system_message(format!("Failed to open file {}", path_buf.display())) + }); + return Ok(()); + }; + if let Err(e) = file.write_all(self.as_str().as_bytes()) { + write_meta(|m| { + m.post_system_message(format!( + "Failed to write to file {}: {e}", + path_buf.display() + )) + }); + } + return Ok(()); + } + WriteDest::Cmd(cmd) => { + let buf = self.as_str().to_string(); + let io_mode = IoMode::Buffer { + tgt_fd: STDIN_FILENO, + buf, + flags: TkFlags::IS_HEREDOC | TkFlags::LIT_HEREDOC, + }; + let redir = Redir::new(io_mode, RedirType::Input); + let mut frame = IoFrame::new(); + frame.push(redir); + let mut stack = IoStack::new(); + stack.push_frame(frame); + exec_input(cmd, Some(stack), false, Some("ex write".into()))?; + } + }, Verb::Edit(path) => { - let input = format!("$EDITOR {}",path.display()); - exec_input(input, None, true, Some("ex edit".into()))?; - } + let input = format!("$EDITOR {}", path.display()); + exec_input(input, None, true, Some("ex edit".into()))?; + } Verb::Normal(_) | Verb::Substitute(..) | Verb::RepeatSubstitute | Verb::RepeatGlobal => {} } Ok(()) diff --git a/src/readline/mod.rs b/src/readline/mod.rs index a8030ae..d07a8f5 100644 --- a/src/readline/mod.rs +++ b/src/readline/mod.rs @@ -346,17 +346,17 @@ impl ShedVi { self } - /// A mutable reference to the currently focused editor - /// This includes the main LineBuf, and sub-editors for modes like Ex mode. - pub fn focused_editor(&mut self) -> &mut LineBuf { - self.mode.editor().unwrap_or(&mut self.editor) - } + /// A mutable reference to the currently focused editor + /// This includes the main LineBuf, and sub-editors for modes like Ex mode. + pub fn focused_editor(&mut self) -> &mut LineBuf { + self.mode.editor().unwrap_or(&mut self.editor) + } - /// A mutable reference to the currently focused history, if any. - /// This includes the main history struct, and history for sub-editors like Ex mode. - pub fn focused_history(&mut self) -> &mut History { - self.mode.history().unwrap_or(&mut self.history) - } + /// A mutable reference to the currently focused history, if any. + /// This includes the main history struct, and history for sub-editors like Ex mode. + pub fn focused_history(&mut self) -> &mut History { + self.mode.history().unwrap_or(&mut self.history) + } /// Feed raw bytes from stdin into the reader's buffer pub fn feed_bytes(&mut self, bytes: &[u8]) { @@ -475,21 +475,21 @@ impl ShedVi { SelectorResponse::Accept(cmd) => { let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnHistorySelect)); - { - let editor = self.focused_editor(); - editor.set_buffer(cmd.to_string()); - editor.move_cursor_to_end(); - } + { + let editor = self.focused_editor(); + editor.set_buffer(cmd.to_string()); + editor.move_cursor_to_end(); + } self .history .update_pending_cmd((self.editor.as_str(), self.editor.cursor.get())); - self.editor.set_hint(None); - { - let mut writer = std::mem::take(&mut self.writer); - self.focused_history().fuzzy_finder.clear(&mut writer)?; - self.writer = writer; - } + self.editor.set_hint(None); + { + let mut writer = std::mem::take(&mut self.writer); + self.focused_history().fuzzy_finder.clear(&mut writer)?; + self.writer = writer; + } self.focused_history().fuzzy_finder.reset(); with_vars([("_HIST_ENTRY".into(), cmd.clone())], || { @@ -513,11 +513,11 @@ impl ShedVi { post_cmds.exec(); self.editor.set_hint(None); - { - let mut writer = std::mem::take(&mut self.writer); - self.focused_history().fuzzy_finder.clear(&mut writer)?; - self.writer = writer; - } + { + let mut writer = std::mem::take(&mut self.writer); + self.focused_history().fuzzy_finder.clear(&mut writer)?; + self.writer = writer; + } write_vars(|v| { v.set_var( "SHED_VI_MODE", @@ -674,8 +674,9 @@ impl ShedVi { } if let KeyEvent(KeyCode::Tab, mod_keys) = key { - if self.mode.report_mode() != ModeReport::Ex - && self.editor.attempt_history_expansion(&self.history) { + if self.mode.report_mode() != ModeReport::Ex + && self.editor.attempt_history_expansion(&self.history) + { // If history expansion occurred, don't attempt completion yet // allow the user to see the expanded command and accept or edit it before completing return Ok(None); @@ -887,14 +888,12 @@ impl ShedVi { let has_edit_verb = cmd.verb().is_some_and(|v| v.1.is_edit()); let is_shell_cmd = cmd.verb().is_some_and(|v| matches!(v.1, Verb::ShellCmd(_))); let is_ex_cmd = cmd.flags.contains(CmdFlags::IS_EX_CMD); - log::debug!("is_ex_cmd: {is_ex_cmd}"); if is_shell_cmd { self.old_layout = None; } if is_ex_cmd { self.ex_history.push(cmd.raw_seq.clone()); self.ex_history.reset(); - log::debug!("ex_history: {:?}", self.ex_history.entries()); } let before = self.editor.buffer.clone(); @@ -1032,11 +1031,11 @@ impl ShedVi { let one_line = new_layout.end.row == 0; self.completer.clear(&mut self.writer)?; - { - let mut writer = std::mem::take(&mut self.writer); - self.focused_history().fuzzy_finder.clear(&mut writer)?; - self.writer = writer; - } + { + let mut writer = std::mem::take(&mut self.writer); + self.focused_history().fuzzy_finder.clear(&mut writer)?; + self.writer = writer; + } if let Some(layout) = self.old_layout.as_ref() { self.writer.clear_rows(layout)?; @@ -1133,11 +1132,11 @@ impl ShedVi { .fuzzy_finder .set_prompt_line_context(preceding_width, new_layout.cursor.col); - { - let mut writer = std::mem::take(&mut self.writer); - self.focused_history().fuzzy_finder.draw(&mut writer)?; - self.writer = writer; - } + { + let mut writer = std::mem::take(&mut self.writer); + self.focused_history().fuzzy_finder.draw(&mut writer)?; + self.writer = writer; + } self.old_layout = Some(new_layout); self.needs_redraw = false; @@ -1416,11 +1415,7 @@ impl ShedVi { self.editor.exec_cmd(cmd.clone())?; - if self.mode.report_mode() == ModeReport::Visual - && cmd - .verb() - .is_some_and(|v| v.1.is_edit() || v.1 == Verb::Yank) - { + if self.mode.report_mode() == ModeReport::Visual && cmd.verb().is_some() { self.editor.stop_selecting(); let mut mode: Box = Box::new(ViNormal::new()); self.swap_mode(&mut mode); diff --git a/src/readline/vicmd.rs b/src/readline/vicmd.rs index 1c66f75..9de0af8 100644 --- a/src/readline/vicmd.rs +++ b/src/readline/vicmd.rs @@ -338,16 +338,8 @@ pub enum Motion { ForwardCharForced, LineUp, LineUpCharwise, - ScreenLineUp, - ScreenLineUpCharwise, LineDown, LineDownCharwise, - ScreenLineDown, - ScreenLineDownCharwise, - BeginningOfScreenLine, - FirstGraphicalOnScreenLine, - HalfOfScreen, - HalfOfScreenLineText, WholeBuffer, StartOfBuffer, EndOfBuffer, @@ -387,12 +379,8 @@ impl Motion { &self, Self::BeginningOfLine | Self::BeginningOfFirstWord - | Self::BeginningOfScreenLine - | Self::FirstGraphicalOnScreenLine | Self::LineDownCharwise | Self::LineUpCharwise - | Self::ScreenLineUpCharwise - | Self::ScreenLineDownCharwise | Self::ToColumn | Self::TextObj(TextObj::Sentence(_)) | Self::TextObj(TextObj::Paragraph(_)) @@ -401,20 +389,13 @@ impl Motion { | Self::ToBrace(_) | Self::ToBracket(_) | Self::ToParen(_) - | Self::ScreenLineDown - | Self::ScreenLineUp | Self::Range(_, _) ) } pub fn is_linewise(&self) -> bool { matches!( self, - Self::WholeLineInclusive - | Self::WholeLineExclusive - | Self::LineUp - | Self::LineDown - | Self::ScreenLineDown - | Self::ScreenLineUp + Self::WholeLineInclusive | Self::WholeLineExclusive | Self::LineUp | Self::LineDown ) } } diff --git a/src/readline/vimode/ex.rs b/src/readline/vimode/ex.rs index faf6c3f..472c392 100644 --- a/src/readline/vimode/ex.rs +++ b/src/readline/vimode/ex.rs @@ -154,13 +154,13 @@ impl ViMode for ViEx { None } - fn editor(&mut self) -> Option<&mut LineBuf> { - Some(&mut self.pending_cmd.buf) - } + fn editor(&mut self) -> Option<&mut LineBuf> { + Some(&mut self.pending_cmd.buf) + } - fn history(&mut self) -> Option<&mut History> { - Some(&mut self.pending_cmd.history) - } + fn history(&mut self) -> Option<&mut History> { + Some(&mut self.pending_cmd.history) + } fn cursor_style(&self) -> String { "\x1b[3 q".to_string() @@ -338,13 +338,13 @@ fn parse_read(chars: &mut Peekable>) -> Result, Option Result> { - log::debug!("Expanding path: {}", path); + log::debug!("Expanding path: {}", path); let expanded = Expander::from_raw(path, TkFlags::empty()) .map_err(|e| Some(format!("Error expanding path: {}", e)))? - .expand() + .expand() .map_err(|e| Some(format!("Error expanding path: {}", e)))? - .join(" "); - log::debug!("Expanded path: {}", expanded); + .join(" "); + log::debug!("Expanded path: {}", expanded); Ok(PathBuf::from(&expanded)) } diff --git a/src/readline/vimode/mod.rs b/src/readline/vimode/mod.rs index 13bf8eb..045059f 100644 --- a/src/readline/vimode/mod.rs +++ b/src/readline/vimode/mod.rs @@ -81,9 +81,15 @@ pub trait ViMode { fn as_replay(&self) -> Option; fn cursor_style(&self) -> String; fn pending_seq(&self) -> Option; - fn pending_cursor(&self) -> Option { None } - fn editor(&mut self) -> Option<&mut LineBuf> { None } - fn history(&mut self) -> Option<&mut History> { None } + fn pending_cursor(&self) -> Option { + None + } + fn editor(&mut self) -> Option<&mut LineBuf> { + None + } + fn history(&mut self) -> Option<&mut History> { + None + } fn move_cursor_on_undo(&self) -> bool; fn clamp_cursor(&self) -> bool; fn hist_scroll_start_pos(&self) -> Option; diff --git a/src/readline/vimode/normal.rs b/src/readline/vimode/normal.rs index 3b2b0d1..2e32c31 100644 --- a/src/readline/vimode/normal.rs +++ b/src/readline/vimode/normal.rs @@ -450,26 +450,10 @@ impl ViNormal { Motion::WordMotion(To::End, Word::Big, Direction::Backward), )); } - 'k' => { - chars = chars_clone; - break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineUp)); - } - 'j' => { - chars = chars_clone; - break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineDown)); - } '_' => { chars = chars_clone; break 'motion_parse Some(MotionCmd(count, Motion::EndOfLastWord)); } - '0' => { - chars = chars_clone; - break 'motion_parse Some(MotionCmd(count, Motion::BeginningOfScreenLine)); - } - '^' => { - chars = chars_clone; - break 'motion_parse Some(MotionCmd(count, Motion::FirstGraphicalOnScreenLine)); - } _ => return self.quit_parse(), } } diff --git a/src/readline/vimode/visual.rs b/src/readline/vimode/visual.rs index 3933346..8c7f782 100644 --- a/src/readline/vimode/visual.rs +++ b/src/readline/vimode/visual.rs @@ -376,16 +376,6 @@ impl ViVisual { Motion::WordMotion(To::End, Word::Big, Direction::Backward), )); } - 'k' => { - chars_clone.next(); - chars = chars_clone; - break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineUp)); - } - 'j' => { - chars_clone.next(); - chars = chars_clone; - break 'motion_parse Some(MotionCmd(count, Motion::ScreenLineDown)); - } _ => return self.quit_parse(), } } else { diff --git a/src/signal.rs b/src/signal.rs index 524d9d9..4060d66 100644 --- a/src/signal.rs +++ b/src/signal.rs @@ -3,7 +3,10 @@ use std::{ sync::atomic::{AtomicBool, AtomicI32, AtomicU64, Ordering}, }; -use nix::{sys::signal::{SaFlags, SigAction, sigaction}, unistd::getpid}; +use nix::{ + sys::signal::{SaFlags, SigAction, sigaction}, + unistd::getpid, +}; use crate::{ builtin::trap::TrapTarget, @@ -98,10 +101,10 @@ pub fn check_signals() -> ShResult<()> { GOT_SIGWINCH.store(true, Ordering::SeqCst); run_trap(Signal::SIGWINCH)?; } - if got_signal(Signal::SIGUSR1) { - GOT_SIGUSR1.store(true, Ordering::SeqCst); - run_trap(Signal::SIGUSR1)?; - } + if got_signal(Signal::SIGUSR1) { + GOT_SIGUSR1.store(true, Ordering::SeqCst); + run_trap(Signal::SIGUSR1)?; + } for sig in MISC_SIGNALS { if got_signal(sig) { @@ -333,13 +336,14 @@ pub fn child_exited(pid: Pid, status: WtStat) -> ShResult<()> { let job_complete_msg = job.display(&job_order, JobCmdFlags::PIDS).to_string(); let statuses = job.get_stats(); - for status in &statuses { - if let WtStat::Signaled(_, sig, _) = status - && *sig == Signal::SIGINT { - // Necessary to interrupt stuff like shell loops - kill(getpid(), Signal::SIGINT).ok(); - } - } + for status in &statuses { + if let WtStat::Signaled(_, sig, _) = status + && *sig == Signal::SIGINT + { + // Necessary to interrupt stuff like shell loops + kill(getpid(), Signal::SIGINT).ok(); + } + } if let Some(pipe_status) = Job::pipe_status(&statuses) { let pipe_status = pipe_status