From 4bfe1f263ac3dda60d1f91c737fc516689997dca Mon Sep 17 00:00:00 2001 From: qkzk Date: Wed, 10 Jan 2024 21:17:31 +0100 Subject: focus struct, following selected tab --- src/app/mod.rs | 1 + src/app/status.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/io/display.rs | 53 +++++++++++++++++++++++++++++++--------------- 3 files changed, 97 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/app/mod.rs b/src/app/mod.rs index e75913d..15a06f4 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -13,6 +13,7 @@ pub use header_footer::{ClickableLine, FlaggedFooter, FlaggedHeader, Footer, Hea pub use internal_settings::InternalSettings; pub use refresher::Refresher; pub use session::Session; +pub use status::Focus; pub use status::Status; pub use status::Window; pub use tab::Tab; diff --git a/src/app/status.rs b/src/app/status.rs index a636e02..5daae02 100644 --- a/src/app/status.rs +++ b/src/app/status.rs @@ -58,6 +58,34 @@ pub enum Window { Footer, } +#[derive(Default)] +pub enum Focus { + #[default] + LeftFile, + LeftMenu, + RightFile, + RightMenu, +} + +impl Focus { + pub fn is_left(&self) -> bool { + matches!(self, Self::LeftMenu | Self::LeftFile) + } + + pub fn is_file(&self) -> bool { + matches!(self, Self::LeftFile | Self::RightFile) + } + + pub fn switch(&self) -> Self { + match self { + Self::LeftFile => Self::RightFile, + Self::LeftMenu => Self::RightFile, + Self::RightFile => Self::LeftFile, + Self::RightMenu => Self::LeftFile, + } + } +} + /// Holds every mutable parameter of the application itself, except for /// the "display" information. /// It holds 2 tabs (left & right), even if only one can be displayed sometimes. @@ -81,6 +109,7 @@ pub struct Status { pub display_settings: Session, /// Interna settings pub internal_settings: InternalSettings, + pub focus: Focus, } impl Status { @@ -111,6 +140,7 @@ impl Status { Tab::new(&args, height, users_left)?, Tab::new(&args, height, users_right)?, ]; + let focus = Focus::default(); Ok(Self { tabs, index, @@ -118,6 +148,7 @@ impl Status { menu, display_settings, internal_settings, + focus, }) } @@ -141,17 +172,40 @@ impl Status { self.internal_settings.must_quit } + pub fn switch_focus(&mut self) { + if (self.index == 0 && !self.focus.is_left()) || (self.index == 1 && self.focus.is_left()) { + self.focus = self.focus.switch(); + } + } + + pub fn set_focus(&mut self) { + if self.index == 0 { + if matches!(self.tabs[self.index].edit_mode, Edit::Nothing) { + self.focus = Focus::LeftFile; + } else { + self.focus = Focus::LeftMenu; + } + } else { + if matches!(self.tabs[self.index].edit_mode, Edit::Nothing) { + self.focus = Focus::RightFile; + } else { + self.focus = Focus::RightMenu; + } + } + } + /// Select the other tab if two are displayed. Does nother otherwise. pub fn next(&mut self) { if !self.display_settings.dual() { return; } - self.index = 1 - self.index + self.index = 1 - self.index; + self.switch_focus(); } /// Select the other tab if two are displayed. Does nother otherwise. pub fn prev(&mut self) { - self.next() + self.next(); } /// Select the left or right tab depending on where the user clicked. @@ -243,11 +297,13 @@ impl Status { /// Select the left tab pub fn select_left(&mut self) { self.index = 0; + self.switch_focus(); } /// Select the right tab pub fn select_right(&mut self) { self.index = 1; + self.switch_focus(); } /// Refresh every disk information. @@ -392,6 +448,7 @@ impl Status { let len = self.menu.len(edit_mode); let height = self.second_window_height()?; self.menu.window = ContentWindow::new(len, height); + self.set_focus(); self.refresh_status() } @@ -1010,7 +1067,7 @@ impl Status { /// Execute an action when the header line was clicked. pub fn header_action(&mut self, col: u16, binds: &Bindings) -> Result<()> { - let is_right = self.index == 1; + let is_right = !self.focus.is_left(); match self.current_tab().display_mode { Display::Preview => Ok(()), Display::Flagged => FlaggedHeader::new(self)? diff --git a/src/io/display.rs b/src/io/display.rs index d0a3a7b..a2c66f0 100644 --- a/src/io/display.rs +++ b/src/io/display.rs @@ -7,11 +7,11 @@ use tuikit::attr::{Attr, Color}; use tuikit::prelude::*; use tuikit::term::Term; -use crate::app::Footer; use crate::app::Header; use crate::app::Status; use crate::app::Tab; use crate::app::{ClickableLine, FlaggedFooter, FlaggedHeader}; +use crate::app::{Focus, Footer}; use crate::common::path_to_string; use crate::common::{ ENCRYPTED_DEVICE_BINDS, HELP_FIRST_SENTENCE, HELP_SECOND_SENTENCE, LOG_FIRST_SENTENCE, @@ -122,7 +122,6 @@ struct WinMain<'a> { impl<'a> Draw for WinMain<'a> { fn draw(&self, canvas: &mut dyn Canvas) -> DrawResult<()> { - // canvas.clear()?; if self.status.display_settings.dual() && self.is_right() && self.status.display_settings.preview() @@ -765,7 +764,6 @@ struct WinSecondary<'a> { impl<'a> Draw for WinSecondary<'a> { fn draw(&self, canvas: &mut dyn Canvas) -> DrawResult<()> { - // canvas.clear()?; match self.tab.edit_mode { Edit::Navigate(mode) => self.draw_navigate(mode, canvas), Edit::NeedConfirmation(mode) => self.draw_confirm(mode, canvas), @@ -1278,7 +1276,8 @@ impl Display { &self, win_main: &'a WinMain, win_secondary: &'a WinSecondary, - border: Attr, + file_border: Attr, + menu_border: Attr, size: usize, ) -> Result> { Ok(VSplit::default() @@ -1287,34 +1286,51 @@ impl Display { .basis(self.height()? - size) .shrink(4) .border(true) - .border_attr(border), + .border_attr(file_border), ) .split( Win::new(win_secondary) .basis(size) .shrink(0) .border(true) - .border_attr(border), + .border_attr(menu_border), )) } - fn borders(&self, status: &Status) -> (Attr, Attr) { - if status.index == 0 { - ( + /// Left File, Left Menu, Right File, Right Menu + fn borders(&self, status: &Status) -> [Attr; 4] { + match status.focus { + Focus::LeftFile => [ color_to_attr(MENU_COLORS.selected_border), color_to_attr(MENU_COLORS.inert_border), - ) - } else { - ( + color_to_attr(MENU_COLORS.inert_border), + color_to_attr(MENU_COLORS.inert_border), + ], + Focus::LeftMenu => [ color_to_attr(MENU_COLORS.inert_border), color_to_attr(MENU_COLORS.selected_border), - ) + color_to_attr(MENU_COLORS.inert_border), + color_to_attr(MENU_COLORS.inert_border), + ], + Focus::RightFile => [ + color_to_attr(MENU_COLORS.inert_border), + color_to_attr(MENU_COLORS.inert_border), + color_to_attr(MENU_COLORS.selected_border), + color_to_attr(MENU_COLORS.inert_border), + ], + Focus::RightMenu => [ + color_to_attr(MENU_COLORS.inert_border), + color_to_attr(MENU_COLORS.inert_border), + color_to_attr(MENU_COLORS.inert_border), + color_to_attr(MENU_COLORS.selected_border), + ], } } fn draw_dual_pane(&mut self, status: &Status) -> Result<()> { let (width, _) = self.term.term_size()?; - let (first_selected, second_selected) = (status.index == 0, status.index == 1); + let first_selected = status.focus.is_left(); + let second_selected = !first_selected; let attributes_left = WinMainAttributes::new( 0, TabPosition::Left, @@ -1331,20 +1347,22 @@ impl Display { let win_main_right = WinMain::new(status, 1, attributes_right); let win_second_left = WinSecondary::new(status, 0); let win_second_right = WinSecondary::new(status, 1); - let (border_left, border_right) = self.borders(status); + let borders = self.borders(status); let percent_left = self.size_for_second_window(&status.tabs[0])?; let percent_right = self.size_for_second_window(&status.tabs[1])?; let hsplit = HSplit::default() .split(self.vertical_split( &win_main_left, &win_second_left, - border_left, + borders[0], + borders[1], percent_left, )?) .split(self.vertical_split( &win_main_right, &win_second_right, - border_right, + borders[2], + borders[3], percent_right, )?); Ok(self.term.draw(&hsplit)?) @@ -1364,6 +1382,7 @@ impl Display { &win_main_left, &win_second_left, color_to_attr(MENU_COLORS.selected_border), + color_to_attr(MENU_COLORS.selected_border), percent_left, )?; Ok(self.term.draw(&win)?) -- cgit v1.2.3 From 526269f0a21ef40dfe9018fbed1b16920e13ba13 Mon Sep 17 00:00:00 2001 From: qkzk Date: Wed, 10 Jan 2024 21:47:44 +0100 Subject: removed mocp --- src/config/keybindings.rs | 19 +++---- src/event/action_map.rs | 20 +++---- src/event/event_exec.rs | 97 ++++++++++++++++----------------- src/modes/edit/help.rs | 9 ---- src/modes/edit/mocp.rs | 134 ---------------------------------------------- src/modes/edit/mod.rs | 3 -- 6 files changed, 67 insertions(+), 215 deletions(-) delete mode 100644 src/modes/edit/mocp.rs (limited to 'src') diff --git a/src/config/keybindings.rs b/src/config/keybindings.rs index 6ed570d..e290f32 100644 --- a/src/config/keybindings.rs +++ b/src/config/keybindings.rs @@ -57,6 +57,7 @@ impl Bindings { (Key::Char('!'), ActionMap::ShellCommand), (Key::Char('@'), ActionMap::GoStart), (Key::Char(':'), ActionMap::Action), + (Key::Char('6'), ActionMap::History), (Key::Char('C'), ActionMap::Compress), (Key::Char('E'), ActionMap::ToggleDisplayFull), (Key::Char('G'), ActionMap::End), @@ -100,7 +101,7 @@ impl Bindings { (Key::Alt('e'), ActionMap::EncryptedDrive), (Key::Alt('f'), ActionMap::Filter), (Key::Alt('g'), ActionMap::Cd), - (Key::Alt('h'), ActionMap::History), + (Key::Alt('h'), ActionMap::Help), (Key::Alt('i'), ActionMap::CliMenu), (Key::Alt('j'), ActionMap::Jump), (Key::Alt('l'), ActionMap::Log), @@ -116,23 +117,23 @@ impl Bindings { (Key::Ctrl('d'), ActionMap::PageDown), (Key::Ctrl('f'), ActionMap::FuzzyFind), (Key::Ctrl('g'), ActionMap::Shortcut), - (Key::Ctrl('h'), ActionMap::Help), - (Key::Ctrl('k'), ActionMap::Delete), (Key::Ctrl('s'), ActionMap::FuzzyFindLine), (Key::Ctrl('u'), ActionMap::PageUp), (Key::Ctrl('o'), ActionMap::OpenAll), (Key::Ctrl('p'), ActionMap::CopyFilepath), (Key::Ctrl('q'), ActionMap::ResetMode), (Key::Ctrl('r'), ActionMap::RefreshView), - (Key::Ctrl('x'), ActionMap::MocpClearPlaylist), (Key::Ctrl('z'), ActionMap::TreeFoldAll), (Key::ShiftDown, ActionMap::NextSibling), (Key::ShiftUp, ActionMap::PreviousSibling), - (Key::AltEnter, ActionMap::MocpGoToSong), - (Key::CtrlUp, ActionMap::MocpAddToPlayList), - (Key::CtrlDown, ActionMap::MocpTogglePause), - (Key::CtrlRight, ActionMap::MocpNext), - (Key::CtrlLeft, ActionMap::MocpPrevious), + (Key::CtrlUp, ActionMap::FocusGoUp), + (Key::CtrlDown, ActionMap::FocusGoDown), + (Key::CtrlRight, ActionMap::FocusGoRight), + (Key::CtrlLeft, ActionMap::FocusGoLeft), + (Key::Ctrl('h'), ActionMap::FocusGoLeft), + (Key::Ctrl('j'), ActionMap::FocusGoDown), + (Key::Ctrl('k'), ActionMap::FocusGoUp), + (Key::Ctrl('l'), ActionMap::FocusGoRight), ]); let custom = None; Self { binds, custom } diff --git a/src/event/action_map.rs b/src/event/action_map.rs index a64f28d..da97e85 100644 --- a/src/event/action_map.rs +++ b/src/event/action_map.rs @@ -36,6 +36,10 @@ pub enum ActionMap { Exec, Filter, FlagAll, + FocusGoLeft, + FocusGoRight, + FocusGoDown, + FocusGoUp, FuzzyFind, FuzzyFindHelp, FuzzyFindLine, @@ -50,12 +54,6 @@ pub enum ActionMap { Log, MarksJump, MarksNew, - MocpAddToPlayList, - MocpClearPlaylist, - MocpGoToSong, - MocpNext, - MocpPrevious, - MocpTogglePause, MoveDown, MoveLeft, MoveRight, @@ -137,6 +135,10 @@ impl ActionMap { Self::Exec => EventAction::exec(status), Self::Filter => EventAction::filter(status), Self::FlagAll => EventAction::flag_all(status), + Self::FocusGoLeft => EventAction::focus_go_left(status), + Self::FocusGoRight => EventAction::focus_go_right(status), + Self::FocusGoDown => EventAction::focus_go_down(status), + Self::FocusGoUp => EventAction::focus_go_up(status), Self::FuzzyFind => EventAction::fuzzyfind(status), Self::FuzzyFindHelp => EventAction::fuzzyfind_help(status, binds), Self::FuzzyFindLine => EventAction::fuzzyfind_line(status), @@ -152,12 +154,6 @@ impl ActionMap { Self::LazyGit => EventAction::lazygit(status), Self::MarksJump => EventAction::marks_jump(status), Self::MarksNew => EventAction::marks_new(status), - Self::MocpAddToPlayList => EventAction::mocp_add_to_playlist(current_tab), - Self::MocpClearPlaylist => EventAction::mocp_clear_playlist(), - Self::MocpGoToSong => EventAction::mocp_go_to_song(status), - Self::MocpNext => EventAction::mocp_next(), - Self::MocpPrevious => EventAction::mocp_previous(), - Self::MocpTogglePause => EventAction::mocp_toggle_pause(status), Self::MoveDown => EventAction::move_down(status), Self::MoveLeft => EventAction::move_left(status), Self::MoveRight => EventAction::move_right(status), diff --git a/src/event/event_exec.rs b/src/event/event_exec.rs index 454887b..8a3b0a2 100644 --- a/src/event/event_exec.rs +++ b/src/event/event_exec.rs @@ -3,6 +3,7 @@ use std::path; use anyhow::{Context, Result}; +use crate::app::Focus; use crate::app::Status; use crate::app::Tab; use crate::common::filename_to_clipboard; @@ -28,13 +29,11 @@ use crate::modes::InputCompleted; use crate::modes::InputSimple; use crate::modes::LeaveMode; use crate::modes::MarkAction; -use crate::modes::Mocp; use crate::modes::Navigate; use crate::modes::NeedConfirmation; use crate::modes::Preview; use crate::modes::RemovableDevices; use crate::modes::Selectable; -use crate::modes::MOCP; /// Links events from tuikit to custom actions. /// It mutates `Status` or its children `Tab`. @@ -1199,61 +1198,63 @@ impl EventAction { open_tui_program(status, NCDU) } - /// Add a song or a folder to MOC playlist. Start it first... - pub fn mocp_add_to_playlist(tab: &Tab) -> Result<()> { - if !is_program_in_path(MOCP) { - log_line!("mocp isn't installed"); - return Ok(()); - } - Mocp::add_to_playlist(tab) - } - - pub fn mocp_clear_playlist() -> Result<()> { - if !is_program_in_path(MOCP) { - log_line!("mocp isn't installed"); - return Ok(()); - } - Mocp::clear() - } - - /// Add a song or a folder to MOC playlist. Start it first... - pub fn mocp_go_to_song(status: &mut Status) -> Result<()> { - let tab = status.current_tab_mut(); - if !is_program_in_path(MOCP) { - log_line!("mocp isn't installed"); - return Ok(()); + pub fn focus_go_left(status: &mut Status) -> Result<()> { + match status.focus { + Focus::LeftMenu | Focus::LeftFile => (), + Focus::RightFile => { + status.focus = Focus::LeftFile; + } + Focus::RightMenu => { + if matches!(status.tabs[0].edit_mode, Edit::Nothing) { + status.focus = Focus::LeftFile; + } else { + status.focus = Focus::LeftMenu; + } + } } - Mocp::go_to_song(tab)?; - - status.update_second_pane_for_preview() + Ok(()) } - /// Toggle play/pause on MOC. - /// Starts the server if needed, preventing the output to fill the screen. - /// Then toggle play/pause - pub fn mocp_toggle_pause(status: &mut Status) -> Result<()> { - if !is_program_in_path(MOCP) { - log_line!("mocp isn't installed"); - return Ok(()); + pub fn focus_go_right(status: &mut Status) -> Result<()> { + match status.focus { + Focus::RightMenu | Focus::RightFile => (), + Focus::LeftFile => { + status.focus = Focus::RightFile; + } + Focus::LeftMenu => { + if matches!(status.tabs[1].edit_mode, Edit::Nothing) { + status.focus = Focus::RightFile; + } else { + status.focus = Focus::RightMenu; + } + } } - Mocp::toggle_pause(status) + Ok(()) } - /// Skip to the next song in MOC - pub fn mocp_next() -> Result<()> { - if !is_program_in_path(MOCP) { - log_line!("mocp isn't installed"); - return Ok(()); + pub fn focus_go_down(status: &mut Status) -> Result<()> { + match status.focus { + Focus::RightMenu | Focus::LeftMenu => (), + Focus::LeftFile => { + if !matches!(status.tabs[0].edit_mode, Edit::Nothing) { + status.focus = Focus::LeftMenu; + } + } + Focus::RightFile => { + if !matches!(status.tabs[1].edit_mode, Edit::Nothing) { + status.focus = Focus::RightMenu; + } + } } - Mocp::next() + Ok(()) } - /// Go to the previous song in MOC - pub fn mocp_previous() -> Result<()> { - if !is_program_in_path(MOCP) { - log_line!("mocp isn't installed"); - return Ok(()); + pub fn focus_go_up(status: &mut Status) -> Result<()> { + match status.focus { + Focus::LeftFile | Focus::RightFile => (), + Focus::LeftMenu => status.focus = Focus::LeftFile, + Focus::RightMenu => status.focus = Focus::RightFile, } - Mocp::previous() + Ok(()) } } diff --git a/src/modes/edit/help.rs b/src/modes/edit/help.rs index dcd09ee..e30a52f 100644 --- a/src/modes/edit/help.rs +++ b/src/modes/edit/help.rs @@ -113,15 +113,6 @@ Different modes for the bottom window {Filter:<10}: FILTER (by name \"n name\", by ext \"e ext\", \"d only directories\" or \"a all\" for reset) {Enter:<10}: Execute mode then NORMAL - -- MOC - -Control MOC from your TUI -{MocpAddToPlayList:<10}: MOCP: Add selected file or folder to the playlist -{MocpPrevious:<10}: MOCP: Previous song -{MocpTogglePause:<10}: MOCP: Toggle play/pause. -{MocpNext:<10}: MOCP: Next song -{MocpGoToSong:<10}: MOCP: Go to currently playing song -{MocpClearPlaylist:<10}: MOCP: Clear the playlist "; const CUSTOM_HELP: &str = " diff --git a/src/modes/edit/mocp.rs b/src/modes/edit/mocp.rs deleted file mode 100644 index 5cd436b..0000000 --- a/src/modes/edit/mocp.rs +++ /dev/null @@ -1,134 +0,0 @@ -use anyhow::Result; - -use crate::app::Status; -use crate::app::Tab; -use crate::common::OPENER_AUDIO; -use crate::io::{execute, execute_and_capture_output, execute_and_capture_output_without_check}; -use crate::log_info; - -pub const MOCP: &str = OPENER_AUDIO.0; - -/// A bunch of methods to control MOC. -/// It relies on the application `mocp` itself to : -/// - start & server (if needed) and add a song/folder to the current playlist, -/// - toggle pause / play, -/// - go to next song, -/// - go to previous song, -/// -/// It should never fail but may force a refresh and flicker the screen if the server -/// wasn't running already. -pub struct Mocp {} - -impl Mocp { - /// Add a song or a folder to MOC playlist. Start it first... - /// - /// # Errors - /// - /// It should never fail. - pub fn add_to_playlist(tab: &Tab) -> Result<()> { - let _ = execute_and_capture_output_without_check(MOCP, &["-S"]); - let Ok(path_str) = tab.current_file_string() else { - return Ok(()); - }; - log_info!("mocp add to playlist {path_str:?}"); - let _ = execute_and_capture_output_without_check(MOCP, &["-a", &path_str]); - Ok(()) - } - - /// Move to the currently playing song. - /// - /// # Errors - /// - /// It may fail if the command `mocp -Q %file` fails - pub fn go_to_song(tab: &mut Tab) -> Result<()> { - let output = execute_and_capture_output_without_check(MOCP, &["-Q", "%file"])?; - let filepath = std::path::PathBuf::from(output.trim()); - let Some(parent) = filepath.parent() else { - return Ok(()); - }; - let Some(filename) = filepath.file_name() else { - return Ok(()); - }; - let Some(filename) = filename.to_str() else { - return Ok(()); - }; - tab.cd(parent)?; - tab.search_from(filename, 0); - Ok(()) - } - - /// Toggle play/pause on MOC. - /// Starts the server if needed, preventing the output to fill the screen. - /// Then toggle play/pause - /// - /// # Errors - /// - /// It should never fail - pub fn toggle_pause(status: &mut Status) -> Result<()> { - log_info!("mocp toggle pause"); - match execute_and_capture_output(MOCP, &["-i"]) { - Ok(stdout) => { - // server is runing - if stdout.contains("STOP") { - // music is stopped, start playing music - let _ = execute_and_capture_output(MOCP, &["-p"]); - } else { - // music is playing or paused, toggle play/pause - let _ = execute_and_capture_output(MOCP, &["-G"]); - } - } - Err(e) => { - status.force_clear(); - log_info!("mocp -i error:\n{e:?}"); - // server is stopped, start it. - let c = execute(MOCP, &["-S"]); - let Ok(mut c) = c else { - // it shouldn't fail, something is wrong. It's better not to do anything. - return Ok(()); - }; - let _ = c.wait(); - // start playing music - let _ = execute_and_capture_output(MOCP, &["-p"]); - } - } - Ok(()) - } - - /// Skip to the next song in MOC - /// - /// # Errors - /// - /// It should never fail - pub fn next() -> Result<()> { - log_info!("mocp next"); - let _ = execute_and_capture_output_without_check(MOCP, &["-f"]); - Ok(()) - } - - /// Go to the previous song in MOC - /// - /// # Errors - /// - /// It should never fail - pub fn previous() -> Result<()> { - log_info!("mocp previous"); - let _ = execute_and_capture_output_without_check(MOCP, &["-r"]); - Ok(()) - } - - /// Clear the playlist - /// Since clearing the playlist exit the server, - /// we have to restart it afterwards. - /// - /// # Errors - /// - /// It should never fail - pub fn clear() -> Result<()> { - log_info!("mocp clear"); - // Clear the playlist **and exit** - let _ = execute_and_capture_output_without_check(MOCP, &["-c"]); - // Restart the server - let _ = execute_and_capture_output_without_check(MOCP, &["-S"]); - Ok(()) - } -} diff --git a/src/modes/edit/mod.rs b/src/modes/edit/mod.rs index dfbeb24..e8aeea6 100644 --- a/src/modes/edit/mod.rs +++ b/src/modes/edit/mod.rs @@ -16,7 +16,6 @@ mod leave_mode; mod line_display; mod marks; mod menu; -mod mocp; mod mount_help; mod node_creation; mod nvim; @@ -53,8 +52,6 @@ pub use leave_mode::LeaveMode; pub use line_display::LineDisplay; pub use marks::Marks; pub use menu::Menu; -pub use mocp::Mocp; -pub use mocp::MOCP; pub use mount_help::{MountCommands, MountParameters, MountRepr}; pub use node_creation::NodeCreation; pub use nvim::nvim; -- cgit v1.2.3 From 972d6f253c0540861d7d62a9e4d9e2e84a111023 Mon Sep 17 00:00:00 2001 From: qkzk Date: Wed, 10 Jan 2024 21:50:14 +0100 Subject: single pane borders follow focus --- src/io/display.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/io/display.rs b/src/io/display.rs index a2c66f0..e246c76 100644 --- a/src/io/display.rs +++ b/src/io/display.rs @@ -1378,11 +1378,12 @@ impl Display { let win_main_left = WinMain::new(status, 0, attributes_left); let win_second_left = WinSecondary::new(status, 0); let percent_left = self.size_for_second_window(&status.tabs[0])?; + let borders = self.borders(status); let win = self.vertical_split( &win_main_left, &win_second_left, - color_to_attr(MENU_COLORS.selected_border), - color_to_attr(MENU_COLORS.selected_border), + borders[0], + borders[1], percent_left, )?; Ok(self.term.draw(&win)?) -- cgit v1.2.3 From c364727c8c4ab6e692e8bd966744c08855e8fc79 Mon Sep 17 00:00:00 2001 From: qkzk Date: Thu, 11 Jan 2024 21:50:06 +0100 Subject: give focus with click --- src/app/status.rs | 38 +++++++++++++++++++++++++++++++++----- src/event/event_exec.rs | 1 - 2 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/app/status.rs b/src/app/status.rs index 5daae02..253effd 100644 --- a/src/app/status.rs +++ b/src/app/status.rs @@ -178,7 +178,7 @@ impl Status { } } - pub fn set_focus(&mut self) { + pub fn set_focus_from_mode(&mut self) { if self.index == 0 { if matches!(self.tabs[self.index].edit_mode, Edit::Nothing) { self.focus = Focus::LeftFile; @@ -243,12 +243,22 @@ impl Status { /// Execute a click at `row`, `col`. Action depends on which window was clicked. pub fn click(&mut self, row: u16, col: u16, binds: &Bindings) -> Result<()> { - let window = self.window_from_row(row, self.term_size()?.1); self.select_tab_from_col(col)?; + let window = self.window_from_row(row, self.term_size()?.1); + self.set_focus_from_window_and_index(&window); + self.click_action_from_window(&window, row, col, binds)?; + Ok(()) + } + + fn click_action_from_window( + &mut self, + window: &Window, + row: u16, + col: u16, + binds: &Bindings, + ) -> Result<()> { match window { - Window::Menu => self.menu_action(row), Window::Header => self.header_action(col, binds), - Window::Footer => self.footer_action(col, binds), Window::Files => { if matches!(self.current_tab().display_mode, Display::Flagged) { self.menu.flagged.select_row(row) @@ -257,9 +267,27 @@ impl Status { } self.update_second_pane_for_preview() } + Window::Footer => self.footer_action(col, binds), + Window::Menu => self.menu_action(row), } } + fn set_focus_from_window_and_index(&mut self, window: &Window) { + self.focus = if self.index == 0 { + if matches!(window, Window::Menu) { + Focus::LeftMenu + } else { + Focus::LeftFile + } + } else { + if matches!(window, Window::Menu) { + Focus::RightMenu + } else { + Focus::RightFile + } + }; + } + pub fn second_window_height(&self) -> Result { let (_, height) = self.term_size()?; Ok(height / 2 + (height % 2)) @@ -448,7 +476,7 @@ impl Status { let len = self.menu.len(edit_mode); let height = self.second_window_height()?; self.menu.window = ContentWindow::new(len, height); - self.set_focus(); + self.set_focus_from_mode(); self.refresh_status() } diff --git a/src/event/event_exec.rs b/src/event/event_exec.rs index 8a3b0a2..d142f8d 100644 --- a/src/event/event_exec.rs +++ b/src/event/event_exec.rs @@ -783,7 +783,6 @@ impl EventAction { } pub fn left_click(status: &mut Status, binds: &Bindings, row: u16, col: u16) -> Result<()> { - EventAction::select_pane(status, col)?; EventAction::click(status, row, col, binds) } -- cgit v1.2.3 From ffba90deb7332985362b311cac5f6f7354c8764c Mon Sep 17 00:00:00 2001 From: qkzk Date: Thu, 11 Jan 2024 22:13:46 +0100 Subject: use focus to decide movement --- src/event/event_dispatch.rs | 26 +++++---- src/event/event_exec.rs | 138 +++++++++++++++++++++++++++----------------- 2 files changed, 100 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/event/event_dispatch.rs b/src/event/event_dispatch.rs index 2a52714..db06d14 100644 --- a/src/event/event_dispatch.rs +++ b/src/event/event_dispatch.rs @@ -71,18 +71,22 @@ impl EventDispatcher { } fn char(&self, status: &mut Status, c: char) -> Result<()> { - let tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::InputSimple(InputSimple::Sort) => status.sort(c), - Edit::InputSimple(InputSimple::RegexMatch) => status.input_regex(c), - Edit::InputSimple(_) => status.menu.input_insert(c), - Edit::InputCompleted(_) => status.input_complete(c), - Edit::NeedConfirmation(confirmed_action) => status.confirm(c, confirmed_action), - Edit::Navigate(navigate) => Self::navigate_char(navigate, status, c), - Edit::Nothing if matches!(tab.display_mode, Display::Preview) => { - tab.reset_display_mode_and_view() + if status.focus.is_file() { + self.key_matcher(status, Key::Char(c)) + } else { + let tab = status.current_tab_mut(); + match tab.edit_mode { + Edit::InputSimple(InputSimple::Sort) => status.sort(c), + Edit::InputSimple(InputSimple::RegexMatch) => status.input_regex(c), + Edit::InputSimple(_) => status.menu.input_insert(c), + Edit::InputCompleted(_) => status.input_complete(c), + Edit::NeedConfirmation(confirmed_action) => status.confirm(c, confirmed_action), + Edit::Navigate(navigate) => Self::navigate_char(navigate, status, c), + Edit::Nothing if matches!(tab.display_mode, Display::Preview) => { + tab.reset_display_mode_and_view() + } + Edit::Nothing => self.key_matcher(status, Key::Char(c)), } - Edit::Nothing => self.key_matcher(status, Key::Char(c)), } } diff --git a/src/event/event_exec.rs b/src/event/event_exec.rs index d142f8d..05ac778 100644 --- a/src/event/event_exec.rs +++ b/src/event/event_exec.rs @@ -690,14 +690,20 @@ impl EventAction { /// Move up one row in modes allowing movement. /// Does nothing if the selected item is already the first in list. pub fn move_up(status: &mut Status) -> Result<()> { - let tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::Nothing => Self::move_display_up(status)?, - Edit::Navigate(Navigate::History) => tab.history.prev(), - Edit::Navigate(navigate) => status.menu.prev(navigate), - Edit::InputCompleted(input_completed) => status.menu.completion_prev(input_completed), - _ => (), - }; + if status.focus.is_file() { + Self::move_display_up(status)?; + } else { + let tab = status.current_tab_mut(); + match tab.edit_mode { + Edit::Nothing => Self::move_display_up(status)?, + Edit::Navigate(Navigate::History) => tab.history.prev(), + Edit::Navigate(navigate) => status.menu.prev(navigate), + Edit::InputCompleted(input_completed) => { + status.menu.completion_prev(input_completed) + } + _ => (), + }; + } status.update_second_pane_for_preview() } @@ -739,46 +745,64 @@ impl EventAction { /// Move down one row in modes allowing movements. /// Does nothing if the user is already at the bottom. pub fn move_down(status: &mut Status) -> Result<()> { - match status.current_tab_mut().edit_mode { - Edit::Nothing => Self::move_display_down(status)?, - Edit::Navigate(Navigate::History) => status.current_tab_mut().history.next(), - Edit::Navigate(navigate) => status.menu.next(navigate), - Edit::InputCompleted(input_completed) => status.menu.completion_next(input_completed), - _ => (), - }; + if status.focus.is_file() { + Self::move_display_down(status)? + } else { + match status.current_tab_mut().edit_mode { + Edit::Nothing => Self::move_display_down(status)?, + Edit::Navigate(Navigate::History) => status.current_tab_mut().history.next(), + Edit::Navigate(navigate) => status.menu.next(navigate), + Edit::InputCompleted(input_completed) => { + status.menu.completion_next(input_completed) + } + _ => (), + }; + } status.update_second_pane_for_preview() } /// Move to parent in normal mode, /// move left one char in mode requiring text input. pub fn move_left(status: &mut Status) -> Result<()> { - let tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::InputSimple(_) | Edit::InputCompleted(_) => { - status.menu.input.cursor_left(); - } - Edit::Nothing => match tab.display_mode { - Display::Directory => tab.move_to_parent()?, - Display::Tree => tab.tree_select_parent()?, + if status.focus.is_file() { + Self::file_move_left(status.current_tab_mut())?; + } else { + let tab = status.current_tab_mut(); + match tab.edit_mode { + Edit::InputSimple(_) | Edit::InputCompleted(_) => { + status.menu.input.cursor_left(); + } + Edit::Nothing => Self::file_move_left(tab)?, _ => (), - }, - - _ => (), + } } status.update_second_pane_for_preview() } + fn file_move_left(tab: &mut Tab) -> Result<()> { + match tab.display_mode { + Display::Directory => tab.move_to_parent()?, + Display::Tree => tab.tree_select_parent()?, + _ => (), + }; + Ok(()) + } + /// Move to child if any or open a regular file in normal mode. /// Move the cursor one char to right in mode requiring text input. pub fn move_right(status: &mut Status) -> Result<()> { - let tab: &mut Tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::InputSimple(_) | Edit::InputCompleted(_) => { - status.menu.input.cursor_right(); - Ok(()) + if status.focus.is_file() { + Self::enter_file(status) + } else { + let tab: &mut Tab = status.current_tab_mut(); + match tab.edit_mode { + Edit::InputSimple(_) | Edit::InputCompleted(_) => { + status.menu.input.cursor_right(); + Ok(()) + } + Edit::Nothing => Self::enter_file(status), + _ => Ok(()), } - Edit::Nothing => Self::enter_file(status), - _ => Ok(()), } } @@ -869,17 +893,21 @@ impl EventAction { /// Move up 10 lines in normal mode and preview. pub fn page_up(status: &mut Status) -> Result<()> { - let tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::Nothing => Self::file_page_up(status)?, - Edit::Navigate(navigate) => status.menu.page_up(navigate), - Edit::InputCompleted(input_completed) => { - for _ in 0..10 { - status.menu.completion_prev(input_completed) + if status.focus.is_file() { + Self::file_page_up(status)?; + } else { + let tab = status.current_tab_mut(); + match tab.edit_mode { + Edit::Nothing => Self::file_page_up(status)?, + Edit::Navigate(navigate) => status.menu.page_up(navigate), + Edit::InputCompleted(input_completed) => { + for _ in 0..10 { + status.menu.completion_prev(input_completed) + } } - } - _ => (), - }; + _ => (), + }; + } Ok(()) } @@ -902,17 +930,21 @@ impl EventAction { /// Move down 10 lines in normal & preview mode. pub fn page_down(status: &mut Status) -> Result<()> { - let tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::Nothing => Self::file_page_down(status)?, - Edit::Navigate(navigate) => status.menu.page_down(navigate), - Edit::InputCompleted(input_completed) => { - for _ in 0..10 { - status.menu.completion_next(input_completed) + if status.focus.is_file() { + Self::file_page_down(status)?; + } else { + let tab = status.current_tab_mut(); + match tab.edit_mode { + Edit::Nothing => Self::file_page_down(status)?, + Edit::Navigate(navigate) => status.menu.page_down(navigate), + Edit::InputCompleted(input_completed) => { + for _ in 0..10 { + status.menu.completion_next(input_completed) + } } - } - _ => (), - }; + _ => (), + }; + } Ok(()) } -- cgit v1.2.3 From 24034b80e9d146aeeb28ecfc8e440fdd39370de4 Mon Sep 17 00:00:00 2001 From: qkzk Date: Thu, 11 Jan 2024 22:25:59 +0100 Subject: WIP. May have to be reversed. Should I create a window kind object and send it actions ? --- src/event/event_exec.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/event/event_exec.rs b/src/event/event_exec.rs index 05ac778..b7dcad3 100644 --- a/src/event/event_exec.rs +++ b/src/event/event_exec.rs @@ -1193,8 +1193,15 @@ impl EventAction { /// Enter action mode in which you can type any valid action. /// Some action does nothing as they require to be executed from a specific context. pub fn action(status: &mut Status) -> Result<()> { - status.set_edit_mode(status.index, Edit::InputCompleted(InputCompleted::Action))?; - status.menu.completion.reset(); + if matches!( + status.current_tab().edit_mode, + Edit::InputCompleted(InputCompleted::Action) + ) { + status.reset_edit_mode()?; + } else { + status.set_edit_mode(status.index, Edit::InputCompleted(InputCompleted::Action))?; + status.menu.completion.reset(); + } Ok(()) } -- cgit v1.2.3 From c8ddc5f0f9e63525ea3d598132eac9cbd2c288d6 Mon Sep 17 00:00:00 2001 From: qkzk Date: Fri, 12 Jan 2024 23:37:29 +0100 Subject: WIP: check focus before executing action --- src/event/action_map.rs | 8 +- src/event/event_exec.rs | 228 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 177 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/event/action_map.rs b/src/event/action_map.rs index da97e85..2cb8baa 100644 --- a/src/event/action_map.rs +++ b/src/event/action_map.rs @@ -117,6 +117,7 @@ impl ActionMap { Self::BackTab => EventAction::backtab(status), Self::Backspace => EventAction::backspace(status), Self::Bulk => EventAction::bulk(status), + Self::Cd => EventAction::cd(status), Self::Chmod => EventAction::chmod(status), Self::ClearFlags => EventAction::clear_flags(status), Self::CliMenu => EventAction::cli_menu(status), @@ -144,13 +145,12 @@ impl ActionMap { Self::FuzzyFindLine => EventAction::fuzzyfind_line(status), Self::GoRoot => EventAction::go_root(status), Self::GoStart => EventAction::go_start(status), - Self::Cd => EventAction::cd(status), Self::Help => EventAction::help(status, binds), Self::History => EventAction::history(status), Self::Home => EventAction::home(status), Self::Jump => EventAction::jump(status), Self::KeyHome => EventAction::key_home(status), - Self::Log => EventAction::log(current_tab), + Self::Log => EventAction::log(status), Self::LazyGit => EventAction::lazygit(status), Self::MarksJump => EventAction::marks_jump(status), Self::MarksNew => EventAction::marks_new(status), @@ -158,8 +158,8 @@ impl ActionMap { Self::MoveLeft => EventAction::move_left(status), Self::MoveRight => EventAction::move_right(status), Self::MoveUp => EventAction::move_up(status), - Self::NextSibling => EventAction::next_sibling(current_tab), Self::Ncdu => EventAction::ncdu(status), + Self::NextSibling => EventAction::next_sibling(status), Self::NewDir => EventAction::new_dir(status), Self::NewFile => EventAction::new_file(status), Self::NvimFilepicker => EventAction::nvim_filepicker(status), @@ -170,7 +170,7 @@ impl ActionMap { Self::PageDown => EventAction::page_down(status), Self::PageUp => EventAction::page_up(status), Self::Preview => EventAction::preview(current_tab), - Self::PreviousSibling => EventAction::previous_sibling(current_tab), + Self::PreviousSibling => EventAction::previous_sibling(status), Self::Quit => EventAction::quit(status), Self::RefreshIfNeeded => EventAction::refresh_if_needed(current_tab), Self::RefreshView => EventAction::refresh_view(status), diff --git a/src/event/event_exec.rs b/src/event/event_exec.rs index b7dcad3..02b37ec 100644 --- a/src/event/event_exec.rs +++ b/src/event/event_exec.rs @@ -43,7 +43,11 @@ impl EventAction { /// Once a quit event is received, we change a flag and break the main loop. /// It's usefull to reset the cursor before leaving the application. pub fn quit(status: &mut Status) -> Result<()> { - status.internal_settings.must_quit = true; + if status.focus.is_file() { + status.internal_settings.must_quit = true; + } else { + status.reset_edit_mode()?; + } Ok(()) } @@ -141,6 +145,9 @@ impl EventAction { } pub fn display_flagged(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } if matches!(status.current_tab().display_mode, Display::Flagged) { status .current_tab_mut() @@ -170,26 +177,34 @@ impl EventAction { /// Remove every flag on files in this directory and others. pub fn clear_flags(status: &mut Status) -> Result<()> { - status.menu.flagged.clear(); + if status.focus.is_file() { + status.menu.flagged.clear(); + } Ok(()) } /// Flag all files in the current directory. pub fn flag_all(status: &mut Status) -> Result<()> { - status.flag_all(); + if status.focus.is_file() { + status.flag_all(); + } Ok(()) } /// Reverse every flag in _current_ directory. Flagged files in other /// directory aren't affected. pub fn reverse_flags(status: &mut Status) -> Result<()> { - status.reverse_flags(); + if status.focus.is_file() { + status.reverse_flags(); + } Ok(()) } /// Toggle a single flag and move down one row. pub fn toggle_flag(status: &mut Status) -> Result<()> { - status.toggle_flag_for_selected(); + if status.focus.is_file() { + status.toggle_flag_for_selected(); + } Ok(()) } @@ -198,6 +213,13 @@ impl EventAction { /// When we enter rename from a "tree" mode, we'll need to rename the selected file in the tree, /// not the selected file in the pathcontent. pub fn rename(status: &mut Status) -> Result<()> { + if matches!( + status.current_tab().edit_mode, + Edit::InputSimple(InputSimple::Rename) + ) { + status.reset_edit_mode()?; + return Ok(()); + }; let selected = status.current_tab().current_file()?; let sel_path = selected.path; if sel_path == status.current_tab().directory.path { @@ -219,7 +241,15 @@ impl EventAction { /// the current directory. /// Does nothing if no file is flagged. pub fn copy_paste(status: &mut Status) -> Result<()> { - Self::set_copy_paste(status, NeedConfirmation::Copy) + if matches!( + status.current_tab().edit_mode, + Edit::NeedConfirmation(NeedConfirmation::Copy) + ) { + status.reset_edit_mode()?; + } else { + Self::set_copy_paste(status, NeedConfirmation::Copy)?; + } + Ok(()) } /// Enter the 'move' mode. @@ -227,7 +257,15 @@ impl EventAction { /// the current directory. /// Does nothing if no file is flagged. pub fn cut_paste(status: &mut Status) -> Result<()> { - Self::set_copy_paste(status, NeedConfirmation::Move) + if matches!( + status.current_tab().edit_mode, + Edit::NeedConfirmation(NeedConfirmation::Move) + ) { + status.reset_edit_mode()?; + } else { + Self::set_copy_paste(status, NeedConfirmation::Move)?; + } + Ok(()) } fn set_copy_paste(status: &mut Status, copy_or_move: NeedConfirmation) -> Result<()> { @@ -242,6 +280,9 @@ impl EventAction { /// Creates a symlink of every flagged file to the current directory. pub fn symlink(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } for original_file in status.menu.flagged.content.iter() { let filename = original_file .as_path() @@ -273,11 +314,26 @@ impl EventAction { /// Change to CHMOD mode allowing to edit permissions of a file. pub fn chmod(status: &mut Status) -> Result<()> { - status.set_mode_chmod() + if matches!( + status.current_tab().edit_mode, + Edit::InputSimple(InputSimple::Chmod) + ) { + status.reset_edit_mode()?; + } else { + status.set_mode_chmod()?; + } + Ok(()) } /// Enter the new dir mode. pub fn new_dir(status: &mut Status) -> Result<()> { + if matches!( + status.current_tab().edit_mode, + Edit::InputSimple(InputSimple::Newdir) + ) { + status.reset_edit_mode()?; + return Ok(()); + } if matches!( status.current_tab().display_mode, Display::Directory | Display::Tree @@ -290,6 +346,13 @@ impl EventAction { /// Enter the new file mode. pub fn new_file(status: &mut Status) -> Result<()> { + if matches!( + status.current_tab().edit_mode, + Edit::InputSimple(InputSimple::Newfile) + ) { + status.reset_edit_mode()?; + return Ok(()); + } if matches!( status.current_tab().display_mode, Display::Directory | Display::Tree @@ -304,7 +367,7 @@ impl EventAction { match status.current_tab_mut().display_mode { Display::Directory => Self::normal_enter_file(status), Display::Tree => Self::tree_enter_file(status), - Display::Flagged => Self::jump_fuzzy(status), + Display::Flagged => Self::jump_flagged(status), _ => Ok(()), } } @@ -347,6 +410,9 @@ impl EventAction { /// current tab multiple times. It may change in the future. /// Only files which use an external opener are supported. pub fn open_file(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } if status.menu.flagged.is_empty() { status.open_selected_file() } else { @@ -361,6 +427,13 @@ impl EventAction { /// Enter the execute mode. Most commands must be executed to allow for /// a confirmation. pub fn exec(status: &mut Status) -> Result<()> { + if matches!( + status.current_tab().edit_mode, + Edit::InputCompleted(InputCompleted::Exec) + ) { + status.reset_edit_mode()?; + return Ok(()); + } if status.menu.flagged.is_empty() { status .menu @@ -452,6 +525,9 @@ impl EventAction { /// Display the help which can be navigated and displays the configrable /// binds. pub fn help(status: &mut Status, binds: &Bindings) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } let help = help_string(binds, &status.internal_settings.opener); status.current_tab_mut().set_display_mode(Display::Preview); status.current_tab_mut().preview = Preview::help(&help); @@ -461,10 +537,14 @@ impl EventAction { } /// Display the last actions impacting the file tree - pub fn log(tab: &mut Tab) -> Result<()> { + pub fn log(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } let Ok(log) = read_log() else { return Ok(()); }; + let tab = status.current_tab_mut(); tab.set_display_mode(Display::Preview); tab.preview = Preview::log(log); tab.window.reset(tab.preview.len()); @@ -564,15 +644,15 @@ impl EventAction { /// Enter Marks jump mode, allowing to jump to a marked file. pub fn marks_jump(status: &mut Status) -> Result<()> { - if status.menu.marks.is_empty() { - return Ok(()); - } if matches!( status.current_tab().edit_mode, Edit::Navigate(Navigate::Marks(MarkAction::Jump)) ) { status.reset_edit_mode()?; } else { + if status.menu.marks.is_empty() { + return Ok(()); + } status.set_edit_mode( status.index, Edit::Navigate(Navigate::Marks(MarkAction::Jump)), @@ -605,6 +685,9 @@ impl EventAction { /// reasons unknow to me - it does nothing. /// It requires the "nvim-send" application to be in $PATH. pub fn nvim_filepicker(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } status.update_nvim_listen_address(); if status.internal_settings.nvim_server.is_empty() { return Ok(()); @@ -628,17 +711,30 @@ impl EventAction { /// Enter the set neovim RPC address mode where the user can type /// the RPC address himself pub fn set_nvim_server(status: &mut Status) -> Result<()> { + if matches!( + status.current_tab().edit_mode, + Edit::InputSimple(InputSimple::SetNvimAddr) + ) { + status.reset_edit_mode()?; + return Ok(()); + }; status.set_edit_mode(status.index, Edit::InputSimple(InputSimple::SetNvimAddr)) } /// Move back in history to the last visited directory. pub fn back(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } status.current_tab_mut().back()?; status.update_second_pane_for_preview() } /// Move to $HOME aka ~. pub fn home(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } let home_cow = shellexpand::tilde("~"); let home: &str = home_cow.borrow(); let home_path = path::Path::new(home); @@ -647,17 +743,23 @@ impl EventAction { } pub fn go_root(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } let root_path = std::path::PathBuf::from("/"); status.current_tab_mut().cd(&root_path)?; status.update_second_pane_for_preview() } pub fn go_start(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } status.current_tab_mut().cd(&START_FOLDER)?; status.update_second_pane_for_preview() } - pub fn jump_fuzzy(status: &mut Status) -> Result<()> { + fn jump_flagged(status: &mut Status) -> Result<()> { let Some(path) = status.menu.flagged.selected() else { return Ok(()); }; @@ -707,16 +809,18 @@ impl EventAction { status.update_second_pane_for_preview() } - pub fn next_sibling(tab: &mut Tab) -> Result<()> { - if matches!(tab.display_mode, Display::Tree) { - tab.tree_next_sibling(); + pub fn next_sibling(status: &mut Status) -> Result<()> { + if matches!(status.tabs[status.index].display_mode, Display::Tree) && status.focus.is_file() + { + status.current_tab_mut().tree_next_sibling(); } Ok(()) } - pub fn previous_sibling(tab: &mut Tab) -> Result<()> { - if matches!(tab.display_mode, Display::Tree) { - tab.tree_prev_sibling(); + pub fn previous_sibling(status: &mut Status) -> Result<()> { + if matches!(status.tabs[status.index].display_mode, Display::Tree) && status.focus.is_file() + { + status.current_tab_mut().tree_prev_sibling(); } Ok(()) } @@ -836,14 +940,19 @@ impl EventAction { /// Delete a char to the left in modes allowing edition. pub fn backspace(status: &mut Status) -> Result<()> { + if status.focus.is_file() { + return Ok(()); + } match status.current_tab().edit_mode { - Edit::Navigate(Navigate::Marks(MarkAction::New)) => status.menu.marks.remove_selected(), + Edit::Navigate(Navigate::Marks(MarkAction::New)) => { + status.menu.marks.remove_selected()?; + } Edit::InputSimple(_) | Edit::InputCompleted(_) => { status.menu.input.delete_char_left(); - Ok(()) } - _ => Ok(()), + _ => (), } + Ok(()) } /// Delete all chars to the right in mode allowing edition. @@ -859,36 +968,36 @@ impl EventAction { /// Move to leftmost char in mode allowing edition. pub fn key_home(status: &mut Status) -> Result<()> { - let tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::Nothing => { - match tab.display_mode { - Display::Directory => tab.normal_go_top(), - Display::Preview => tab.preview_go_top(), - Display::Tree => tab.tree_go_to_root()?, - Display::Flagged => status.menu.flagged.select_first(), - }; - } - _ => status.menu.input.cursor_start(), + if status.focus.is_file() { + let tab = status.current_tab_mut(); + match tab.display_mode { + Display::Directory => tab.normal_go_top(), + Display::Preview => tab.preview_go_top(), + Display::Tree => tab.tree_go_to_root()?, + Display::Flagged => status.menu.flagged.select_first(), + }; + status.update_second_pane_for_preview() + } else { + status.menu.input.cursor_start(); + Ok(()) } - status.update_second_pane_for_preview() } /// Move to the bottom in any mode. pub fn end(status: &mut Status) -> Result<()> { - let tab = status.current_tab_mut(); - match tab.edit_mode { - Edit::Nothing => { - match tab.display_mode { - Display::Directory => tab.normal_go_bottom(), - Display::Preview => tab.preview_go_bottom(), - Display::Tree => tab.tree_go_to_bottom_leaf()?, - Display::Flagged => status.menu.flagged.select_last(), - }; - } - _ => status.menu.input.cursor_end(), + if status.focus.is_file() { + let tab = status.current_tab_mut(); + match tab.display_mode { + Display::Directory => tab.normal_go_bottom(), + Display::Preview => tab.preview_go_bottom(), + Display::Tree => tab.tree_go_to_bottom_leaf()?, + Display::Flagged => status.menu.flagged.select_last(), + }; + status.update_second_pane_for_preview()?; + } else { + status.menu.input.cursor_end(); } - status.update_second_pane_for_preview() + Ok(()) } /// Move up 10 lines in normal mode and preview. @@ -971,7 +1080,7 @@ impl EventAction { /// In normal mode, it will open the file. /// Reset to normal mode afterwards. pub fn enter(status: &mut Status, binds: &Bindings) -> Result<()> { - if matches!(status.current_tab().edit_mode, Edit::Nothing) { + if status.focus.is_file() { Self::enter_file(status) } else { LeaveMode::leave_edit_mode(status, binds) @@ -981,17 +1090,17 @@ impl EventAction { /// Change tab in normal mode with dual pane displayed, /// insert a completion in modes allowing completion. pub fn tab(status: &mut Status) -> Result<()> { - match status.current_tab_mut().edit_mode { - Edit::InputCompleted(_) => status.menu.completion_tab(), - Edit::Nothing => status.next(), - _ => (), - }; + if status.focus.is_file() { + status.next() + } else if let Edit::InputCompleted(_) = status.current_tab_mut().edit_mode { + status.menu.completion_tab() + } Ok(()) } - /// Change tab in normal mode. + /// Change tab pub fn backtab(status: &mut Status) -> Result<()> { - if matches!(status.current_tab().edit_mode, Edit::Nothing) { + if status.focus.is_file() { status.prev() }; Ok(()) @@ -1017,6 +1126,9 @@ impl EventAction { /// Copy the filename of the selected file in normal mode. pub fn copy_filename(status: &Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } match status.current_tab().display_mode { Display::Tree | Display::Directory => { let Ok(file_info) = status.current_tab().current_file() else { @@ -1037,6 +1149,9 @@ impl EventAction { /// Copy the filepath of the selected file in normal mode. pub fn copy_filepath(status: &Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } match status.current_tab().display_mode { Display::Tree | Display::Directory => { let Ok(file_info) = status.current_tab().current_file() else { @@ -1151,6 +1266,9 @@ impl EventAction { /// Open the config file. pub fn open_config(status: &mut Status) -> Result<()> { + if !status.focus.is_file() { + return Ok(()); + } match status .internal_settings .opener -- cgit v1.2.3 From 92e567d09b6b5cc039a760210db82d0893de5e50 Mon Sep 17 00:00:00 2001 From: qkzk Date: Sun, 14 Jan 2024 17:43:34 +0100 Subject: WIP: check focus or edit mode before most actions. Still some edge cases to work on --- src/event/action_map.rs | 8 ++--- src/event/event_exec.rs | 70 ++++++++++++++++++++++++++++++++++++++++---- src/modes/edit/leave_mode.rs | 7 ++++- 3 files changed, 75 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/event/action_map.rs b/src/event/action_map.rs index 2cb8baa..1a1772a 100644 --- a/src/event/action_map.rs +++ b/src/event/action_map.rs @@ -191,16 +191,16 @@ impl ActionMap { Self::ToggleDisplayFull => EventAction::toggle_display_full(status), Self::ToggleDualPane => EventAction::toggle_dualpane(status), Self::ToggleFlag => EventAction::toggle_flag(status), - Self::ToggleHidden => EventAction::toggle_hidden(current_tab), + Self::ToggleHidden => EventAction::toggle_hidden(status), Self::TogglePreviewSecond => EventAction::toggle_preview_second(status), Self::TrashEmpty => EventAction::trash_empty(status), Self::TrashMoveFile => EventAction::trash_move_file(status), Self::TrashOpen => EventAction::trash_open(status), Self::TrashRestoreFile => LeaveMode::trash(status), Self::Tree => EventAction::tree(status), - Self::TreeFold => EventAction::tree_fold(current_tab), - Self::TreeFoldAll => EventAction::tree_fold_all(current_tab), - Self::TreeUnFoldAll => EventAction::tree_unfold_all(current_tab), + Self::TreeFold => EventAction::tree_fold(status), + Self::TreeFoldAll => EventAction::tree_fold_all(status), + Self::TreeUnFoldAll => EventAction::tree_unfold_all(status), Self::TuiMenu => EventAction::tui_menu(status), Self::Custom(string) => EventAction::custom(status, string), diff --git a/src/event/event_exec.rs b/src/event/event_exec.rs index 02b37ec..e2a59f6 100644 --- a/src/event/event_exec.rs +++ b/src/event/event_exec.rs @@ -103,6 +103,9 @@ impl EventAction { /// Toggle the second pane between preview & normal mode (files). pub fn toggle_preview_second(status: &mut Status) -> Result<()> { + if !status.display_settings.dual() { + Self::toggle_dualpane(status)?; + } status.display_settings.toggle_preview(); if status.display_settings.preview() { status.update_second_pane_for_preview()?; @@ -117,13 +120,20 @@ impl EventAction { /// Creates a tree in every mode but "Tre