Code review changes

This commit is contained in:
Conrad Irwin 2023-09-20 20:54:30 -06:00
parent 4bf4c780be
commit 32f8733313
11 changed files with 127 additions and 187 deletions

View file

@ -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

View file

@ -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() {

View file

@ -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();

View file

@ -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,

View file

@ -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| {

View file

@ -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(),
), ),

View file

@ -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)
} }
} }

View file

@ -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

View file

@ -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,
) )

View file

@ -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),
], ],

View file

@ -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);