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:
parent
c31626717f
commit
a42b987929
3 changed files with 53 additions and 11 deletions
|
@ -201,6 +201,34 @@ pub fn command_interceptor(mut query: &str, cx: &AppContext) -> Option<CommandIn
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.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)
|
// quickfix / loclist (merged together for now)
|
||||||
"cl" | "cli" | "clis" | "clist" => (
|
"cl" | "cli" | "clis" | "clist" => (
|
||||||
|
|
|
@ -66,6 +66,12 @@ pub struct CloseActiveItem {
|
||||||
pub save_intent: Option<SaveIntent>,
|
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)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CloseAllItems {
|
pub struct CloseAllItems {
|
||||||
|
@ -83,6 +89,7 @@ impl_actions!(
|
||||||
[
|
[
|
||||||
CloseAllItems,
|
CloseAllItems,
|
||||||
CloseActiveItem,
|
CloseActiveItem,
|
||||||
|
CloseInactiveItems,
|
||||||
ActivateItem,
|
ActivateItem,
|
||||||
RevealInProjectPanel
|
RevealInProjectPanel
|
||||||
]
|
]
|
||||||
|
@ -94,7 +101,6 @@ actions!(
|
||||||
ActivatePrevItem,
|
ActivatePrevItem,
|
||||||
ActivateNextItem,
|
ActivateNextItem,
|
||||||
ActivateLastItem,
|
ActivateLastItem,
|
||||||
CloseInactiveItems,
|
|
||||||
CloseCleanItems,
|
CloseCleanItems,
|
||||||
CloseItemsToTheLeft,
|
CloseItemsToTheLeft,
|
||||||
CloseItemsToTheRight,
|
CloseItemsToTheRight,
|
||||||
|
@ -767,7 +773,7 @@ impl Pane {
|
||||||
|
|
||||||
pub fn close_inactive_items(
|
pub fn close_inactive_items(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &CloseInactiveItems,
|
action: &CloseInactiveItems,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
if self.items.is_empty() {
|
if self.items.is_empty() {
|
||||||
|
@ -775,9 +781,11 @@ impl Pane {
|
||||||
}
|
}
|
||||||
|
|
||||||
let active_item_id = self.items[self.active_item_index].item_id();
|
let active_item_id = self.items[self.active_item_index].item_id();
|
||||||
Some(self.close_items(cx, SaveIntent::Close, move |item_id| {
|
Some(self.close_items(
|
||||||
item_id != active_item_id
|
cx,
|
||||||
}))
|
action.save_intent.unwrap_or(SaveIntent::Close),
|
||||||
|
move |item_id| item_id != active_item_id,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_clean_items(
|
pub fn close_clean_items(
|
||||||
|
@ -1397,7 +1405,7 @@ impl Pane {
|
||||||
)
|
)
|
||||||
.entry(
|
.entry(
|
||||||
"Close Others",
|
"Close Others",
|
||||||
Some(Box::new(CloseInactiveItems)),
|
Some(Box::new(CloseInactiveItems { save_intent: None })),
|
||||||
cx.handler_for(&pane, move |pane, cx| {
|
cx.handler_for(&pane, move |pane, cx| {
|
||||||
pane.close_items(cx, SaveIntent::Close, |id| id != item_id)
|
pane.close_items(cx, SaveIntent::Close, |id| id != item_id)
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
|
@ -2432,7 +2440,7 @@ mod tests {
|
||||||
set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
|
set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
|
||||||
|
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.close_inactive_items(&CloseInactiveItems, cx)
|
pane.close_inactive_items(&CloseInactiveItems { save_intent: None }, cx)
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -103,7 +103,6 @@ actions!(
|
||||||
NewFile,
|
NewFile,
|
||||||
NewWindow,
|
NewWindow,
|
||||||
CloseWindow,
|
CloseWindow,
|
||||||
CloseInactiveTabsAndPanes,
|
|
||||||
AddFolderToProject,
|
AddFolderToProject,
|
||||||
Unfollow,
|
Unfollow,
|
||||||
SaveAs,
|
SaveAs,
|
||||||
|
@ -161,6 +160,12 @@ pub struct CloseAllItemsAndPanes {
|
||||||
pub save_intent: Option<SaveIntent>,
|
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)]
|
#[derive(Clone, Deserialize, PartialEq)]
|
||||||
pub struct SendKeystrokes(pub String);
|
pub struct SendKeystrokes(pub String);
|
||||||
|
|
||||||
|
@ -170,6 +175,7 @@ impl_actions!(
|
||||||
ActivatePane,
|
ActivatePane,
|
||||||
ActivatePaneInDirection,
|
ActivatePaneInDirection,
|
||||||
CloseAllItemsAndPanes,
|
CloseAllItemsAndPanes,
|
||||||
|
CloseInactiveTabsAndPanes,
|
||||||
NewFileInDirection,
|
NewFileInDirection,
|
||||||
OpenTerminal,
|
OpenTerminal,
|
||||||
Save,
|
Save,
|
||||||
|
@ -1620,10 +1626,10 @@ impl Workspace {
|
||||||
|
|
||||||
pub fn close_inactive_items_and_panes(
|
pub fn close_inactive_items_and_panes(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &CloseInactiveTabsAndPanes,
|
action: &CloseInactiveTabsAndPanes,
|
||||||
cx: &mut ViewContext<Self>,
|
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));
|
.map(|task| task.detach_and_log_err(cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1648,7 +1654,7 @@ impl Workspace {
|
||||||
|
|
||||||
if retain_active_pane {
|
if retain_active_pane {
|
||||||
if let Some(current_pane_close) = current_pane.update(cx, |pane, cx| {
|
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);
|
tasks.push(current_pane_close);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue