From 065f71d671829caafb1cd15a6391d2470de511f1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 19 May 2023 22:06:47 +0300 Subject: [PATCH 01/37] Do not refocus project search query on ESC press --- crates/search/src/project_search.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index d96d77eb005aa099642f01f6499db60363caaf6d..915957401d440c40dd13d4b3364b0be76e09f3ef 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -48,7 +48,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(ProjectSearchBar::search_in_new); cx.add_action(ProjectSearchBar::select_next_match); cx.add_action(ProjectSearchBar::select_prev_match); - cx.add_action(ProjectSearchBar::toggle_focus); + cx.add_action(ProjectSearchBar::move_focus_to_results); cx.capture_action(ProjectSearchBar::tab); cx.capture_action(ProjectSearchBar::tab_previous); add_toggle_option_action::(SearchOption::CaseSensitive, cx); @@ -794,18 +794,16 @@ impl ProjectSearchBar { } } - fn toggle_focus(pane: &mut Pane, _: &ToggleFocus, cx: &mut ViewContext) { + fn move_focus_to_results(pane: &mut Pane, _: &ToggleFocus, cx: &mut ViewContext) { if let Some(search_view) = pane .active_item() .and_then(|item| item.downcast::()) { search_view.update(cx, |search_view, cx| { - if search_view.query_editor.is_focused(cx) { - if !search_view.model.read(cx).match_ranges.is_empty() { - search_view.focus_results_editor(cx); - } - } else { - search_view.focus_query_editor(cx); + if search_view.query_editor.is_focused(cx) + && !search_view.model.read(cx).match_ranges.is_empty() + { + search_view.focus_results_editor(cx); } }); } else { From fb11c3e4bf559ffe07563b2b453cf31f52529fa1 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 19 May 2023 16:52:30 -0700 Subject: [PATCH 02/37] Remove stray prints --- crates/project/src/project.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 15741a27f17ce202468680af1f9d9e12a996293d..f91cd999f9dd0068f98ae9f30fda3067469481d2 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2870,10 +2870,8 @@ impl Project { if let Some(LanguageServerState::Running { watched_paths, .. }) = self.language_servers.get_mut(&language_server_id) { - eprintln!("change watch"); let mut builders = HashMap::default(); for watcher in params.watchers { - eprintln!(" {}", watcher.glob_pattern); for worktree in &self.worktrees { if let Some(worktree) = worktree.upgrade(cx) { let worktree = worktree.read(cx); From e32233c8268216ec46ba12475ab35984cf4452e4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 19 May 2023 17:15:05 -0700 Subject: [PATCH 03/37] Fix spurious setting error logs on non-existent setting keys --- crates/client/src/client.rs | 2 +- crates/editor/src/editor_settings.rs | 5 ++- crates/language/src/language_settings.rs | 2 +- crates/project/src/project_settings.rs | 2 +- crates/settings/src/settings_store.rs | 42 ++++++++++++---------- crates/workspace/src/workspace_settings.rs | 2 +- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 311d9a2b8872cd3d63ad861cc986849d93d1e240..c9b83d805a4a87a65eda95f5b765c35841627d30 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -339,7 +339,7 @@ pub struct TelemetrySettings { pub metrics: bool, } -#[derive(Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Default, Clone, Serialize, Deserialize, JsonSchema)] pub struct TelemetrySettingsContent { pub diagnostics: Option, pub metrics: Option, diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index 5108d2740875bd38dabea3c4ca06ca78784d1f35..a3f38a3dc096c6a4ce8365911313c31c147d06e7 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -10,17 +10,16 @@ pub struct EditorSettings { pub show_scrollbars: ShowScrollbars, } -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum ShowScrollbars { - #[default] Auto, System, Always, Never, } -#[derive(Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] pub struct EditorSettingsContent { pub cursor_blink: Option, pub hover_popover_enabled: Option, diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index d877304f1d991eeb22a58022f6c9723be71ba1cd..c98297c03648f7db9c307a592b4f7bf2dcfe279d 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -49,7 +49,7 @@ pub struct CopilotSettings { pub disabled_globs: Vec, } -#[derive(Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] pub struct AllLanguageSettingsContent { #[serde(default)] pub features: Option, diff --git a/crates/project/src/project_settings.rs b/crates/project/src/project_settings.rs index 92e8cfcca79fc59f17a879c5c7ade0264a6b40bf..c542d1d13fd42c3cd2721c92981e74129556a554 100644 --- a/crates/project/src/project_settings.rs +++ b/crates/project/src/project_settings.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use settings::Setting; use std::sync::Arc; -#[derive(Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] pub struct ProjectSettings { #[serde(default)] pub lsp: HashMap, LspSettings>, diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index dd81b05434af71680f85f18b644839d7a6b47875..329b290a3192c66545e7001635917e448acc1e81 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -25,7 +25,7 @@ pub trait Setting: 'static { const KEY: Option<&'static str>; /// The type that is stored in an individual JSON file. - type FileContent: Clone + Serialize + DeserializeOwned + JsonSchema; + type FileContent: Clone + Default + Serialize + DeserializeOwned + JsonSchema; /// The logic for combining together values from one or more JSON files into the /// final value for this setting. @@ -460,11 +460,12 @@ impl SettingsStore { // If the global settings file changed, reload the global value for the field. if changed_local_path.is_none() { - setting_value.set_global_value(setting_value.load_setting( - &default_settings, - &user_settings_stack, - cx, - )?); + if let Some(value) = setting_value + .load_setting(&default_settings, &user_settings_stack, cx) + .log_err() + { + setting_value.set_global_value(value); + } } // Reload the local values for the setting. @@ -495,14 +496,12 @@ impl SettingsStore { continue; } - setting_value.set_local_value( - path.clone(), - setting_value.load_setting( - &default_settings, - &user_settings_stack, - cx, - )?, - ); + if let Some(value) = setting_value + .load_setting(&default_settings, &user_settings_stack, cx) + .log_err() + { + setting_value.set_local_value(path.clone(), value); + } } } } @@ -536,7 +535,12 @@ impl AnySettingValue for SettingValue { fn deserialize_setting(&self, mut json: &serde_json::Value) -> Result { if let Some(key) = T::KEY { - json = json.get(key).unwrap_or(&serde_json::Value::Null); + if let Some(value) = json.get(key) { + json = value; + } else { + let value = T::FileContent::default(); + return Ok(DeserializedSetting(Box::new(value))); + } } let value = T::FileContent::deserialize(json)?; Ok(DeserializedSetting(Box::new(value))) @@ -1126,7 +1130,7 @@ mod tests { staff: bool, } - #[derive(Clone, Serialize, Deserialize, JsonSchema)] + #[derive(Default, Clone, Serialize, Deserialize, JsonSchema)] struct UserSettingsJson { name: Option, age: Option, @@ -1170,7 +1174,7 @@ mod tests { key2: String, } - #[derive(Clone, Serialize, Deserialize, JsonSchema)] + #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] struct MultiKeySettingsJson { key1: Option, key2: Option, @@ -1203,7 +1207,7 @@ mod tests { Hour24, } - #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] + #[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema)] struct JournalSettingsJson { pub path: Option, pub hour_format: Option, @@ -1223,7 +1227,7 @@ mod tests { } } - #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] + #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] struct LanguageSettings { #[serde(default)] languages: HashMap, diff --git a/crates/workspace/src/workspace_settings.rs b/crates/workspace/src/workspace_settings.rs index 41e47964910575a06fb0891c5e75d6ced13eefd7..4ec0a22b06800869bce8dcbd0ef13a5e646b2c8b 100644 --- a/crates/workspace/src/workspace_settings.rs +++ b/crates/workspace/src/workspace_settings.rs @@ -17,7 +17,7 @@ pub struct WorkspaceSettings { pub git: GitSettings, } -#[derive(Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] pub struct WorkspaceSettingsContent { pub active_pane_magnification: Option, pub confirm_quit: Option, From 7190840081212e1013dad588dbb3af913c89b304 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 22 May 2023 09:12:36 -0400 Subject: [PATCH 04/37] Add paragraph based vertical movements --- assets/keymaps/default.json | 4 ++ crates/editor/src/editor.rs | 82 +++++++++++++++++++++++++++++++++++ crates/editor/src/movement.rs | 38 ++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 01a09e0cba8f54dc2b436914cf515fcc120d7eff..cab4333f74c30842e2f23927ece00c4c03a398f1 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -67,10 +67,12 @@ "cmd-z": "editor::Undo", "cmd-shift-z": "editor::Redo", "up": "editor::MoveUp", + "ctrl-up": "editor::MoveToStartOfParagraph", "pageup": "editor::PageUp", "shift-pageup": "editor::MovePageUp", "home": "editor::MoveToBeginningOfLine", "down": "editor::MoveDown", + "ctrl-down": "editor::MoveToEndOfParagraph", "pagedown": "editor::PageDown", "shift-pagedown": "editor::MovePageDown", "end": "editor::MoveToEndOfLine", @@ -103,6 +105,8 @@ "alt-shift-b": "editor::SelectToPreviousWordStart", "alt-shift-right": "editor::SelectToNextWordEnd", "alt-shift-f": "editor::SelectToNextWordEnd", + "ctrl-shift-up": "editor::SelectToStartOfParagraph", + "ctrl-shift-down": "editor::SelectToEndOfParagraph", "cmd-shift-up": "editor::SelectToBeginning", "cmd-shift-down": "editor::SelectToEnd", "cmd-a": "editor::SelectAll", diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 7207e3c91c6da9f1e1ecfb37b94a560c875127d3..cf614fccf729ae90ca9ea5f7d527e4979869ef9d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -216,6 +216,8 @@ actions!( MoveToNextSubwordEnd, MoveToBeginningOfLine, MoveToEndOfLine, + MoveToStartOfParagraph, + MoveToEndOfParagraph, MoveToBeginning, MoveToEnd, SelectUp, @@ -226,6 +228,8 @@ actions!( SelectToPreviousSubwordStart, SelectToNextWordEnd, SelectToNextSubwordEnd, + SelectToStartOfParagraph, + SelectToEndOfParagraph, SelectToBeginning, SelectToEnd, SelectAll, @@ -337,6 +341,8 @@ pub fn init(cx: &mut AppContext) { cx.add_action(Editor::move_to_next_subword_end); cx.add_action(Editor::move_to_beginning_of_line); cx.add_action(Editor::move_to_end_of_line); + cx.add_action(Editor::move_to_start_of_paragraph); + cx.add_action(Editor::move_to_end_of_paragraph); cx.add_action(Editor::move_to_beginning); cx.add_action(Editor::move_to_end); cx.add_action(Editor::select_up); @@ -349,6 +355,8 @@ pub fn init(cx: &mut AppContext) { cx.add_action(Editor::select_to_next_subword_end); cx.add_action(Editor::select_to_beginning_of_line); cx.add_action(Editor::select_to_end_of_line); + cx.add_action(Editor::select_to_start_of_paragraph); + cx.add_action(Editor::select_to_end_of_paragraph); cx.add_action(Editor::select_to_beginning); cx.add_action(Editor::select_to_end); cx.add_action(Editor::select_all); @@ -4762,6 +4770,80 @@ impl Editor { }); } + pub fn move_to_start_of_paragraph( + &mut self, + _: &MoveToStartOfParagraph, + cx: &mut ViewContext, + ) { + if matches!(self.mode, EditorMode::SingleLine) { + cx.propagate_action(); + return; + } + + self.change_selections(Some(Autoscroll::fit()), cx, |s| { + s.move_with(|map, selection| { + selection.collapse_to( + movement::start_of_paragraph(map, selection.head()), + SelectionGoal::None, + ) + }); + }) + } + + pub fn move_to_end_of_paragraph( + &mut self, + _: &MoveToEndOfParagraph, + cx: &mut ViewContext, + ) { + if matches!(self.mode, EditorMode::SingleLine) { + cx.propagate_action(); + return; + } + + self.change_selections(Some(Autoscroll::fit()), cx, |s| { + s.move_with(|map, selection| { + selection.collapse_to( + movement::end_of_paragraph(map, selection.head()), + SelectionGoal::None, + ) + }); + }) + } + + pub fn select_to_start_of_paragraph( + &mut self, + _: &SelectToStartOfParagraph, + cx: &mut ViewContext, + ) { + if matches!(self.mode, EditorMode::SingleLine) { + cx.propagate_action(); + return; + } + + self.change_selections(Some(Autoscroll::fit()), cx, |s| { + s.move_heads_with(|map, head, _| { + (movement::start_of_paragraph(map, head), SelectionGoal::None) + }); + }) + } + + pub fn select_to_end_of_paragraph( + &mut self, + _: &SelectToEndOfParagraph, + cx: &mut ViewContext, + ) { + if matches!(self.mode, EditorMode::SingleLine) { + cx.propagate_action(); + return; + } + + self.change_selections(Some(Autoscroll::fit()), cx, |s| { + s.move_heads_with(|map, head, _| { + (movement::end_of_paragraph(map, head), SelectionGoal::None) + }); + }) + } + pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext) { if matches!(self.mode, EditorMode::SingleLine) { cx.propagate_action(); diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index 6c9bd6cb4fe1554d9a04a840db78ff8edc88b4c9..523a0af9640aa98b3f3e3d7b9fd980768f1e4f89 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -193,6 +193,44 @@ pub fn next_subword_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPo }) } +pub fn start_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint { + let point = display_point.to_point(map); + if point.row == 0 { + return map.max_point(); + } + + let mut found_non_blank_line = false; + for row in (0..point.row + 1).rev() { + let blank = map.buffer_snapshot.is_line_blank(row); + if found_non_blank_line && blank { + return Point::new(row, 0).to_display_point(map); + } + + found_non_blank_line |= !blank; + } + + DisplayPoint::zero() +} + +pub fn end_of_paragraph(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint { + let point = display_point.to_point(map); + if point.row == map.max_buffer_row() { + return DisplayPoint::zero(); + } + + let mut found_non_blank_line = false; + for row in point.row..map.max_buffer_row() + 1 { + let blank = map.buffer_snapshot.is_line_blank(row); + if found_non_blank_line && blank { + return Point::new(row, 0).to_display_point(map); + } + + found_non_blank_line |= !blank; + } + + map.max_point() +} + /// Scans for a boundary preceding the given start point `from` until a boundary is found, indicated by the /// given predicate returning true. The predicate is called with the character to the left and right /// of the candidate boundary location, and will be called with `\n` characters indicating the start From 44903bc193fc0b8ef04990aa3fd9073117fe9514 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 22 May 2023 11:48:07 -0400 Subject: [PATCH 05/37] Add test for paragraph vertical movements --- crates/editor/src/editor_tests.rs | 112 ++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 9a21429301b6906e025f87c14659a8594279c11d..180de155e998fff1492c22311502d87ebcf744bf 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -1243,6 +1243,118 @@ fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) { }); } +#[gpui::test] +async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx); + + let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); + cx.simulate_window_resize(cx.window_id, vec2f(100., 4. * line_height)); + + cx.set_state( + &r#"ˇone + two + + three + fourˇ + five + + six"# + .unindent(), + ); + + cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two + ˇ + three + four + five + ˇ + six"# + .unindent(), + ); + + cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two + + three + four + five + ˇ + sixˇ"# + .unindent(), + ); + + cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); + cx.assert_editor_state( + &r#"ˇone + two + + three + four + five + + sixˇ"# + .unindent(), + ); + + cx.update_editor(|editor, cx| editor.move_to_end_of_paragraph(&MoveToEndOfParagraph, cx)); + cx.assert_editor_state( + &r#"ˇone + two + ˇ + three + four + five + + six"# + .unindent(), + ); + + cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); + cx.assert_editor_state( + &r#"ˇone + two + + three + four + five + + sixˇ"# + .unindent(), + ); + + cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two + + three + four + five + ˇ + sixˇ"# + .unindent(), + ); + + cx.update_editor(|editor, cx| editor.move_to_start_of_paragraph(&MoveToStartOfParagraph, cx)); + cx.assert_editor_state( + &r#"one + two + ˇ + three + four + five + ˇ + six"# + .unindent(), + ); +} + #[gpui::test] async fn test_move_page_up_page_down(cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); From 21ada545b07030398a90bf1ef1dbe386cb6cd26c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 22 May 2023 08:48:37 -0700 Subject: [PATCH 06/37] Remove assertions about behavior on invalid settings file --- crates/settings/src/settings_store.rs | 31 --------------------------- 1 file changed, 31 deletions(-) diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 329b290a3192c66545e7001635917e448acc1e81..71b3cc635f4e03465d94cb498567c21bd36bd76a 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -830,37 +830,6 @@ mod tests { store.register_setting::(cx); store.register_setting::(cx); store.register_setting::(cx); - - // error - missing required field in default settings - store - .set_default_settings( - r#"{ - "user": { - "name": "John Doe", - "age": 30, - "staff": false - } - }"#, - cx, - ) - .unwrap_err(); - - // error - type error in default settings - store - .set_default_settings( - r#"{ - "turbo": "the-wrong-type", - "user": { - "name": "John Doe", - "age": 30, - "staff": false - } - }"#, - cx, - ) - .unwrap_err(); - - // valid default settings. store .set_default_settings( r#"{ From b80cb737452fe5fd84d4d295c1cfcb826496070f Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 22 May 2023 12:09:54 -0400 Subject: [PATCH 07/37] Add git to project panel in theme, use different values for dark and light --- styles/src/styleTree/editor.ts | 15 +++++++++++---- styles/src/styleTree/projectPanel.ts | 13 ++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index 7caa8b1c674996822d91a0a3b120b44be6e44cbc..2443717e4d54e2d1e6a38d30cc379865f79d767b 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -3,9 +3,10 @@ import { ColorScheme, Layer, StyleSets } from "../themes/common/colorScheme" import { background, border, borderColor, foreground, text } from "./components" import hoverPopover from "./hoverPopover" -import { SyntaxHighlightStyle, buildSyntax } from "../themes/common/syntax" +import { buildSyntax } from "../themes/common/syntax" export default function editor(colorScheme: ColorScheme) { + const { isLight } = colorScheme let layer = colorScheme.highest const autocompleteItem = { @@ -97,9 +98,15 @@ export default function editor(colorScheme: ColorScheme) { foldBackground: foreground(layer, "variant"), }, diff: { - deleted: foreground(layer, "negative"), - modified: foreground(layer, "warning"), - inserted: foreground(layer, "positive"), + deleted: isLight + ? colorScheme.ramps.red(0.5).hex() + : colorScheme.ramps.red(0.4).hex(), + modified: isLight + ? colorScheme.ramps.yellow(0.3).hex() + : colorScheme.ramps.yellow(0.5).hex(), + inserted: isLight + ? colorScheme.ramps.green(0.4).hex() + : colorScheme.ramps.green(0.5).hex(), removedWidthEm: 0.275, widthEm: 0.22, cornerRadius: 0.2, diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 3d06a683abebf71d55311273f8e93f08876ea509..0c32ee7132c62e195a749d12e8bc1391490266fd 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -3,6 +3,7 @@ import { withOpacity } from "../utils/color" import { background, border, foreground, text } from "./components" export default function projectPanel(colorScheme: ColorScheme) { + const { isLight } = colorScheme let layer = colorScheme.middle let baseEntry = { @@ -28,6 +29,16 @@ export default function projectPanel(colorScheme: ColorScheme) { background: background(layer, "active"), text: text(layer, "mono", "active", { size: "sm" }), }, + status: { + git: { + modified: isLight + ? colorScheme.ramps.yellow(0.6).hex() + : colorScheme.ramps.yellow(0.5).hex(), + inserted: isLight + ? colorScheme.ramps.green(0.4).hex() + : colorScheme.ramps.green(0.5).hex(), + } + } } return { @@ -79,6 +90,6 @@ export default function projectPanel(colorScheme: ColorScheme) { background: background(layer, "on"), text: text(layer, "mono", "on", { size: "sm" }), selection: colorScheme.players[0], - }, + } } } From 2200a22c07c4939e1f9f3370442e25531521335c Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 09:55:59 -0700 Subject: [PATCH 08/37] Wire project panel themes into rust --- crates/project_panel/src/project_panel.rs | 33 ++++++++------ crates/theme/src/theme.rs | 12 +++++ crates/theme/src/ui.rs | 55 +---------------------- styles/src/styleTree/projectPanel.ts | 23 +++++----- 4 files changed, 47 insertions(+), 76 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index ce0dd9e22212ad954e5398eff8c3a209b7ea4e78..dd28bdd73e2ec3231188690ca06309deaaa1bfab 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -6,8 +6,8 @@ use gpui::{ actions, anyhow::{anyhow, Result}, elements::{ - AnchorCorner, ChildView, ComponentHost, ContainerStyle, Empty, Flex, MouseEventHandler, - ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, + AnchorCorner, ChildView, ContainerStyle, Empty, Flex, Label, + MouseEventHandler, ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, }, geometry::vector::Vector2F, keymap_matcher::KeymapContext, @@ -28,7 +28,7 @@ use std::{ path::Path, sync::Arc, }; -use theme::{ui::FileName, ProjectPanelEntry}; +use theme::ProjectPanelEntry; use unicase::UniCase; use workspace::Workspace; @@ -1079,6 +1079,17 @@ impl ProjectPanel { let kind = details.kind; let show_editor = details.is_editing && !details.is_processing; + let mut filename_text_style = style.text.clone(); + filename_text_style.color = details + .git_status + .as_ref() + .map(|status| match status { + GitFileStatus::Added => style.status.git.inserted, + GitFileStatus::Modified => style.status.git.modified, + GitFileStatus::Conflict => style.text.color, + }) + .unwrap_or(style.text.color); + Flex::row() .with_child( if kind == EntryKind::Dir { @@ -1106,16 +1117,12 @@ impl ProjectPanel { .flex(1.0, true) .into_any() } else { - ComponentHost::new(FileName::new( - details.filename.clone(), - details.git_status, - FileName::style(style.text.clone(), &theme::current(cx)), - )) - .contained() - .with_margin_left(style.icon_spacing) - .aligned() - .left() - .into_any() + Label::new(details.filename.clone(), filename_text_style) + .contained() + .with_margin_left(style.icon_spacing) + .aligned() + .left() + .into_any() }) .constrained() .with_height(style.height) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index eb404cdaad6ad5a8d5e7fa5c572e0ad709e6c4e4..5a799465893e61cda58d8f9a0ecd0cc69bd59591 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -446,6 +446,18 @@ pub struct ProjectPanelEntry { pub icon_color: Color, pub icon_size: f32, pub icon_spacing: f32, + pub status: EntryStatus, +} + +#[derive(Clone, Debug, Deserialize, Default)] +pub struct EntryStatus { + pub git: GitProjectStatus, +} + +#[derive(Clone, Debug, Deserialize, Default)] +pub struct GitProjectStatus { + pub modified: Color, + pub inserted: Color, } #[derive(Clone, Debug, Deserialize, Default)] diff --git a/crates/theme/src/ui.rs b/crates/theme/src/ui.rs index e4df24c89fcf92842e663e8a50792709a19b7981..1799f37aedb85b87b736057813de0f168546248c 100644 --- a/crates/theme/src/ui.rs +++ b/crates/theme/src/ui.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; -use fs::repository::GitFileStatus; use gpui::{ color::Color, elements::{ @@ -12,11 +11,11 @@ use gpui::{ platform, platform::MouseButton, scene::MouseClick, - Action, AnyElement, Element, EventContext, MouseState, View, ViewContext, + Action, Element, EventContext, MouseState, View, ViewContext, }; use serde::Deserialize; -use crate::{ContainedText, Interactive, Theme}; +use crate::{ContainedText, Interactive}; #[derive(Clone, Deserialize, Default)] pub struct CheckboxStyle { @@ -253,53 +252,3 @@ where .constrained() .with_height(style.dimensions().y()) } - -pub struct FileName { - filename: String, - git_status: Option, - style: FileNameStyle, -} - -pub struct FileNameStyle { - template_style: LabelStyle, - git_inserted: Color, - git_modified: Color, - git_deleted: Color, -} - -impl FileName { - pub fn new(filename: String, git_status: Option, style: FileNameStyle) -> Self { - FileName { - filename, - git_status, - style, - } - } - - pub fn style>(style: I, theme: &Theme) -> FileNameStyle { - FileNameStyle { - template_style: style.into(), - git_inserted: theme.editor.diff.inserted, - git_modified: theme.editor.diff.modified, - git_deleted: theme.editor.diff.deleted, - } - } -} - -impl gpui::elements::Component for FileName { - fn render(&self, _: &mut V, _: &mut ViewContext) -> AnyElement { - // Prepare colors for git statuses - let mut filename_text_style = self.style.template_style.text.clone(); - filename_text_style.color = self - .git_status - .as_ref() - .map(|status| match status { - GitFileStatus::Added => self.style.git_inserted, - GitFileStatus::Modified => self.style.git_modified, - GitFileStatus::Conflict => self.style.git_deleted, - }) - .unwrap_or(self.style.template_style.text.color); - - Label::new(self.filename.clone(), filename_text_style).into_any() - } -} diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 0c32ee7132c62e195a749d12e8bc1391490266fd..976cdede5cdab5f3760fd51a4343b04a771944b5 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -13,6 +13,17 @@ export default function projectPanel(colorScheme: ColorScheme) { iconSpacing: 8, } + let status = { + git: { + modified: isLight + ? colorScheme.ramps.yellow(0.6).hex() + : colorScheme.ramps.yellow(0.5).hex(), + inserted: isLight + ? colorScheme.ramps.green(0.4).hex() + : colorScheme.ramps.green(0.5).hex(), + } + } + let entry = { ...baseEntry, text: text(layer, "mono", "variant", { size: "sm" }), @@ -29,16 +40,7 @@ export default function projectPanel(colorScheme: ColorScheme) { background: background(layer, "active"), text: text(layer, "mono", "active", { size: "sm" }), }, - status: { - git: { - modified: isLight - ? colorScheme.ramps.yellow(0.6).hex() - : colorScheme.ramps.yellow(0.5).hex(), - inserted: isLight - ? colorScheme.ramps.green(0.4).hex() - : colorScheme.ramps.green(0.5).hex(), - } - } + status } return { @@ -70,6 +72,7 @@ export default function projectPanel(colorScheme: ColorScheme) { entry, draggedEntry: { ...baseEntry, + status, text: text(layer, "mono", "on", { size: "sm" }), background: withOpacity(background(layer, "on"), 0.9), border: border(layer), From af73c1af06b6165550d32dab9d9c5b980e4bbace Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 10:03:02 -0700 Subject: [PATCH 09/37] Add seperate scrollbar styling --- crates/editor/src/element.rs | 2 +- crates/theme/src/theme.rs | 8 ++++++++ crates/theme/src/ui.rs | 2 +- styles/src/styleTree/editor.ts | 11 +++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 57dc3293f6f9dc322c1a7744f97b21000fb34c0c..502975c144ff5ff7d187378c54d085edb3837f7c 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1052,7 +1052,7 @@ impl EditorElement { ..Default::default() }); - let diff_style = theme::current(cx).editor.diff.clone(); + let diff_style = &theme::current(cx).editor.scrollbar.git; for hunk in layout .position_map .snapshot diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 5a799465893e61cda58d8f9a0ecd0cc69bd59591..c589137e73c5df2cc917959c3793999e8d05f78c 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -682,6 +682,14 @@ pub struct Scrollbar { pub thumb: ContainerStyle, pub width: f32, pub min_height_factor: f32, + pub git: GitDiffColors +} + +#[derive(Clone, Deserialize, Default)] +pub struct GitDiffColors { + pub inserted: Color, + pub modified: Color, + pub deleted: Color } #[derive(Clone, Deserialize, Default)] diff --git a/crates/theme/src/ui.rs b/crates/theme/src/ui.rs index 1799f37aedb85b87b736057813de0f168546248c..b86bfca8c42ae05900d76d86e19544531c245899 100644 --- a/crates/theme/src/ui.rs +++ b/crates/theme/src/ui.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use gpui::{ color::Color, elements::{ - ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label, LabelStyle, + ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label, MouseEventHandler, ParentElement, Stack, Svg, }, fonts::TextStyle, diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index 2443717e4d54e2d1e6a38d30cc379865f79d767b..a13ae49c7d89f1a1589fcf3677f51d9993d4c217 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -247,6 +247,17 @@ export default function editor(colorScheme: ColorScheme) { color: borderColor(layer, "variant"), }, }, + git: { + deleted: isLight + ? colorScheme.ramps.red(0.5).hex() + : colorScheme.ramps.red(0.4).hex(), + modified: isLight + ? colorScheme.ramps.yellow(0.3).hex() + : colorScheme.ramps.yellow(0.5).hex(), + inserted: isLight + ? colorScheme.ramps.green(0.4).hex() + : colorScheme.ramps.green(0.5).hex(), + } }, compositionMark: { underline: { From a355b4c135c1c9f656bc3c3fa3057a052ffea196 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 10:09:55 -0700 Subject: [PATCH 10/37] Add conflict styles to project panel --- crates/theme/src/theme.rs | 1 + styles/src/styleTree/projectPanel.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index c589137e73c5df2cc917959c3793999e8d05f78c..b5ac126a690ca2ba7023e526297f57302934bb4a 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -458,6 +458,7 @@ pub struct EntryStatus { pub struct GitProjectStatus { pub modified: Color, pub inserted: Color, + pub conflict: Color, } #[derive(Clone, Debug, Deserialize, Default)] diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 976cdede5cdab5f3760fd51a4343b04a771944b5..81dded151e54a091ac91ceba130c27449946594d 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -21,6 +21,9 @@ export default function projectPanel(colorScheme: ColorScheme) { inserted: isLight ? colorScheme.ramps.green(0.4).hex() : colorScheme.ramps.green(0.5).hex(), + conflict: isLight + ? colorScheme.ramps.red(0.4).hex() + : colorScheme.ramps.red(0.5).hex(), } } From ef81813d569fb1d815eaba2f5aebaa7a4157610f Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 10:10:47 -0700 Subject: [PATCH 11/37] Wire in conflict styling --- crates/project_panel/src/project_panel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index dd28bdd73e2ec3231188690ca06309deaaa1bfab..22b6b3fd75b767a99c0a453dd531000fad4242f4 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1086,7 +1086,7 @@ impl ProjectPanel { .map(|status| match status { GitFileStatus::Added => style.status.git.inserted, GitFileStatus::Modified => style.status.git.modified, - GitFileStatus::Conflict => style.text.color, + GitFileStatus::Conflict => style.status.git.conflict, }) .unwrap_or(style.text.color); From 8669dcdc81332f1d3f1cf89a45d3e919a6349277 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 10:55:44 -0700 Subject: [PATCH 12/37] Make scrollbar content detection cheaper Remove scrollbars from multibuffers co-authored-by: max --- crates/editor/src/editor.rs | 8 +-- crates/editor/src/element.rs | 93 ++++++++++++++++--------------- crates/editor/src/multi_buffer.rs | 9 +++ crates/git/src/diff.rs | 4 ++ 4 files changed, 65 insertions(+), 49 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 7207e3c91c6da9f1e1ecfb37b94a560c875127d3..0a4204ba2a0b635aec36818bc68cefb7ceb9a2fa 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -526,11 +526,9 @@ pub struct EditorSnapshot { } impl EditorSnapshot { - fn has_scrollbar_info(&self) -> bool { - self.buffer_snapshot - .git_diff_hunks_in_range(0..self.max_point().row()) - .next() - .is_some() + fn has_scrollbar_info(&self, is_singleton: bool) -> bool { + is_singleton && self.buffer_snapshot + .has_git_diffs() } } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 57dc3293f6f9dc322c1a7744f97b21000fb34c0c..5a057390d58ac7c8f01138166b531085492948a7 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1052,51 +1052,53 @@ impl EditorElement { ..Default::default() }); - let diff_style = theme::current(cx).editor.diff.clone(); - for hunk in layout - .position_map - .snapshot - .buffer_snapshot - .git_diff_hunks_in_range(0..(max_row.floor() as u32)) - { - let start_display = Point::new(hunk.buffer_range.start, 0) - .to_display_point(&layout.position_map.snapshot.display_snapshot); - let end_display = Point::new(hunk.buffer_range.end, 0) - .to_display_point(&layout.position_map.snapshot.display_snapshot); - let start_y = y_for_row(start_display.row() as f32); - let mut end_y = if hunk.buffer_range.start == hunk.buffer_range.end { - y_for_row((end_display.row() + 1) as f32) - } else { - y_for_row((end_display.row()) as f32) - }; + if layout.is_singleton { + let diff_style = theme::current(cx).editor.diff.clone(); + for hunk in layout + .position_map + .snapshot + .buffer_snapshot + .git_diff_hunks_in_range(0..(max_row.floor() as u32)) + { + let start_display = Point::new(hunk.buffer_range.start, 0) + .to_display_point(&layout.position_map.snapshot.display_snapshot); + let end_display = Point::new(hunk.buffer_range.end, 0) + .to_display_point(&layout.position_map.snapshot.display_snapshot); + let start_y = y_for_row(start_display.row() as f32); + let mut end_y = if hunk.buffer_range.start == hunk.buffer_range.end { + y_for_row((end_display.row() + 1) as f32) + } else { + y_for_row((end_display.row()) as f32) + }; - if end_y - start_y < 1. { - end_y = start_y + 1.; - } - let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); - - let color = match hunk.status() { - DiffHunkStatus::Added => diff_style.inserted, - DiffHunkStatus::Modified => diff_style.modified, - DiffHunkStatus::Removed => diff_style.deleted, - }; - - let border = Border { - width: 1., - color: style.thumb.border.color, - overlay: false, - top: false, - right: true, - bottom: false, - left: true, - }; + if end_y - start_y < 1. { + end_y = start_y + 1.; + } + let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y)); - scene.push_quad(Quad { - bounds, - background: Some(color), - border, - corner_radius: style.thumb.corner_radius, - }) + let color = match hunk.status() { + DiffHunkStatus::Added => diff_style.inserted, + DiffHunkStatus::Modified => diff_style.modified, + DiffHunkStatus::Removed => diff_style.deleted, + }; + + let border = Border { + width: 1., + color: style.thumb.border.color, + overlay: false, + top: false, + right: true, + bottom: false, + left: true, + }; + + scene.push_quad(Quad { + bounds, + background: Some(color), + border, + corner_radius: style.thumb.corner_radius, + }) + } } scene.push_quad(Quad { @@ -2067,7 +2069,8 @@ impl Element for EditorElement { let show_scrollbars = match settings::get::(cx).show_scrollbars { ShowScrollbars::Auto => { - snapshot.has_scrollbar_info() || editor.scroll_manager.scrollbars_visible() + snapshot.has_scrollbar_info(is_singleton) + || editor.scroll_manager.scrollbars_visible() } ShowScrollbars::System => editor.scroll_manager.scrollbars_visible(), ShowScrollbars::Always => true, @@ -2290,6 +2293,7 @@ impl Element for EditorElement { text_size, scrollbar_row_range, show_scrollbars, + is_singleton, max_row, gutter_margin, active_rows, @@ -2445,6 +2449,7 @@ pub struct LayoutState { selections: Vec<(ReplicaId, Vec)>, scrollbar_row_range: Range, show_scrollbars: bool, + is_singleton: bool, max_row: u32, context_menu: Option<(DisplayPoint, AnyElement)>, code_actions_indicator: Option<(u32, AnyElement)>, diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 1423473e1ad8c3d952d6bb47ef95d20286e0a46f..6a617756974ee5a2021c1377ba2edb00468aa304 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -2841,6 +2841,15 @@ impl MultiBufferSnapshot { }) } + pub fn has_git_diffs(&self) -> bool { + for excerpt in self.excerpts.iter() { + if !excerpt.buffer.git_diff.is_empty() { + return true; + } + } + false + } + pub fn git_diff_hunks_in_range_rev<'a>( &'a self, row_range: Range, diff --git a/crates/git/src/diff.rs b/crates/git/src/diff.rs index 8704f850055aa4edb5f03109ecd1fa5d18d4aa5c..8260dfc98d9834f8cefff6dfc274a4d7a9e237d7 100644 --- a/crates/git/src/diff.rs +++ b/crates/git/src/diff.rs @@ -71,6 +71,10 @@ impl BufferDiff { } } + pub fn is_empty(&self) -> bool { + self.tree.is_empty() + } + pub fn hunks_in_row_range<'a>( &'a self, range: Range, From 6264b2478809b807e36dc33f0aa27be421bf5c0c Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 11:04:36 -0700 Subject: [PATCH 13/37] fmt --- crates/editor/src/editor.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 0a4204ba2a0b635aec36818bc68cefb7ceb9a2fa..12f5b3b872f6c51fb5b33324c249e77659d3785e 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -527,8 +527,7 @@ pub struct EditorSnapshot { impl EditorSnapshot { fn has_scrollbar_info(&self, is_singleton: bool) -> bool { - is_singleton && self.buffer_snapshot - .has_git_diffs() + is_singleton && self.buffer_snapshot.has_git_diffs() } } From 6f4b6eec5b2584c33602928a0bc64f9f0af18f01 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 11:10:13 -0700 Subject: [PATCH 14/37] Diagnostics pane was not focusable with the mouse --- crates/diagnostics/src/diagnostics.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index a202a6082c0522901a349c9537e49a2fe7e2c6b8..27f75ea89680de1cc6fbe80d909edc33503dd690 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -33,7 +33,7 @@ use theme::ThemeSettings; use util::TryFutureExt; use workspace::{ item::{BreadcrumbText, Item, ItemEvent, ItemHandle}, - ItemNavHistory, Pane, ToolbarItemLocation, Workspace, + ItemNavHistory, Pane, ToolbarItemLocation, Workspace, PaneBackdrop, }; actions!(diagnostics, [Deploy]); @@ -90,11 +90,12 @@ impl View for ProjectDiagnosticsEditor { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if self.path_states.is_empty() { let theme = &theme::current(cx).project_diagnostics; - Label::new("No problems in workspace", theme.empty_message.clone()) + PaneBackdrop::new(cx.view_id(), Label::new("No problems in workspace", theme.empty_message.clone()) .aligned() .contained() .with_style(theme.container) - .into_any() + .into_any()).into_any() + } else { ChildView::new(&self.editor, cx).into_any() } From 04355215b2d1489a763345ac73078399bad7d18f Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 22 May 2023 14:44:05 -0400 Subject: [PATCH 15/37] Indent all release note lines for each PR --- script/get-preview-channel-changes | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/script/get-preview-channel-changes b/script/get-preview-channel-changes index 47623125f9c28fa12898a21d1a629c69fcf6158e..5a0be3ed6669233bb50e001320259f09c626c288 100755 --- a/script/get-preview-channel-changes +++ b/script/get-preview-channel-changes @@ -69,9 +69,12 @@ async function main() { let releaseNotes = (pullRequest.body || "").split("Release Notes:")[1]; if (releaseNotes) { - releaseNotes = releaseNotes.trim(); + releaseNotes = releaseNotes.trim().split("\n") console.log(" Release Notes:"); - console.log(` ${releaseNotes}`); + + for (const line of releaseNotes) { + console.log(` ${line}`); + } } console.log() From e59c8e9d611405eb7063751f2ba87d2d0bc72324 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 11:44:23 -0700 Subject: [PATCH 16/37] Fix diagnostic pane not being closeable --- crates/diagnostics/src/diagnostics.rs | 26 +++++++++++++++++--------- crates/editor/src/editor.rs | 2 ++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 27f75ea89680de1cc6fbe80d909edc33503dd690..182efdfdd6c520e30d285ed822f66f9a3f98a368 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -33,7 +33,7 @@ use theme::ThemeSettings; use util::TryFutureExt; use workspace::{ item::{BreadcrumbText, Item, ItemEvent, ItemHandle}, - ItemNavHistory, Pane, ToolbarItemLocation, Workspace, PaneBackdrop, + ItemNavHistory, Pane, PaneBackdrop, ToolbarItemLocation, Workspace, }; actions!(diagnostics, [Deploy]); @@ -90,12 +90,15 @@ impl View for ProjectDiagnosticsEditor { fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if self.path_states.is_empty() { let theme = &theme::current(cx).project_diagnostics; - PaneBackdrop::new(cx.view_id(), Label::new("No problems in workspace", theme.empty_message.clone()) - .aligned() - .contained() - .with_style(theme.container) - .into_any()).into_any() - + PaneBackdrop::new( + cx.view_id(), + Label::new("No problems in workspace", theme.empty_message.clone()) + .aligned() + .contained() + .with_style(theme.container) + .into_any(), + ) + .into_any() } else { ChildView::new(&self.editor, cx).into_any() } @@ -162,8 +165,13 @@ impl ProjectDiagnosticsEditor { editor.set_vertical_scroll_margin(5, cx); editor }); - cx.subscribe(&editor, |_, _, event, cx| cx.emit(event.clone())) - .detach(); + cx.subscribe(&editor, |this, _, event, cx| { + cx.emit(event.clone()); + if event == &editor::Event::Focused && this.path_states.is_empty() { + cx.focus_self() + } + }) + .detach(); let project = project_handle.read(cx); let paths_to_update = project diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 7207e3c91c6da9f1e1ecfb37b94a560c875127d3..94fa23939bcdcfe0958945cad8fdc726c1720693 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7128,6 +7128,7 @@ pub enum Event { BufferEdited, Edited, Reparsed, + Focused, Blurred, DirtyChanged, Saved, @@ -7181,6 +7182,7 @@ impl View for Editor { fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { if cx.is_self_focused() { let focused_event = EditorFocused(cx.handle()); + cx.emit(Event::Focused); cx.emit_global(focused_event); } if let Some(rename) = self.pending_rename.as_ref() { From bafc1d922e756cd369bea7cada4c85bc0c561595 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 11:46:52 -0700 Subject: [PATCH 17/37] fmt --- crates/diagnostics/src/diagnostics.rs | 5 +++-- crates/editor/src/editor.rs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 182efdfdd6c520e30d285ed822f66f9a3f98a368..29ea1273e24f4cf62942ad9627448920467cb1b1 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -105,8 +105,9 @@ impl View for ProjectDiagnosticsEditor { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - if cx.is_self_focused() && !self.path_states.is_empty() { - cx.focus(&self.editor); + dbg!("Focus in"); + if dbg!(cx.is_self_focused()) && dbg!(!self.path_states.is_empty()) { + dbg!(cx.focus(&self.editor)); } } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 94fa23939bcdcfe0958945cad8fdc726c1720693..6a43e5a93b86284c3547bcc6656bad3b0eab1e55 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7180,6 +7180,7 @@ impl View for Editor { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + dbg!("Editor Focus in"); if cx.is_self_focused() { let focused_event = EditorFocused(cx.handle()); cx.emit(Event::Focused); From 9c32b774aad9c152fd330f801a842ac2c8676720 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 22 May 2023 14:53:07 -0400 Subject: [PATCH 18/37] Add example of changelog line in PR template --- .github/pull_request_template.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8d16a59bc12852ec9f06f3efa7ff43e0d333c038..f66fdce683a1d8633e25710e172b2ec1d553503a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,4 +2,5 @@ Release Notes: -* [[Added foo / Fixed bar / No notes]] +* (Added|Fixed|Improved) ... ([#](https://github.com/zed-industries/community/issues/)). +* ... From 49566e5677affcf3a7a1378897ebf14ba61f07c3 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 22 May 2023 15:00:57 -0400 Subject: [PATCH 19/37] Update pull_request_template.md --- .github/pull_request_template.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f66fdce683a1d8633e25710e172b2ec1d553503a..67a7ed31c9b5a4cfbf3ab6881c627b1a9db126c5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,5 +2,12 @@ Release Notes: -* (Added|Fixed|Improved) ... ([#](https://github.com/zed-industries/community/issues/)). +Use `N/A` in this section if this item should be skipped in the release notes. + +Add release note lines here: + +* (Added|Fixed|Improved) ... ([#](https://github.com/zed-industries/community/issues/)). * ... + +If the release notes are only intended for a specific release channel only, add `(-only)` to the end of the release note line. +These will be removed by the person making the release. From 366f13bb5c5a9fa41c75deff76ee400ac9a7a31a Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 12:12:56 -0700 Subject: [PATCH 20/37] Adjust scrollbar settings to be expandable --- assets/settings/default.json | 31 ++++++++++++++++------------ crates/editor/src/editor.rs | 6 ------ crates/editor/src/editor_settings.rs | 18 +++++++++++++--- crates/editor/src/element.rs | 21 +++++++++++-------- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 4f149edb1053d10dfb6ae4764b439978f5130825..84db3f8ea1be70aa1243664a5bb5de3b04abf25a 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -52,19 +52,24 @@ // 3. Draw all invisible symbols: // "all" "show_whitespaces": "selection", - // Whether to show the scrollbar in the editor. - // This setting can take four values: - // - // 1. Show the scrollbar if there's important information or - // follow the system's configured behavior (default): - // "auto" - // 2. Match the system's configured behavior: - // "system" - // 3. Always show the scrollbar: - // "always" - // 4. Never show the scrollbar: - // "never" - "show_scrollbars": "auto", + // Scrollbar related settings + "scrollbar": { + // When to show the scrollbar in the editor. + // This setting can take four values: + // + // 1. Show the scrollbar if there's important information or + // follow the system's configured behavior (default): + // "auto" + // 2. Match the system's configured behavior: + // "system" + // 3. Always show the scrollbar: + // "always" + // 4. Never show the scrollbar: + // "never" + "when_to_show": "auto", + // Whether to show git diff indicators in the scrollbar. + "git_diff": true + }, // Whether the screen sharing icon is shown in the os status bar. "show_call_status_icon": true, // Whether to use language servers to provide code intelligence. diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 814435059ee9f9df5406a1ec1d786263a6971439..d8bf71e2f292490c4bc8a0f808194dbb1d48915a 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -533,12 +533,6 @@ pub struct EditorSnapshot { ongoing_scroll: OngoingScroll, } -impl EditorSnapshot { - fn has_scrollbar_info(&self, is_singleton: bool) -> bool { - is_singleton && self.buffer_snapshot.has_git_diffs() - } -} - #[derive(Clone, Debug)] struct SelectionHistoryEntry { selections: Arc<[Selection]>, diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index a3f38a3dc096c6a4ce8365911313c31c147d06e7..05045ca49067727edc01468cc29517715a8ecc9f 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -7,12 +7,18 @@ pub struct EditorSettings { pub cursor_blink: bool, pub hover_popover_enabled: bool, pub show_completions_on_input: bool, - pub show_scrollbars: ShowScrollbars, + pub scrollbar: Scrollbar, +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub struct Scrollbar { + pub when_to_show: ShowScrollbar, + pub git_diff: bool } #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "snake_case")] -pub enum ShowScrollbars { +pub enum ShowScrollbar { Auto, System, Always, @@ -24,7 +30,13 @@ pub struct EditorSettingsContent { pub cursor_blink: Option, pub hover_popover_enabled: Option, pub show_completions_on_input: Option, - pub show_scrollbars: Option, + pub scrollbar: Option, +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub struct ScrollbarContent { + pub when_to_show: Option, + pub git_diff: Option } impl Setting for EditorSettings { diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 5a057390d58ac7c8f01138166b531085492948a7..b5e09fc86c20e2897c1a45fbac5ee2efb10c0651 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ display_map::{BlockStyle, DisplaySnapshot, FoldStatus, TransformBlock}, - editor_settings::ShowScrollbars, + editor_settings::ShowScrollbar, git::{diff_hunk_to_display, DisplayDiffHunk}, hover_popover::{ hide_hover, hover_at, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, @@ -1052,7 +1052,7 @@ impl EditorElement { ..Default::default() }); - if layout.is_singleton { + if layout.is_singleton && settings::get::(cx).scrollbar.git_diff { let diff_style = theme::current(cx).editor.diff.clone(); for hunk in layout .position_map @@ -2067,14 +2067,17 @@ impl Element for EditorElement { )); } - let show_scrollbars = match settings::get::(cx).show_scrollbars { - ShowScrollbars::Auto => { - snapshot.has_scrollbar_info(is_singleton) - || editor.scroll_manager.scrollbars_visible() + let scrollbar_settings = &settings::get::(cx).scrollbar; + let show_scrollbars = match scrollbar_settings.when_to_show { + ShowScrollbar::Auto => { + // Git + (is_singleton && scrollbar_settings.git_diff && snapshot.buffer_snapshot.has_git_diffs()) + // Scrollmanager + || editor.scroll_manager.scrollbars_visible() } - ShowScrollbars::System => editor.scroll_manager.scrollbars_visible(), - ShowScrollbars::Always => true, - ShowScrollbars::Never => false, + ShowScrollbar::System => editor.scroll_manager.scrollbars_visible(), + ShowScrollbar::Always => true, + ShowScrollbar::Never => false, }; let include_root = editor From 687ccd4c6feb25031f9a490257e87ea624159493 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 12:13:23 -0700 Subject: [PATCH 21/37] fmt --- crates/editor/src/editor_settings.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index 05045ca49067727edc01468cc29517715a8ecc9f..d97006e5839248960edc3e0b35dc61890613dcaa 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -13,7 +13,7 @@ pub struct EditorSettings { #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct Scrollbar { pub when_to_show: ShowScrollbar, - pub git_diff: bool + pub git_diff: bool, } #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -36,7 +36,7 @@ pub struct EditorSettingsContent { #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct ScrollbarContent { pub when_to_show: Option, - pub git_diff: Option + pub git_diff: Option, } impl Setting for EditorSettings { From cfdf9198dac938140daa662325bd5c043e69cbe0 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 12:16:47 -0700 Subject: [PATCH 22/37] Switch back to --- assets/settings/default.json | 2 +- crates/editor/src/editor_settings.rs | 4 ++-- crates/editor/src/element.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 84db3f8ea1be70aa1243664a5bb5de3b04abf25a..e4e7a8c522d3585dda3ef9ac05a01d37b72bcda5 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -66,7 +66,7 @@ // "always" // 4. Never show the scrollbar: // "never" - "when_to_show": "auto", + "show": "auto", // Whether to show git diff indicators in the scrollbar. "git_diff": true }, diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index d97006e5839248960edc3e0b35dc61890613dcaa..7f01834b161b8f1db75a40145694f1c80e473755 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -12,7 +12,7 @@ pub struct EditorSettings { #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct Scrollbar { - pub when_to_show: ShowScrollbar, + pub show: ShowScrollbar, pub git_diff: bool, } @@ -35,7 +35,7 @@ pub struct EditorSettingsContent { #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct ScrollbarContent { - pub when_to_show: Option, + pub show: Option, pub git_diff: Option, } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index b5e09fc86c20e2897c1a45fbac5ee2efb10c0651..13a24bfc2c1f884dc2dc1d8cc916e6fc22855ea4 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -2068,7 +2068,7 @@ impl Element for EditorElement { } let scrollbar_settings = &settings::get::(cx).scrollbar; - let show_scrollbars = match scrollbar_settings.when_to_show { + let show_scrollbars = match scrollbar_settings.show { ShowScrollbar::Auto => { // Git (is_singleton && scrollbar_settings.git_diff && snapshot.buffer_snapshot.has_git_diffs()) From 7689cdf3f944f44e28f14da389c07f4c417df47d Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 22 May 2023 12:53:22 -0700 Subject: [PATCH 23/37] Clear old diagnostics when restarting a language server --- crates/language/src/buffer.rs | 15 +++-- crates/language/src/diagnostic_set.rs | 4 ++ crates/project/src/project.rs | 17 +++++ crates/project/src/project_tests.rs | 89 +++++++++++++++++++++++++++ crates/project/src/worktree.rs | 39 ++++++++++++ 5 files changed, 160 insertions(+), 4 deletions(-) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 3a977024873baa82d39e50bae06a3e3e43b7f254..5539d1d941726148fc543a59652d57190e1d400d 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1644,10 +1644,17 @@ impl Buffer { cx: &mut ModelContext, ) { if lamport_timestamp > self.diagnostics_timestamp { - match self.diagnostics.binary_search_by_key(&server_id, |e| e.0) { - Err(ix) => self.diagnostics.insert(ix, (server_id, diagnostics)), - Ok(ix) => self.diagnostics[ix].1 = diagnostics, - }; + let ix = self.diagnostics.binary_search_by_key(&server_id, |e| e.0); + if diagnostics.len() == 0 { + if let Ok(ix) = ix { + self.diagnostics.remove(ix); + } + } else { + match ix { + Err(ix) => self.diagnostics.insert(ix, (server_id, diagnostics)), + Ok(ix) => self.diagnostics[ix].1 = diagnostics, + }; + } self.diagnostics_timestamp = lamport_timestamp; self.diagnostics_update_count += 1; self.text.lamport_clock.observe(lamport_timestamp); diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index 948a7ee39471579a4cc9a8553b700ccf26c2b9ae..f269fce88d694c8efe2f255e302bbef7aed865ea 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -80,6 +80,10 @@ impl DiagnosticSet { } } + pub fn len(&self) -> usize { + self.diagnostics.summary().count + } + pub fn iter(&self) -> impl Iterator> { self.diagnostics.iter() } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index f91cd999f9dd0068f98ae9f30fda3067469481d2..5b5d9038224925f1882b544e280083f546238c77 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2565,6 +2565,23 @@ impl Project { } } + for buffer in self.opened_buffers.values() { + if let Some(buffer) = buffer.upgrade(cx) { + buffer.update(cx, |buffer, cx| { + buffer.update_diagnostics(server_id, Default::default(), cx); + }); + } + } + for worktree in &self.worktrees { + if let Some(worktree) = worktree.upgrade(cx) { + worktree.update(cx, |worktree, cx| { + if let Some(worktree) = worktree.as_local_mut() { + worktree.clear_diagnostics_for_language_server(server_id, cx); + } + }); + } + } + self.language_server_statuses.remove(&server_id); cx.notify(); diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 69bcea8ce0426f7fe812618542336f3a018262f3..e48ce6258b34f38f438dd6035a533a99a0be5d0a 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -926,6 +926,95 @@ async fn test_restarting_server_with_diagnostics_running(cx: &mut gpui::TestAppC }); } +#[gpui::test] +async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAppContext) { + init_test(cx); + + let mut language = Language::new( + LanguageConfig { + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + None, + ); + let mut fake_servers = language + .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { + ..Default::default() + })) + .await; + + let fs = FakeFs::new(cx.background()); + fs.insert_tree("/dir", json!({ "a.rs": "x" })).await; + + let project = Project::test(fs, ["/dir".as_ref()], cx).await; + project.update(cx, |project, _| project.languages.add(Arc::new(language))); + + let buffer = project + .update(cx, |project, cx| project.open_local_buffer("/dir/a.rs", cx)) + .await + .unwrap(); + + // Publish diagnostics + let fake_server = fake_servers.next().await.unwrap(); + fake_server.notify::(lsp::PublishDiagnosticsParams { + uri: Url::from_file_path("/dir/a.rs").unwrap(), + version: None, + diagnostics: vec![lsp::Diagnostic { + range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 0)), + severity: Some(lsp::DiagnosticSeverity::ERROR), + message: "the message".to_string(), + ..Default::default() + }], + }); + + cx.foreground().run_until_parked(); + buffer.read_with(cx, |buffer, _| { + assert_eq!( + buffer + .snapshot() + .diagnostics_in_range::<_, usize>(0..1, false) + .map(|entry| entry.diagnostic.message.clone()) + .collect::>(), + ["the message".to_string()] + ); + }); + project.read_with(cx, |project, cx| { + assert_eq!( + project.diagnostic_summary(cx), + DiagnosticSummary { + error_count: 1, + warning_count: 0, + } + ); + }); + + project.update(cx, |project, cx| { + project.restart_language_servers_for_buffers([buffer.clone()], cx); + }); + + // The diagnostics are cleared. + cx.foreground().run_until_parked(); + buffer.read_with(cx, |buffer, _| { + assert_eq!( + buffer + .snapshot() + .diagnostics_in_range::<_, usize>(0..1, false) + .map(|entry| entry.diagnostic.message.clone()) + .collect::>(), + Vec::::new(), + ); + }); + project.read_with(cx, |project, cx| { + assert_eq!( + project.diagnostic_summary(cx), + DiagnosticSummary { + error_count: 0, + warning_count: 0, + } + ); + }); +} + #[gpui::test] async fn test_restarted_server_reporting_invalid_buffer_version(cx: &mut gpui::TestAppContext) { init_test(cx); diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 4f898aa91d2558c606b39dda29b83ea6ff24a3d8..7df99b577bfde01b0f405c0dc5a0bf9a1002e4c4 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -737,6 +737,45 @@ impl LocalWorktree { self.diagnostics.get(path).cloned().unwrap_or_default() } + pub fn clear_diagnostics_for_language_server( + &mut self, + server_id: LanguageServerId, + _: &mut ModelContext, + ) { + let worktree_id = self.id().to_proto(); + self.diagnostic_summaries + .retain(|path, summaries_by_server_id| { + if summaries_by_server_id.remove(&server_id).is_some() { + if let Some(share) = self.share.as_ref() { + self.client + .send(proto::UpdateDiagnosticSummary { + project_id: share.project_id, + worktree_id, + summary: Some(proto::DiagnosticSummary { + path: path.to_string_lossy().to_string(), + language_server_id: server_id.0 as u64, + error_count: 0, + warning_count: 0, + }), + }) + .log_err(); + } + !summaries_by_server_id.is_empty() + } else { + true + } + }); + + self.diagnostics.retain(|_, diagnostics_by_server_id| { + if let Ok(ix) = diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) { + diagnostics_by_server_id.remove(ix); + !diagnostics_by_server_id.is_empty() + } else { + true + } + }); + } + pub fn update_diagnostics( &mut self, server_id: LanguageServerId, From 96224fa7e84e97779911f17a9e1e65dd446cd71a Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 13:57:07 -0700 Subject: [PATCH 24/37] Only fire update diff base when the dot repo is scanned --- crates/project/src/worktree.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 4f898aa91d2558c606b39dda29b83ea6ff24a3d8..8d0896d2d1b66001b538c2f33e909e80d9650b71 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -329,7 +329,7 @@ pub struct LocalMutableSnapshot { #[derive(Debug, Clone)] pub struct LocalRepositoryEntry { pub(crate) scan_id: usize, - pub(crate) full_scan_id: usize, + pub(crate) git_dir_scan_id: usize, pub(crate) repo_ptr: Arc>, /// Path to the actual .git folder. /// Note: if .git is a file, this points to the folder indicated by the .git file @@ -830,7 +830,7 @@ impl LocalWorktree { old_repos.next(); } Ordering::Equal => { - if old_repo.scan_id != new_repo.scan_id { + if old_repo.git_dir_scan_id != new_repo.git_dir_scan_id { if let Some(entry) = self.entry_for_id(**new_entry_id) { diff.insert(entry.path.clone(), (*new_repo).clone()); } @@ -2006,7 +2006,7 @@ impl LocalSnapshot { work_dir_id, LocalRepositoryEntry { scan_id, - full_scan_id: scan_id, + git_dir_scan_id: scan_id, repo_ptr: repo, git_dir_path: parent_path.clone(), }, @@ -3166,7 +3166,7 @@ impl BackgroundScanner { snapshot.build_repo(dot_git_dir.into(), fs); return None; }; - if repo.full_scan_id == scan_id { + if repo.git_dir_scan_id == scan_id { return None; } (*entry_id, repo.repo_ptr.to_owned()) @@ -3183,7 +3183,7 @@ impl BackgroundScanner { snapshot.git_repositories.update(&entry_id, |entry| { entry.scan_id = scan_id; - entry.full_scan_id = scan_id; + entry.git_dir_scan_id = scan_id; }); snapshot.repository_entries.update(&work_dir, |entry| { @@ -3212,7 +3212,7 @@ impl BackgroundScanner { let local_repo = snapshot.get_local_repo(&repo)?.to_owned(); // Short circuit if we've already scanned everything - if local_repo.full_scan_id == scan_id { + if local_repo.git_dir_scan_id == scan_id { return None; } From 11eb9b17c998dc436a6d3a3cebc91a57fccb6110 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 22 May 2023 17:47:52 -0400 Subject: [PATCH 25/37] Update project panel & scroll bar git colors --- styles/src/styleTree/editor.ts | 24 ++++++++++++------------ styles/src/styleTree/projectPanel.ts | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index a13ae49c7d89f1a1589fcf3677f51d9993d4c217..786f01024248f93f7a35b1e7cb530a0bd627c3db 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -108,8 +108,8 @@ export default function editor(colorScheme: ColorScheme) { ? colorScheme.ramps.green(0.4).hex() : colorScheme.ramps.green(0.5).hex(), removedWidthEm: 0.275, - widthEm: 0.22, - cornerRadius: 0.2, + widthEm: 0.15, + cornerRadius: 0.05, }, /** Highlights matching occurences of what is under the cursor * as well as matched brackets @@ -241,22 +241,22 @@ export default function editor(colorScheme: ColorScheme) { border: border(layer, "variant", { left: true }), }, thumb: { - background: withOpacity(background(layer, "inverted"), 0.4), + background: withOpacity(background(layer, "inverted"), 0.3), border: { width: 1, color: borderColor(layer, "variant"), }, }, git: { - deleted: isLight - ? colorScheme.ramps.red(0.5).hex() - : colorScheme.ramps.red(0.4).hex(), - modified: isLight - ? colorScheme.ramps.yellow(0.3).hex() - : colorScheme.ramps.yellow(0.5).hex(), - inserted: isLight - ? colorScheme.ramps.green(0.4).hex() - : colorScheme.ramps.green(0.5).hex(), + deleted: isLight + ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8), + modified: isLight + ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8), + inserted: isLight + ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8), } }, compositionMark: { diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 81dded151e54a091ac91ceba130c27449946594d..7af59521545dce8db9574f707d4a69afdd53d763 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -19,11 +19,11 @@ export default function projectPanel(colorScheme: ColorScheme) { ? colorScheme.ramps.yellow(0.6).hex() : colorScheme.ramps.yellow(0.5).hex(), inserted: isLight - ? colorScheme.ramps.green(0.4).hex() + ? colorScheme.ramps.green(0.45).hex() : colorScheme.ramps.green(0.5).hex(), conflict: isLight - ? colorScheme.ramps.red(0.4).hex() - : colorScheme.ramps.red(0.5).hex(), + ? colorScheme.ramps.red(0.6).hex() + : colorScheme.ramps.red(0.5).hex() } } From 5dfb0e36910afa9738fc9ee9346b249d295413af Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 14:56:35 -0700 Subject: [PATCH 26/37] remove border from thumb --- styles/src/styleTree/editor.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index 786f01024248f93f7a35b1e7cb530a0bd627c3db..91c131835913887b86fabe3eb5ef90a5094add8b 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -245,6 +245,10 @@ export default function editor(colorScheme: ColorScheme) { border: { width: 1, color: borderColor(layer, "variant"), + top: false, + right: true, + left: true, + bottom: false, }, }, git: { From 9bec74f1d4cd4b147918f49d1402545b587edd28 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 15:04:51 -0700 Subject: [PATCH 27/37] fmt --- crates/editor/src/editor.rs | 1 - crates/editor/src/element.rs | 1 - crates/project_panel/src/project_panel.rs | 4 ++-- crates/theme/src/theme.rs | 4 ++-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 57d5ec6e95ac327e187a34f09a549f57f9d9e6bc..ce67a59bd39238f819fa38d3ceb807842e664a9b 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7253,7 +7253,6 @@ impl View for Editor { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - dbg!("Editor Focus in"); if cx.is_self_focused() { let focused_event = EditorFocused(cx.handle()); cx.emit(Event::Focused); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index ba9adfdd16bf7be0062aa14dd46e55207da8b2aa..13a24bfc2c1f884dc2dc1d8cc916e6fc22855ea4 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1052,7 +1052,6 @@ impl EditorElement { ..Default::default() }); - if layout.is_singleton && settings::get::(cx).scrollbar.git_diff { let diff_style = theme::current(cx).editor.diff.clone(); for hunk in layout diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 22b6b3fd75b767a99c0a453dd531000fad4242f4..a7895172d56d02a0da84c890eafd774b9f3fa905 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -6,8 +6,8 @@ use gpui::{ actions, anyhow::{anyhow, Result}, elements::{ - AnchorCorner, ChildView, ContainerStyle, Empty, Flex, Label, - MouseEventHandler, ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, + AnchorCorner, ChildView, ContainerStyle, Empty, Flex, Label, MouseEventHandler, + ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, }, geometry::vector::Vector2F, keymap_matcher::KeymapContext, diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index b5ac126a690ca2ba7023e526297f57302934bb4a..cd2bf90b7eb85fb51068e11c31fa7be6b0ef84ce 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -683,14 +683,14 @@ pub struct Scrollbar { pub thumb: ContainerStyle, pub width: f32, pub min_height_factor: f32, - pub git: GitDiffColors + pub git: GitDiffColors, } #[derive(Clone, Deserialize, Default)] pub struct GitDiffColors { pub inserted: Color, pub modified: Color, - pub deleted: Color + pub deleted: Color, } #[derive(Clone, Deserialize, Default)] From 2d1c4a1971ffd8a214b9f21eec5e632b1a32acdd Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 15:31:14 -0700 Subject: [PATCH 28/37] Revert "Touch up git in project panel and scroll bar styling" --- crates/editor/src/editor.rs | 1 + crates/project_panel/src/project_panel.rs | 31 +++++------- crates/theme/src/theme.rs | 21 --------- crates/theme/src/ui.rs | 57 +++++++++++++++++++++-- styles/src/styleTree/editor.ts | 36 +++----------- styles/src/styleTree/projectPanel.ts | 19 +------- 6 files changed, 75 insertions(+), 90 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ce67a59bd39238f819fa38d3ceb807842e664a9b..57d5ec6e95ac327e187a34f09a549f57f9d9e6bc 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7253,6 +7253,7 @@ impl View for Editor { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + dbg!("Editor Focus in"); if cx.is_self_focused() { let focused_event = EditorFocused(cx.handle()); cx.emit(Event::Focused); diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a7895172d56d02a0da84c890eafd774b9f3fa905..ce0dd9e22212ad954e5398eff8c3a209b7ea4e78 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -6,7 +6,7 @@ use gpui::{ actions, anyhow::{anyhow, Result}, elements::{ - AnchorCorner, ChildView, ContainerStyle, Empty, Flex, Label, MouseEventHandler, + AnchorCorner, ChildView, ComponentHost, ContainerStyle, Empty, Flex, MouseEventHandler, ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, }, geometry::vector::Vector2F, @@ -28,7 +28,7 @@ use std::{ path::Path, sync::Arc, }; -use theme::ProjectPanelEntry; +use theme::{ui::FileName, ProjectPanelEntry}; use unicase::UniCase; use workspace::Workspace; @@ -1079,17 +1079,6 @@ impl ProjectPanel { let kind = details.kind; let show_editor = details.is_editing && !details.is_processing; - let mut filename_text_style = style.text.clone(); - filename_text_style.color = details - .git_status - .as_ref() - .map(|status| match status { - GitFileStatus::Added => style.status.git.inserted, - GitFileStatus::Modified => style.status.git.modified, - GitFileStatus::Conflict => style.status.git.conflict, - }) - .unwrap_or(style.text.color); - Flex::row() .with_child( if kind == EntryKind::Dir { @@ -1117,12 +1106,16 @@ impl ProjectPanel { .flex(1.0, true) .into_any() } else { - Label::new(details.filename.clone(), filename_text_style) - .contained() - .with_margin_left(style.icon_spacing) - .aligned() - .left() - .into_any() + ComponentHost::new(FileName::new( + details.filename.clone(), + details.git_status, + FileName::style(style.text.clone(), &theme::current(cx)), + )) + .contained() + .with_margin_left(style.icon_spacing) + .aligned() + .left() + .into_any() }) .constrained() .with_height(style.height) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index cd2bf90b7eb85fb51068e11c31fa7be6b0ef84ce..eb404cdaad6ad5a8d5e7fa5c572e0ad709e6c4e4 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -446,19 +446,6 @@ pub struct ProjectPanelEntry { pub icon_color: Color, pub icon_size: f32, pub icon_spacing: f32, - pub status: EntryStatus, -} - -#[derive(Clone, Debug, Deserialize, Default)] -pub struct EntryStatus { - pub git: GitProjectStatus, -} - -#[derive(Clone, Debug, Deserialize, Default)] -pub struct GitProjectStatus { - pub modified: Color, - pub inserted: Color, - pub conflict: Color, } #[derive(Clone, Debug, Deserialize, Default)] @@ -683,14 +670,6 @@ pub struct Scrollbar { pub thumb: ContainerStyle, pub width: f32, pub min_height_factor: f32, - pub git: GitDiffColors, -} - -#[derive(Clone, Deserialize, Default)] -pub struct GitDiffColors { - pub inserted: Color, - pub modified: Color, - pub deleted: Color, } #[derive(Clone, Deserialize, Default)] diff --git a/crates/theme/src/ui.rs b/crates/theme/src/ui.rs index b86bfca8c42ae05900d76d86e19544531c245899..e4df24c89fcf92842e663e8a50792709a19b7981 100644 --- a/crates/theme/src/ui.rs +++ b/crates/theme/src/ui.rs @@ -1,9 +1,10 @@ use std::borrow::Cow; +use fs::repository::GitFileStatus; use gpui::{ color::Color, elements::{ - ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label, + ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label, LabelStyle, MouseEventHandler, ParentElement, Stack, Svg, }, fonts::TextStyle, @@ -11,11 +12,11 @@ use gpui::{ platform, platform::MouseButton, scene::MouseClick, - Action, Element, EventContext, MouseState, View, ViewContext, + Action, AnyElement, Element, EventContext, MouseState, View, ViewContext, }; use serde::Deserialize; -use crate::{ContainedText, Interactive}; +use crate::{ContainedText, Interactive, Theme}; #[derive(Clone, Deserialize, Default)] pub struct CheckboxStyle { @@ -252,3 +253,53 @@ where .constrained() .with_height(style.dimensions().y()) } + +pub struct FileName { + filename: String, + git_status: Option, + style: FileNameStyle, +} + +pub struct FileNameStyle { + template_style: LabelStyle, + git_inserted: Color, + git_modified: Color, + git_deleted: Color, +} + +impl FileName { + pub fn new(filename: String, git_status: Option, style: FileNameStyle) -> Self { + FileName { + filename, + git_status, + style, + } + } + + pub fn style>(style: I, theme: &Theme) -> FileNameStyle { + FileNameStyle { + template_style: style.into(), + git_inserted: theme.editor.diff.inserted, + git_modified: theme.editor.diff.modified, + git_deleted: theme.editor.diff.deleted, + } + } +} + +impl gpui::elements::Component for FileName { + fn render(&self, _: &mut V, _: &mut ViewContext) -> AnyElement { + // Prepare colors for git statuses + let mut filename_text_style = self.style.template_style.text.clone(); + filename_text_style.color = self + .git_status + .as_ref() + .map(|status| match status { + GitFileStatus::Added => self.style.git_inserted, + GitFileStatus::Modified => self.style.git_modified, + GitFileStatus::Conflict => self.style.git_deleted, + }) + .unwrap_or(self.style.template_style.text.color); + + Label::new(self.filename.clone(), filename_text_style).into_any() + } +} diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index 91c131835913887b86fabe3eb5ef90a5094add8b..7caa8b1c674996822d91a0a3b120b44be6e44cbc 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -3,10 +3,9 @@ import { ColorScheme, Layer, StyleSets } from "../themes/common/colorScheme" import { background, border, borderColor, foreground, text } from "./components" import hoverPopover from "./hoverPopover" -import { buildSyntax } from "../themes/common/syntax" +import { SyntaxHighlightStyle, buildSyntax } from "../themes/common/syntax" export default function editor(colorScheme: ColorScheme) { - const { isLight } = colorScheme let layer = colorScheme.highest const autocompleteItem = { @@ -98,18 +97,12 @@ export default function editor(colorScheme: ColorScheme) { foldBackground: foreground(layer, "variant"), }, diff: { - deleted: isLight - ? colorScheme.ramps.red(0.5).hex() - : colorScheme.ramps.red(0.4).hex(), - modified: isLight - ? colorScheme.ramps.yellow(0.3).hex() - : colorScheme.ramps.yellow(0.5).hex(), - inserted: isLight - ? colorScheme.ramps.green(0.4).hex() - : colorScheme.ramps.green(0.5).hex(), + deleted: foreground(layer, "negative"), + modified: foreground(layer, "warning"), + inserted: foreground(layer, "positive"), removedWidthEm: 0.275, - widthEm: 0.15, - cornerRadius: 0.05, + widthEm: 0.22, + cornerRadius: 0.2, }, /** Highlights matching occurences of what is under the cursor * as well as matched brackets @@ -241,27 +234,12 @@ export default function editor(colorScheme: ColorScheme) { border: border(layer, "variant", { left: true }), }, thumb: { - background: withOpacity(background(layer, "inverted"), 0.3), + background: withOpacity(background(layer, "inverted"), 0.4), border: { width: 1, color: borderColor(layer, "variant"), - top: false, - right: true, - left: true, - bottom: false, }, }, - git: { - deleted: isLight - ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8) - : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8), - modified: isLight - ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8) - : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8), - inserted: isLight - ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8) - : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8), - } }, compositionMark: { underline: { diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 7af59521545dce8db9574f707d4a69afdd53d763..3d06a683abebf71d55311273f8e93f08876ea509 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -3,7 +3,6 @@ import { withOpacity } from "../utils/color" import { background, border, foreground, text } from "./components" export default function projectPanel(colorScheme: ColorScheme) { - const { isLight } = colorScheme let layer = colorScheme.middle let baseEntry = { @@ -13,20 +12,6 @@ export default function projectPanel(colorScheme: ColorScheme) { iconSpacing: 8, } - let status = { - git: { - modified: isLight - ? colorScheme.ramps.yellow(0.6).hex() - : colorScheme.ramps.yellow(0.5).hex(), - inserted: isLight - ? colorScheme.ramps.green(0.45).hex() - : colorScheme.ramps.green(0.5).hex(), - conflict: isLight - ? colorScheme.ramps.red(0.6).hex() - : colorScheme.ramps.red(0.5).hex() - } - } - let entry = { ...baseEntry, text: text(layer, "mono", "variant", { size: "sm" }), @@ -43,7 +28,6 @@ export default function projectPanel(colorScheme: ColorScheme) { background: background(layer, "active"), text: text(layer, "mono", "active", { size: "sm" }), }, - status } return { @@ -75,7 +59,6 @@ export default function projectPanel(colorScheme: ColorScheme) { entry, draggedEntry: { ...baseEntry, - status, text: text(layer, "mono", "on", { size: "sm" }), background: withOpacity(background(layer, "on"), 0.9), border: border(layer), @@ -96,6 +79,6 @@ export default function projectPanel(colorScheme: ColorScheme) { background: background(layer, "on"), text: text(layer, "mono", "on", { size: "sm" }), selection: colorScheme.players[0], - } + }, } } From 5c31c84c90768cd2c1af3dc797e27a20718fe9cc Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 15:51:31 -0700 Subject: [PATCH 29/37] Fixed contrast in project panel and scrollbar co-authored-by: nate --- crates/diagnostics/src/diagnostics.rs | 5 +- crates/editor/src/editor.rs | 1 - crates/project_panel/src/project_panel.rs | 33 +++++++------ crates/theme/src/theme.rs | 23 ++++++++- crates/theme/src/ui.rs | 57 ++--------------------- styles/src/styleTree/editor.ts | 41 ++++++++++++---- styles/src/styleTree/projectPanel.ts | 18 +++++++ 7 files changed, 97 insertions(+), 81 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 29ea1273e24f4cf62942ad9627448920467cb1b1..182efdfdd6c520e30d285ed822f66f9a3f98a368 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -105,9 +105,8 @@ impl View for ProjectDiagnosticsEditor { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - dbg!("Focus in"); - if dbg!(cx.is_self_focused()) && dbg!(!self.path_states.is_empty()) { - dbg!(cx.focus(&self.editor)); + if cx.is_self_focused() && !self.path_states.is_empty() { + cx.focus(&self.editor); } } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 57d5ec6e95ac327e187a34f09a549f57f9d9e6bc..ce67a59bd39238f819fa38d3ceb807842e664a9b 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7253,7 +7253,6 @@ impl View for Editor { } fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - dbg!("Editor Focus in"); if cx.is_self_focused() { let focused_event = EditorFocused(cx.handle()); cx.emit(Event::Focused); diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index ce0dd9e22212ad954e5398eff8c3a209b7ea4e78..b67af5898eae754815a12c3dfcff59abbde6fedd 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -6,8 +6,8 @@ use gpui::{ actions, anyhow::{anyhow, Result}, elements::{ - AnchorCorner, ChildView, ComponentHost, ContainerStyle, Empty, Flex, MouseEventHandler, - ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, + AnchorCorner, ChildView, ContainerStyle, Empty, Flex, MouseEventHandler, + ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, Label, }, geometry::vector::Vector2F, keymap_matcher::KeymapContext, @@ -28,7 +28,7 @@ use std::{ path::Path, sync::Arc, }; -use theme::{ui::FileName, ProjectPanelEntry}; +use theme::ProjectPanelEntry; use unicase::UniCase; use workspace::Workspace; @@ -1079,6 +1079,17 @@ impl ProjectPanel { let kind = details.kind; let show_editor = details.is_editing && !details.is_processing; + let mut filename_text_style = style.text.clone(); + filename_text_style.color = details + .git_status + .as_ref() + .map(|status| match status { + GitFileStatus::Added => style.status.git.inserted, + GitFileStatus::Modified => style.status.git.modified, + GitFileStatus::Conflict => style.status.git.conflict, + }) + .unwrap_or(style.text.color); + Flex::row() .with_child( if kind == EntryKind::Dir { @@ -1106,16 +1117,12 @@ impl ProjectPanel { .flex(1.0, true) .into_any() } else { - ComponentHost::new(FileName::new( - details.filename.clone(), - details.git_status, - FileName::style(style.text.clone(), &theme::current(cx)), - )) - .contained() - .with_margin_left(style.icon_spacing) - .aligned() - .left() - .into_any() + Label::new(details.filename.clone(), filename_text_style) + .contained() + .with_margin_left(style.icon_spacing) + .aligned() + .left() + .into_any() }) .constrained() .with_height(style.height) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index eb404cdaad6ad5a8d5e7fa5c572e0ad709e6c4e4..f23493c75dffd3d77898eb25a81d69a2d64a22ab 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -446,7 +446,20 @@ pub struct ProjectPanelEntry { pub icon_color: Color, pub icon_size: f32, pub icon_spacing: f32, -} + pub status: EntryStatus, + } + + #[derive(Clone, Debug, Deserialize, Default)] + pub struct EntryStatus { + pub git: GitProjectStatus, + } + + #[derive(Clone, Debug, Deserialize, Default)] + pub struct GitProjectStatus { + pub modified: Color, + pub inserted: Color, + pub conflict: Color, + } #[derive(Clone, Debug, Deserialize, Default)] pub struct ContextMenu { @@ -670,6 +683,14 @@ pub struct Scrollbar { pub thumb: ContainerStyle, pub width: f32, pub min_height_factor: f32, + pub git: GitDiffColors, +} + +#[derive(Clone, Deserialize, Default)] +pub struct GitDiffColors { + pub inserted: Color, + pub modified: Color, + pub deleted: Color, } #[derive(Clone, Deserialize, Default)] diff --git a/crates/theme/src/ui.rs b/crates/theme/src/ui.rs index e4df24c89fcf92842e663e8a50792709a19b7981..b86bfca8c42ae05900d76d86e19544531c245899 100644 --- a/crates/theme/src/ui.rs +++ b/crates/theme/src/ui.rs @@ -1,10 +1,9 @@ use std::borrow::Cow; -use fs::repository::GitFileStatus; use gpui::{ color::Color, elements::{ - ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label, LabelStyle, + ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label, MouseEventHandler, ParentElement, Stack, Svg, }, fonts::TextStyle, @@ -12,11 +11,11 @@ use gpui::{ platform, platform::MouseButton, scene::MouseClick, - Action, AnyElement, Element, EventContext, MouseState, View, ViewContext, + Action, Element, EventContext, MouseState, View, ViewContext, }; use serde::Deserialize; -use crate::{ContainedText, Interactive, Theme}; +use crate::{ContainedText, Interactive}; #[derive(Clone, Deserialize, Default)] pub struct CheckboxStyle { @@ -253,53 +252,3 @@ where .constrained() .with_height(style.dimensions().y()) } - -pub struct FileName { - filename: String, - git_status: Option, - style: FileNameStyle, -} - -pub struct FileNameStyle { - template_style: LabelStyle, - git_inserted: Color, - git_modified: Color, - git_deleted: Color, -} - -impl FileName { - pub fn new(filename: String, git_status: Option, style: FileNameStyle) -> Self { - FileName { - filename, - git_status, - style, - } - } - - pub fn style>(style: I, theme: &Theme) -> FileNameStyle { - FileNameStyle { - template_style: style.into(), - git_inserted: theme.editor.diff.inserted, - git_modified: theme.editor.diff.modified, - git_deleted: theme.editor.diff.deleted, - } - } -} - -impl gpui::elements::Component for FileName { - fn render(&self, _: &mut V, _: &mut ViewContext) -> AnyElement { - // Prepare colors for git statuses - let mut filename_text_style = self.style.template_style.text.clone(); - filename_text_style.color = self - .git_status - .as_ref() - .map(|status| match status { - GitFileStatus::Added => self.style.git_inserted, - GitFileStatus::Modified => self.style.git_modified, - GitFileStatus::Conflict => self.style.git_deleted, - }) - .unwrap_or(self.style.template_style.text.color); - - Label::new(self.filename.clone(), filename_text_style).into_any() - } -} diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index 7caa8b1c674996822d91a0a3b120b44be6e44cbc..deeff855ff0f61dc8e51c9a8b8065d8a29b9c437 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -6,6 +6,8 @@ import hoverPopover from "./hoverPopover" import { SyntaxHighlightStyle, buildSyntax } from "../themes/common/syntax" export default function editor(colorScheme: ColorScheme) { + const { isLight } = colorScheme + let layer = colorScheme.highest const autocompleteItem = { @@ -97,12 +99,18 @@ export default function editor(colorScheme: ColorScheme) { foldBackground: foreground(layer, "variant"), }, diff: { - deleted: foreground(layer, "negative"), - modified: foreground(layer, "warning"), - inserted: foreground(layer, "positive"), + deleted: isLight + ? colorScheme.ramps.red(0.5).hex() + : colorScheme.ramps.red(0.4).hex(), + modified: isLight + ? colorScheme.ramps.yellow(0.3).hex() + : colorScheme.ramps.yellow(0.5).hex(), + inserted: isLight + ? colorScheme.ramps.green(0.4).hex() + : colorScheme.ramps.green(0.5).hex(), removedWidthEm: 0.275, - widthEm: 0.22, - cornerRadius: 0.2, + widthEm: 0.15, + cornerRadius: 0.05, }, /** Highlights matching occurences of what is under the cursor * as well as matched brackets @@ -234,12 +242,27 @@ export default function editor(colorScheme: ColorScheme) { border: border(layer, "variant", { left: true }), }, thumb: { - background: withOpacity(background(layer, "inverted"), 0.4), + background: withOpacity(background(layer, "inverted"), 0.3), border: { - width: 1, - color: borderColor(layer, "variant"), - }, + width: 1, + color: borderColor(layer, "variant"), + top: false, + right: true, + left: true, + bottom: false, + } }, + git: { + deleted: isLight + ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8), + modified: isLight + ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8), + inserted: isLight + ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8) + : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8), + } }, compositionMark: { underline: { diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 3d06a683abebf71d55311273f8e93f08876ea509..08117bf6b01d5fe7b14f2e0ace22dc680c5cefac 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -3,6 +3,8 @@ import { withOpacity } from "../utils/color" import { background, border, foreground, text } from "./components" export default function projectPanel(colorScheme: ColorScheme) { + const { isLight } = colorScheme + let layer = colorScheme.middle let baseEntry = { @@ -12,6 +14,20 @@ export default function projectPanel(colorScheme: ColorScheme) { iconSpacing: 8, } + let status = { + git: { + modified: isLight + ? colorScheme.ramps.yellow(0.6).hex() + : colorScheme.ramps.yellow(0.5).hex(), + inserted: isLight + ? colorScheme.ramps.green(0.45).hex() + : colorScheme.ramps.green(0.5).hex(), + conflict: isLight + ? colorScheme.ramps.red(0.6).hex() + : colorScheme.ramps.red(0.5).hex() + } + } + let entry = { ...baseEntry, text: text(layer, "mono", "variant", { size: "sm" }), @@ -28,6 +44,7 @@ export default function projectPanel(colorScheme: ColorScheme) { background: background(layer, "active"), text: text(layer, "mono", "active", { size: "sm" }), }, + status } return { @@ -62,6 +79,7 @@ export default function projectPanel(colorScheme: ColorScheme) { text: text(layer, "mono", "on", { size: "sm" }), background: withOpacity(background(layer, "on"), 0.9), border: border(layer), + status }, ignoredEntry: { ...entry, From e4454f1e7fa245f5dfae1fa80ec2aabd0f973ea8 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 15:53:29 -0700 Subject: [PATCH 30/37] fmt --- crates/project_panel/src/project_panel.rs | 4 ++-- crates/theme/src/theme.rs | 26 +++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index b67af5898eae754815a12c3dfcff59abbde6fedd..a7895172d56d02a0da84c890eafd774b9f3fa905 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -6,8 +6,8 @@ use gpui::{ actions, anyhow::{anyhow, Result}, elements::{ - AnchorCorner, ChildView, ContainerStyle, Empty, Flex, MouseEventHandler, - ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, Label, + AnchorCorner, ChildView, ContainerStyle, Empty, Flex, Label, MouseEventHandler, + ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState, }, geometry::vector::Vector2F, keymap_matcher::KeymapContext, diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index f23493c75dffd3d77898eb25a81d69a2d64a22ab..cd2bf90b7eb85fb51068e11c31fa7be6b0ef84ce 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -447,19 +447,19 @@ pub struct ProjectPanelEntry { pub icon_size: f32, pub icon_spacing: f32, pub status: EntryStatus, - } - - #[derive(Clone, Debug, Deserialize, Default)] - pub struct EntryStatus { - pub git: GitProjectStatus, - } - - #[derive(Clone, Debug, Deserialize, Default)] - pub struct GitProjectStatus { - pub modified: Color, - pub inserted: Color, - pub conflict: Color, - } +} + +#[derive(Clone, Debug, Deserialize, Default)] +pub struct EntryStatus { + pub git: GitProjectStatus, +} + +#[derive(Clone, Debug, Deserialize, Default)] +pub struct GitProjectStatus { + pub modified: Color, + pub inserted: Color, + pub conflict: Color, +} #[derive(Clone, Debug, Deserialize, Default)] pub struct ContextMenu { From fc8248912864fc0df1e8dd9f7dbb842ea41348d2 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 16:23:36 -0700 Subject: [PATCH 31/37] Update scrollbar styling --- crates/editor/src/element.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 13a24bfc2c1f884dc2dc1d8cc916e6fc22855ea4..4e5863407f208ae0d4b0b84030d1b21521164ec6 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1053,7 +1053,7 @@ impl EditorElement { }); if layout.is_singleton && settings::get::(cx).scrollbar.git_diff { - let diff_style = theme::current(cx).editor.diff.clone(); + let diff_style = theme::current(cx).editor.scrollbar.git.clone(); for hunk in layout .position_map .snapshot From 51d94f532b6bc6f1e4e207bb16d56b0a1d288079 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 18:26:33 -0700 Subject: [PATCH 32/37] Load diff base for buffers that are opening but not yet opened when repositories are discovered --- crates/project/src/project.rs | 120 +++++++++++++++++++++++++-------- crates/project/src/worktree.rs | 1 + 2 files changed, 92 insertions(+), 29 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 5b5d9038224925f1882b544e280083f546238c77..dd53c30d140534c3b15ea5a562b6ebc3c92fe2d6 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -16,6 +16,7 @@ use copilot::Copilot; use futures::{ channel::mpsc::{self, UnboundedReceiver}, future::{try_join_all, Shared}, + stream::FuturesUnordered, AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt, }; use globset::{Glob, GlobSet, GlobSetBuilder}; @@ -1374,7 +1375,7 @@ impl Project { return Task::ready(Ok(existing_buffer)); } - let mut loading_watch = match self.loading_buffers_by_path.entry(project_path.clone()) { + let loading_watch = match self.loading_buffers_by_path.entry(project_path.clone()) { // If the given path is already being loaded, then wait for that existing // task to complete and return the same buffer. hash_map::Entry::Occupied(e) => e.get().clone(), @@ -1405,15 +1406,9 @@ impl Project { }; cx.foreground().spawn(async move { - loop { - if let Some(result) = loading_watch.borrow().as_ref() { - match result { - Ok(buffer) => return Ok(buffer.clone()), - Err(error) => return Err(anyhow!("{}", error)), - } - } - loading_watch.next().await; - } + pump_loading_buffer_reciever(loading_watch) + .await + .map_err(|error| anyhow!("{}", error)) }) } @@ -4822,6 +4817,51 @@ impl Project { ) { debug_assert!(worktree_handle.read(cx).is_local()); + // Setup the pending buffers + let future_buffers = self + .loading_buffers_by_path + .iter() + .filter_map(|(path, receiver)| { + let path = &path.path; + let (work_directory, repo) = repos + .iter() + .find(|(work_directory, _)| path.starts_with(work_directory))?; + + let repo_relative_path = path.strip_prefix(work_directory).log_err()?; + + let receiver = receiver.clone(); + let repo_ptr = repo.repo_ptr.clone(); + let repo_relative_path = repo_relative_path.to_owned(); + Some(async move { + pump_loading_buffer_reciever(receiver) + .await + .ok() + .map(|buffer| (buffer, repo_relative_path, repo_ptr)) + }) + }) + .collect::>() + .filter_map(|result| async move { + let (buffer_handle, repo_relative_path, repo_ptr) = result?; + + let lock = repo_ptr.lock(); + lock.load_index_text(&repo_relative_path) + .map(|diff_base| (diff_base, buffer_handle)) + }); + + let update_diff_base_fn = update_diff_base(self); + cx.spawn(|_, mut cx| async move { + let diff_base_tasks = cx + .background() + .spawn(future_buffers.collect::>()) + .await; + + for (diff_base, buffer) in diff_base_tasks.into_iter() { + update_diff_base_fn(Some(diff_base), buffer, &mut cx); + } + }) + .detach(); + + // And the current buffers for (_, buffer) in &self.opened_buffers { if let Some(buffer) = buffer.upgrade(cx) { let file = match File::from_dyn(buffer.read(cx).file()) { @@ -4841,18 +4881,17 @@ impl Project { .find(|(work_directory, _)| path.starts_with(work_directory)) { Some(repo) => repo.clone(), - None => return, + None => continue, }; let relative_repo = match path.strip_prefix(work_directory).log_err() { Some(relative_repo) => relative_repo.to_owned(), - None => return, + None => continue, }; drop(worktree); - let remote_id = self.remote_id(); - let client = self.client.clone(); + let update_diff_base_fn = update_diff_base(self); let git_ptr = repo.repo_ptr.clone(); let diff_base_task = cx .background() @@ -4860,21 +4899,7 @@ impl Project { cx.spawn(|_, mut cx| async move { let diff_base = diff_base_task.await; - - let buffer_id = buffer.update(&mut cx, |buffer, cx| { - buffer.set_diff_base(diff_base.clone(), cx); - buffer.remote_id() - }); - - if let Some(project_id) = remote_id { - client - .send(proto::UpdateDiffBase { - project_id, - buffer_id: buffer_id as u64, - diff_base, - }) - .log_err(); - } + update_diff_base_fn(diff_base, buffer, &mut cx); }) .detach(); } @@ -6764,3 +6789,40 @@ impl Item for Buffer { }) } } + +async fn pump_loading_buffer_reciever( + mut receiver: postage::watch::Receiver, Arc>>>, +) -> Result, Arc> { + loop { + if let Some(result) = receiver.borrow().as_ref() { + match result { + Ok(buffer) => return Ok(buffer.to_owned()), + Err(e) => return Err(e.to_owned()), + } + } + receiver.next().await; + } +} + +fn update_diff_base( + project: &Project, +) -> impl Fn(Option, ModelHandle, &mut AsyncAppContext) { + let remote_id = project.remote_id(); + let client = project.client().clone(); + move |diff_base, buffer, cx| { + let buffer_id = buffer.update(cx, |buffer, cx| { + buffer.set_diff_base(diff_base.clone(), cx); + buffer.remote_id() + }); + + if let Some(project_id) = remote_id { + client + .send(proto::UpdateDiffBase { + project_id, + buffer_id: buffer_id as u64, + diff_base, + }) + .log_err(); + } + } +} diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 2e1059437871c9094152b6507a2f015e3f72824b..d2c035f91675a779b84a4facfc6331091b481910 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -839,6 +839,7 @@ impl LocalWorktree { fn set_snapshot(&mut self, new_snapshot: LocalSnapshot, cx: &mut ModelContext) { let updated_repos = self.changed_repos(&self.git_repositories, &new_snapshot.git_repositories); + self.snapshot = new_snapshot; if let Some(share) = self.share.as_mut() { From 9307719a4b4f9419347314c9f79ab14107eebee8 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 18:40:12 -0700 Subject: [PATCH 33/37] Add run until parked for test --- crates/collab/src/tests/integration_tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 807510d70555ed446d9ecf9d9bc40a6aa652f162..439ee0786a1b850bb68ffef539be1651f8ca0480 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -2688,6 +2688,7 @@ async fn test_git_branch_name( }); let project_remote_c = client_c.build_remote_project(project_id, cx_c).await; + deterministic.run_until_parked(); project_remote_c.read_with(cx_c, |project, cx| { assert_branch(Some("branch-2"), project, cx) }); From 7be8dead07b86683a627a1fa2969b3947fc44f1c Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 20:23:07 -0700 Subject: [PATCH 34/37] Add initial project panel settings --- Cargo.lock | 4 +++ assets/settings/default.json | 4 +++ crates/project_panel/Cargo.toml | 6 ++++ crates/project_panel/src/project_panel.rs | 7 ++++- .../src/project_panel_settings.rs | 29 +++++++++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 crates/project_panel/src/project_panel_settings.rs diff --git a/Cargo.lock b/Cargo.lock index 3ae96f4751751fb06ce6250a31b138f93cd4cdf0..981005f3f2b0e0de0364a67378903f41e5383b2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4886,6 +4886,7 @@ dependencies = [ name = "project_panel" version = "0.1.0" dependencies = [ + "anyhow", "client", "context_menu", "drag_and_drop", @@ -4896,6 +4897,9 @@ dependencies = [ "menu", "postage", "project", + "schemars", + "serde", + "serde_derive", "serde_json", "settings", "theme", diff --git a/assets/settings/default.json b/assets/settings/default.json index e4e7a8c522d3585dda3ef9ac05a01d37b72bcda5..38d0ce820ba3eaf06281bb9992e5ed0c3a0b56ae 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -70,6 +70,10 @@ // Whether to show git diff indicators in the scrollbar. "git_diff": true }, + "project_panel": { + // Whether to show the git status in the project panel. + "git_status": true + }, // Whether the screen sharing icon is shown in the os status bar. "show_call_status_icon": true, // Whether to use language servers to provide code intelligence. diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 6fcdf06d2c736c63ea19cc5bd5ebdd79e7c36061..01d1be53b9eaeb572a69de15c655a750812f7df3 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -21,6 +21,12 @@ util = { path = "../util" } workspace = { path = "../workspace" } postage.workspace = true futures.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true +anyhow.workspace = true +schemars.workspace = true + unicase = "2.6" [dev-dependencies] diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a7895172d56d02a0da84c890eafd774b9f3fa905..d4cd0074549fdd6bc86159319395ee25a46fd47f 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1,3 +1,5 @@ +mod project_panel_settings; + use context_menu::{ContextMenu, ContextMenuItem}; use drag_and_drop::{DragAndDrop, Draggable}; use editor::{Cancel, Editor}; @@ -20,6 +22,7 @@ use project::{ repository::GitFileStatus, Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId, }; +use project_panel_settings::ProjectPanelSettings; use std::{ cmp::Ordering, collections::{hash_map, HashMap}, @@ -111,6 +114,7 @@ actions!( ); pub fn init(cx: &mut AppContext) { + settings::register::(cx); cx.add_action(ProjectPanel::expand_selected_entry); cx.add_action(ProjectPanel::collapse_selected_entry); cx.add_action(ProjectPanel::select_prev); @@ -1000,6 +1004,7 @@ impl ProjectPanel { } let end_ix = range.end.min(ix + visible_worktree_entries.len()); + let git_status_setting = settings::get::(cx).git_status; if let Some(worktree) = self.project.read(cx).worktree_for_id(*worktree_id, cx) { let snapshot = worktree.read(cx).snapshot(); let root_name = OsStr::new(snapshot.root_name()); @@ -1013,7 +1018,7 @@ impl ProjectPanel { for (entry, repo) in snapshot.entries_with_repositories(visible_worktree_entries[entry_range].iter()) { - let status = (entry.path.parent().is_some() && !entry.is_ignored) + let status = (git_status_setting && entry.path.parent().is_some() && !entry.is_ignored) .then(|| repo.and_then(|repo| repo.status_for_path(&snapshot, &entry.path))) .flatten(); diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs new file mode 100644 index 0000000000000000000000000000000000000000..01a15d089bfed0b794777f8479580d98e097eccf --- /dev/null +++ b/crates/project_panel/src/project_panel_settings.rs @@ -0,0 +1,29 @@ +use serde_derive::{Deserialize, Serialize}; +use anyhow; +use settings::Setting; +use schemars::JsonSchema; + + +#[derive(Deserialize, Debug)] +pub struct ProjectPanelSettings { + pub git_status: bool, +} + +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] +pub struct ProjectPanelSettingsContent { + pub git_status: Option, +} + +impl Setting for ProjectPanelSettings { + const KEY: Option<&'static str> = Some("project_panel"); + + type FileContent = ProjectPanelSettingsContent; + + fn load( + default_value: &Self::FileContent, + user_values: &[&Self::FileContent], + _: &gpui::AppContext, + ) -> anyhow::Result { + Self::load_via_json_merge(default_value, user_values) + } +} From da96802bf03644d4f056ff4bd8f8be97fd3e069b Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 20:25:27 -0700 Subject: [PATCH 35/37] fmt --- crates/project_panel/src/project_panel.rs | 4 +++- crates/project_panel/src/project_panel_settings.rs | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index d4cd0074549fdd6bc86159319395ee25a46fd47f..66f0fe77182d0ef1a1493141be93483624392078 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1018,7 +1018,9 @@ impl ProjectPanel { for (entry, repo) in snapshot.entries_with_repositories(visible_worktree_entries[entry_range].iter()) { - let status = (git_status_setting && entry.path.parent().is_some() && !entry.is_ignored) + let status = (git_status_setting + && entry.path.parent().is_some() + && !entry.is_ignored) .then(|| repo.and_then(|repo| repo.status_for_path(&snapshot, &entry.path))) .flatten(); diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 01a15d089bfed0b794777f8479580d98e097eccf..7786f1b4380b10956c8b3ea327f98b349c0e6ad3 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -1,8 +1,7 @@ -use serde_derive::{Deserialize, Serialize}; use anyhow; -use settings::Setting; use schemars::JsonSchema; - +use serde_derive::{Deserialize, Serialize}; +use settings::Setting; #[derive(Deserialize, Debug)] pub struct ProjectPanelSettings { From b19a712799a042596d8e75654c9419a70b946532 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 20:33:18 -0700 Subject: [PATCH 36/37] Add init_settings to tests --- crates/project_panel/src/project_panel.rs | 7 ++++++- crates/zed/src/zed.rs | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 66f0fe77182d0ef1a1493141be93483624392078..40ba0b7e67de51b3f2d0677257cb4fc7df11620f 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -113,8 +113,12 @@ actions!( ] ); -pub fn init(cx: &mut AppContext) { +pub fn init_settings(cx: &mut AppContext) { settings::register::(cx); +} + +pub fn init(cx: &mut AppContext) { + init_settings(cx); cx.add_action(ProjectPanel::expand_selected_entry); cx.add_action(ProjectPanel::collapse_selected_entry); cx.add_action(ProjectPanel::select_prev); @@ -2051,6 +2055,7 @@ mod tests { cx.foreground().forbid_parking(); cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); + init_settings(cx); theme::init((), cx); language::init(cx); editor::init_settings(cx); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 376ecfc06bd43aeb2753345aa2301b8bd7d60cf7..95d09e82ec445ea245508f8e31441772b118ba6f 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -2068,6 +2068,7 @@ mod tests { workspace::init(app_state.clone(), cx); language::init(cx); editor::init(cx); + project_panel::init_settings(cx); pane::init(cx); app_state }) From a37b1b6a45c97f99cf236ffb71d3e27e42f72f4b Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 22 May 2023 20:38:30 -0700 Subject: [PATCH 37/37] Add other setting init --- crates/project_panel/src/project_panel.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 40ba0b7e67de51b3f2d0677257cb4fc7df11620f..69d8b8be4ddeca6f63c59368be4dda153c80965c 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -2068,6 +2068,7 @@ mod tests { cx.update(|cx| { let app_state = AppState::test(cx); theme::init((), cx); + init_settings(cx); language::init(cx); editor::init(cx); pane::init(cx);