Code review changes
This commit is contained in:
parent
4bf4c780be
commit
32f8733313
11 changed files with 127 additions and 187 deletions
|
@ -206,13 +206,13 @@
|
||||||
"shift-z shift-q": [
|
"shift-z shift-q": [
|
||||||
"pane::CloseActiveItem",
|
"pane::CloseActiveItem",
|
||||||
{
|
{
|
||||||
"saveBehavior": "dontSave"
|
"saveIntent": "skip"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"shift-z shift-z": [
|
"shift-z shift-z": [
|
||||||
"pane::CloseActiveItem",
|
"pane::CloseActiveItem",
|
||||||
{
|
{
|
||||||
"saveBehavior": "promptOnConflict"
|
"saveIntent": "saveAll"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// Count support
|
// Count support
|
||||||
|
|
|
@ -297,7 +297,7 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn humanize_action_name(name: &str) -> String {
|
fn humanize_action_name(name: &str) -> String {
|
||||||
let capacity = name.len() + name.chars().filter(|c| c.is_uppercase()).count();
|
let capacity = name.len() + name.chars().filter(|c| c.is_uppercase()).count();
|
||||||
let mut result = String::with_capacity(capacity);
|
let mut result = String::with_capacity(capacity);
|
||||||
for char in name.chars() {
|
for char in name.chars() {
|
||||||
|
|
|
@ -1528,13 +1528,8 @@ mod tests {
|
||||||
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
|
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
|
||||||
active_pane
|
active_pane
|
||||||
.update(cx, |pane, cx| {
|
.update(cx, |pane, cx| {
|
||||||
pane.close_active_item(
|
pane.close_active_item(&workspace::CloseActiveItem { save_intent: None }, cx)
|
||||||
&workspace::CloseActiveItem {
|
.unwrap()
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -33,7 +33,7 @@ use super::{
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TestAppContext {
|
pub struct TestAppContext {
|
||||||
pub cx: Rc<RefCell<AppContext>>,
|
cx: Rc<RefCell<AppContext>>,
|
||||||
foreground_platform: Rc<platform::test::ForegroundPlatform>,
|
foreground_platform: Rc<platform::test::ForegroundPlatform>,
|
||||||
condition_duration: Option<Duration>,
|
condition_duration: Option<Duration>,
|
||||||
pub function_name: String,
|
pub function_name: String,
|
||||||
|
|
|
@ -284,12 +284,7 @@ impl TerminalView {
|
||||||
pub fn deploy_context_menu(&mut self, position: Vector2F, cx: &mut ViewContext<Self>) {
|
pub fn deploy_context_menu(&mut self, position: Vector2F, cx: &mut ViewContext<Self>) {
|
||||||
let menu_entries = vec![
|
let menu_entries = vec![
|
||||||
ContextMenuItem::action("Clear", Clear),
|
ContextMenuItem::action("Clear", Clear),
|
||||||
ContextMenuItem::action(
|
ContextMenuItem::action("Close", pane::CloseActiveItem { save_intent: None }),
|
||||||
"Close",
|
|
||||||
pane::CloseActiveItem {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
self.context_menu.update(cx, |menu, cx| {
|
self.context_menu.update(cx, |menu, cx| {
|
||||||
|
|
|
@ -50,119 +50,119 @@ pub fn command_interceptor(mut query: &str, _: &AppContext) -> Option<CommandInt
|
||||||
"w" | "wr" | "wri" | "writ" | "write" => (
|
"w" | "wr" | "wri" | "writ" | "write" => (
|
||||||
"write",
|
"write",
|
||||||
workspace::Save {
|
workspace::Save {
|
||||||
save_behavior: Some(SaveIntent::Save),
|
save_intent: Some(SaveIntent::Save),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"w!" | "wr!" | "wri!" | "writ!" | "write!" => (
|
"w!" | "wr!" | "wri!" | "writ!" | "write!" => (
|
||||||
"write!",
|
"write!",
|
||||||
workspace::Save {
|
workspace::Save {
|
||||||
save_behavior: Some(SaveIntent::Overwrite),
|
save_intent: Some(SaveIntent::Overwrite),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"q" | "qu" | "qui" | "quit" => (
|
"q" | "qu" | "qui" | "quit" => (
|
||||||
"quit",
|
"quit",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem {
|
||||||
save_behavior: Some(SaveIntent::Close),
|
save_intent: Some(SaveIntent::Close),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"q!" | "qu!" | "qui!" | "quit!" => (
|
"q!" | "qu!" | "qui!" | "quit!" => (
|
||||||
"quit!",
|
"quit!",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem {
|
||||||
save_behavior: Some(SaveIntent::Skip),
|
save_intent: Some(SaveIntent::Skip),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"wq" => (
|
"wq" => (
|
||||||
"wq",
|
"wq",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem {
|
||||||
save_behavior: Some(SaveIntent::Save),
|
save_intent: Some(SaveIntent::Save),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"wq!" => (
|
"wq!" => (
|
||||||
"wq!",
|
"wq!",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem {
|
||||||
save_behavior: Some(SaveIntent::Overwrite),
|
save_intent: Some(SaveIntent::Overwrite),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"x" | "xi" | "xit" | "exi" | "exit" => (
|
"x" | "xi" | "xit" | "exi" | "exit" => (
|
||||||
"exit",
|
"exit",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem {
|
||||||
save_behavior: Some(SaveIntent::Save),
|
save_intent: Some(SaveIntent::SaveAll),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"x!" | "xi!" | "xit!" | "exi!" | "exit!" => (
|
"x!" | "xi!" | "xit!" | "exi!" | "exit!" => (
|
||||||
"exit!",
|
"exit!",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem {
|
||||||
save_behavior: Some(SaveIntent::Overwrite),
|
save_intent: Some(SaveIntent::Overwrite),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"up" | "upd" | "upda" | "updat" | "update" => (
|
"up" | "upd" | "upda" | "updat" | "update" => (
|
||||||
"update",
|
"update",
|
||||||
workspace::Save {
|
workspace::Save {
|
||||||
save_behavior: Some(SaveIntent::SaveAll),
|
save_intent: Some(SaveIntent::SaveAll),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"wa" | "wal" | "wall" => (
|
"wa" | "wal" | "wall" => (
|
||||||
"wall",
|
"wall",
|
||||||
workspace::SaveAll {
|
workspace::SaveAll {
|
||||||
save_behavior: Some(SaveIntent::SaveAll),
|
save_intent: Some(SaveIntent::SaveAll),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"wa!" | "wal!" | "wall!" => (
|
"wa!" | "wal!" | "wall!" => (
|
||||||
"wall!",
|
"wall!",
|
||||||
workspace::SaveAll {
|
workspace::SaveAll {
|
||||||
save_behavior: Some(SaveIntent::Overwrite),
|
save_intent: Some(SaveIntent::Overwrite),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"qa" | "qal" | "qall" | "quita" | "quital" | "quitall" => (
|
"qa" | "qal" | "qall" | "quita" | "quital" | "quitall" => (
|
||||||
"quitall",
|
"quitall",
|
||||||
workspace::CloseAllItemsAndPanes {
|
workspace::CloseAllItemsAndPanes {
|
||||||
save_behavior: Some(SaveIntent::Close),
|
save_intent: Some(SaveIntent::Close),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"qa!" | "qal!" | "qall!" | "quita!" | "quital!" | "quitall!" => (
|
"qa!" | "qal!" | "qall!" | "quita!" | "quital!" | "quitall!" => (
|
||||||
"quitall!",
|
"quitall!",
|
||||||
workspace::CloseAllItemsAndPanes {
|
workspace::CloseAllItemsAndPanes {
|
||||||
save_behavior: Some(SaveIntent::Skip),
|
save_intent: Some(SaveIntent::Skip),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"xa" | "xal" | "xall" => (
|
"xa" | "xal" | "xall" => (
|
||||||
"xall",
|
"xall",
|
||||||
workspace::CloseAllItemsAndPanes {
|
workspace::CloseAllItemsAndPanes {
|
||||||
save_behavior: Some(SaveIntent::SaveAll),
|
save_intent: Some(SaveIntent::SaveAll),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"xa!" | "xal!" | "xall!" => (
|
"xa!" | "xal!" | "xall!" => (
|
||||||
"xall!",
|
"xall!",
|
||||||
workspace::CloseAllItemsAndPanes {
|
workspace::CloseAllItemsAndPanes {
|
||||||
save_behavior: Some(SaveIntent::Overwrite),
|
save_intent: Some(SaveIntent::Overwrite),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"wqa" | "wqal" | "wqall" => (
|
"wqa" | "wqal" | "wqall" => (
|
||||||
"wqall",
|
"wqall",
|
||||||
workspace::CloseAllItemsAndPanes {
|
workspace::CloseAllItemsAndPanes {
|
||||||
save_behavior: Some(SaveIntent::SaveAll),
|
save_intent: Some(SaveIntent::SaveAll),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
"wqa!" | "wqal!" | "wqall!" => (
|
"wqa!" | "wqal!" | "wqall!" => (
|
||||||
"wqall!",
|
"wqall!",
|
||||||
workspace::CloseAllItemsAndPanes {
|
workspace::CloseAllItemsAndPanes {
|
||||||
save_behavior: Some(SaveIntent::Overwrite),
|
save_intent: Some(SaveIntent::Overwrite),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
|
@ -197,7 +197,7 @@ pub fn command_interceptor(mut query: &str, _: &AppContext) -> Option<CommandInt
|
||||||
"tabc" | "tabcl" | "tabclo" | "tabclos" | "tabclose" => (
|
"tabc" | "tabcl" | "tabclo" | "tabclos" | "tabclose" => (
|
||||||
"tabclose",
|
"tabclose",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem {
|
||||||
save_behavior: Some(SaveIntent::Close),
|
save_intent: Some(SaveIntent::Close),
|
||||||
}
|
}
|
||||||
.boxed_clone(),
|
.boxed_clone(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -220,53 +220,58 @@ fn replace_command(
|
||||||
let replacement = parse_replace_all(&action.query);
|
let replacement = parse_replace_all(&action.query);
|
||||||
let pane = workspace.active_pane().clone();
|
let pane = workspace.active_pane().clone();
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() else {
|
||||||
let search = search_bar.update(cx, |search_bar, cx| {
|
return;
|
||||||
if !search_bar.show(cx) {
|
};
|
||||||
return None;
|
let search = search_bar.update(cx, |search_bar, cx| {
|
||||||
}
|
if !search_bar.show(cx) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let mut options = SearchOptions::default();
|
let mut options = SearchOptions::default();
|
||||||
if replacement.is_case_sensitive {
|
if replacement.is_case_sensitive {
|
||||||
options.set(SearchOptions::CASE_SENSITIVE, true)
|
options.set(SearchOptions::CASE_SENSITIVE, true)
|
||||||
}
|
}
|
||||||
let search = if replacement.search == "" {
|
let search = if replacement.search == "" {
|
||||||
search_bar.query(cx)
|
search_bar.query(cx)
|
||||||
} else {
|
} else {
|
||||||
replacement.search
|
replacement.search
|
||||||
};
|
};
|
||||||
|
|
||||||
search_bar.set_replacement(Some(&replacement.replacement), cx);
|
search_bar.set_replacement(Some(&replacement.replacement), cx);
|
||||||
search_bar.activate_search_mode(SearchMode::Regex, cx);
|
search_bar.activate_search_mode(SearchMode::Regex, cx);
|
||||||
Some(search_bar.search(&search, Some(options), cx))
|
Some(search_bar.search(&search, Some(options), cx))
|
||||||
});
|
});
|
||||||
let Some(search) = search else { return };
|
let Some(search) = search else { return };
|
||||||
let search_bar = search_bar.downgrade();
|
let search_bar = search_bar.downgrade();
|
||||||
cx.spawn(|_, mut cx| async move {
|
cx.spawn(|_, mut cx| async move {
|
||||||
search.await?;
|
search.await?;
|
||||||
search_bar.update(&mut cx, |search_bar, cx| {
|
search_bar.update(&mut cx, |search_bar, cx| {
|
||||||
if replacement.should_replace_all {
|
if replacement.should_replace_all {
|
||||||
search_bar.select_last_match(cx);
|
search_bar.select_last_match(cx);
|
||||||
search_bar.replace_all(&Default::default(), cx);
|
search_bar.replace_all(&Default::default(), cx);
|
||||||
Vim::update(cx, |vim, cx| {
|
Vim::update(cx, |vim, cx| {
|
||||||
move_cursor(
|
move_cursor(
|
||||||
vim,
|
vim,
|
||||||
Motion::StartOfLine {
|
Motion::StartOfLine {
|
||||||
display_lines: false,
|
display_lines: false,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert a vim query into something more usable by zed.
|
||||||
|
// we don't attempt to fully convert between the two regex syntaxes,
|
||||||
|
// but we do flip \( and \) to ( and ) (and vice-versa) in the pattern,
|
||||||
|
// and convert \0..\9 to $0..$9 in the replacement so that common idioms work.
|
||||||
fn parse_replace_all(query: &str) -> Replacement {
|
fn parse_replace_all(query: &str) -> Replacement {
|
||||||
let mut chars = query.chars();
|
let mut chars = query.chars();
|
||||||
if Some('%') != chars.next() || Some('s') != chars.next() {
|
if Some('%') != chars.next() || Some('s') != chars.next() {
|
||||||
|
@ -284,17 +289,18 @@ fn parse_replace_all(query: &str) -> Replacement {
|
||||||
let mut buffer = &mut search;
|
let mut buffer = &mut search;
|
||||||
|
|
||||||
let mut escaped = false;
|
let mut escaped = false;
|
||||||
|
// 0 - parsing search
|
||||||
|
// 1 - parsing replacement
|
||||||
|
// 2 - parsing flags
|
||||||
let mut phase = 0;
|
let mut phase = 0;
|
||||||
|
|
||||||
for c in chars {
|
for c in chars {
|
||||||
if escaped {
|
if escaped {
|
||||||
escaped = false;
|
escaped = false;
|
||||||
if phase == 1 && c.is_digit(10) {
|
if phase == 1 && c.is_digit(10) {
|
||||||
// help vim users discover zed regex syntax
|
|
||||||
// (though we don't try and fix arbitrary patterns for them)
|
|
||||||
buffer.push('$')
|
buffer.push('$')
|
||||||
|
// unescape escaped parens
|
||||||
} else if phase == 0 && c == '(' || c == ')' {
|
} else if phase == 0 && c == '(' || c == ')' {
|
||||||
// un-escape parens
|
|
||||||
} else if c != delimeter {
|
} else if c != delimeter {
|
||||||
buffer.push('\\')
|
buffer.push('\\')
|
||||||
}
|
}
|
||||||
|
@ -312,6 +318,10 @@ fn parse_replace_all(query: &str) -> Replacement {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// escape unescaped parens
|
||||||
|
if phase == 0 && c == '(' || c == ')' {
|
||||||
|
buffer.push('\\')
|
||||||
|
}
|
||||||
buffer.push(c)
|
buffer.push(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,13 +86,13 @@ pub struct CloseItemsToTheRightById {
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CloseActiveItem {
|
pub struct CloseActiveItem {
|
||||||
pub save_behavior: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CloseAllItems {
|
pub struct CloseAllItems {
|
||||||
pub save_behavior: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
|
@ -734,7 +734,7 @@ impl Pane {
|
||||||
let active_item_id = self.items[self.active_item_index].id();
|
let active_item_id = self.items[self.active_item_index].id();
|
||||||
Some(self.close_item_by_id(
|
Some(self.close_item_by_id(
|
||||||
active_item_id,
|
active_item_id,
|
||||||
action.save_behavior.unwrap_or(SaveIntent::Close),
|
action.save_intent.unwrap_or(SaveIntent::Close),
|
||||||
cx,
|
cx,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -742,12 +742,10 @@ impl Pane {
|
||||||
pub fn close_item_by_id(
|
pub fn close_item_by_id(
|
||||||
&mut self,
|
&mut self,
|
||||||
item_id_to_close: usize,
|
item_id_to_close: usize,
|
||||||
save_behavior: SaveIntent,
|
save_intent: SaveIntent,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Task<Result<()>> {
|
) -> Task<Result<()>> {
|
||||||
self.close_items(cx, save_behavior, move |view_id| {
|
self.close_items(cx, save_intent, move |view_id| view_id == item_id_to_close)
|
||||||
view_id == item_id_to_close
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_inactive_items(
|
pub fn close_inactive_items(
|
||||||
|
@ -844,17 +842,17 @@ impl Pane {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(self.close_items(
|
Some(
|
||||||
cx,
|
self.close_items(cx, action.save_intent.unwrap_or(SaveIntent::Close), |_| {
|
||||||
action.save_behavior.unwrap_or(SaveIntent::Close),
|
true
|
||||||
|_| true,
|
}),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_items(
|
pub fn close_items(
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: &mut ViewContext<Pane>,
|
cx: &mut ViewContext<Pane>,
|
||||||
save_behavior: SaveIntent,
|
save_intent: SaveIntent,
|
||||||
should_close: impl 'static + Fn(usize) -> bool,
|
should_close: impl 'static + Fn(usize) -> bool,
|
||||||
) -> Task<Result<()>> {
|
) -> Task<Result<()>> {
|
||||||
// Find the items to close.
|
// Find the items to close.
|
||||||
|
@ -912,7 +910,7 @@ impl Pane {
|
||||||
&pane,
|
&pane,
|
||||||
item_ix,
|
item_ix,
|
||||||
&*item,
|
&*item,
|
||||||
save_behavior,
|
save_intent,
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
|
@ -1010,14 +1008,14 @@ impl Pane {
|
||||||
pane: &WeakViewHandle<Pane>,
|
pane: &WeakViewHandle<Pane>,
|
||||||
item_ix: usize,
|
item_ix: usize,
|
||||||
item: &dyn ItemHandle,
|
item: &dyn ItemHandle,
|
||||||
save_behavior: SaveIntent,
|
save_intent: SaveIntent,
|
||||||
cx: &mut AsyncAppContext,
|
cx: &mut AsyncAppContext,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
const CONFLICT_MESSAGE: &str =
|
const CONFLICT_MESSAGE: &str =
|
||||||
"This file has changed on disk since you started editing it. Do you want to overwrite it?";
|
"This file has changed on disk since you started editing it. Do you want to overwrite it?";
|
||||||
const DIRTY_MESSAGE: &str = "This file contains unsaved edits. Do you want to save it?";
|
const DIRTY_MESSAGE: &str = "This file contains unsaved edits. Do you want to save it?";
|
||||||
|
|
||||||
if save_behavior == SaveIntent::Skip {
|
if save_intent == SaveIntent::Skip {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,17 +1029,17 @@ impl Pane {
|
||||||
});
|
});
|
||||||
|
|
||||||
// when saving a single buffer, we ignore whether or not it's dirty.
|
// when saving a single buffer, we ignore whether or not it's dirty.
|
||||||
if save_behavior == SaveIntent::Save {
|
if save_intent == SaveIntent::Save {
|
||||||
is_dirty = true;
|
is_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if save_behavior == SaveIntent::SaveAs {
|
if save_intent == SaveIntent::SaveAs {
|
||||||
is_dirty = true;
|
is_dirty = true;
|
||||||
has_conflict = false;
|
has_conflict = false;
|
||||||
can_save = false;
|
can_save = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if save_behavior == SaveIntent::Overwrite {
|
if save_intent == SaveIntent::Overwrite {
|
||||||
has_conflict = false;
|
has_conflict = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,7 +1058,7 @@ impl Pane {
|
||||||
_ => return Ok(false),
|
_ => return Ok(false),
|
||||||
}
|
}
|
||||||
} else if is_dirty && (can_save || can_save_as) {
|
} else if is_dirty && (can_save || can_save_as) {
|
||||||
if save_behavior == SaveIntent::Close {
|
if save_intent == SaveIntent::Close {
|
||||||
let will_autosave = cx.read(|cx| {
|
let will_autosave = cx.read(|cx| {
|
||||||
matches!(
|
matches!(
|
||||||
settings::get::<WorkspaceSettings>(cx).autosave,
|
settings::get::<WorkspaceSettings>(cx).autosave,
|
||||||
|
@ -1188,9 +1186,7 @@ impl Pane {
|
||||||
vec![
|
vec![
|
||||||
ContextMenuItem::action(
|
ContextMenuItem::action(
|
||||||
"Close Active Item",
|
"Close Active Item",
|
||||||
CloseActiveItem {
|
CloseActiveItem { save_intent: None },
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ContextMenuItem::action("Close Inactive Items", CloseInactiveItems),
|
ContextMenuItem::action("Close Inactive Items", CloseInactiveItems),
|
||||||
ContextMenuItem::action("Close Clean Items", CloseCleanItems),
|
ContextMenuItem::action("Close Clean Items", CloseCleanItems),
|
||||||
|
@ -1198,9 +1194,7 @@ impl Pane {
|
||||||
ContextMenuItem::action("Close Items To The Right", CloseItemsToTheRight),
|
ContextMenuItem::action("Close Items To The Right", CloseItemsToTheRight),
|
||||||
ContextMenuItem::action(
|
ContextMenuItem::action(
|
||||||
"Close All Items",
|
"Close All Items",
|
||||||
CloseAllItems {
|
CloseAllItems { save_intent: None },
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
|
@ -1247,9 +1241,7 @@ impl Pane {
|
||||||
}),
|
}),
|
||||||
ContextMenuItem::action(
|
ContextMenuItem::action(
|
||||||
"Close All Items",
|
"Close All Items",
|
||||||
CloseAllItems {
|
CloseAllItems { save_intent: None },
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -2182,12 +2174,7 @@ mod tests {
|
||||||
|
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
assert!(pane
|
assert!(pane
|
||||||
.close_active_item(
|
.close_active_item(&CloseActiveItem { save_intent: None }, cx)
|
||||||
&CloseActiveItem {
|
|
||||||
save_behavior: None
|
|
||||||
},
|
|
||||||
cx
|
|
||||||
)
|
|
||||||
.is_none())
|
.is_none())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2439,12 +2426,7 @@ mod tests {
|
||||||
assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx);
|
assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx);
|
||||||
|
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.close_active_item(
|
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
|
||||||
&CloseActiveItem {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
@ -2455,12 +2437,7 @@ mod tests {
|
||||||
assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
|
assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
|
||||||
|
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.close_active_item(
|
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
|
||||||
&CloseActiveItem {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
@ -2468,12 +2445,7 @@ mod tests {
|
||||||
assert_item_labels(&pane, ["A", "B*", "C"], cx);
|
assert_item_labels(&pane, ["A", "B*", "C"], cx);
|
||||||
|
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.close_active_item(
|
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
|
||||||
&CloseActiveItem {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
@ -2481,12 +2453,7 @@ mod tests {
|
||||||
assert_item_labels(&pane, ["A", "C*"], cx);
|
assert_item_labels(&pane, ["A", "C*"], cx);
|
||||||
|
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.close_active_item(
|
pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
|
||||||
&CloseActiveItem {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
@ -2597,12 +2564,7 @@ mod tests {
|
||||||
assert_item_labels(&pane, ["A", "B", "C*"], cx);
|
assert_item_labels(&pane, ["A", "B", "C*"], cx);
|
||||||
|
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.close_all_items(
|
pane.close_all_items(&CloseAllItems { save_intent: None }, cx)
|
||||||
&CloseAllItems {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -163,19 +163,19 @@ pub struct NewFileInDirection(pub SplitDirection);
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct SaveAll {
|
pub struct SaveAll {
|
||||||
pub save_behavior: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Save {
|
pub struct Save {
|
||||||
pub save_behavior: Option<SaveIntent>,
|
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 CloseAllItemsAndPanes {
|
pub struct CloseAllItemsAndPanes {
|
||||||
pub save_behavior: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -294,7 +294,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||||
cx.add_action(
|
cx.add_action(
|
||||||
|workspace: &mut Workspace, action: &Save, cx: &mut ViewContext<Workspace>| {
|
|workspace: &mut Workspace, action: &Save, cx: &mut ViewContext<Workspace>| {
|
||||||
workspace
|
workspace
|
||||||
.save_active_item(action.save_behavior.unwrap_or(SaveIntent::Save), cx)
|
.save_active_item(action.save_intent.unwrap_or(SaveIntent::Save), cx)
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1363,7 +1363,7 @@ impl Workspace {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
let save_all =
|
let save_all =
|
||||||
self.save_all_internal(action.save_behavior.unwrap_or(SaveIntent::SaveAll), cx);
|
self.save_all_internal(action.save_intent.unwrap_or(SaveIntent::SaveAll), cx);
|
||||||
Some(cx.foreground().spawn(async move {
|
Some(cx.foreground().spawn(async move {
|
||||||
save_all.await?;
|
save_all.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1372,7 +1372,7 @@ impl Workspace {
|
||||||
|
|
||||||
fn save_all_internal(
|
fn save_all_internal(
|
||||||
&mut self,
|
&mut self,
|
||||||
save_behaviour: SaveIntent,
|
save_intent: SaveIntent,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Task<Result<bool>> {
|
) -> Task<Result<bool>> {
|
||||||
if self.project.read(cx).is_read_only() {
|
if self.project.read(cx).is_read_only() {
|
||||||
|
@ -1407,7 +1407,7 @@ impl Workspace {
|
||||||
&pane,
|
&pane,
|
||||||
ix,
|
ix,
|
||||||
&*item,
|
&*item,
|
||||||
save_behaviour,
|
save_intent,
|
||||||
&mut cx,
|
&mut cx,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
|
@ -1679,7 +1679,7 @@ impl Workspace {
|
||||||
|
|
||||||
pub fn save_active_item(
|
pub fn save_active_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
save_behavior: SaveIntent,
|
save_intent: SaveIntent,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Task<Result<()>> {
|
) -> Task<Result<()>> {
|
||||||
let project = self.project.clone();
|
let project = self.project.clone();
|
||||||
|
@ -1690,16 +1690,9 @@ impl Workspace {
|
||||||
|
|
||||||
cx.spawn(|_, mut cx| async move {
|
cx.spawn(|_, mut cx| async move {
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
Pane::save_item(
|
Pane::save_item(project, &pane, item_ix, item.as_ref(), save_intent, &mut cx)
|
||||||
project,
|
.await
|
||||||
&pane,
|
.map(|_| ())
|
||||||
item_ix,
|
|
||||||
item.as_ref(),
|
|
||||||
save_behavior,
|
|
||||||
&mut cx,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map(|_| ())
|
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1719,13 +1712,13 @@ impl Workspace {
|
||||||
action: &CloseAllItemsAndPanes,
|
action: &CloseAllItemsAndPanes,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
self.close_all_internal(false, action.save_behavior.unwrap_or(SaveIntent::Close), cx)
|
self.close_all_internal(false, action.save_intent.unwrap_or(SaveIntent::Close), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_all_internal(
|
fn close_all_internal(
|
||||||
&mut self,
|
&mut self,
|
||||||
retain_active_pane: bool,
|
retain_active_pane: bool,
|
||||||
save_behavior: SaveIntent,
|
save_intent: SaveIntent,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
let current_pane = self.active_pane();
|
let current_pane = self.active_pane();
|
||||||
|
@ -1748,7 +1741,7 @@ impl Workspace {
|
||||||
if let Some(close_pane_items) = pane.update(cx, |pane: &mut Pane, cx| {
|
if let Some(close_pane_items) = pane.update(cx, |pane: &mut Pane, cx| {
|
||||||
pane.close_all_items(
|
pane.close_all_items(
|
||||||
&CloseAllItems {
|
&CloseAllItems {
|
||||||
save_behavior: Some(save_behavior),
|
save_intent: Some(save_intent),
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
|
|
@ -38,24 +38,12 @@ pub fn menus() -> Vec<Menu<'static>> {
|
||||||
MenuItem::action("Open Recent...", recent_projects::OpenRecent),
|
MenuItem::action("Open Recent...", recent_projects::OpenRecent),
|
||||||
MenuItem::separator(),
|
MenuItem::separator(),
|
||||||
MenuItem::action("Add Folder to Project…", workspace::AddFolderToProject),
|
MenuItem::action("Add Folder to Project…", workspace::AddFolderToProject),
|
||||||
MenuItem::action(
|
MenuItem::action("Save", workspace::Save { save_intent: None }),
|
||||||
"Save",
|
|
||||||
workspace::Save {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
MenuItem::action("Save As…", workspace::SaveAs),
|
MenuItem::action("Save As…", workspace::SaveAs),
|
||||||
MenuItem::action(
|
MenuItem::action("Save All", workspace::SaveAll { save_intent: None }),
|
||||||
"Save All",
|
|
||||||
workspace::SaveAll {
|
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
MenuItem::action(
|
MenuItem::action(
|
||||||
"Close Editor",
|
"Close Editor",
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem { save_intent: None },
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
MenuItem::action("Close Window", workspace::CloseWindow),
|
MenuItem::action("Close Window", workspace::CloseWindow),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1318,6 +1318,7 @@ mod tests {
|
||||||
let save_task = workspace.update(cx, |workspace, cx| {
|
let save_task = workspace.update(cx, |workspace, cx| {
|
||||||
workspace.save_active_item(SaveIntent::Save, cx)
|
workspace.save_active_item(SaveIntent::Save, cx)
|
||||||
});
|
});
|
||||||
|
cx.foreground().run_until_parked();
|
||||||
window.simulate_prompt_answer(0, cx);
|
window.simulate_prompt_answer(0, cx);
|
||||||
save_task.await.unwrap();
|
save_task.await.unwrap();
|
||||||
editor.read_with(cx, |editor, cx| {
|
editor.read_with(cx, |editor, cx| {
|
||||||
|
@ -1522,9 +1523,7 @@ mod tests {
|
||||||
});
|
});
|
||||||
cx.dispatch_action(
|
cx.dispatch_action(
|
||||||
window.into(),
|
window.into(),
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem { save_intent: None },
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
cx.foreground().run_until_parked();
|
cx.foreground().run_until_parked();
|
||||||
|
@ -1535,9 +1534,7 @@ mod tests {
|
||||||
|
|
||||||
cx.dispatch_action(
|
cx.dispatch_action(
|
||||||
window.into(),
|
window.into(),
|
||||||
workspace::CloseActiveItem {
|
workspace::CloseActiveItem { save_intent: None },
|
||||||
save_behavior: None,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
cx.foreground().run_until_parked();
|
cx.foreground().run_until_parked();
|
||||||
window.simulate_prompt_answer(1, cx);
|
window.simulate_prompt_answer(1, cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue