diff --git a/CHANGELOG.md b/CHANGELOG.md index e60180cdc5..9fb43befbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixes * resolve `core.hooksPath` relative to `GIT_WORK_TREE` [[@naseschwarz](https://github.com/naseschwarz)] ([#2571](https://github.com/gitui-org/gitui/issues/2571)) * yanking commit ranges no longer generates incorrect dotted range notations, but lists each individual commit [[@naseschwarz](https://github.com/naseschwarz)] (https://github.com/gitui-org/gitui/issues/2576) +* disable blame and history popup keybinds for untracked files [[@kpbaks](https://github.com/kpbaks)] ([#2489](https://github.com/gitui-org/gitui/pull/2489)) ## [0.27.0] - 2024-01-14 diff --git a/src/components/status_tree.rs b/src/components/status_tree.rs index 1d5f39cb6f..1cd8bd941b 100644 --- a/src/components/status_tree.rs +++ b/src/components/status_tree.rs @@ -395,11 +395,18 @@ impl Component for StatusTreeComponent { out: &mut Vec, force_all: bool, ) -> CommandBlocking { + let available = self.focused || force_all; + let selection = self.selection_file(); + let selected_is_file = selection.is_some(); + let tracked = selection.is_some_and(|s| { + !matches!(s.status, StatusItemType::New) + }); + out.push( CommandInfo::new( strings::commands::navigate_tree(&self.key_config), !self.is_empty(), - self.focused || force_all, + available, ) .order(order::NAV), ); @@ -407,8 +414,8 @@ impl Component for StatusTreeComponent { out.push( CommandInfo::new( strings::commands::blame_file(&self.key_config), - self.selection_file().is_some(), - self.focused || force_all, + selected_is_file && tracked, + available, ) .order(order::RARE_ACTION), ); @@ -418,8 +425,8 @@ impl Component for StatusTreeComponent { strings::commands::open_file_history( &self.key_config, ), - self.selection_file().is_some(), - self.focused || force_all, + selected_is_file && tracked, + available, ) .order(order::RARE_ACTION), ); @@ -427,8 +434,8 @@ impl Component for StatusTreeComponent { out.push( CommandInfo::new( strings::commands::edit_item(&self.key_config), - self.selection_file().is_some(), - self.focused || force_all, + selected_is_file, + available, ) .order(order::RARE_ACTION), ); @@ -436,8 +443,8 @@ impl Component for StatusTreeComponent { out.push( CommandInfo::new( strings::commands::copy_path(&self.key_config), - self.selection_file().is_some(), - self.focused || force_all, + selected_is_file, + available, ) .order(order::RARE_ACTION), ); @@ -445,34 +452,58 @@ impl Component for StatusTreeComponent { CommandBlocking::PassingOn } + #[expect(clippy::cognitive_complexity)] fn event(&mut self, ev: &Event) -> Result { if self.focused { if let Event::Key(e) = ev { return if key_match(e, self.key_config.keys.blame) { - if let Some(status_item) = self.selection_file() { - self.hide(); - self.queue.push(InternalEvent::OpenPopup( - StackablePopupOpen::BlameFile( - BlameFileOpen { - file_path: status_item.path, - commit_id: self.revision, - selection: None, - }, - ), - )); + match self.selection_file() { + Some(status_item) + if !matches!( + status_item.status, + StatusItemType::New + ) => + { + self.hide(); + self.queue.push( + InternalEvent::OpenPopup( + StackablePopupOpen::BlameFile( + BlameFileOpen { + file_path: status_item + .path, + commit_id: self.revision, + selection: None, + }, + ), + ), + ); + } + _ => {} } Ok(EventState::Consumed) } else if key_match( e, self.key_config.keys.file_history, ) { - if let Some(status_item) = self.selection_file() { - self.hide(); - self.queue.push(InternalEvent::OpenPopup( - StackablePopupOpen::FileRevlog( - FileRevOpen::new(status_item.path), - ), - )); + match self.selection_file() { + Some(status_item) + if !matches!( + status_item.status, + StatusItemType::New + ) => + { + self.hide(); + self.queue.push( + InternalEvent::OpenPopup( + StackablePopupOpen::FileRevlog( + FileRevOpen::new( + status_item.path, + ), + ), + ), + ); + } + _ => {} } Ok(EventState::Consumed) } else if key_match(e, self.key_config.keys.edit_file)