Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to activate left neighbour tab on tab close #21800

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions assets/settings/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -561,9 +561,11 @@
// What to do after closing the current tab.
//
// 1. Activate the tab that was open previously (default)
// "History"
// 2. Activate the neighbour tab (prefers the right one, if present)
// "Neighbour"
// "history"
// 2. Activate the right neighbour tab if present
// "neighbour"
// 3. Activate the left neighbour tab if present
// "left_neighbour"
"activate_on_close": "history",
/// Which files containing diagnostic errors/warnings to mark in the tabs.
/// Diagnostics are only shown when file icons are also active.
Expand Down
3 changes: 2 additions & 1 deletion crates/workspace/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ pub enum ShowDiagnostics {
}

#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
#[serde(rename_all = "snake_case")]
pub enum ActivateOnClose {
#[default]
History,
Neighbour,
LeftNeighbour,
}

#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
Expand Down
70 changes: 69 additions & 1 deletion crates/workspace/src/pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,7 @@ impl Pane {
self.pinned_tab_count -= 1;
}
if item_index == self.active_item_index {
let left_neighbour_index = || item_index.min(self.items.len()).saturating_sub(1);
let index_to_activate = match activate_on_close {
ActivateOnClose::History => self
.activation_history
Expand All @@ -1517,7 +1518,7 @@ impl Pane {
})
// We didn't have a valid activation history entry, so fallback
// to activating the item to the left
.unwrap_or_else(|| item_index.min(self.items.len()).saturating_sub(1)),
.unwrap_or_else(left_neighbour_index),
ActivateOnClose::Neighbour => {
self.activation_history.pop();
if item_index + 1 < self.items.len() {
Expand All @@ -1526,6 +1527,10 @@ impl Pane {
item_index.saturating_sub(1)
}
}
ActivateOnClose::LeftNeighbour => {
self.activation_history.pop();
left_neighbour_index()
}
};

let should_activate = activate_pane || self.has_focus(cx);
Expand Down Expand Up @@ -3666,6 +3671,69 @@ mod tests {
assert_item_labels(&pane, ["A*"], cx);
}

#[gpui::test]
async fn test_remove_item_ordering_left_neighbour(cx: &mut TestAppContext) {
init_test(cx);
cx.update_global::<SettingsStore, ()>(|s, cx| {
s.update_user_settings::<ItemSettings>(cx, |s| {
s.activate_on_close = Some(ActivateOnClose::LeftNeighbour);
});
});
let fs = FakeFs::new(cx.executor());

let project = Project::test(fs, None, cx).await;
let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());

add_labeled_item(&pane, "A", false, cx);
add_labeled_item(&pane, "B", false, cx);
add_labeled_item(&pane, "C", false, cx);
add_labeled_item(&pane, "D", false, cx);
assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);

pane.update(cx, |pane, cx| pane.activate_item(1, false, false, cx));
add_labeled_item(&pane, "1", false, cx);
assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx);

pane.update(cx, |pane, cx| {
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["A", "B*", "C", "D"], cx);

pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx));
assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);

pane.update(cx, |pane, cx| {
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["A", "B", "C*"], cx);

pane.update(cx, |pane, cx| pane.activate_item(0, false, false, cx));
assert_item_labels(&pane, ["A*", "B", "C"], cx);

pane.update(cx, |pane, cx| {
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["B*", "C"], cx);

pane.update(cx, |pane, cx| {
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
})
.unwrap()
.await
.unwrap();
assert_item_labels(&pane, ["C*"], cx);
}

#[gpui::test]
async fn test_close_inactive_items(cx: &mut TestAppContext) {
init_test(cx);
Expand Down
10 changes: 9 additions & 1 deletion docs/src/configuring-zed.md
Original file line number Diff line number Diff line change
Expand Up @@ -691,14 +691,22 @@ List of `string` values
}
```

2. Activate the neighbour tab (prefers the right one, if present):
2. Activate the right neighbour tab if present:

```json
{
"activate_on_close": "neighbour"
}
```

3. Activate the left neighbour tab if present:

```json
{
"activate_on_close": "left_neighbour"
}
```

### Always show the close button

- Description: Whether to always show the close button on tabs.
Expand Down
Loading