From e1a6dc90770ad5269ad5d464606028a6dadfe160 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:03:02 +0200 Subject: [PATCH 01/22] search: Add a default tooltip for empty searches Z-1074 --- crates/search/src/project_search.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 2c22517e2040c87f3573cfdc099dcb2cab2ee070..0f8c9173bc3efbadcccdf47d2c83649ded58be85 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -25,7 +25,7 @@ use std::{ borrow::Cow, collections::HashSet, mem, - ops::Range, + ops::{Not, Range}, path::PathBuf, sync::Arc, }; @@ -242,7 +242,13 @@ impl View for ProjectSearchView { impl Item for ProjectSearchView { fn tab_tooltip_text(&self, cx: &AppContext) -> Option> { - Some(self.query_editor.read(cx).text(cx).into()) + let query_text = self.query_editor.read(cx).text(cx); + + query_text + .is_empty() + .not() + .then(|| query_text.into()) + .or_else(|| Some("Project search".into())) } fn act_as_type<'a>( From 01621972c5d05c5f377487a1dcf8b39bb3977969 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 1 Jun 2023 12:31:37 +0200 Subject: [PATCH 02/22] Change "Project search" to "Project Search" --- crates/search/src/project_search.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 0f8c9173bc3efbadcccdf47d2c83649ded58be85..27aac1762bec9f37389e0cba1a47d4e5a11016e0 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -248,7 +248,7 @@ impl Item for ProjectSearchView { .is_empty() .not() .then(|| query_text.into()) - .or_else(|| Some("Project search".into())) + .or_else(|| Some("Project Search".into())) } fn act_as_type<'a>( From cc055901e1b530c80a73eb5f98ba1572064c77bd Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Thu, 1 Jun 2023 23:34:39 -0400 Subject: [PATCH 03/22] Add additional panic information to panic events --- crates/feedback/src/system_specs.rs | 2 ++ crates/zed/src/main.rs | 24 +++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/feedback/src/system_specs.rs b/crates/feedback/src/system_specs.rs index b6eb6e8b6d0f630778398a18b2e2645b807f756b..48955a86291282a3ef4bf55ca27e9a838a2f51e9 100644 --- a/crates/feedback/src/system_specs.rs +++ b/crates/feedback/src/system_specs.rs @@ -6,6 +6,8 @@ use std::{env, fmt::Display}; use sysinfo::{System, SystemExt}; use util::channel::ReleaseChannel; +// TODO: Move this file out of feedback and into a more general place + #[derive(Clone, Debug, Serialize)] pub struct SystemSpecs { #[serde(serialize_with = "serialize_app_version")] diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 9ec3e3d3f6b5c23c33e0a46ec683ad0bd2f98022..4b0661c6e62f02c05b68172d38c14f886e991136 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -70,10 +70,7 @@ fn main() { log::info!("========== starting zed =========="); let mut app = gpui::App::new(Assets).unwrap(); - let app_version = ZED_APP_VERSION - .or_else(|| app.platform().app_version().ok()) - .map_or("dev".to_string(), |v| v.to_string()); - init_panic_hook(app_version); + init_panic_hook(&app); app.background(); @@ -376,19 +373,29 @@ struct Panic { backtrace: Vec, // TODO // stripped_backtrace: String, + release_channel: String, + os_name: String, + os_version: Option, + architecture: String, time: u128, } #[derive(Serialize)] struct PanicRequest { panic: Panic, + // TODO: Move to Panic struct, as app_version - requires changing zed.dev version: String, token: String, } -fn init_panic_hook(app_version: String) { +fn init_panic_hook(app: &App) { let is_pty = stdout_is_a_pty(); + let platform = app.platform(); + panic::set_hook(Box::new(move |info| { + let app_version = ZED_APP_VERSION + .or_else(|| platform.app_version().ok()) + .map_or("dev".to_string(), |v| v.to_string()); let backtrace = Backtrace::new(); let thread = thread::current(); @@ -414,6 +421,13 @@ fn init_panic_hook(app_version: String) { .map(|line| line.to_string()) .collect(), // modified_backtrace: None, + release_channel: RELEASE_CHANNEL.dev_name().into(), + os_name: platform.os_name().into(), + os_version: platform + .os_version() + .ok() + .map(|os_version| os_version.to_string()), + architecture: env::consts::ARCH.into(), time: SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() From c55aee84d3fcd6d9a4a073168825262dba8d4b73 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 2 Jun 2023 01:33:25 -0400 Subject: [PATCH 04/22] Rename field to panicked_on --- crates/zed/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 4b0661c6e62f02c05b68172d38c14f886e991136..e22edee5f6ce95b6d179af065efff0d1eec9d749 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -377,7 +377,7 @@ struct Panic { os_name: String, os_version: Option, architecture: String, - time: u128, + panicked_on: u128, } #[derive(Serialize)] @@ -428,7 +428,7 @@ fn init_panic_hook(app: &App) { .ok() .map(|os_version| os_version.to_string()), architecture: env::consts::ARCH.into(), - time: SystemTime::now() + panicked_on: SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_millis(), From 345fad3e9d522d0e1c8c91674606ca8c5e20de37 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 2 Jun 2023 17:32:34 +0200 Subject: [PATCH 05/22] editor: add select previous command (#2556) Added a `select previous` command to complement `select next`. Release Notes: - Added "Select previous" editor command, mirroring `Select next`. Ticket number: Z-366 --- assets/keymaps/atom.json | 6 ++ assets/keymaps/default.json | 12 ++++ assets/keymaps/jetbrains.json | 6 ++ crates/editor/src/editor.rs | 110 ++++++++++++++++++++++++++++++ crates/editor/src/editor_tests.rs | 51 ++++++++++++++ crates/editor/src/multi_buffer.rs | 87 ++++++++++++++++++++++- crates/rope/src/rope.rs | 48 ++++++++++--- crates/text/src/text.rs | 6 ++ 8 files changed, 316 insertions(+), 10 deletions(-) diff --git a/assets/keymaps/atom.json b/assets/keymaps/atom.json index 634aed322abde3333cef56f352a752d03e68005f..25143914cc4828d14e36af9e4b77b5a41cc87d4b 100644 --- a/assets/keymaps/atom.json +++ b/assets/keymaps/atom.json @@ -16,6 +16,12 @@ "replace_newest": true } ], + "ctrl-cmd-g": [ + "editor::SelectPrevious", + { + "replace_newest": true + } + ], "ctrl-shift-down": "editor::AddSelectionBelow", "ctrl-shift-up": "editor::AddSelectionAbove", "cmd-shift-backspace": "editor::DeleteToBeginningOfLine", diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 7e1a8429bfd695a75b423b5e2a175d474ad3d49b..46a3fb5a5a7f63d5855d8fb2f8ff9023b82c9dac 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -250,12 +250,24 @@ "replace_newest": false } ], + "ctrl-cmd-d": [ + "editor::SelectPrevious", + { + "replace_newest": false + } + ], "cmd-k cmd-d": [ "editor::SelectNext", { "replace_newest": true } ], + "cmd-k ctrl-cmd-d": [ + "editor::SelectPrevious", + { + "replace_newest": true + } + ], "cmd-k cmd-i": "editor::Hover", "cmd-/": [ "editor::ToggleComments", diff --git a/assets/keymaps/jetbrains.json b/assets/keymaps/jetbrains.json index 4825d3e8b5fa2163e5a40b446c390f8d18ef96e8..b3e8f989a4a0337a3c1dd9dff63ef640d64dc6ef 100644 --- a/assets/keymaps/jetbrains.json +++ b/assets/keymaps/jetbrains.json @@ -26,6 +26,12 @@ "replace_newest": false } ], + "ctrl-cmd-g": [ + "editor::SelectPrevious", + { + "replace_newest": false + } + ], "cmd-/": [ "editor::ToggleComments", { diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 5c19bb0121bdd0302c41c9b067eb72a9eea2e88b..af7344a91f230b6ace019a179ea242011958c597 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -111,6 +111,12 @@ pub struct SelectNext { pub replace_newest: bool, } +#[derive(Clone, Deserialize, PartialEq, Default)] +pub struct SelectPrevious { + #[serde(default)] + pub replace_newest: bool, +} + #[derive(Clone, Deserialize, PartialEq)] pub struct SelectToBeginningOfLine { #[serde(default)] @@ -272,6 +278,7 @@ impl_actions!( editor, [ SelectNext, + SelectPrevious, SelectToBeginningOfLine, SelectToEndOfLine, ToggleCodeActions, @@ -367,6 +374,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(Editor::add_selection_above); cx.add_action(Editor::add_selection_below); cx.add_action(Editor::select_next); + cx.add_action(Editor::select_previous); cx.add_action(Editor::toggle_comments); cx.add_action(Editor::select_larger_syntax_node); cx.add_action(Editor::select_smaller_syntax_node); @@ -484,6 +492,7 @@ pub struct Editor { columnar_selection_tail: Option, add_selections_state: Option, select_next_state: Option, + select_prev_state: Option, selection_history: SelectionHistory, autoclose_regions: Vec, snippet_stack: InvalidationStack, @@ -539,6 +548,7 @@ pub struct EditorSnapshot { struct SelectionHistoryEntry { selections: Arc<[Selection]>, select_next_state: Option, + select_prev_state: Option, add_selections_state: Option, } @@ -1286,6 +1296,7 @@ impl Editor { columnar_selection_tail: None, add_selections_state: None, select_next_state: None, + select_prev_state: None, selection_history: Default::default(), autoclose_regions: Default::default(), snippet_stack: Default::default(), @@ -1507,6 +1518,7 @@ impl Editor { let buffer = &display_map.buffer_snapshot; self.add_selections_state = None; self.select_next_state = None; + self.select_prev_state = None; self.select_larger_syntax_node_stack.clear(); self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer); self.snippet_stack @@ -5213,6 +5225,101 @@ impl Editor { } } + pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext) { + self.push_to_selection_history(); + let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); + let buffer = &display_map.buffer_snapshot; + let mut selections = self.selections.all::(cx); + if let Some(mut select_prev_state) = self.select_prev_state.take() { + let query = &select_prev_state.query; + if !select_prev_state.done { + let first_selection = selections.iter().min_by_key(|s| s.id).unwrap(); + let last_selection = selections.iter().max_by_key(|s| s.id).unwrap(); + let mut next_selected_range = None; + // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer. + let bytes_before_last_selection = + buffer.reversed_bytes_in_range(0..last_selection.start); + let bytes_after_first_selection = + buffer.reversed_bytes_in_range(first_selection.end..buffer.len()); + let query_matches = query + .stream_find_iter(bytes_before_last_selection) + .map(|result| (last_selection.start, result)) + .chain( + query + .stream_find_iter(bytes_after_first_selection) + .map(|result| (buffer.len(), result)), + ); + for (end_offset, query_match) in query_matches { + let query_match = query_match.unwrap(); // can only fail due to I/O + let offset_range = + end_offset - query_match.end()..end_offset - query_match.start(); + let display_range = offset_range.start.to_display_point(&display_map) + ..offset_range.end.to_display_point(&display_map); + + if !select_prev_state.wordwise + || (!movement::is_inside_word(&display_map, display_range.start) + && !movement::is_inside_word(&display_map, display_range.end)) + { + next_selected_range = Some(offset_range); + break; + } + } + + if let Some(next_selected_range) = next_selected_range { + self.unfold_ranges([next_selected_range.clone()], false, true, cx); + self.change_selections(Some(Autoscroll::newest()), cx, |s| { + if action.replace_newest { + s.delete(s.newest_anchor().id); + } + s.insert_range(next_selected_range); + }); + } else { + select_prev_state.done = true; + } + } + + self.select_prev_state = Some(select_prev_state); + } else if selections.len() == 1 { + let selection = selections.last_mut().unwrap(); + if selection.start == selection.end { + let word_range = movement::surrounding_word( + &display_map, + selection.start.to_display_point(&display_map), + ); + selection.start = word_range.start.to_offset(&display_map, Bias::Left); + selection.end = word_range.end.to_offset(&display_map, Bias::Left); + selection.goal = SelectionGoal::None; + selection.reversed = false; + + let query = buffer + .text_for_range(selection.start..selection.end) + .collect::(); + let query = query.chars().rev().collect::(); + let select_state = SelectNextState { + query: AhoCorasick::new_auto_configured(&[query]), + wordwise: true, + done: false, + }; + self.unfold_ranges([selection.start..selection.end], false, true, cx); + self.change_selections(Some(Autoscroll::newest()), cx, |s| { + s.select(selections); + }); + self.select_prev_state = Some(select_state); + } else { + let query = buffer + .text_for_range(selection.start..selection.end) + .collect::(); + let query = query.chars().rev().collect::(); + self.select_prev_state = Some(SelectNextState { + query: AhoCorasick::new_auto_configured(&[query]), + wordwise: false, + done: false, + }); + self.select_previous(action, cx); + } + } + } + pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext) { self.transact(cx, |this, cx| { let mut selections = this.selections.all::(cx); @@ -5586,6 +5693,7 @@ impl Editor { if let Some(entry) = self.selection_history.undo_stack.pop_back() { self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec())); self.select_next_state = entry.select_next_state; + self.select_prev_state = entry.select_prev_state; self.add_selections_state = entry.add_selections_state; self.request_autoscroll(Autoscroll::newest(), cx); } @@ -5598,6 +5706,7 @@ impl Editor { if let Some(entry) = self.selection_history.redo_stack.pop_back() { self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec())); self.select_next_state = entry.select_next_state; + self.select_prev_state = entry.select_prev_state; self.add_selections_state = entry.add_selections_state; self.request_autoscroll(Autoscroll::newest(), cx); } @@ -6375,6 +6484,7 @@ impl Editor { self.selection_history.push(SelectionHistoryEntry { selections: self.selections.disjoint_anchors(), select_next_state: self.select_next_state.clone(), + select_prev_state: self.select_prev_state.clone(), add_selections_state: self.add_selections_state.clone(), }); } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index bc671b9ffc3652856d16faf567784eab438440b7..969b9c882d937a165473e06715b29f6352ed4fbc 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -3107,6 +3107,57 @@ async fn test_select_next(cx: &mut gpui::TestAppContext) { cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»"); } +#[gpui::test] +async fn test_select_previous(cx: &mut gpui::TestAppContext) { + init_test(cx, |_| {}); + { + // `Select previous` without a selection (selects wordwise) + let mut cx = EditorTestContext::new(cx).await; + cx.set_state("abc\nˇabc abc\ndefabc\nabc"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\nabc"); + + cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx)); + cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc"); + + cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx)); + cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\nabc"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndefabc\n«abcˇ»"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»"); + } + { + // `Select previous` with a selection + let mut cx = EditorTestContext::new(cx).await; + cx.set_state("abc\n«ˇabc» abc\ndefabc\nabc"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\nabc"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\n«abcˇ»"); + + cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx)); + cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\nabc"); + + cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx)); + cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndefabc\n«abcˇ»"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("«abcˇ»\n«ˇabc» abc\ndef«abcˇ»\n«abcˇ»"); + + cx.update_editor(|e, cx| e.select_previous(&SelectPrevious::default(), cx)); + cx.assert_editor_state("«abcˇ»\n«ˇabc» «abcˇ»\ndef«abcˇ»\n«abcˇ»"); + } +} + #[gpui::test] async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index b7b2b89c8ca312667bfb3b5988da8292fd33c6bc..af0003ec2dde8f6fe302c9fb7c0aabfdcf91c2ff 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -196,6 +196,13 @@ pub struct MultiBufferBytes<'a> { chunk: &'a [u8], } +pub struct ReversedMultiBufferBytes<'a> { + range: Range, + excerpts: Cursor<'a, Excerpt, usize>, + excerpt_bytes: Option>, + chunk: &'a [u8], +} + struct ExcerptChunks<'a> { content_chunks: BufferChunks<'a>, footer_height: usize, @@ -1967,7 +1974,6 @@ impl MultiBufferSnapshot { } else { None }; - MultiBufferBytes { range, excerpts, @@ -1976,6 +1982,33 @@ impl MultiBufferSnapshot { } } + pub fn reversed_bytes_in_range( + &self, + range: Range, + ) -> ReversedMultiBufferBytes { + let range = range.start.to_offset(self)..range.end.to_offset(self); + let mut excerpts = self.excerpts.cursor::(); + excerpts.seek(&range.end, Bias::Left, &()); + + let mut chunk = &[][..]; + let excerpt_bytes = if let Some(excerpt) = excerpts.item() { + let mut excerpt_bytes = excerpt.reversed_bytes_in_range( + range.start - excerpts.start()..range.end - excerpts.start(), + ); + chunk = excerpt_bytes.next().unwrap_or(&[][..]); + Some(excerpt_bytes) + } else { + None + }; + + ReversedMultiBufferBytes { + range, + excerpts, + excerpt_bytes, + chunk, + } + } + pub fn buffer_rows(&self, start_row: u32) -> MultiBufferRows { let mut result = MultiBufferRows { buffer_row_range: 0..0, @@ -3409,6 +3442,26 @@ impl Excerpt { } } + fn reversed_bytes_in_range(&self, range: Range) -> ExcerptBytes { + let content_start = self.range.context.start.to_offset(&self.buffer); + let bytes_start = content_start + range.start; + let bytes_end = content_start + cmp::min(range.end, self.text_summary.len); + let footer_height = if self.has_trailing_newline + && range.start <= self.text_summary.len + && range.end > self.text_summary.len + { + 1 + } else { + 0 + }; + let content_bytes = self.buffer.reversed_bytes_in_range(bytes_start..bytes_end); + + ExcerptBytes { + content_bytes, + footer_height, + } + } + fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor { if text_anchor .cmp(&self.range.context.start, &self.buffer) @@ -3727,6 +3780,38 @@ impl<'a> io::Read for MultiBufferBytes<'a> { } } +impl<'a> ReversedMultiBufferBytes<'a> { + fn consume(&mut self, len: usize) { + self.range.end -= len; + self.chunk = &self.chunk[..self.chunk.len() - len]; + + if !self.range.is_empty() && self.chunk.is_empty() { + if let Some(chunk) = self.excerpt_bytes.as_mut().and_then(|bytes| bytes.next()) { + self.chunk = chunk; + } else { + self.excerpts.next(&()); + if let Some(excerpt) = self.excerpts.item() { + let mut excerpt_bytes = + excerpt.bytes_in_range(0..self.range.end - self.excerpts.start()); + self.chunk = excerpt_bytes.next().unwrap(); + self.excerpt_bytes = Some(excerpt_bytes); + } + } + } + } +} + +impl<'a> io::Read for ReversedMultiBufferBytes<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let len = cmp::min(buf.len(), self.chunk.len()); + buf[..len].copy_from_slice(&self.chunk[..len]); + buf[..len].reverse(); + if len > 0 { + self.consume(len); + } + Ok(len) + } +} impl<'a> Iterator for ExcerptBytes<'a> { type Item = &'a [u8]; diff --git a/crates/rope/src/rope.rs b/crates/rope/src/rope.rs index 797fb39317bd42596063406a85d4ee6f2d7bf37c..6b6f364fdb0b7395be9db6d516a46f1b40d042bd 100644 --- a/crates/rope/src/rope.rs +++ b/crates/rope/src/rope.rs @@ -179,7 +179,11 @@ impl Rope { } pub fn bytes_in_range(&self, range: Range) -> Bytes { - Bytes::new(self, range) + Bytes::new(self, range, false) + } + + pub fn reversed_bytes_in_range(&self, range: Range) -> Bytes { + Bytes::new(self, range, true) } pub fn chunks(&self) -> Chunks { @@ -579,22 +583,33 @@ impl<'a> Iterator for Chunks<'a> { pub struct Bytes<'a> { chunks: sum_tree::Cursor<'a, Chunk, usize>, range: Range, + reversed: bool, } impl<'a> Bytes<'a> { - pub fn new(rope: &'a Rope, range: Range) -> Self { + pub fn new(rope: &'a Rope, range: Range, reversed: bool) -> Self { let mut chunks = rope.chunks.cursor(); - chunks.seek(&range.start, Bias::Right, &()); - Self { chunks, range } + if reversed { + chunks.seek(&range.end, Bias::Left, &()); + } else { + chunks.seek(&range.start, Bias::Right, &()); + } + Self { + chunks, + range, + reversed, + } } pub fn peek(&self) -> Option<&'a [u8]> { let chunk = self.chunks.item()?; + if self.reversed && self.range.start >= self.chunks.end(&()) { + return None; + } let chunk_start = *self.chunks.start(); if self.range.end <= chunk_start { return None; } - let start = self.range.start.saturating_sub(chunk_start); let end = self.range.end - chunk_start; Some(&chunk.0.as_bytes()[start..chunk.0.len().min(end)]) @@ -607,7 +622,11 @@ impl<'a> Iterator for Bytes<'a> { fn next(&mut self) -> Option { let result = self.peek(); if result.is_some() { - self.chunks.next(&()); + if self.reversed { + self.chunks.prev(&()); + } else { + self.chunks.next(&()); + } } result } @@ -617,10 +636,21 @@ impl<'a> io::Read for Bytes<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result { if let Some(chunk) = self.peek() { let len = cmp::min(buf.len(), chunk.len()); - buf[..len].copy_from_slice(&chunk[..len]); - self.range.start += len; + if self.reversed { + buf[..len].copy_from_slice(&chunk[chunk.len() - len..]); + buf[..len].reverse(); + self.range.end -= len; + } else { + buf[..len].copy_from_slice(&chunk[..len]); + self.range.start += len; + } + if len == chunk.len() { - self.chunks.next(&()); + if self.reversed { + self.chunks.prev(&()); + } else { + self.chunks.next(&()); + } } Ok(len) } else { diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index dcfaf818d1f97f98002d60fecf90533d50c2969b..2693add8ed0ac0d9d032ad5bd3f5e540138cf2fe 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1749,6 +1749,12 @@ impl BufferSnapshot { self.visible_text.bytes_in_range(start..end) } + pub fn reversed_bytes_in_range(&self, range: Range) -> rope::Bytes<'_> { + let start = range.start.to_offset(self); + let end = range.end.to_offset(self); + self.visible_text.reversed_bytes_in_range(start..end) + } + pub fn text_for_range(&self, range: Range) -> Chunks<'_> { let start = range.start.to_offset(self); let end = range.end.to_offset(self); From f6a4706410ed9d547cd3757c41ee63e76a97bce3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 2 Jun 2023 12:32:36 -0700 Subject: [PATCH 06/22] Improve panic reports * Add an 'identifying_backtrace' field that only contains symbols in our codebase, which can be used for better deduplication. * In the main backtrace, include file and line numbers for all symbols in our codebase --- crates/zed/src/main.rs | 85 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 15 deletions(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index e22edee5f6ce95b6d179af065efff0d1eec9d749..6248ccf4f0bf888028a7dae775f7e7e0bcbefdae 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -32,6 +32,7 @@ use std::{ ffi::OsStr, fs::OpenOptions, io::Write as _, + ops::Not, os::unix::prelude::OsStrExt, panic, path::{Path, PathBuf}, @@ -371,13 +372,12 @@ struct Panic { #[serde(skip_serializing_if = "Option::is_none")] location_data: Option, backtrace: Vec, - // TODO - // stripped_backtrace: String, release_channel: String, os_name: String, os_version: Option, architecture: String, panicked_on: u128, + identifying_backtrace: Option>, } #[derive(Serialize)] @@ -396,18 +396,73 @@ fn init_panic_hook(app: &App) { let app_version = ZED_APP_VERSION .or_else(|| platform.app_version().ok()) .map_or("dev".to_string(), |v| v.to_string()); - let backtrace = Backtrace::new(); let thread = thread::current(); let thread = thread.name().unwrap_or(""); - let payload = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &**s, - None => "Box", - }, - }; + let payload = info.payload(); + let payload = None + .or_else(|| payload.downcast_ref::<&str>().map(|s| s.to_string())) + .or_else(|| payload.downcast_ref::().map(|s| s.clone())) + .unwrap_or_else(|| "Box".to_string()); + + let backtrace = Backtrace::new(); + let backtrace = backtrace + .frames() + .iter() + .filter_map(|frame| { + let symbol = frame.symbols().first()?; + let path = symbol.filename()?; + Some((path, symbol.lineno(), format!("{:#}", symbol.name()?))) + }) + .collect::>(); + + let this_file_path = Path::new(file!()); + + // Find the first frame in the backtrace for this panic hook itself. Exclude + // that frame and all frames before it. + let mut start_frame_ix = 0; + let mut codebase_root_path = None; + for (ix, (path, _, _)) in backtrace.iter().enumerate() { + if path.ends_with(this_file_path) { + start_frame_ix = ix + 1; + codebase_root_path = path.ancestors().nth(this_file_path.components().count()); + break; + } + } + + // Exclude any subsequent frames inside of rust's panic handling system. + while let Some((path, _, _)) = backtrace.get(start_frame_ix) { + if path.starts_with("/rustc") { + start_frame_ix += 1; + } else { + break; + } + } + + // Build two backtraces: + // * one for display, which includes symbol names for all frames, and files + // and line numbers for symbols in this codebase + // * one for identification and de-duplication, which only includes symbol + // names for symbols in this codebase. + let mut display_backtrace = Vec::new(); + let mut identifying_backtrace = Vec::new(); + for (path, line, symbol) in &backtrace[start_frame_ix..] { + display_backtrace.push(symbol.clone()); + + if let Some(codebase_root_path) = &codebase_root_path { + if let Ok(suffix) = path.strip_prefix(&codebase_root_path) { + identifying_backtrace.push(symbol.clone()); + + let display_path = suffix.to_string_lossy(); + if let Some(line) = line { + display_backtrace.push(format!(" {display_path}:{line}")); + } else { + display_backtrace.push(format!(" {display_path}")); + } + } + } + } let panic_data = Panic { thread: thread.into(), @@ -416,11 +471,6 @@ fn init_panic_hook(app: &App) { file: location.file().into(), line: location.line(), }), - backtrace: format!("{:?}", backtrace) - .split("\n") - .map(|line| line.to_string()) - .collect(), - // modified_backtrace: None, release_channel: RELEASE_CHANNEL.dev_name().into(), os_name: platform.os_name().into(), os_version: platform @@ -432,6 +482,11 @@ fn init_panic_hook(app: &App) { .duration_since(UNIX_EPOCH) .unwrap() .as_millis(), + backtrace: display_backtrace, + identifying_backtrace: identifying_backtrace + .is_empty() + .not() + .then_some(identifying_backtrace), }; if let Some(panic_data_json) = serde_json::to_string_pretty(&panic_data).log_err() { From 7417835f06a851ad1c6a6416727dbd06f15a1bf5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 2 Jun 2023 13:02:17 -0700 Subject: [PATCH 07/22] Avoid writing spurious nulls to settings file when updating it programatically --- crates/settings/src/settings_store.rs | 62 ++++++++++++++++----------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 3fdb81dd45cfee2671314ecc902cb38958841579..1133cb597067e70472ec6267ffb9575751efe36a 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -623,22 +623,6 @@ impl AnySettingValue for SettingValue { } } -// impl Debug for SettingsStore { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// return f -// .debug_struct("SettingsStore") -// .field( -// "setting_value_sets_by_type", -// &self -// .setting_values -// .values() -// .map(|set| (set.setting_type_name(), set)) -// .collect::>(), -// ) -// .finish_non_exhaustive(); -// } -// } - fn update_value_in_json_text<'a>( text: &mut String, key_path: &mut Vec<&'a str>, @@ -681,6 +665,10 @@ fn update_value_in_json_text<'a>( key_path.pop(); } } else if old_value != new_value { + let mut new_value = new_value.clone(); + if let Some(new_object) = new_value.as_object_mut() { + new_object.retain(|_, v| !v.is_null()); + } let (range, replacement) = replace_value_in_json_text(text, &key_path, tab_size, &new_value); text.replace_range(range.clone(), &replacement); @@ -692,7 +680,7 @@ fn replace_value_in_json_text( text: &str, key_path: &[&str], tab_size: usize, - new_value: impl Serialize, + new_value: &serde_json::Value, ) -> (Range, String) { const LANGUAGE_OVERRIDES: &'static str = "language_overrides"; const LANGUAGES: &'static str = "languages"; @@ -1039,24 +1027,32 @@ mod tests { r#"{ "languages": { "JSON": { - "is_enabled": true + "language_setting_1": true } } }"# .unindent(), |settings| { - settings.languages.get_mut("JSON").unwrap().is_enabled = false; settings .languages - .insert("Rust".into(), LanguageSettingEntry { is_enabled: true }); + .get_mut("JSON") + .unwrap() + .language_setting_1 = Some(false); + settings.languages.insert( + "Rust".into(), + LanguageSettingEntry { + language_setting_2: Some(true), + ..Default::default() + }, + ); }, r#"{ "languages": { "Rust": { - "is_enabled": true + "language_setting_2": true }, "JSON": { - "is_enabled": false + "language_setting_1": false } } }"# @@ -1119,6 +1115,23 @@ mod tests { .unindent(), cx, ); + + check_settings_update::( + &mut store, + r#"{ + } + "# + .unindent(), + |settings| settings.age = Some(37), + r#"{ + "user": { + "age": 37 + } + } + "# + .unindent(), + cx, + ); } fn check_settings_update( @@ -1247,9 +1260,10 @@ mod tests { languages: HashMap, } - #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] + #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] struct LanguageSettingEntry { - is_enabled: bool, + language_setting_1: Option, + language_setting_2: Option, } impl Setting for LanguageSettings { From 7c60f636d5d0d947137e750461219e15a588c655 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 2 Jun 2023 22:02:19 -0400 Subject: [PATCH 08/22] Fix typos --- assets/keymaps/default.json | 2 +- assets/settings/default.json | 2 +- crates/cli/src/main.rs | 5 +---- crates/collab_ui/src/collab_titlebar_item.rs | 2 +- crates/copilot/src/copilot.rs | 2 +- crates/editor/src/display_map.rs | 4 ++-- crates/editor/src/editor.rs | 6 +++--- crates/editor/src/editor_tests.rs | 6 +++--- crates/editor/src/element.rs | 2 +- crates/editor/src/multi_buffer.rs | 2 +- crates/editor/src/test.rs | 4 ++-- crates/fs/src/fs.rs | 6 +++--- crates/gpui/src/app.rs | 4 ++-- crates/gpui/src/keymap_matcher.rs | 2 +- crates/language/src/language_settings.rs | 2 +- crates/language/src/syntax_map.rs | 4 ++-- crates/plugin_macros/src/lib.rs | 4 ++-- crates/plugin_runtime/OPAQUE.md | 4 ++-- crates/plugin_runtime/src/plugin.rs | 10 +++++----- crates/project/src/project.rs | 2 +- crates/project/src/worktree.rs | 4 ++-- crates/project_symbols/src/project_symbols.rs | 2 +- crates/rpc/proto/zed.proto | 2 +- crates/rpc/src/auth.rs | 2 +- crates/sqlez/src/thread_safe_connection.rs | 8 ++++---- crates/terminal/src/mappings/colors.rs | 4 ++-- crates/terminal_view/README.md | 2 +- crates/terminal_view/scripts/print256color.sh | 2 +- crates/terminal_view/src/terminal_element.rs | 4 ++-- crates/terminal_view/src/terminal_view.rs | 4 ++-- crates/text/src/tests.rs | 4 ++-- crates/vim/src/normal.rs | 2 +- crates/vim/src/test/neovim_connection.rs | 2 +- crates/workspace/src/pane.rs | 2 +- crates/workspace/src/workspace.rs | 2 +- crates/zed/src/languages/typescript.rs | 2 +- crates/zed/src/main.rs | 2 +- styles/src/buildLicenses.ts | 2 +- styles/src/styleTree/editor.ts | 2 +- styles/src/styleTree/search.ts | 2 +- styles/src/system/types.ts | 10 +++++----- 41 files changed, 69 insertions(+), 72 deletions(-) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 46a3fb5a5a7f63d5855d8fb2f8ff9023b82c9dac..d37bc7d2ed0e049f3dff7d5197900e915b733f4e 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -516,7 +516,7 @@ "terminal::SendText", "\u0001" ], - // Terminal.app compatability + // Terminal.app compatibility "alt-left": [ "terminal::SendText", "\u001bb" diff --git a/assets/settings/default.json b/assets/settings/default.json index 23599c8dfb1e327d9d842b76fb8c5e2914c23b3f..8a7a215e9d2c665e1dd4f0a1c8f94928447a333a 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -245,7 +245,7 @@ // copy to the system clipboard. "copy_on_select": false, // Any key-value pairs added to this list will be added to the terminal's - // enviroment. Use `:` to seperate multiple values. + // environment. Use `:` to separate multiple values. "env": { // "KEY": "value1:value2" }, diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index feebbff61b93043b88ed2eaa0603018eb191fd69..bdf677512c4b0326cf2bc0e513a00bbb563f0a02 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -159,10 +159,7 @@ impl Bundle { fn path(&self) -> &Path { match self { Self::App { app_bundle, .. } => app_bundle, - Self::LocalPath { - executable: excutable, - .. - } => excutable, + Self::LocalPath { executable, .. } => executable, } } diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index eb1755a9ff3c25494c93c5e320362d08da45c56b..720a73f477e1c5ceb4e8888de95afefe937f1589 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -472,7 +472,7 @@ impl CollabTitlebarItem { Stack::new() .with_child( MouseEventHandler::::new(0, cx, |state, _| { - //TODO: Ensure this button has consistant width for both text variations + //TODO: Ensure this button has consistent width for both text variations let style = titlebar.share_button.style_for(state, false); Label::new(label, style.text.clone()) .contained() diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 7834603552fa14a36d81109c2a8030a8fef4efee..04e8764f7b0d5d72f50fd36f3b83c2b7ab25bea3 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -375,7 +375,7 @@ impl Copilot { server .on_notification::(|params, _cx| { match params.level { - // Copilot is pretty agressive about logging + // Copilot is pretty aggressive about logging 0 => debug!("copilot: {}", params.message), 1 => debug!("copilot: {}", params.message), _ => error!("copilot: {}", params.message), diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index b0483db68dcb781619188791b3f9b3630e902584..a594af51a6307bbfda7b421c8a723e0c0e3563ef 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -475,7 +475,7 @@ impl DisplaySnapshot { }) } - /// Returns an iterator of the start positions of the occurances of `target` in the `self` after `from` + /// Returns an iterator of the start positions of the occurrences of `target` in the `self` after `from` /// Stops if `condition` returns false for any of the character position pairs observed. pub fn find_while<'a>( &'a self, @@ -486,7 +486,7 @@ impl DisplaySnapshot { Self::find_internal(self.chars_at(from), target.chars().collect(), condition) } - /// Returns an iterator of the end positions of the occurances of `target` in the `self` before `from` + /// Returns an iterator of the end positions of the occurrences of `target` in the `self` before `from` /// Stops if `condition` returns false for any of the character position pairs observed. pub fn reverse_find_while<'a>( &'a self, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index af7344a91f230b6ace019a179ea242011958c597..d98bd92532238337381dfb100f38b44c18369d1d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2539,7 +2539,7 @@ impl Editor { .read(cx) .text_anchor_for_position(position.clone(), cx)?; - // OnTypeFormatting retuns a list of edits, no need to pass them between Zed instances, + // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances, // hence we do LSP request & edit on host side only — add formats to host's history. let push_to_lsp_host_history = true; // If this is not the host, append its history with new edits. @@ -7913,13 +7913,13 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend } pub fn highlight_diagnostic_message( - inital_highlights: Vec, + initial_highlights: Vec, message: &str, ) -> (String, Vec) { let mut message_without_backticks = String::new(); let mut prev_offset = 0; let mut inside_block = false; - let mut highlights = inital_highlights; + let mut highlights = initial_highlights; for (match_ix, (offset, _)) in message .match_indices('`') .chain([(message.len(), "")]) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 969b9c882d937a165473e06715b29f6352ed4fbc..35d61bf0cf666e009dd6a6f685fbfb5e97559b30 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -4321,7 +4321,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { ); assert!(!cx.read(|cx| editor.is_dirty(cx))); - // Set rust language override and assert overriden tabsize is sent to language server + // Set rust language override and assert overridden tabsize is sent to language server update_test_settings(cx, |settings| { settings.languages.insert( "Rust".into(), @@ -4435,7 +4435,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { ); assert!(!cx.read(|cx| editor.is_dirty(cx))); - // Set rust language override and assert overriden tabsize is sent to language server + // Set rust language override and assert overridden tabsize is sent to language server update_test_settings(cx, |settings| { settings.languages.insert( "Rust".into(), @@ -4776,7 +4776,7 @@ async fn test_completion(cx: &mut gpui::TestAppContext) { two threeˇ "}, - "overlapping aditional edit", + "overlapping additional edit", ), ( indoc! {" diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 6be065084814e570a0411ffb91df4a4eb380e1ac..a74775e7f6d5042e69669d731474cc465a0abafc 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -3080,7 +3080,7 @@ mod tests { editor_width: f32, ) -> Vec { info!( - "Creating editor with mode {editor_mode:?}, witdh {editor_width} and text '{input_text}'" + "Creating editor with mode {editor_mode:?}, width {editor_width} and text '{input_text}'" ); let (_, editor) = cx.add_window(|cx| { let buffer = MultiBuffer::build_simple(&input_text, cx); diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index af0003ec2dde8f6fe302c9fb7c0aabfdcf91c2ff..28b60f4c025b9a3cb94ce439a6e8e87f3762f6e9 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -5332,7 +5332,7 @@ mod tests { assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678"); // An undo in the multibuffer undoes the multibuffer transaction - // and also any individual buffer edits that have occured since + // and also any individual buffer edits that have occurred since // that transaction. multibuffer.undo(cx); assert_eq!(multibuffer.read(cx).text(), "AB1234\nAB5678"); diff --git a/crates/editor/src/test.rs b/crates/editor/src/test.rs index 8a3e08bea570ec745b527c24951540026caa4879..9b568e4a4fe27ed36c47c9fb02561d4a63cfb237 100644 --- a/crates/editor/src/test.rs +++ b/crates/editor/src/test.rs @@ -48,8 +48,8 @@ pub fn marked_display_snapshot( } pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContext) { - let (umarked_text, text_ranges) = marked_text_ranges(marked_text, true); - assert_eq!(editor.text(cx), umarked_text); + let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true); + assert_eq!(editor.text(cx), unmarked_text); editor.change_selections(None, cx, |s| s.select_ranges(text_ranges)); } diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 99562405b5b909e30e27df8b713e13c7e6c30cc5..4c6b6c24d300273b1cbe3f2386cc51ba19cdc5d5 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -32,7 +32,7 @@ use repository::{FakeGitRepositoryState, GitFileStatus}; use std::sync::Weak; lazy_static! { - static ref LINE_SEPERATORS_REGEX: Regex = Regex::new("\r\n|\r|\u{2028}|\u{2029}").unwrap(); + static ref LINE_SEPARATORS_REGEX: Regex = Regex::new("\r\n|\r|\u{2028}|\u{2029}").unwrap(); } #[derive(Clone, Copy, Debug, PartialEq)] @@ -77,13 +77,13 @@ impl LineEnding { } pub fn normalize(text: &mut String) { - if let Cow::Owned(replaced) = LINE_SEPERATORS_REGEX.replace_all(text, "\n") { + if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(text, "\n") { *text = replaced; } } pub fn normalize_arc(text: Arc) -> Arc { - if let Cow::Owned(replaced) = LINE_SEPERATORS_REGEX.replace_all(&text, "\n") { + if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(&text, "\n") { replaced.into() } else { text diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index d0388a9aedebbec4618fa02b22b335e2a659c5aa..882800f128abe8d41dd48e83a694b48d0020778b 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -6335,9 +6335,9 @@ mod tests { #[crate::test(self)] async fn test_labeled_tasks(cx: &mut TestAppContext) { assert_eq!(None, cx.update(|cx| cx.active_labeled_tasks().next())); - let (mut sender, mut reciever) = postage::oneshot::channel::<()>(); + let (mut sender, mut receiver) = postage::oneshot::channel::<()>(); let task = cx - .update(|cx| cx.spawn_labeled("Test Label", |_| async move { reciever.recv().await })); + .update(|cx| cx.spawn_labeled("Test Label", |_| async move { receiver.recv().await })); assert_eq!( Some("Test Label"), diff --git a/crates/gpui/src/keymap_matcher.rs b/crates/gpui/src/keymap_matcher.rs index 0c088f9728977379ee0f8fcd80d5d9d1209f5d20..bc70638b2c077bf5aee53f9fedd22e96938d6b4b 100644 --- a/crates/gpui/src/keymap_matcher.rs +++ b/crates/gpui/src/keymap_matcher.rs @@ -67,7 +67,7 @@ impl KeymapMatcher { /// MatchResult::Pending => /// There exist bindings which are still waiting for more keys. /// MatchResult::Complete(matches) => - /// 1 or more bindings have recieved the necessary key presses. + /// 1 or more bindings have received the necessary key presses. /// The order of the matched actions is by position of the matching first, // and order in the keymap second. pub fn push_keystroke( diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 332e789b4d7e364ab24c382a4daa9928291967cd..1a953b0bf21c0f3ed7d162a516657ce69cbb6a0b 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -264,7 +264,7 @@ impl settings::Setting for AllLanguageSettings { let mut root_schema = generator.root_schema_for::(); // Create a schema for a 'languages overrides' object, associating editor - // settings with specific langauges. + // settings with specific languages. assert!(root_schema .definitions .contains_key("LanguageSettingsContent")); diff --git a/crates/language/src/syntax_map.rs b/crates/language/src/syntax_map.rs index ce1196e946cacdaf6bef12db21c4dfcd3b4a157b..16313db49881070f6c0baac9b71b317761079830 100644 --- a/crates/language/src/syntax_map.rs +++ b/crates/language/src/syntax_map.rs @@ -773,7 +773,7 @@ impl<'a> SyntaxMapCaptures<'a> { } in layers { let grammar = match &language.grammar { - Some(grammer) => grammer, + Some(grammar) => grammar, None => continue, }; let query = match query(&grammar) { @@ -896,7 +896,7 @@ impl<'a> SyntaxMapMatches<'a> { } in layers { let grammar = match &language.grammar { - Some(grammer) => grammer, + Some(grammar) => grammar, None => continue, }; let query = match query(&grammar) { diff --git a/crates/plugin_macros/src/lib.rs b/crates/plugin_macros/src/lib.rs index 3f708658fd4f368088f58a837087ef89d722a9ba..2fe8b31b613b6fdf9206c39bac3d9083c3111a6e 100644 --- a/crates/plugin_macros/src/lib.rs +++ b/crates/plugin_macros/src/lib.rs @@ -11,7 +11,7 @@ use syn::{parse_macro_input, Block, FnArg, ForeignItemFn, Ident, ItemFn, Pat, Ty /// "Hello from Wasm".into() /// } /// ``` -/// This macro makes a function defined guest-side avaliable host-side. +/// This macro makes a function defined guest-side available host-side. /// Note that all arguments and return types must be `serde`. #[proc_macro_attribute] pub fn export(args: TokenStream, function: TokenStream) -> TokenStream { @@ -92,7 +92,7 @@ pub fn export(args: TokenStream, function: TokenStream) -> TokenStream { /// #[import] /// pub fn operating_system_name() -> String; /// ``` -/// This macro makes a function defined host-side avaliable guest-side. +/// This macro makes a function defined host-side available guest-side. /// Note that all arguments and return types must be `serde`. /// All that's provided is a signature, as the function is implemented host-side. #[proc_macro_attribute] diff --git a/crates/plugin_runtime/OPAQUE.md b/crates/plugin_runtime/OPAQUE.md index c99224edeb45d54e29deb75d77ac970c75839345..52ee75dbf9bab78811d0ad858d2036889d9a0517 100644 --- a/crates/plugin_runtime/OPAQUE.md +++ b/crates/plugin_runtime/OPAQUE.md @@ -127,7 +127,7 @@ use plugin_handles::RopeHandle; pub fn append(rope: RopeHandle, string: &str); ``` -This allows us to perform an operation on a `Rope`, but how do we get a `RopeHandle` into a plugin? Well, as plugins, we can only aquire resources to handles we're given, so we'd need to expose a fuction that takes a handle. +This allows us to perform an operation on a `Rope`, but how do we get a `RopeHandle` into a plugin? Well, as plugins, we can only acquire resources to handles we're given, so we'd need to expose a function that takes a handle. To illustrate that point, here's an example. First, we'd define a plugin-side function as follows: @@ -177,7 +177,7 @@ So here's what calling `append_newline` would do, from the top: 6. And from here on out we return up the callstack, through Wasm, to Rust all the way back to where we started. Right before we return, we clear out the `ResourcePool`, so that we're no longer holding onto the underlying resource. -Throughout this entire chain of calls, the resource remain host-side. By temporarilty checking it into a `ResourcePool`, we're able to keep a reference to the resource that we can use, while avoiding copying the uncopyable resource. +Throughout this entire chain of calls, the resource remain host-side. By temporarily checking it into a `ResourcePool`, we're able to keep a reference to the resource that we can use, while avoiding copying the uncopyable resource. ## Final Notes diff --git a/crates/plugin_runtime/src/plugin.rs b/crates/plugin_runtime/src/plugin.rs index bfcb024faa4514da0cc19186a38e0bc971c8d221..8070539b35da3ab2ec438c3886defe3e8cff8578 100644 --- a/crates/plugin_runtime/src/plugin.rs +++ b/crates/plugin_runtime/src/plugin.rs @@ -132,7 +132,7 @@ impl PluginBuilder { "env", &format!("__{}", name), move |mut caller: Caller<'_, WasiCtxAlloc>, packed_buffer: u64| { - // TODO: use try block once avaliable + // TODO: use try block once available let result: Result<(WasiBuffer, Memory, _), Trap> = (|| { // grab a handle to the memory let plugin_memory = match caller.get_export("memory") { @@ -211,7 +211,7 @@ impl PluginBuilder { "env", &format!("__{}", name), move |mut caller: Caller<'_, WasiCtxAlloc>, packed_buffer: u64| { - // TODO: use try block once avaliable + // TODO: use try block once available let result: Result<(WasiBuffer, Memory, Vec), Trap> = (|| { // grab a handle to the memory let plugin_memory = match caller.get_export("memory") { @@ -297,7 +297,7 @@ pub enum PluginBinary<'a> { Precompiled(&'a [u8]), } -/// Represents a WebAssembly plugin, with access to the WebAssembly System Inferface. +/// Represents a WebAssembly plugin, with access to the WebAssembly System Interface. /// Build a new plugin using [`PluginBuilder`]. pub struct Plugin { store: Store, @@ -559,7 +559,7 @@ impl Plugin { .ok_or_else(|| anyhow!("Could not grab slice of plugin memory"))?; // write the argument to linear memory - // this returns a (ptr, lentgh) pair + // this returns a (ptr, length) pair let arg_buffer = Self::bytes_to_buffer( self.store.data().alloc_buffer(), &mut plugin_memory, @@ -569,7 +569,7 @@ impl Plugin { .await?; // call the function, passing in the buffer and its length - // this returns a ptr to a (ptr, lentgh) pair + // this returns a ptr to a (ptr, length) pair let result_buffer = handle .function .call_async(&mut self.store, arg_buffer.into_u64()) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 7ce07959d7972c76f32cb43dce5bf832d5df23d7..b0d0d670bae382c0e42e8bd75b7a3b8a59a904ff 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -4052,7 +4052,7 @@ impl Project { let end_within = range.start.cmp(&primary.end, buffer).is_le() && range.end.cmp(&primary.end, buffer).is_ge(); - //Skip addtional edits which overlap with the primary completion edit + //Skip additional edits which overlap with the primary completion edit //https://github.com/zed-industries/zed/pull/1871 if !start_within && !end_within { buffer.edit([(range, text)], None, cx); diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index a33a0fc050177db96dfbb56a901331bb6928e5ff..97656b7b10053e4d6b7a30982719ebd75adab057 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -157,7 +157,7 @@ impl RepositoryEntry { self.statuses .iter_from(&repo_path) .take_while(|(key, _)| key.starts_with(&repo_path)) - // Short circut once we've found the highest level + // Short circuit once we've found the highest level .take_until(|(_, status)| status == &&GitFileStatus::Conflict) .map(|(_, status)| status) .reduce( @@ -3623,7 +3623,7 @@ pub trait WorktreeHandle { impl WorktreeHandle for ModelHandle { // When the worktree's FS event stream sometimes delivers "redundant" events for FS changes that - // occurred before the worktree was constructed. These events can cause the worktree to perfrom + // occurred before the worktree was constructed. These events can cause the worktree to perform // extra directory scans, and emit extra scan-state notifications. // // This function mutates the worktree's directory and waits for those mutations to be picked up, diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 71271d4e7c736e839fdc2fcc00ccc5678e46f741..0dc5dad3bf8d43edf3cb4c18507a7389ca65c2e1 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -276,7 +276,7 @@ mod tests { .await .unwrap(); - // Set up fake langauge server to return fuzzy matches against + // Set up fake language server to return fuzzy matches against // a fixed set of symbol names. let fake_symbols = [ symbol("one", "/external"), diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 8351cdfd2dfe6a61bcccaad4d7a8dc40ff00bfc2..ca3ec7cafb899a8ccbec6aec548c79d97ea30daa 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -476,7 +476,7 @@ message Symbol { string name = 4; int32 kind = 5; string path = 6; - // Cannot use generate anchors for unopend files, + // Cannot use generate anchors for unopened files, // so we are forced to use point coords instead PointUtf16 start = 7; PointUtf16 end = 8; diff --git a/crates/rpc/src/auth.rs b/crates/rpc/src/auth.rs index 39c8c39a4423de758807e67751a313e091e4f929..ac7bbcebecd98ebfb00a5dad4b92c16eddb3e628 100644 --- a/crates/rpc/src/auth.rs +++ b/crates/rpc/src/auth.rs @@ -42,7 +42,7 @@ impl PublicKey { } impl PrivateKey { - /// Decrypt a base64-encoded string that was encrypted by the correspoding public key. + /// Decrypt a base64-encoded string that was encrypted by the corresponding public key. pub fn decrypt_string(&self, encrypted_string: &str) -> Result { let encrypted_bytes = base64::decode_config(encrypted_string, base64::URL_SAFE) .context("failed to base64-decode encrypted string")?; diff --git a/crates/sqlez/src/thread_safe_connection.rs b/crates/sqlez/src/thread_safe_connection.rs index c3fe4657ee9182dbf1c229e32b19ebf3c30c0ec7..ffadb3af41d165737af55538661ec7100e62daeb 100644 --- a/crates/sqlez/src/thread_safe_connection.rs +++ b/crates/sqlez/src/thread_safe_connection.rs @@ -160,7 +160,7 @@ impl ThreadSafeConnection { // Create a one shot channel for the result of the queued write // so we can await on the result - let (sender, reciever) = oneshot::channel(); + let (sender, receiver) = oneshot::channel(); let thread_safe_connection = (*self).clone(); write_channel(Box::new(move || { @@ -168,7 +168,7 @@ impl ThreadSafeConnection { let result = connection.with_write(|connection| callback(connection)); sender.send(result).ok(); })); - reciever.map(|response| response.expect("Write queue unexpectedly closed")) + receiver.map(|response| response.expect("Write queue unexpectedly closed")) } pub(crate) fn create_connection( @@ -245,10 +245,10 @@ pub fn background_thread_queue() -> WriteQueueConstructor { use std::sync::mpsc::channel; Box::new(|| { - let (sender, reciever) = channel::(); + let (sender, receiver) = channel::(); thread::spawn(move || { - while let Ok(write) = reciever.recv() { + while let Ok(write) = receiver.recv() { write() } }); diff --git a/crates/terminal/src/mappings/colors.rs b/crates/terminal/src/mappings/colors.rs index 5bed4b573c4b97ada6f6c0c3a5ef649c1d1a7e92..3f776251b52693893f58eb6868a53ad995f5ab84 100644 --- a/crates/terminal/src/mappings/colors.rs +++ b/crates/terminal/src/mappings/colors.rs @@ -45,7 +45,7 @@ pub fn convert_color(alac_color: &AnsiColor, style: &TerminalStyle) -> Color { } ///Converts an 8 bit ANSI color to it's GPUI equivalent. -///Accepts usize for compatability with the alacritty::Colors interface, +///Accepts usize for compatibility with the alacritty::Colors interface, ///Other than that use case, should only be called with values in the [0,255] range pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color { match index { @@ -78,7 +78,7 @@ pub fn get_color_at_index(index: &usize, style: &TerminalStyle) -> Color { let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks Color::new(i * step, i * step, i * step, u8::MAX) //Map the ANSI-grayscale components to the RGB-grayscale } - //For compatability with the alacritty::Colors interface + //For compatibility with the alacritty::Colors interface 256 => style.foreground, 257 => style.background, 258 => style.cursor, diff --git a/crates/terminal_view/README.md b/crates/terminal_view/README.md index 272212a538a06766d254b6bbd675643af62e1175..019460067ebf20f991b18a9cd5ce262ae7675504 100644 --- a/crates/terminal_view/README.md +++ b/crates/terminal_view/README.md @@ -18,6 +18,6 @@ There are currently many distinct paths for getting keystrokes to the terminal: 3. IME text. When the special character mappings fail, we pass the keystroke back to GPUI to hand it to the IME system. This comes back to us in the `View::replace_text_in_range()` method, and we then send that to the terminal directly, bypassing `try_keystroke()`. -4. Pasted text has a seperate pathway. +4. Pasted text has a separate pathway. Generally, there's a distinction between 'keystrokes that need to be mapped' and 'strings which need to be written'. I've attempted to unify these under the '.try_keystroke()' API and the `.input()` API (which try_keystroke uses) so we have consistent input handling across the terminal \ No newline at end of file diff --git a/crates/terminal_view/scripts/print256color.sh b/crates/terminal_view/scripts/print256color.sh index 99e3d8c9f9d3ae7d37e006fe9af328f0c7ea849c..8a53f3bc025842d900b5b4797eefc6d8a0946120 100755 --- a/crates/terminal_view/scripts/print256color.sh +++ b/crates/terminal_view/scripts/print256color.sh @@ -40,7 +40,7 @@ function contrast_colour { # Uncomment the below for more precise luminance calculations - # # Calculate percieved brightness + # # Calculate perceived brightness # # See https://www.w3.org/TR/AERT#color-contrast # # and http://www.itu.int/rec/R-REC-BT.601 # # Luminance is in range 0..5000 as each value is 0..5 diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index 18c85db980ba14aab27ad91254ee022db57b1a0f..2f2ff2cdc3bde8bb5ee1c4a32978ed28518bd94f 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -34,7 +34,7 @@ use std::{mem, ops::Range}; use crate::TerminalView; -///The information generated during layout that is nescessary for painting +///The information generated during layout that is necessary for painting pub struct LayoutState { cells: Vec, rects: Vec, @@ -206,7 +206,7 @@ impl TerminalElement { //Expand background rect range { if matches!(bg, Named(NamedColor::Background)) { - //Continue to next cell, resetting variables if nescessary + //Continue to next cell, resetting variables if necessary cur_alac_color = None; if let Some(rect) = cur_rect { rects.push(rect); diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 9478b3eef14221782050ca9ddf269878a91fef28..c40a1a7ccd3d493e16e6a4b03a2d36e21a0b0c14 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -804,7 +804,7 @@ mod tests { let workspace = workspace.read(cx); let active_entry = project.read(cx).active_entry(); - //Make sure enviroment is as expeted + //Make sure environment is as expected assert!(active_entry.is_none()); assert!(workspace.worktrees(cx).next().is_none()); @@ -825,7 +825,7 @@ mod tests { let workspace = workspace.read(cx); let active_entry = project.read(cx).active_entry(); - //Make sure enviroment is as expeted + //Make sure environment is as expected assert!(active_entry.is_none()); assert!(workspace.worktrees(cx).next().is_some()); diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index 4b8266120a3682e118c497c3d4ba3cea7cd9e2df..7e26e0a29649681346ce6148a71f7dc1058467da 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -193,7 +193,7 @@ fn test_line_len() { } #[test] -fn test_common_prefix_at_positionn() { +fn test_common_prefix_at_position() { let text = "a = str; b = δα"; let buffer = Buffer::new(0, 0, text.into()); @@ -216,7 +216,7 @@ fn test_common_prefix_at_positionn() { empty_range_after(text, "str"), ); - // prefix matching is case insenstive. + // prefix matching is case insensitive. assert_eq!( buffer.common_prefix_at(offset1, "Strαngε"), range_of(text, "str"), diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 83a18a1ac9f585fe80e657752983b120b021dfd5..91be1022a3dd7bb448dbbc447dff7175dfdceeb9 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -756,7 +756,7 @@ mod test { ˇ The quick"}) .await; - // Indoc disallows trailing whitspace. + // Indoc disallows trailing whitespace. cx.assert(" ˇ \nThe quick").await; } diff --git a/crates/vim/src/test/neovim_connection.rs b/crates/vim/src/test/neovim_connection.rs index 538e83a8036f114c84c34f1c4e833ed449fa7c45..c3916722ddeaad974747a63729058b73c7d7d544 100644 --- a/crates/vim/src/test/neovim_connection.rs +++ b/crates/vim/src/test/neovim_connection.rs @@ -29,7 +29,7 @@ use tokio::{ use crate::state::Mode; use collections::VecDeque; -// Neovim doesn't like to be started simultaneously from multiple threads. We use thsi lock +// Neovim doesn't like to be started simultaneously from multiple threads. We use this lock // to ensure we are only constructing one neovim connection at a time. #[cfg(feature = "neovim")] lazy_static! { diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 1fa8c15f9bc1f5399fbcda51cb68d2b594543c46..b784cb39b8297d176fc1f0667b09054a86d127d0 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1022,7 +1022,7 @@ impl Pane { let is_active_item = target_item_id == active_item_id; let target_pane = cx.weak_handle(); - // The `CloseInactiveItems` action should really be called "CloseOthers" and the behaviour should be dynamically based on the tab the action is ran on. Currenlty, this is a weird action because you can run it on a non-active tab and it will close everything by the actual active tab + // The `CloseInactiveItems` action should really be called "CloseOthers" and the behaviour should be dynamically based on the tab the action is ran on. Currently, this is a weird action because you can run it on a non-active tab and it will close everything by the actual active tab self.tab_context_menu.update(cx, |menu, cx| { menu.show( diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 795747cfcc5045a8c554b9ca8f206b57bb313dc8..95d0bf653855bc5effbfe015e38ba7232fd9ccd3 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -4424,7 +4424,7 @@ mod tests { assert!(!panel.has_focus(cx)); }); - // Transfering focus back to the panel keeps it zoomed + // Transferring focus back to the panel keeps it zoomed workspace.update(cx, |workspace, cx| { workspace.toggle_panel_focus::(cx); }); diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index 429a5d942151cd9dbd3661b2ebb6bbc16a6505e3..a25d7d02ea550b84a88482be86d3501ecea8032d 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -207,7 +207,7 @@ impl LspAdapter for EsLintLspAdapter { http: Arc, ) -> Result> { // At the time of writing the latest vscode-eslint release was released in 2020 and requires - // special custom LSP protocol extensions be handled to fully initalize. Download the latest + // special custom LSP protocol extensions be handled to fully initialize. Download the latest // prerelease instead to sidestep this issue let release = latest_github_release("microsoft/vscode-eslint", true, http).await?; Ok(Box::new(GitHubLspBinaryVersion { diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 6248ccf4f0bf888028a7dae775f7e7e0bcbefdae..18ee4baeb23b3884249707b17f18e536f29bac93 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -1,4 +1,4 @@ -// Allow binary to be called Zed for a nice application menu when running executable direcly +// Allow binary to be called Zed for a nice application menu when running executable directly #![allow(non_snake_case)] use anyhow::{anyhow, Context, Result}; diff --git a/styles/src/buildLicenses.ts b/styles/src/buildLicenses.ts index 9a053e9c0c9ca7732a71b149a884df4a11b9391c..e77cb11bb9ec3c8bfbc381d5942c76709082deeb 100644 --- a/styles/src/buildLicenses.ts +++ b/styles/src/buildLicenses.ts @@ -23,7 +23,7 @@ function checkLicenses( licenses: string[] ) { for (const { meta } of schemeMetaWithLicense) { - // FIXME: Add support for conjuctions and conditions + // FIXME: Add support for conjunctions and conditions if (licenses.indexOf(meta.license.SPDX) < 0) { throw Error( `License for theme ${meta.name} (${meta.license.SPDX}) is not supported` diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index fa0aec2012dee96d07e4359761c1d723fc41f0bd..66074aa684bc5719ac7ce7061e4afb8b28b7e95e 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -112,7 +112,7 @@ export default function editor(colorScheme: ColorScheme) { widthEm: 0.15, cornerRadius: 0.05, }, - /** Highlights matching occurences of what is under the cursor + /** Highlights matching occurrences of what is under the cursor * as well as matched brackets */ documentHighlightReadBackground: withOpacity( diff --git a/styles/src/styleTree/search.ts b/styles/src/styleTree/search.ts index 6fc8a95d7dbde571103d6d1ebebf4265837ba1b4..2094a2e369739327d968a6616ebab0b373f916f0 100644 --- a/styles/src/styleTree/search.ts +++ b/styles/src/styleTree/search.ts @@ -33,7 +33,7 @@ export default function search(colorScheme: ColorScheme) { }; return { - // TODO: Add an activeMatchBackground on the rust side to differenciate between active and inactive + // TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive matchBackground: withOpacity(foreground(layer, "accent"), 0.4), optionButton: { ...text(layer, "mono", "on"), diff --git a/styles/src/system/types.ts b/styles/src/system/types.ts index 8bfa2dd7dbf9608f4549fdc2adde412c7da5022d..8de65a37eb131ba412fe269529106d58070669ee 100644 --- a/styles/src/system/types.ts +++ b/styles/src/system/types.ts @@ -1,6 +1,6 @@ import { Curve } from "./ref/curves" -export interface ColorAccessiblityValue { +export interface ColorAccessibilityValue { value: number aaPass: boolean aaaPass: boolean @@ -12,14 +12,14 @@ export interface ColorAccessiblityValue { * @note This implementation is currently basic – Currently we only calculate contrasts against black and white, in the future will allow for dynamic color contrast calculation based on the colors present in a given palette. * @note The goal is to align with WCAG3 accessibility standards as they become stabilized. See the [WCAG 3 Introduction](https://www.w3.org/WAI/standards-guidelines/wcag/wcag3-intro/) for more information. */ -export interface ColorAccessiblity { - black: ColorAccessiblityValue - white: ColorAccessiblityValue +export interface ColorAccessibility { + black: ColorAccessibilityValue + white: ColorAccessibilityValue } export type Color = { step: number - contrast: ColorAccessiblity + contrast: ColorAccessibility hex: string lch: number[] rgba: number[] From 5790d6993e79b8200c14d2ac0a7cbd2cda54b670 Mon Sep 17 00:00:00 2001 From: Julia Date: Sun, 4 Jun 2023 23:34:22 -0400 Subject: [PATCH 09/22] Update rust-bindgen dev-dependencies --- Cargo.lock | 113 ++++++++++++++-------------------------- crates/gpui/Cargo.toml | 2 +- crates/media/Cargo.toml | 2 +- 3 files changed, 41 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07a859b058692c2ba7571f75b7cc9a9dd31374cf..7f9a5530132f36be1fe38fd5428611aaf29b2aed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,15 +180,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "anyhow" version = "1.0.71" @@ -404,7 +395,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -452,7 +443,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -495,7 +486,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -715,24 +706,24 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.59.2" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap 2.34.0", - "env_logger 0.9.3", "lazy_static", "lazycell", "log", "peeking_take_while", + "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", + "syn 2.0.18", "which", ] @@ -1085,21 +1076,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim 0.8.0", - "textwrap 0.11.0", - "unicode-width", - "vec_map", -] - [[package]] name = "clap" version = "3.2.25" @@ -1112,9 +1088,9 @@ dependencies = [ "clap_lex", "indexmap", "once_cell", - "strsim 0.10.0", + "strsim", "termcolor", - "textwrap 0.16.0", + "textwrap", ] [[package]] @@ -1144,7 +1120,7 @@ name = "cli" version = "0.1.0" dependencies = [ "anyhow", - "clap 3.2.25", + "clap", "core-foundation", "core-services", "dirs 3.0.2", @@ -1254,7 +1230,7 @@ dependencies = [ "axum-extra", "base64 0.13.1", "call", - "clap 3.2.25", + "clap", "client", "collections", "ctor", @@ -1797,7 +1773,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -1814,7 +1790,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -2587,7 +2563,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -4348,7 +4324,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -4793,6 +4769,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1" +dependencies = [ + "proc-macro2", + "syn 2.0.18", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -4828,9 +4814,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] @@ -5107,9 +5093,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -6053,7 +6039,7 @@ checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -6096,7 +6082,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -6583,12 +6569,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" @@ -6660,9 +6640,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -6848,15 +6828,6 @@ dependencies = [ "util", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "textwrap" version = "0.16.0" @@ -6930,7 +6901,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -7088,7 +7059,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -7276,7 +7247,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -7837,12 +7808,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" @@ -8006,7 +7971,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", "wasm-bindgen-shared", ] @@ -8040,7 +8005,7 @@ checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -8907,7 +8872,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index c1dc13084e804d10d0f2134d0160c165098c4f5f..31b7db008d28d56849c7ce36eb3f23336fe82fad 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -53,7 +53,7 @@ uuid = { version = "1.1.2", features = ["v4"] } waker-fn = "1.1.0" [build-dependencies] -bindgen = "0.59.2" +bindgen = "0.65.1" cc = "1.0.67" [dev-dependencies] diff --git a/crates/media/Cargo.toml b/crates/media/Cargo.toml index 22a494d754ca09c4feef16fa3dc48c505dab48ff..3825897e7b5be2d871bac7cd4a778517191ed1eb 100644 --- a/crates/media/Cargo.toml +++ b/crates/media/Cargo.toml @@ -18,4 +18,4 @@ metal = "0.21.0" objc = "0.2" [build-dependencies] -bindgen = "0.59.2" +bindgen = "0.65.1" From c872f581d14ab26b113ae25a0f930edd8ca0c700 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 5 Jun 2023 12:00:40 +0200 Subject: [PATCH 10/22] Query `rect_for_text_range` on focused view instead of root element This was causing IME input to be drawn in the wrong place when there were splits or panels in the window. --- crates/gpui/src/app/window.rs | 4 ++-- crates/gpui/src/app/window_input_handler.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 30d58cdd726e532599a743caa5aae3c01917340f..cfcef626dfa2a5baf36a230eebcd1e5ae2d23495 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -965,10 +965,10 @@ impl<'a> WindowContext<'a> { } pub fn rect_for_text_range(&self, range_utf16: Range) -> Option { - let root_view_id = self.window.root_view().id(); + let focused_view_id = self.window.focused_view_id?; self.window .rendered_views - .get(&root_view_id)? + .get(&focused_view_id)? .rect_for_text_range(range_utf16, self) .log_err() .flatten() diff --git a/crates/gpui/src/app/window_input_handler.rs b/crates/gpui/src/app/window_input_handler.rs index 938dbe1a0390c499575975bfdcda1bf8f2139609..8ee9f7eeff5c2a3e4f4d63ca55c9338f02e3ed69 100644 --- a/crates/gpui/src/app/window_input_handler.rs +++ b/crates/gpui/src/app/window_input_handler.rs @@ -84,8 +84,8 @@ impl InputHandler for WindowInputHandler { fn rect_for_range(&self, range_utf16: Range) -> Option { self.app - .borrow_mut() - .update_window(self.window_id, |cx| cx.rect_for_text_range(range_utf16)) + .borrow() + .read_window(self.window_id, |cx| cx.rect_for_text_range(range_utf16)) .flatten() } } From 917d8949b78c2c1a704b0882dd79fa79310ce6ef Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 5 Jun 2023 14:17:48 -0400 Subject: [PATCH 11/22] Move app version into panic object --- crates/zed/src/main.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 18ee4baeb23b3884249707b17f18e536f29bac93..a3c359c189500343daabf280b3a0c2b42fb847ed 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -372,6 +372,7 @@ struct Panic { #[serde(skip_serializing_if = "Option::is_none")] location_data: Option, backtrace: Vec, + app_version: String, release_channel: String, os_name: String, os_version: Option, @@ -383,8 +384,6 @@ struct Panic { #[derive(Serialize)] struct PanicRequest { panic: Panic, - // TODO: Move to Panic struct, as app_version - requires changing zed.dev - version: String, token: String, } @@ -471,6 +470,7 @@ fn init_panic_hook(app: &App) { file: location.file().into(), line: location.line(), }), + app_version: app_version.clone(), release_channel: RELEASE_CHANNEL.dev_name().into(), os_name: platform.os_name().into(), os_version: platform @@ -496,8 +496,7 @@ fn init_panic_hook(app: &App) { } let timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string(); - let panic_file_path = - paths::LOGS_DIR.join(format!("zed-{}-{}.panic", app_version, timestamp)); + let panic_file_path = paths::LOGS_DIR.join(format!("zed-{}.panic", timestamp)); let panic_file = std::fs::OpenOptions::new() .append(true) .create(true) @@ -532,15 +531,9 @@ fn upload_previous_panics(http: Arc, cx: &mut AppContext) { continue; }; - let mut components = filename.split('-'); - if components.next() != Some("zed") { + if !filename.starts_with("zed") { continue; } - let version = if let Some(version) = components.next() { - version - } else { - continue; - }; if telemetry_settings.diagnostics { let panic_data_text = smol::fs::read_to_string(&child_path) @@ -549,7 +542,6 @@ fn upload_previous_panics(http: Arc, cx: &mut AppContext) { let body = serde_json::to_string(&PanicRequest { panic: serde_json::from_str(&panic_data_text)?, - version: version.to_string(), token: ZED_SECRET_CLIENT_TOKEN.into(), }) .unwrap(); From 70c5489c1345b4f53a0fe603356e9aeffb10337a Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 5 Jun 2023 15:09:47 -0400 Subject: [PATCH 12/22] Stop sending editor events to mixpanel --- crates/editor/src/editor.rs | 15 +++------------ crates/editor/src/editor_tests.rs | 3 ++- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index d98bd92532238337381dfb100f38b44c18369d1d..f956d5725cdb7585f71948cc695a45b242a26713 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -46,9 +46,9 @@ use gpui::{ impl_actions, keymap_matcher::KeymapContext, platform::{CursorStyle, MouseButton}, - serde_json::{self, json}, - AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, Entity, - ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext, + serde_json, AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, + Entity, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, + WindowContext, }; use highlight_matching_bracket::refresh_matching_bracket_highlights; use hover_popover::{hide_hover, HoverState}; @@ -7211,15 +7211,6 @@ impl Editor { .show_copilot_suggestions; let telemetry = project.read(cx).client().telemetry().clone(); - telemetry.report_mixpanel_event( - match name { - "open" => "open editor", - "save" => "save editor", - _ => name, - }, - json!({ "File Extension": file_extension, "Vim Mode": vim_mode, "In Clickhouse": true }), - telemetry_settings, - ); let event = ClickhouseEvent::Editor { file_extension, vim_mode, diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 35d61bf0cf666e009dd6a6f685fbfb5e97559b30..a9d100575f40871fe8dc4be3b9825b2db7e0d8de 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -9,7 +9,8 @@ use gpui::{ executor::Deterministic, geometry::{rect::RectF, vector::vec2f}, platform::{WindowBounds, WindowOptions}, - serde_json, TestAppContext, + serde_json::{self, json}, + TestAppContext, }; use indoc::indoc; use language::{ From 311074e3977f9918ec2b567af6f84702024817a1 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 5 Jun 2023 15:33:17 -0400 Subject: [PATCH 13/22] Remove code sending zed events to mixpanel --- .github/workflows/ci.yml | 1 - .github/workflows/release_actions.yml | 16 -- crates/client/src/client.rs | 18 -- crates/client/src/telemetry.rs | 202 +---------------------- crates/zed/build.rs | 3 - crates/zed/src/main.rs | 5 - script/mixpanel_release/main.py | 30 ---- script/mixpanel_release/requirements.txt | 1 - 8 files changed, 4 insertions(+), 272 deletions(-) delete mode 100644 script/mixpanel_release/main.py delete mode 100644 script/mixpanel_release/requirements.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cd717d5c1f576668fead517290f8be36018e786..f1c16b2d4d2a540da2ff6bbd00f01323b820f12e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,7 +93,6 @@ jobs: MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }} APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }} - ZED_MIXPANEL_TOKEN: ${{ secrets.ZED_MIXPANEL_TOKEN }} steps: - name: Install Rust run: | diff --git a/.github/workflows/release_actions.yml b/.github/workflows/release_actions.yml index 5feb29e46930ab249a62050fcb9c7c1623ca7398..4ccab09cbe10c56f49d43e08d6483b28846021cb 100644 --- a/.github/workflows/release_actions.yml +++ b/.github/workflows/release_actions.yml @@ -21,19 +21,3 @@ jobs: ${{ github.event.release.body }} ``` - mixpanel_release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: "3.10.5" - architecture: "x64" - cache: "pip" - - run: pip install -r script/mixpanel_release/requirements.txt - - run: > - python script/mixpanel_release/main.py - ${{ github.event.release.tag_name }} - ${{ secrets.MIXPANEL_PROJECT_ID }} - ${{ secrets.MIXPANEL_SERVICE_ACCOUNT_USERNAME }} - ${{ secrets.MIXPANEL_SERVICE_ACCOUNT_SECRET }} diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index c9b83d805a4a87a65eda95f5b765c35841627d30..78bcc55e93ffe57dcec4ce760978ab2d22a321e8 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -776,15 +776,6 @@ impl Client { if credentials.is_none() && try_keychain { credentials = read_credentials_from_keychain(cx); read_from_keychain = credentials.is_some(); - if read_from_keychain { - cx.read(|cx| { - self.telemetry().report_mixpanel_event( - "read credentials from keychain", - Default::default(), - *settings::get::(cx), - ); - }); - } } if credentials.is_none() { let mut status_rx = self.status(); @@ -1072,11 +1063,8 @@ impl Client { ) -> Task> { let platform = cx.platform(); let executor = cx.background(); - let telemetry = self.telemetry.clone(); let http = self.http.clone(); - let telemetry_settings = cx.read(|cx| *settings::get::(cx)); - executor.clone().spawn(async move { // Generate a pair of asymmetric encryption keys. The public key will be used by the // zed server to encrypt the user's access token, so that it can'be intercepted by @@ -1159,12 +1147,6 @@ impl Client { .context("failed to decrypt access token")?; platform.activate(true); - telemetry.report_mixpanel_event( - "authenticate with browser", - Default::default(), - telemetry_settings, - ); - Ok(Credentials { user_id: user_id.parse()?, access_token, diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index cf47700dfe26936d44676c208fee941e9e4d9565..c1d58222461e58b8ce48d7853818bc68acb35b46 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -1,14 +1,9 @@ use crate::{TelemetrySettings, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use db::kvp::KEY_VALUE_STORE; -use gpui::{ - executor::Background, - serde_json::{self, value::Map, Value}, - AppContext, Task, -}; +use gpui::{executor::Background, serde_json, AppContext, Task}; use lazy_static::lazy_static; use parking_lot::Mutex; use serde::Serialize; -use serde_json::json; use std::{ env, io::Write, @@ -19,7 +14,7 @@ use std::{ }; use tempfile::NamedTempFile; use util::http::HttpClient; -use util::{channel::ReleaseChannel, post_inc, ResultExt, TryFutureExt}; +use util::{channel::ReleaseChannel, TryFutureExt}; use uuid::Uuid; pub struct Telemetry { @@ -37,23 +32,15 @@ struct TelemetryState { os_name: &'static str, os_version: Option>, architecture: &'static str, - mixpanel_events_queue: Vec, clickhouse_events_queue: Vec, - next_mixpanel_event_id: usize, - flush_mixpanel_events_task: Option>, flush_clickhouse_events_task: Option>, log_file: Option, is_staff: Option, } -const MIXPANEL_EVENTS_URL: &'static str = "https://api.mixpanel.com/track"; -const MIXPANEL_ENGAGE_URL: &'static str = "https://api.mixpanel.com/engage#profile-set"; const CLICKHOUSE_EVENTS_URL_PATH: &'static str = "/api/events"; lazy_static! { - static ref MIXPANEL_TOKEN: Option = std::env::var("ZED_MIXPANEL_TOKEN") - .ok() - .or_else(|| option_env!("ZED_MIXPANEL_TOKEN").map(|key| key.to_string())); static ref CLICKHOUSE_EVENTS_URL: String = format!("{}{}", *ZED_SERVER_URL, CLICKHOUSE_EVENTS_URL_PATH); } @@ -95,47 +82,6 @@ pub enum ClickhouseEvent { }, } -#[derive(Serialize, Debug)] -struct MixpanelEvent { - event: String, - properties: MixpanelEventProperties, -} - -#[derive(Serialize, Debug)] -struct MixpanelEventProperties { - // Mixpanel required fields - #[serde(skip_serializing_if = "str::is_empty")] - token: &'static str, - time: u128, - #[serde(rename = "distinct_id")] - installation_id: Option>, - #[serde(rename = "$insert_id")] - insert_id: usize, - // Custom fields - #[serde(skip_serializing_if = "Option::is_none", flatten)] - event_properties: Option>, - #[serde(rename = "OS Name")] - os_name: &'static str, - #[serde(rename = "OS Version")] - os_version: Option>, - #[serde(rename = "Release Channel")] - release_channel: Option<&'static str>, - #[serde(rename = "App Version")] - app_version: Option>, - #[serde(rename = "Signed In")] - signed_in: bool, -} - -#[derive(Serialize)] -struct MixpanelEngageRequest { - #[serde(rename = "$token")] - token: &'static str, - #[serde(rename = "$distinct_id")] - installation_id: Arc, - #[serde(rename = "$set")] - set: Value, -} - #[cfg(debug_assertions)] const MAX_QUEUE_LEN: usize = 1; @@ -168,29 +114,13 @@ impl Telemetry { release_channel, installation_id: None, metrics_id: None, - mixpanel_events_queue: Default::default(), clickhouse_events_queue: Default::default(), - flush_mixpanel_events_task: Default::default(), flush_clickhouse_events_task: Default::default(), - next_mixpanel_event_id: 0, log_file: None, is_staff: None, }), }); - if MIXPANEL_TOKEN.is_some() { - this.executor - .spawn({ - let this = this.clone(); - async move { - if let Some(tempfile) = NamedTempFile::new().log_err() { - this.state.lock().log_file = Some(tempfile); - } - } - }) - .detach(); - } - this } @@ -218,20 +148,9 @@ impl Telemetry { let mut state = this.state.lock(); state.installation_id = Some(installation_id.clone()); - for event in &mut state.mixpanel_events_queue { - event - .properties - .installation_id - .get_or_insert_with(|| installation_id.clone()); - } - - let has_mixpanel_events = !state.mixpanel_events_queue.is_empty(); let has_clickhouse_events = !state.clickhouse_events_queue.is_empty(); - drop(state); - if has_mixpanel_events { - this.flush_mixpanel_events(); - } + drop(state); if has_clickhouse_events { this.flush_clickhouse_events(); @@ -256,37 +175,11 @@ impl Telemetry { return; } - let this = self.clone(); let mut state = self.state.lock(); - let installation_id = state.installation_id.clone(); let metrics_id: Option> = metrics_id.map(|id| id.into()); state.metrics_id = metrics_id.clone(); state.is_staff = Some(is_staff); drop(state); - - if let Some((token, installation_id)) = MIXPANEL_TOKEN.as_ref().zip(installation_id) { - self.executor - .spawn( - async move { - let json_bytes = serde_json::to_vec(&[MixpanelEngageRequest { - token, - installation_id, - set: json!({ - "Staff": is_staff, - "ID": metrics_id, - "App": true - }), - }])?; - - this.http_client - .post_json(MIXPANEL_ENGAGE_URL, json_bytes.into()) - .await?; - anyhow::Ok(()) - } - .log_err(), - ) - .detach(); - } } pub fn report_clickhouse_event( @@ -310,7 +203,7 @@ impl Telemetry { }); if state.installation_id.is_some() { - if state.mixpanel_events_queue.len() >= MAX_QUEUE_LEN { + if state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { drop(state); self.flush_clickhouse_events(); } else { @@ -324,55 +217,6 @@ impl Telemetry { } } - pub fn report_mixpanel_event( - self: &Arc, - kind: &str, - properties: Value, - telemetry_settings: TelemetrySettings, - ) { - if !telemetry_settings.metrics { - return; - } - - let mut state = self.state.lock(); - let event = MixpanelEvent { - event: kind.into(), - properties: MixpanelEventProperties { - token: "", - time: SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis(), - installation_id: state.installation_id.clone(), - insert_id: post_inc(&mut state.next_mixpanel_event_id), - event_properties: if let Value::Object(properties) = properties { - Some(properties) - } else { - None - }, - os_name: state.os_name, - os_version: state.os_version.clone(), - release_channel: state.release_channel, - app_version: state.app_version.clone(), - signed_in: state.metrics_id.is_some(), - }, - }; - state.mixpanel_events_queue.push(event); - if state.installation_id.is_some() { - if state.mixpanel_events_queue.len() >= MAX_QUEUE_LEN { - drop(state); - self.flush_mixpanel_events(); - } else { - let this = self.clone(); - let executor = self.executor.clone(); - state.flush_mixpanel_events_task = Some(self.executor.spawn(async move { - executor.timer(DEBOUNCE_INTERVAL).await; - this.flush_mixpanel_events(); - })); - } - } - } - pub fn metrics_id(self: &Arc) -> Option> { self.state.lock().metrics_id.clone() } @@ -385,44 +229,6 @@ impl Telemetry { self.state.lock().is_staff } - fn flush_mixpanel_events(self: &Arc) { - let mut state = self.state.lock(); - let mut events = mem::take(&mut state.mixpanel_events_queue); - state.flush_mixpanel_events_task.take(); - drop(state); - - if let Some(token) = MIXPANEL_TOKEN.as_ref() { - let this = self.clone(); - self.executor - .spawn( - async move { - let mut json_bytes = Vec::new(); - - if let Some(file) = &mut this.state.lock().log_file { - let file = file.as_file_mut(); - for event in &mut events { - json_bytes.clear(); - serde_json::to_writer(&mut json_bytes, event)?; - file.write_all(&json_bytes)?; - file.write(b"\n")?; - - event.properties.token = token; - } - } - - json_bytes.clear(); - serde_json::to_writer(&mut json_bytes, &events)?; - this.http_client - .post_json(MIXPANEL_EVENTS_URL, json_bytes.into()) - .await?; - anyhow::Ok(()) - } - .log_err(), - ) - .detach(); - } - } - fn flush_clickhouse_events(self: &Arc) { let mut state = self.state.lock(); let mut events = mem::take(&mut state.clickhouse_events_queue); diff --git a/crates/zed/build.rs b/crates/zed/build.rs index bb971041a5b08f863817cef5ffeec7bee8c015fd..14bf9999fb725c6dae32bfc46341560b662f3d8b 100644 --- a/crates/zed/build.rs +++ b/crates/zed/build.rs @@ -1,9 +1,6 @@ fn main() { println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.15.7"); - if let Ok(value) = std::env::var("ZED_MIXPANEL_TOKEN") { - println!("cargo:rustc-env=ZED_MIXPANEL_TOKEN={value}"); - } if let Ok(value) = std::env::var("ZED_PREVIEW_CHANNEL") { println!("cargo:rustc-env=ZED_PREVIEW_CHANNEL={value}"); } diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index a3c359c189500343daabf280b3a0c2b42fb847ed..59072cc9f4b60df1f71b22c89962615edb0b085a 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -171,11 +171,6 @@ fn main() { .detach(); client.telemetry().start(); - client.telemetry().report_mixpanel_event( - "start app", - Default::default(), - *settings::get::(cx), - ); let app_state = Arc::new(AppState { languages, diff --git a/script/mixpanel_release/main.py b/script/mixpanel_release/main.py deleted file mode 100644 index e2a0eeb990ce8c085fa6d41efeda2a1221c5d512..0000000000000000000000000000000000000000 --- a/script/mixpanel_release/main.py +++ /dev/null @@ -1,30 +0,0 @@ -import datetime -import sys -import requests - -def main(): - version = sys.argv[1] - version = version.removeprefix("v") - project_id = sys.argv[2] - account_username = sys.argv[3] - account_secret = sys.argv[4] - - current_datetime = datetime.datetime.now(datetime.timezone.utc) - current_datetime = current_datetime.strftime("%Y-%m-%d %H:%M:%S") - - url = f"https://mixpanel.com/api/app/projects/{project_id}/annotations" - - payload = { - "date": current_datetime, - "description": version - } - - response = requests.post( - url, - auth=(account_username, account_secret), - json=payload - ) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/script/mixpanel_release/requirements.txt b/script/mixpanel_release/requirements.txt deleted file mode 100644 index 5e77405687287ea27fa8f90ccd80284639112588..0000000000000000000000000000000000000000 --- a/script/mixpanel_release/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -requests==2.28.1 \ No newline at end of file From 624467ebca0bc9e7aae684b9ecfb39fed7d1539a Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 5 Jun 2023 12:53:37 -0700 Subject: [PATCH 14/22] Add file and line number information to logs --- crates/util/src/util.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index 9d787e1389a9742c44e505a96ddf44ee71d04671..5f738132ae0104553ae24f15736fdaaa5dd3b696 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -9,6 +9,7 @@ pub mod test; use std::{ cmp::{self, Ordering}, ops::{AddAssign, Range, RangeInclusive}, + panic::Location, pin::Pin, task::{Context, Poll}, }; @@ -129,11 +130,13 @@ where { type Ok = T; + #[track_caller] fn log_err(self) -> Option { match self { Ok(value) => Some(value), Err(error) => { - log::error!("{:?}", error); + let caller = Location::caller(); + log::error!("{}:{}: {:?}", caller.file(), caller.line(), error); None } } From 12dd91c89ce317774de0ddb58c82b28c4cae5b13 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Jun 2023 14:12:19 -0700 Subject: [PATCH 15/22] Use local ids, not remote ids, to identify buffers to copilot --- crates/copilot/src/copilot.rs | 47 +++++++++++++++-------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 04e8764f7b0d5d72f50fd36f3b83c2b7ab25bea3..e73424f0cd36945f1a24d3155521075c7967fa80 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -4,7 +4,7 @@ mod sign_in; use anyhow::{anyhow, Context, Result}; use async_compression::futures::bufread::GzipDecoder; use async_tar::Archive; -use collections::HashMap; +use collections::{HashMap, HashSet}; use futures::{channel::oneshot, future::Shared, Future, FutureExt, TryFutureExt}; use gpui::{ actions, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Task, WeakModelHandle, @@ -127,7 +127,7 @@ impl CopilotServer { struct RunningCopilotServer { lsp: Arc, sign_in_status: SignInStatus, - registered_buffers: HashMap, + registered_buffers: HashMap, } #[derive(Clone, Debug)] @@ -163,7 +163,6 @@ impl Status { } struct RegisteredBuffer { - id: u64, uri: lsp::Url, language_id: String, snapshot: BufferSnapshot, @@ -178,13 +177,13 @@ impl RegisteredBuffer { buffer: &ModelHandle, cx: &mut ModelContext, ) -> oneshot::Receiver<(i32, BufferSnapshot)> { - let id = self.id; let (done_tx, done_rx) = oneshot::channel(); if buffer.read(cx).version() == self.snapshot.version { let _ = done_tx.send((self.snapshot_version, self.snapshot.clone())); } else { let buffer = buffer.downgrade(); + let id = buffer.id(); let prev_pending_change = mem::replace(&mut self.pending_buffer_change, Task::ready(None)); self.pending_buffer_change = cx.spawn_weak(|copilot, mut cx| async move { @@ -268,7 +267,7 @@ pub struct Copilot { http: Arc, node_runtime: Arc, server: CopilotServer, - buffers: HashMap>, + buffers: HashSet>, } impl Entity for Copilot { @@ -559,8 +558,8 @@ impl Copilot { } pub fn register_buffer(&mut self, buffer: &ModelHandle, cx: &mut ModelContext) { - let buffer_id = buffer.read(cx).remote_id(); - self.buffers.insert(buffer_id, buffer.downgrade()); + let weak_buffer = buffer.downgrade(); + self.buffers.insert(weak_buffer.clone()); if let CopilotServer::Running(RunningCopilotServer { lsp: server, @@ -573,8 +572,7 @@ impl Copilot { return; } - let buffer_id = buffer.read(cx).remote_id(); - registered_buffers.entry(buffer_id).or_insert_with(|| { + registered_buffers.entry(buffer.id()).or_insert_with(|| { let uri: lsp::Url = uri_for_buffer(buffer, cx); let language_id = id_for_language(buffer.read(cx).language()); let snapshot = buffer.read(cx).snapshot(); @@ -592,7 +590,6 @@ impl Copilot { .log_err(); RegisteredBuffer { - id: buffer_id, uri, language_id, snapshot, @@ -603,8 +600,8 @@ impl Copilot { this.handle_buffer_event(buffer, event, cx).log_err(); }), cx.observe_release(buffer, move |this, _buffer, _cx| { - this.buffers.remove(&buffer_id); - this.unregister_buffer(buffer_id); + this.buffers.remove(&weak_buffer); + this.unregister_buffer(&weak_buffer); }), ], } @@ -619,8 +616,7 @@ impl Copilot { cx: &mut ModelContext, ) -> Result<()> { if let Ok(server) = self.server.as_running() { - let buffer_id = buffer.read(cx).remote_id(); - if let Some(registered_buffer) = server.registered_buffers.get_mut(&buffer_id) { + if let Some(registered_buffer) = server.registered_buffers.get_mut(&buffer.id()) { match event { language::Event::Edited => { let _ = registered_buffer.report_changes(&buffer, cx); @@ -674,9 +670,9 @@ impl Copilot { Ok(()) } - fn unregister_buffer(&mut self, buffer_id: u64) { + fn unregister_buffer(&mut self, buffer: &WeakModelHandle) { if let Ok(server) = self.server.as_running() { - if let Some(buffer) = server.registered_buffers.remove(&buffer_id) { + if let Some(buffer) = server.registered_buffers.remove(&buffer.id()) { server .lsp .notify::( @@ -779,8 +775,7 @@ impl Copilot { Err(error) => return Task::ready(Err(error)), }; let lsp = server.lsp.clone(); - let buffer_id = buffer.read(cx).remote_id(); - let registered_buffer = server.registered_buffers.get_mut(&buffer_id).unwrap(); + let registered_buffer = server.registered_buffers.get_mut(&buffer.id()).unwrap(); let snapshot = registered_buffer.report_changes(buffer, cx); let buffer = buffer.read(cx); let uri = registered_buffer.uri.clone(); @@ -850,7 +845,7 @@ impl Copilot { lsp_status: request::SignInStatus, cx: &mut ModelContext, ) { - self.buffers.retain(|_, buffer| buffer.is_upgradable(cx)); + self.buffers.retain(|buffer| buffer.is_upgradable(cx)); if let Ok(server) = self.server.as_running() { match lsp_status { @@ -858,7 +853,7 @@ impl Copilot { | request::SignInStatus::MaybeOk { .. } | request::SignInStatus::AlreadySignedIn { .. } => { server.sign_in_status = SignInStatus::Authorized; - for buffer in self.buffers.values().cloned().collect::>() { + for buffer in self.buffers.iter().cloned().collect::>() { if let Some(buffer) = buffer.upgrade(cx) { self.register_buffer(&buffer, cx); } @@ -866,14 +861,14 @@ impl Copilot { } request::SignInStatus::NotAuthorized { .. } => { server.sign_in_status = SignInStatus::Unauthorized; - for buffer_id in self.buffers.keys().copied().collect::>() { - self.unregister_buffer(buffer_id); + for buffer in self.buffers.iter().copied().collect::>() { + self.unregister_buffer(&buffer); } } request::SignInStatus::NotSignedIn => { server.sign_in_status = SignInStatus::SignedOut; - for buffer_id in self.buffers.keys().copied().collect::>() { - self.unregister_buffer(buffer_id); + for buffer in self.buffers.iter().copied().collect::>() { + self.unregister_buffer(&buffer); } } } @@ -896,9 +891,7 @@ fn uri_for_buffer(buffer: &ModelHandle, cx: &AppContext) -> lsp::Url { if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) { lsp::Url::from_file_path(file.abs_path(cx)).unwrap() } else { - format!("buffer://{}", buffer.read(cx).remote_id()) - .parse() - .unwrap() + format!("buffer://{}", buffer.id()).parse().unwrap() } } From 3d1ba1b36365990bd2743a347b15f81ced8387d5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Jun 2023 14:36:21 -0700 Subject: [PATCH 16/22] Apply bounds to all windows when using start-local-collaboration script --- crates/workspace/src/workspace.rs | 53 +++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 95d0bf653855bc5effbfe015e38ba7232fd9ccd3..a429a30a396cf1971bc9b9817db5e0367a0d4934 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -765,25 +765,21 @@ impl Workspace { DB.next_id().await.unwrap_or(0) }; - let window_bounds_override = - ZED_WINDOW_POSITION - .zip(*ZED_WINDOW_SIZE) - .map(|(position, size)| { - WindowBounds::Fixed(RectF::new( - cx.platform().screens()[0].bounds().origin() + position, - size, - )) - }); - - let build_workspace = |cx: &mut ViewContext| { - Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx) - }; - let workspace = requesting_window_id .and_then(|window_id| { - cx.update(|cx| cx.replace_root_view(window_id, |cx| build_workspace(cx))) + cx.update(|cx| { + cx.replace_root_view(window_id, |cx| { + Workspace::new( + workspace_id, + project_handle.clone(), + app_state.clone(), + cx, + ) + }) + }) }) .unwrap_or_else(|| { + let window_bounds_override = window_bounds_env_override(&cx); let (bounds, display) = if let Some(bounds) = window_bounds_override { (Some(bounds), None) } else { @@ -819,7 +815,14 @@ impl Workspace { // Use the serialized workspace to construct the new window cx.add_window( (app_state.build_window_options)(bounds, display, cx.platform().as_ref()), - |cx| build_workspace(cx), + |cx| { + Workspace::new( + workspace_id, + project_handle.clone(), + app_state.clone(), + cx, + ) + }, ) .1 }); @@ -3110,6 +3113,17 @@ impl Workspace { } } +fn window_bounds_env_override(cx: &AsyncAppContext) -> Option { + ZED_WINDOW_POSITION + .zip(*ZED_WINDOW_SIZE) + .map(|(position, size)| { + WindowBounds::Fixed(RectF::new( + cx.platform().screens()[0].bounds().origin() + position, + size, + )) + }) +} + async fn open_items( serialized_workspace: Option, workspace: &WeakViewHandle, @@ -3642,8 +3656,13 @@ pub fn join_remote_project( }) .await?; + let window_bounds_override = window_bounds_env_override(&cx); let (_, workspace) = cx.add_window( - (app_state.build_window_options)(None, None, cx.platform().as_ref()), + (app_state.build_window_options)( + window_bounds_override, + None, + cx.platform().as_ref(), + ), |cx| Workspace::new(0, project, app_state.clone(), cx), ); (app_state.initialize_workspace)( From 0949ee84d8aa72872455f1c7f38c468b1e83646b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Jun 2023 15:02:29 -0700 Subject: [PATCH 17/22] :art: Move OpenSettings action back to the zed crate --- crates/workspace/src/workspace.rs | 16 +--------------- crates/zed/src/main.rs | 6 ++---- crates/zed/src/menus.rs | 2 +- crates/zed/src/zed.rs | 11 +++++++++++ 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index a429a30a396cf1971bc9b9817db5e0367a0d4934..278b02d74ebfc622043ff61b4299ec0c273ca684 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -15,7 +15,6 @@ mod toolbar; mod workspace_settings; use anyhow::{anyhow, Context, Result}; -use assets::Assets; use call::ActiveCall; use client::{ proto::{self, PeerId}, @@ -83,7 +82,7 @@ use status_bar::StatusBar; pub use status_bar::StatusItemView; use theme::{Theme, ThemeSettings}; pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; -use util::{async_iife, paths, ResultExt}; +use util::{async_iife, ResultExt}; pub use workspace_settings::{AutosaveSetting, GitGutterSetting, WorkspaceSettings}; lazy_static! { @@ -133,8 +132,6 @@ actions!( ] ); -actions!(zed, [OpenSettings]); - #[derive(Clone, PartialEq)] pub struct OpenPaths { pub paths: Vec, @@ -295,17 +292,6 @@ pub fn init(app_state: Arc, cx: &mut AppContext) { .detach(); }); - cx.add_action( - move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext| { - create_and_open_local_file(&paths::SETTINGS, cx, || { - settings::initial_user_settings_content(&Assets) - .as_ref() - .into() - }) - .detach_and_log_err(cx); - }, - ); - let client = &app_state.client; client.add_view_request_handler(Workspace::handle_follow); client.add_view_message_handler(Workspace::handle_unfollow); diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 59072cc9f4b60df1f71b22c89962615edb0b085a..f5031beb2ee5774aa1299dadf7fc2756520534a4 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -56,9 +56,7 @@ use fs::RealFs; #[cfg(debug_assertions)] use staff_mode::StaffMode; use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt}; -use workspace::{ - item::ItemHandle, notifications::NotifyResultExt, AppState, OpenSettings, Workspace, -}; +use workspace::{item::ItemHandle, notifications::NotifyResultExt, AppState, Workspace}; use zed::{ self, build_window_options, handle_keymap_file_changes, initialize_workspace, languages, menus, }; @@ -877,6 +875,6 @@ pub fn background_actions() -> &'static [(&'static str, &'static dyn Action)] { ("Go to file", &file_finder::Toggle), ("Open command palette", &command_palette::Toggle), ("Open recent projects", &recent_projects::OpenRecent), - ("Change your settings", &OpenSettings), + ("Change your settings", &zed::OpenSettings), ] } diff --git a/crates/zed/src/menus.rs b/crates/zed/src/menus.rs index 76e88325f5cc858091cd3fcc367340337d554a9c..83af92e26498e12f5e8789867eae23c5a3bd83b7 100644 --- a/crates/zed/src/menus.rs +++ b/crates/zed/src/menus.rs @@ -12,7 +12,7 @@ pub fn menus() -> Vec> { MenuItem::submenu(Menu { name: "Preferences", items: vec![ - MenuItem::action("Open Settings", workspace::OpenSettings), + MenuItem::action("Open Settings", super::OpenSettings), MenuItem::action("Open Key Bindings", super::OpenKeymap), MenuItem::action("Open Default Settings", super::OpenDefaultSettings), MenuItem::action("Open Default Key Bindings", super::OpenDefaultKeymap), diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 6dbddae2ada970ee754c20c2aa735c3f46c86d91..7472500d3965fb1498935a2eb55dda57589f821f 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -65,6 +65,7 @@ actions!( OpenLicenses, OpenTelemetryLog, OpenKeymap, + OpenSettings, OpenDefaultSettings, OpenDefaultKeymap, IncreaseBufferFontSize, @@ -157,6 +158,16 @@ pub fn init(app_state: &Arc, cx: &mut gpui::AppContext) { create_and_open_local_file(&paths::KEYMAP, cx, Default::default).detach_and_log_err(cx); }, ); + cx.add_action( + move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext| { + create_and_open_local_file(&paths::SETTINGS, cx, || { + settings::initial_user_settings_content(&Assets) + .as_ref() + .into() + }) + .detach_and_log_err(cx); + }, + ); cx.add_action( move |workspace: &mut Workspace, _: &OpenDefaultKeymap, cx: &mut ViewContext| { open_bundled_file( From cb975f125255713bc07b60c1d21d531f1c4e0011 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Jun 2023 17:45:42 -0700 Subject: [PATCH 18/22] Add Zed > Preferences > Local Settings to application menu --- crates/zed/src/menus.rs | 1 + crates/zed/src/zed.rs | 55 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/crates/zed/src/menus.rs b/crates/zed/src/menus.rs index 83af92e26498e12f5e8789867eae23c5a3bd83b7..9112cd207b5da73f6a7d20a0436db152f98114d2 100644 --- a/crates/zed/src/menus.rs +++ b/crates/zed/src/menus.rs @@ -16,6 +16,7 @@ pub fn menus() -> Vec> { MenuItem::action("Open Key Bindings", super::OpenKeymap), MenuItem::action("Open Default Settings", super::OpenDefaultSettings), MenuItem::action("Open Default Key Bindings", super::OpenDefaultKeymap), + MenuItem::action("Open Local Settings", super::OpenLocalSettings), MenuItem::action("Select Theme", theme_selector::Toggle), ], }), diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 7472500d3965fb1498935a2eb55dda57589f821f..ae9370384ae4b8f5ee669f52cbeab58aa699591e 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -33,7 +33,11 @@ use serde_json::to_string_pretty; use settings::{KeymapFileContent, SettingsStore, DEFAULT_SETTINGS_ASSET_PATH}; use std::{borrow::Cow, str, sync::Arc}; use terminal_view::terminal_panel::{self, TerminalPanel}; -use util::{channel::ReleaseChannel, paths, ResultExt}; +use util::{ + channel::ReleaseChannel, + paths::{self, LOCAL_SETTINGS_RELATIVE_PATH}, + ResultExt, +}; use uuid::Uuid; use welcome::BaseKeymap; pub use workspace; @@ -66,6 +70,7 @@ actions!( OpenTelemetryLog, OpenKeymap, OpenSettings, + OpenLocalSettings, OpenDefaultSettings, OpenDefaultKeymap, IncreaseBufferFontSize, @@ -168,6 +173,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::AppContext) { .detach_and_log_err(cx); }, ); + cx.add_action(open_local_settings_file); cx.add_action( move |workspace: &mut Workspace, _: &OpenDefaultKeymap, cx: &mut ViewContext| { open_bundled_file( @@ -555,6 +561,53 @@ pub fn handle_keymap_file_changes( .detach(); } +fn open_local_settings_file( + workspace: &mut Workspace, + _: &OpenLocalSettings, + cx: &mut ViewContext, +) { + let project = workspace.project().clone(); + let worktree = project + .read(cx) + .visible_worktrees(cx) + .find_map(|tree| tree.read(cx).root_entry()?.is_dir().then_some(tree)); + if let Some(worktree) = worktree { + let tree_id = worktree.read(cx).id(); + cx.spawn(|workspace, mut cx| async move { + let file_path = &*LOCAL_SETTINGS_RELATIVE_PATH; + + if let Some(dir_path) = file_path.parent() { + if worktree.read_with(&cx, |tree, _| tree.entry_for_path(dir_path).is_none()) { + project + .update(&mut cx, |project, cx| { + project.create_entry((tree_id, dir_path), true, cx) + }) + .ok_or_else(|| anyhow!("worktree was removed"))? + .await?; + } + } + + if worktree.read_with(&cx, |tree, _| tree.entry_for_path(file_path).is_none()) { + project + .update(&mut cx, |project, cx| { + project.create_entry((tree_id, file_path), false, cx) + }) + .ok_or_else(|| anyhow!("worktree was removed"))? + .await?; + } + + workspace + .update(&mut cx, |workspace, cx| { + workspace.open_path((tree_id, file_path), None, true, cx) + })? + .await?; + + anyhow::Ok(()) + }) + .detach(); + } +} + fn open_telemetry_log_file(workspace: &mut Workspace, cx: &mut ViewContext) { workspace.with_local_workspace(cx, move |workspace, cx| { let app_state = workspace.app_state().clone(); From 296a0bf51060eab6c8eaf1b530f529ee62bce04a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 5 Jun 2023 18:09:42 -0700 Subject: [PATCH 19/22] Populate created local settings file with an empty JSON object and comments --- assets/settings/initial_local_settings.json | 11 +++++++++ crates/collab/src/rpc.rs | 4 +-- crates/settings/src/settings.rs | 19 ++++++++++++--- crates/settings/src/settings_file.rs | 14 +++-------- crates/zed/src/zed.rs | 27 ++++++++++++++++++--- 5 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 assets/settings/initial_local_settings.json diff --git a/assets/settings/initial_local_settings.json b/assets/settings/initial_local_settings.json new file mode 100644 index 0000000000000000000000000000000000000000..69be683aa81d758e114f02b9bf41d45dcfe32d81 --- /dev/null +++ b/assets/settings/initial_local_settings.json @@ -0,0 +1,11 @@ +// Folder-specific Zed settings +// +// A subset of Zed's settings can be configured on a per-folder basis. +// +// For information on how to configure Zed, see the Zed +// documentation: https://zed.dev/docs/configuring-zed +// +// To see all of Zed's default settings without changing your +// custom settings, run the `open default settings` command +// from the command palette or from `Zed` application menu. +{} diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 61c6123a827e897d9bf8c5db15e9e79fdbd4b951..8d210513c2d3dc32fdac676b4953147cc4f0208e 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -1424,7 +1424,7 @@ async fn join_project( )?; } - for settings_file in dbg!(worktree.settings_files) { + for settings_file in worktree.settings_files { session.peer.send( session.connection_id, proto::UpdateWorktreeSettings { @@ -1554,8 +1554,6 @@ async fn update_worktree_settings( message: proto::UpdateWorktreeSettings, session: Session, ) -> Result<()> { - dbg!(&message); - let guest_connection_ids = session .db() .await diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index 840797c6ad644cc851c298712e7db080a0650d78..1c131e5916c5d11746881d729cf93a254d0effd0 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -9,10 +9,23 @@ pub use settings_store::{Setting, SettingsJsonSchemaParams, SettingsStore}; use std::{borrow::Cow, str}; pub const DEFAULT_SETTINGS_ASSET_PATH: &str = "settings/default.json"; -pub const INITIAL_USER_SETTINGS_ASSET_PATH: &str = "settings/initial_user_settings.json"; +const INITIAL_USER_SETTINGS_ASSET_PATH: &str = "settings/initial_user_settings.json"; +const INITIAL_LOCAL_SETTINGS_ASSET_PATH: &str = "settings/initial_local_settings.json"; -pub fn initial_user_settings_content(assets: &'static impl AssetSource) -> Cow<'static, str> { - match assets.load(INITIAL_USER_SETTINGS_ASSET_PATH).unwrap() { +pub fn default_settings() -> Cow<'static, str> { + asset_str(&assets::Assets, DEFAULT_SETTINGS_ASSET_PATH) +} + +pub fn initial_user_settings_content(assets: &dyn AssetSource) -> Cow<'_, str> { + asset_str(assets, INITIAL_USER_SETTINGS_ASSET_PATH) +} + +pub fn initial_local_settings_content(assets: &dyn AssetSource) -> Cow<'_, str> { + asset_str(assets, INITIAL_LOCAL_SETTINGS_ASSET_PATH) +} + +fn asset_str<'a>(assets: &'a dyn AssetSource, path: &str) -> Cow<'a, str> { + match assets.load(path).unwrap() { Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), } diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index 3505330eda6fb94cc4ded9d90f313c40a11e7866..edd4fe0d9dea93cb7444656772311f6dbd439e9b 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -1,11 +1,10 @@ -use crate::{settings_store::SettingsStore, Setting, DEFAULT_SETTINGS_ASSET_PATH}; +use crate::{settings_store::SettingsStore, Setting}; use anyhow::Result; use assets::Assets; use fs::Fs; use futures::{channel::mpsc, StreamExt}; -use gpui::{executor::Background, AppContext, AssetSource}; +use gpui::{executor::Background, AppContext}; use std::{ - borrow::Cow, io::ErrorKind, path::{Path, PathBuf}, str, @@ -28,19 +27,12 @@ pub fn get_local<'a, T: Setting>(location: Option<(usize, &Path)>, cx: &'a AppCo cx.global::().get(location) } -pub fn default_settings() -> Cow<'static, str> { - match Assets.load(DEFAULT_SETTINGS_ASSET_PATH).unwrap() { - Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), - Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), - } -} - pub const EMPTY_THEME_NAME: &'static str = "empty-theme"; #[cfg(any(test, feature = "test-support"))] pub fn test_settings() -> String { let mut value = crate::settings_store::parse_json_with_comments::( - default_settings().as_ref(), + crate::default_settings().as_ref(), ) .unwrap(); util::merge_non_null_json_value_into( diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index ae9370384ae4b8f5ee669f52cbeab58aa699591e..f0e88133f3e20c668b2c9c86108ed3abfe1f712e 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -30,7 +30,9 @@ use project_panel::ProjectPanel; use search::{BufferSearchBar, ProjectSearchBar}; use serde::Deserialize; use serde_json::to_string_pretty; -use settings::{KeymapFileContent, SettingsStore, DEFAULT_SETTINGS_ASSET_PATH}; +use settings::{ + initial_local_settings_content, KeymapFileContent, SettingsStore, DEFAULT_SETTINGS_ASSET_PATH, +}; use std::{borrow::Cow, str, sync::Arc}; use terminal_view::terminal_panel::{self, TerminalPanel}; use util::{ @@ -596,11 +598,30 @@ fn open_local_settings_file( .await?; } - workspace + let editor = workspace .update(&mut cx, |workspace, cx| { workspace.open_path((tree_id, file_path), None, true, cx) })? - .await?; + .await? + .downcast::() + .ok_or_else(|| anyhow!("unexpected item type"))?; + + editor + .downgrade() + .update(&mut cx, |editor, cx| { + if let Some(buffer) = editor.buffer().read(cx).as_singleton() { + if buffer.read(cx).is_empty() { + buffer.update(cx, |buffer, cx| { + buffer.edit( + [(0..0, initial_local_settings_content(&Assets))], + None, + cx, + ) + }); + } + } + }) + .ok(); anyhow::Ok(()) }) From a0e2e5db7dca2157d2693d91e98052c1351ca5f9 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 6 Jun 2023 16:55:38 +0200 Subject: [PATCH 20/22] project panel/styles: Align child's chevron with parent path (#2559) Z-1012 Release notes: - Adjust indent of files in subdirectories. --- styles/src/styleTree/projectPanel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 08117bf6b01d5fe7b14f2e0ace22dc680c5cefac..666d236da674690f8d2fcd9073165ab82484b307 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -72,7 +72,7 @@ export default function projectPanel(colorScheme: ColorScheme) { }, background: background(layer), padding: { left: 12, right: 12, top: 6, bottom: 6 }, - indentWidth: 8, + indentWidth: 16, entry, draggedEntry: { ...baseEntry, From 7b066df7e6a03c66b2f393d2b630ce939a1d6b00 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 6 Jun 2023 11:31:53 -0400 Subject: [PATCH 21/22] Tighten up spacing in the project panel (#2574) Following https://github.com/zed-industries/zed/pull/2559 the project panel entries become pretty wide again. This PR tries to mitigate that and just make some general improvements to visual density in the project panel. - Reduces padding around items - Removes top margin - Slightly reduces the height of each item - Fixes an issue where ignored files had the wrong color chevron Release Notes: - Improved density of the project panel and tidied up some visual issues. --- styles/src/styleTree/projectPanel.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/styles/src/styleTree/projectPanel.ts b/styles/src/styleTree/projectPanel.ts index 666d236da674690f8d2fcd9073165ab82484b307..d2cc1294526470f33d75cee3da4cbdb52eee00e0 100644 --- a/styles/src/styleTree/projectPanel.ts +++ b/styles/src/styleTree/projectPanel.ts @@ -8,10 +8,10 @@ export default function projectPanel(colorScheme: ColorScheme) { let layer = colorScheme.middle let baseEntry = { - height: 24, + height: 22, iconColor: foreground(layer, "variant"), - iconSize: 8, - iconSpacing: 8, + iconSize: 7, + iconSpacing: 5, } let status = { @@ -71,8 +71,8 @@ export default function projectPanel(colorScheme: ColorScheme) { }, }, background: background(layer), - padding: { left: 12, right: 12, top: 6, bottom: 6 }, - indentWidth: 16, + padding: { left: 6, right: 6, top: 0, bottom: 6 }, + indentWidth: 12, entry, draggedEntry: { ...baseEntry, @@ -83,7 +83,12 @@ export default function projectPanel(colorScheme: ColorScheme) { }, ignoredEntry: { ...entry, + iconColor: foreground(layer, "disabled"), text: text(layer, "mono", "disabled"), + active: { + ...entry.active, + iconColor: foreground(layer, "variant"), + } }, cutEntry: { ...entry, From cfcfc3bf6b1493e7668ed6a0c433f198690d6358 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 6 Jun 2023 09:03:57 -0700 Subject: [PATCH 22/22] Show notification when attempting to open local settings in a project w/ no folders --- crates/zed/src/zed.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index f0e88133f3e20c668b2c9c86108ed3abfe1f712e..8d27a378c5c49d6ebf3d7de3b043e3a908423420 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -44,8 +44,9 @@ use uuid::Uuid; use welcome::BaseKeymap; pub use workspace; use workspace::{ - create_and_open_local_file, dock::PanelHandle, open_new, AppState, NewFile, NewWindow, - Workspace, WorkspaceSettings, + create_and_open_local_file, dock::PanelHandle, + notifications::simple_message_notification::MessageNotification, open_new, AppState, NewFile, + NewWindow, Workspace, WorkspaceSettings, }; #[derive(Deserialize, Clone, PartialEq)] @@ -626,6 +627,10 @@ fn open_local_settings_file( anyhow::Ok(()) }) .detach(); + } else { + workspace.show_notification(0, cx, |cx| { + cx.add_view(|_| MessageNotification::new("This project has no folders open.")) + }) } }