git: New actions for git panel navigation (#43701)
I could not find any related issue, but at least I want to use the git panel like this :) Being used to `lazygit`, this PR makes navigation of the git panel more similar to the CLI tool. Instead of selecting -> enter'ing for skimming each file, I just want to move between the files in the git panel and have the diff multibuffer advance to the appropriate file. This also adheres to the behavior of the outline panel, which I like better. If the multibuffer is not active, it behaves same as before (just selecting the file in the panel, nothing else). I did not modify existing `menu::Select*` actions in case anybody still prefers previous behavior. https://github.com/user-attachments/assets/2d1303d4-50c8-4500-ab3b-302eb7d4afda Release Notes: - Improved navigation of the git panel, by advancing the "Uncommitted Changes" multibuffer to the current selected file. To restore the old behavior, you can bind `up` and `down` to `menu::SelectPrevious` and `menu::SelectNext` under the `GitPanel` context in your keymap. Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
1 parent
7eb6805f55
commit
a00de2736c
4 files changed
+75
-21
No files matched your search
@@ -905,8 +905,8 @@
|
||||
"bindings": {
|
||||
"left": "git_panel::CollapseSelectedEntry",
|
||||
"right": "git_panel::ExpandSelectedEntry",
|
||||
"up": "menu::SelectPrevious",
|
||||
"down": "menu::SelectNext",
|
||||
"up": "git_panel::PreviousEntry",
|
||||
"down": "git_panel::NextEntry",
|
||||
"enter": "menu::Confirm",
|
||||
"alt-y": "git::StageFile",
|
||||
"alt-shift-y": "git::UnstageFile",
|
||||
|
||||
@@ -981,12 +981,12 @@
|
||||
"context": "GitPanel && ChangesList",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"up": "git_panel::PreviousEntry",
|
||||
"down": "git_panel::NextEntry",
|
||||
"cmd-up": "git_panel::FirstEntry",
|
||||
"cmd-down": "git_panel::LastEntry",
|
||||
"left": "git_panel::CollapseSelectedEntry",
|
||||
"right": "git_panel::ExpandSelectedEntry",
|
||||
"up": "menu::SelectPrevious",
|
||||
"down": "menu::SelectNext",
|
||||
"cmd-up": "menu::SelectFirst",
|
||||
"cmd-down": "menu::SelectLast",
|
||||
"enter": "menu::Confirm",
|
||||
"cmd-alt-y": "git::ToggleStaged",
|
||||
"space": "git::ToggleStaged",
|
||||
|
||||
@@ -908,10 +908,10 @@
|
||||
"context": "GitPanel && ChangesList",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"up": "git_panel::PreviousEntry",
|
||||
"down": "git_panel::NextEntry",
|
||||
"left": "git_panel::CollapseSelectedEntry",
|
||||
"right": "git_panel::ExpandSelectedEntry",
|
||||
"up": "menu::SelectPrevious",
|
||||
"down": "menu::SelectNext",
|
||||
"enter": "menu::Confirm",
|
||||
"alt-y": "git::StageFile",
|
||||
"shift-alt-y": "git::UnstageFile",
|
||||
|
||||
@@ -46,7 +46,7 @@ use language_model::{
|
||||
ConfiguredModel, LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage,
|
||||
Role, ZED_CLOUD_PROVIDER_ID,
|
||||
};
|
||||
use menu::{Confirm, SecondaryConfirm, SelectFirst, SelectLast, SelectNext, SelectPrevious};
|
||||
use menu;
|
||||
use multi_buffer::ExcerptInfo;
|
||||
use notifications::status_toast::{StatusToast, ToastIcon};
|
||||
use panel::{
|
||||
@@ -93,6 +93,14 @@ actions!(
|
||||
FocusEditor,
|
||||
/// Focuses on the changes list.
|
||||
FocusChanges,
|
||||
/// Select next git panel menu item, and show it in the diff view
|
||||
NextEntry,
|
||||
/// Select previous git panel menu item, and show it in the diff view
|
||||
PreviousEntry,
|
||||
/// Select first git panel menu item, and show it in the diff view
|
||||
FirstEntry,
|
||||
/// Select last git panel menu item, and show it in the diff view
|
||||
LastEntry,
|
||||
/// Toggles automatic co-author suggestions.
|
||||
ToggleFillCoAuthors,
|
||||
/// Toggles sorting entries by path vs status.
|
||||
@@ -914,12 +922,12 @@ impl GitPanel {
|
||||
|
||||
if let GitListEntry::Directory(dir_entry) = entry {
|
||||
if dir_entry.expanded {
|
||||
self.select_next(&SelectNext, window, cx);
|
||||
self.select_next(&menu::SelectNext, window, cx);
|
||||
} else {
|
||||
self.toggle_directory(&dir_entry.key, window, cx);
|
||||
}
|
||||
} else {
|
||||
self.select_next(&SelectNext, window, cx);
|
||||
self.select_next(&menu::SelectNext, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -937,14 +945,19 @@ impl GitPanel {
|
||||
if dir_entry.expanded {
|
||||
self.toggle_directory(&dir_entry.key, window, cx);
|
||||
} else {
|
||||
self.select_previous(&SelectPrevious, window, cx);
|
||||
self.select_previous(&menu::SelectPrevious, window, cx);
|
||||
}
|
||||
} else {
|
||||
self.select_previous(&SelectPrevious, window, cx);
|
||||
self.select_previous(&menu::SelectPrevious, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn select_first(&mut self, _: &SelectFirst, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn select_first(
|
||||
&mut self,
|
||||
_: &menu::SelectFirst,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let first_entry = match &self.view_mode {
|
||||
GitPanelViewMode::Flat => self
|
||||
.entries
|
||||
@@ -967,7 +980,7 @@ impl GitPanel {
|
||||
|
||||
fn select_previous(
|
||||
&mut self,
|
||||
_: &SelectPrevious,
|
||||
_: &menu::SelectPrevious,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
@@ -1016,7 +1029,7 @@ impl GitPanel {
|
||||
self.scroll_to_selected_entry(cx);
|
||||
}
|
||||
|
||||
fn select_next(&mut self, _: &SelectNext, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn select_next(&mut self, _: &menu::SelectNext, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
let item_count = self.entries.len();
|
||||
if item_count == 0 {
|
||||
return;
|
||||
@@ -1054,13 +1067,50 @@ impl GitPanel {
|
||||
self.scroll_to_selected_entry(cx);
|
||||
}
|
||||
|
||||
fn select_last(&mut self, _: &SelectLast, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn select_last(&mut self, _: &menu::SelectLast, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.entries.last().is_some() {
|
||||
self.selected_entry = Some(self.entries.len() - 1);
|
||||
self.scroll_to_selected_entry(cx);
|
||||
}
|
||||
}
|
||||
|
||||
/// Show diff view at selected entry, only if the diff view is open
|
||||
fn move_diff_to_entry(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
maybe!({
|
||||
let workspace = self.workspace.upgrade()?;
|
||||
|
||||
if let Some(project_diff) = workspace.read(cx).item_of_type::<ProjectDiff>(cx) {
|
||||
let entry = self.entries.get(self.selected_entry?)?.status_entry()?;
|
||||
|
||||
project_diff.update(cx, |project_diff, cx| {
|
||||
project_diff.move_to_entry(entry.clone(), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
Some(())
|
||||
});
|
||||
}
|
||||
|
||||
fn first_entry(&mut self, _: &FirstEntry, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.select_first(&menu::SelectFirst, window, cx);
|
||||
self.move_diff_to_entry(window, cx);
|
||||
}
|
||||
|
||||
fn last_entry(&mut self, _: &LastEntry, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.select_last(&menu::SelectLast, window, cx);
|
||||
self.move_diff_to_entry(window, cx);
|
||||
}
|
||||
|
||||
fn next_entry(&mut self, _: &NextEntry, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.select_next(&menu::SelectNext, window, cx);
|
||||
self.move_diff_to_entry(window, cx);
|
||||
}
|
||||
|
||||
fn previous_entry(&mut self, _: &PreviousEntry, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.select_previous(&menu::SelectPrevious, window, cx);
|
||||
self.move_diff_to_entry(window, cx);
|
||||
}
|
||||
|
||||
fn focus_editor(&mut self, _: &FocusEditor, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.commit_editor.update(cx, |editor, cx| {
|
||||
window.focus(&editor.focus_handle(cx), cx);
|
||||
@@ -1074,7 +1124,7 @@ impl GitPanel {
|
||||
.as_ref()
|
||||
.is_some_and(|active_repository| active_repository.read(cx).status_summary().count > 0);
|
||||
if have_entries && self.selected_entry.is_none() {
|
||||
self.select_first(&SelectFirst, window, cx);
|
||||
self.select_first(&menu::SelectFirst, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4726,8 +4776,8 @@ impl GitPanel {
|
||||
git::AddToGitignore.boxed_clone(),
|
||||
)
|
||||
.separator()
|
||||
.action("Open Diff", Confirm.boxed_clone())
|
||||
.action("Open File", SecondaryConfirm.boxed_clone())
|
||||
.action("Open Diff", menu::Confirm.boxed_clone())
|
||||
.action("Open File", menu::SecondaryConfirm.boxed_clone())
|
||||
.separator()
|
||||
.action_disabled_when(is_created, "View File History", Box::new(git::FileHistory))
|
||||
});
|
||||
@@ -5390,6 +5440,10 @@ impl Render for GitPanel {
|
||||
.on_action(cx.listener(Self::select_next))
|
||||
.on_action(cx.listener(Self::select_previous))
|
||||
.on_action(cx.listener(Self::select_last))
|
||||
.on_action(cx.listener(Self::first_entry))
|
||||
.on_action(cx.listener(Self::next_entry))
|
||||
.on_action(cx.listener(Self::previous_entry))
|
||||
.on_action(cx.listener(Self::last_entry))
|
||||
.on_action(cx.listener(Self::close_panel))
|
||||
.on_action(cx.listener(Self::open_diff))
|
||||
.on_action(cx.listener(Self::open_file))
|
||||
@@ -6855,7 +6909,7 @@ mod tests {
|
||||
// the Project Diff's active path.
|
||||
panel.update_in(cx, |panel, window, cx| {
|
||||
panel.selected_entry = Some(1);
|
||||
panel.open_diff(&Confirm, window, cx);
|
||||
panel.open_diff(&menu::Confirm, window, cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
|
||||
Reference in new issue
Block a user