Add :tabonly and :only vim commands (#8337)

Release Notes:

- Added
[`:tabo[nly][!]`](https://neovim.io/doc/user/tabpage.html#%3Atabonly),
closes all the tabs except the active one but in the current pane only,
every other split pane remains unaffected.
The version with the `!` force closes the tabs while the one without
asks you to save or discard the changes.
- Added [`:on[ly][!]`](https://neovim.io/doc/user/windows.html#%3Aonly),
closes all the tabs *and* panes except the active one.
The version with the `!` force closes the tabs while the one without
asks you to save or discard the changes.
Since Zed does not have different splits per tab like in Neovim `:only`
works the same as it does in VscodeVim.

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
riccardofano 2024-02-27 06:15:50 +01:00 committed by GitHub
parent c31626717f
commit a42b987929
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 11 deletions

View File

@ -201,6 +201,34 @@ pub fn command_interceptor(mut query: &str, cx: &AppContext) -> Option<CommandIn
}
.boxed_clone(),
),
"tabo" | "tabon" | "tabonl" | "tabonly" => (
"tabonly",
workspace::CloseInactiveItems {
save_intent: Some(SaveIntent::Close),
}
.boxed_clone(),
),
"tabo!" | "tabon!" | "tabonl!" | "tabonly!" => (
"tabonly!",
workspace::CloseInactiveItems {
save_intent: Some(SaveIntent::Skip),
}
.boxed_clone(),
),
"on" | "onl" | "only" => (
"only",
workspace::CloseInactiveTabsAndPanes {
save_intent: Some(SaveIntent::Close),
}
.boxed_clone(),
),
"on!" | "onl!" | "only!" => (
"only!",
workspace::CloseInactiveTabsAndPanes {
save_intent: Some(SaveIntent::Skip),
}
.boxed_clone(),
),
// quickfix / loclist (merged together for now)
"cl" | "cli" | "clis" | "clist" => (

View File

@ -66,6 +66,12 @@ pub struct CloseActiveItem {
pub save_intent: Option<SaveIntent>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CloseInactiveItems {
pub save_intent: Option<SaveIntent>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CloseAllItems {
@ -83,6 +89,7 @@ impl_actions!(
[
CloseAllItems,
CloseActiveItem,
CloseInactiveItems,
ActivateItem,
RevealInProjectPanel
]
@ -94,7 +101,6 @@ actions!(
ActivatePrevItem,
ActivateNextItem,
ActivateLastItem,
CloseInactiveItems,
CloseCleanItems,
CloseItemsToTheLeft,
CloseItemsToTheRight,
@ -767,7 +773,7 @@ impl Pane {
pub fn close_inactive_items(
&mut self,
_: &CloseInactiveItems,
action: &CloseInactiveItems,
cx: &mut ViewContext<Self>,
) -> Option<Task<Result<()>>> {
if self.items.is_empty() {
@ -775,9 +781,11 @@ impl Pane {
}
let active_item_id = self.items[self.active_item_index].item_id();
Some(self.close_items(cx, SaveIntent::Close, move |item_id| {
item_id != active_item_id
}))
Some(self.close_items(
cx,
action.save_intent.unwrap_or(SaveIntent::Close),
move |item_id| item_id != active_item_id,
))
}
pub fn close_clean_items(
@ -1397,7 +1405,7 @@ impl Pane {
)
.entry(
"Close Others",
Some(Box::new(CloseInactiveItems)),
Some(Box::new(CloseInactiveItems { save_intent: None })),
cx.handler_for(&pane, move |pane, cx| {
pane.close_items(cx, SaveIntent::Close, |id| id != item_id)
.detach_and_log_err(cx);
@ -2432,7 +2440,7 @@ mod tests {
set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
pane.update(cx, |pane, cx| {
pane.close_inactive_items(&CloseInactiveItems, cx)
pane.close_inactive_items(&CloseInactiveItems { save_intent: None }, cx)
})
.unwrap()
.await

View File

@ -103,7 +103,6 @@ actions!(
NewFile,
NewWindow,
CloseWindow,
CloseInactiveTabsAndPanes,
AddFolderToProject,
Unfollow,
SaveAs,
@ -161,6 +160,12 @@ pub struct CloseAllItemsAndPanes {
pub save_intent: Option<SaveIntent>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CloseInactiveTabsAndPanes {
pub save_intent: Option<SaveIntent>,
}
#[derive(Clone, Deserialize, PartialEq)]
pub struct SendKeystrokes(pub String);
@ -170,6 +175,7 @@ impl_actions!(
ActivatePane,
ActivatePaneInDirection,
CloseAllItemsAndPanes,
CloseInactiveTabsAndPanes,
NewFileInDirection,
OpenTerminal,
Save,
@ -1620,10 +1626,10 @@ impl Workspace {
pub fn close_inactive_items_and_panes(
&mut self,
_: &CloseInactiveTabsAndPanes,
action: &CloseInactiveTabsAndPanes,
cx: &mut ViewContext<Self>,
) {
self.close_all_internal(true, SaveIntent::Close, cx)
self.close_all_internal(true, action.save_intent.unwrap_or(SaveIntent::Close), cx)
.map(|task| task.detach_and_log_err(cx));
}
@ -1648,7 +1654,7 @@ impl Workspace {
if retain_active_pane {
if let Some(current_pane_close) = current_pane.update(cx, |pane, cx| {
pane.close_inactive_items(&CloseInactiveItems, cx)
pane.close_inactive_items(&CloseInactiveItems { save_intent: None }, cx)
}) {
tasks.push(current_pane_close);
};