Merge remote-tracking branch 'origin/main' into paint-context
This commit is contained in:
commit
db96fb1307
163 changed files with 9459 additions and 4729 deletions
|
@ -47,6 +47,7 @@ workspace = { path = "../workspace" }
|
|||
|
||||
aho-corasick = "0.7"
|
||||
anyhow.workspace = true
|
||||
convert_case = "0.6.0"
|
||||
futures.workspace = true
|
||||
indoc = "1.0.4"
|
||||
itertools = "0.10"
|
||||
|
@ -56,12 +57,12 @@ ordered-float.workspace = true
|
|||
parking_lot.workspace = true
|
||||
postage.workspace = true
|
||||
pulldown-cmark = { version = "0.9.2", default-features = false }
|
||||
rand.workspace = true
|
||||
schemars.workspace = true
|
||||
serde.workspace = true
|
||||
serde_derive.workspace = true
|
||||
smallvec.workspace = true
|
||||
smol.workspace = true
|
||||
rand.workspace = true
|
||||
|
||||
tree-sitter-rust = { workspace = true, optional = true }
|
||||
tree-sitter-html = { workspace = true, optional = true }
|
||||
|
|
|
@ -397,7 +397,7 @@ impl InlayMap {
|
|||
buffer_snapshot: MultiBufferSnapshot,
|
||||
mut buffer_edits: Vec<text::Edit<usize>>,
|
||||
) -> (InlaySnapshot, Vec<InlayEdit>) {
|
||||
let mut snapshot = &mut self.snapshot;
|
||||
let snapshot = &mut self.snapshot;
|
||||
|
||||
if buffer_edits.is_empty() {
|
||||
if snapshot.buffer.trailing_excerpt_update_count()
|
||||
|
@ -572,7 +572,6 @@ impl InlayMap {
|
|||
})
|
||||
.collect();
|
||||
let buffer_snapshot = snapshot.buffer.clone();
|
||||
drop(snapshot);
|
||||
let (snapshot, edits) = self.sync(buffer_snapshot, buffer_edits);
|
||||
(snapshot, edits)
|
||||
}
|
||||
|
@ -635,7 +634,6 @@ impl InlayMap {
|
|||
}
|
||||
log::info!("removing inlays: {:?}", to_remove);
|
||||
|
||||
drop(snapshot);
|
||||
let (snapshot, edits) = self.splice(to_remove, to_insert);
|
||||
(snapshot, edits)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ use blink_manager::BlinkManager;
|
|||
use client::{ClickhouseEvent, TelemetrySettings};
|
||||
use clock::{Global, ReplicaId};
|
||||
use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
|
||||
use convert_case::{Case, Casing};
|
||||
use copilot::Copilot;
|
||||
pub use display_map::DisplayPoint;
|
||||
use display_map::*;
|
||||
|
@ -89,7 +90,7 @@ use std::{
|
|||
cmp::{self, Ordering, Reverse},
|
||||
mem,
|
||||
num::NonZeroU32,
|
||||
ops::{ControlFlow, Deref, DerefMut, Range},
|
||||
ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
|
||||
path::Path,
|
||||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
|
@ -231,6 +232,13 @@ actions!(
|
|||
SortLinesCaseInsensitive,
|
||||
ReverseLines,
|
||||
ShuffleLines,
|
||||
ConvertToUpperCase,
|
||||
ConvertToLowerCase,
|
||||
ConvertToTitleCase,
|
||||
ConvertToSnakeCase,
|
||||
ConvertToKebabCase,
|
||||
ConvertToUpperCamelCase,
|
||||
ConvertToLowerCamelCase,
|
||||
Transpose,
|
||||
Cut,
|
||||
Copy,
|
||||
|
@ -353,6 +361,13 @@ pub fn init(cx: &mut AppContext) {
|
|||
cx.add_action(Editor::sort_lines_case_insensitive);
|
||||
cx.add_action(Editor::reverse_lines);
|
||||
cx.add_action(Editor::shuffle_lines);
|
||||
cx.add_action(Editor::convert_to_upper_case);
|
||||
cx.add_action(Editor::convert_to_lower_case);
|
||||
cx.add_action(Editor::convert_to_title_case);
|
||||
cx.add_action(Editor::convert_to_snake_case);
|
||||
cx.add_action(Editor::convert_to_kebab_case);
|
||||
cx.add_action(Editor::convert_to_upper_camel_case);
|
||||
cx.add_action(Editor::convert_to_lower_camel_case);
|
||||
cx.add_action(Editor::delete_to_previous_word_start);
|
||||
cx.add_action(Editor::delete_to_previous_subword_start);
|
||||
cx.add_action(Editor::delete_to_next_word_end);
|
||||
|
@ -543,6 +558,7 @@ pub struct Editor {
|
|||
show_local_selections: bool,
|
||||
mode: EditorMode,
|
||||
show_gutter: bool,
|
||||
show_wrap_guides: Option<bool>,
|
||||
placeholder_text: Option<Arc<str>>,
|
||||
highlighted_rows: Option<Range<u32>>,
|
||||
#[allow(clippy::type_complexity)]
|
||||
|
@ -1375,6 +1391,7 @@ impl Editor {
|
|||
show_local_selections: true,
|
||||
mode,
|
||||
show_gutter: mode == EditorMode::Full,
|
||||
show_wrap_guides: None,
|
||||
placeholder_text: None,
|
||||
highlighted_rows: None,
|
||||
background_highlights: Default::default(),
|
||||
|
@ -1537,7 +1554,7 @@ impl Editor {
|
|||
self.collapse_matches = collapse_matches;
|
||||
}
|
||||
|
||||
fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
|
||||
pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
|
||||
if self.collapse_matches {
|
||||
return range.start..range.start;
|
||||
}
|
||||
|
@ -4219,7 +4236,7 @@ impl Editor {
|
|||
_: &SortLinesCaseSensitive,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.manipulate_lines(cx, |text| text.sort())
|
||||
self.manipulate_lines(cx, |lines| lines.sort())
|
||||
}
|
||||
|
||||
pub fn sort_lines_case_insensitive(
|
||||
|
@ -4227,7 +4244,7 @@ impl Editor {
|
|||
_: &SortLinesCaseInsensitive,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.manipulate_lines(cx, |text| text.sort_by_key(|line| line.to_lowercase()))
|
||||
self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
|
||||
}
|
||||
|
||||
pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
|
||||
|
@ -4265,19 +4282,19 @@ impl Editor {
|
|||
let text = buffer
|
||||
.text_for_range(start_point..end_point)
|
||||
.collect::<String>();
|
||||
let mut text = text.split("\n").collect_vec();
|
||||
let mut lines = text.split("\n").collect_vec();
|
||||
|
||||
let text_len = text.len();
|
||||
callback(&mut text);
|
||||
let lines_len = lines.len();
|
||||
callback(&mut lines);
|
||||
|
||||
// This is a current limitation with selections.
|
||||
// If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
|
||||
debug_assert!(
|
||||
text.len() == text_len,
|
||||
lines.len() == lines_len,
|
||||
"callback should not change the number of lines"
|
||||
);
|
||||
|
||||
edits.push((start_point..end_point, text.join("\n")));
|
||||
edits.push((start_point..end_point, lines.join("\n")));
|
||||
let start_anchor = buffer.anchor_after(start_point);
|
||||
let end_anchor = buffer.anchor_before(end_point);
|
||||
|
||||
|
@ -4304,6 +4321,97 @@ impl Editor {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
|
||||
self.manipulate_text(cx, |text| text.to_uppercase())
|
||||
}
|
||||
|
||||
pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
|
||||
self.manipulate_text(cx, |text| text.to_lowercase())
|
||||
}
|
||||
|
||||
pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
|
||||
self.manipulate_text(cx, |text| text.to_case(Case::Title))
|
||||
}
|
||||
|
||||
pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
|
||||
self.manipulate_text(cx, |text| text.to_case(Case::Snake))
|
||||
}
|
||||
|
||||
pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
|
||||
self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
|
||||
}
|
||||
|
||||
pub fn convert_to_upper_camel_case(
|
||||
&mut self,
|
||||
_: &ConvertToUpperCamelCase,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.manipulate_text(cx, |text| text.to_case(Case::UpperCamel))
|
||||
}
|
||||
|
||||
pub fn convert_to_lower_camel_case(
|
||||
&mut self,
|
||||
_: &ConvertToLowerCamelCase,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.manipulate_text(cx, |text| text.to_case(Case::Camel))
|
||||
}
|
||||
|
||||
fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
|
||||
where
|
||||
Fn: FnMut(&str) -> String,
|
||||
{
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||
|
||||
let mut new_selections = Vec::new();
|
||||
let mut edits = Vec::new();
|
||||
let mut selection_adjustment = 0i32;
|
||||
|
||||
for selection in self.selections.all::<usize>(cx) {
|
||||
let selection_is_empty = selection.is_empty();
|
||||
|
||||
let (start, end) = if selection_is_empty {
|
||||
let word_range = movement::surrounding_word(
|
||||
&display_map,
|
||||
selection.start.to_display_point(&display_map),
|
||||
);
|
||||
let start = word_range.start.to_offset(&display_map, Bias::Left);
|
||||
let end = word_range.end.to_offset(&display_map, Bias::Left);
|
||||
(start, end)
|
||||
} else {
|
||||
(selection.start, selection.end)
|
||||
};
|
||||
|
||||
let text = buffer.text_for_range(start..end).collect::<String>();
|
||||
let old_length = text.len() as i32;
|
||||
let text = callback(&text);
|
||||
|
||||
new_selections.push(Selection {
|
||||
start: (start as i32 - selection_adjustment) as usize,
|
||||
end: ((start + text.len()) as i32 - selection_adjustment) as usize,
|
||||
goal: SelectionGoal::None,
|
||||
..selection
|
||||
});
|
||||
|
||||
selection_adjustment += old_length - text.len() as i32;
|
||||
|
||||
edits.push((start..end, text));
|
||||
}
|
||||
|
||||
self.transact(cx, |this, cx| {
|
||||
this.buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(edits, None, cx);
|
||||
});
|
||||
|
||||
this.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.select(new_selections);
|
||||
});
|
||||
|
||||
this.request_autoscroll(Autoscroll::fit(), cx);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = &display_map.buffer_snapshot;
|
||||
|
@ -6374,8 +6482,8 @@ impl Editor {
|
|||
.range
|
||||
.to_offset(definition.target.buffer.read(cx));
|
||||
|
||||
let range = self.range_for_match(&range);
|
||||
if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
|
||||
let range = self.range_for_match(&range);
|
||||
self.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.select_ranges([range]);
|
||||
});
|
||||
|
@ -6392,7 +6500,6 @@ impl Editor {
|
|||
// When selecting a definition in a different buffer, disable the nav history
|
||||
// to avoid creating a history entry at the previous cursor location.
|
||||
pane.update(cx, |pane, _| pane.disable_history());
|
||||
let range = target_editor.range_for_match(&range);
|
||||
target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||
s.select_ranges([range]);
|
||||
});
|
||||
|
@ -7188,6 +7295,10 @@ impl Editor {
|
|||
pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
|
||||
let mut wrap_guides = smallvec::smallvec![];
|
||||
|
||||
if self.show_wrap_guides == Some(false) {
|
||||
return wrap_guides;
|
||||
}
|
||||
|
||||
let settings = self.buffer.read(cx).settings_at(0, cx);
|
||||
if settings.show_wrap_guides {
|
||||
if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
|
||||
|
@ -7245,6 +7356,11 @@ impl Editor {
|
|||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
|
||||
self.show_wrap_guides = Some(show_gutter);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
|
||||
if let Some(buffer) = self.buffer().read(cx).as_singleton() {
|
||||
if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
|
||||
|
@ -7433,6 +7549,78 @@ impl Editor {
|
|||
results
|
||||
}
|
||||
|
||||
pub fn background_highlight_row_ranges<T: 'static>(
|
||||
&self,
|
||||
search_range: Range<Anchor>,
|
||||
display_snapshot: &DisplaySnapshot,
|
||||
count: usize,
|
||||
) -> Vec<RangeInclusive<DisplayPoint>> {
|
||||
let mut results = Vec::new();
|
||||
let buffer = &display_snapshot.buffer_snapshot;
|
||||
let Some((_, ranges)) = self.background_highlights
|
||||
.get(&TypeId::of::<T>()) else {
|
||||
return vec![];
|
||||
};
|
||||
|
||||
let start_ix = match ranges.binary_search_by(|probe| {
|
||||
let cmp = probe.end.cmp(&search_range.start, buffer);
|
||||
if cmp.is_gt() {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Less
|
||||
}
|
||||
}) {
|
||||
Ok(i) | Err(i) => i,
|
||||
};
|
||||
let mut push_region = |start: Option<Point>, end: Option<Point>| {
|
||||
if let (Some(start_display), Some(end_display)) = (start, end) {
|
||||
results.push(
|
||||
start_display.to_display_point(display_snapshot)
|
||||
..=end_display.to_display_point(display_snapshot),
|
||||
);
|
||||
}
|
||||
};
|
||||
let mut start_row: Option<Point> = None;
|
||||
let mut end_row: Option<Point> = None;
|
||||
if ranges.len() > count {
|
||||
return vec![];
|
||||
}
|
||||
for range in &ranges[start_ix..] {
|
||||
if range.start.cmp(&search_range.end, buffer).is_ge() {
|
||||
break;
|
||||
}
|
||||
let end = range.end.to_point(buffer);
|
||||
if let Some(current_row) = &end_row {
|
||||
if end.row == current_row.row {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let start = range.start.to_point(buffer);
|
||||
|
||||
if start_row.is_none() {
|
||||
assert_eq!(end_row, None);
|
||||
start_row = Some(start);
|
||||
end_row = Some(end);
|
||||
continue;
|
||||
}
|
||||
if let Some(current_end) = end_row.as_mut() {
|
||||
if start.row > current_end.row + 1 {
|
||||
push_region(start_row, end_row);
|
||||
start_row = Some(start);
|
||||
end_row = Some(end);
|
||||
} else {
|
||||
// Merge two hunks.
|
||||
*current_end = end;
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
// We might still have a hunk that was not rendered (if there was a search hit on the last line)
|
||||
push_region(start_row, end_row);
|
||||
results
|
||||
}
|
||||
|
||||
pub fn highlight_text<T: 'static>(
|
||||
&mut self,
|
||||
ranges: Vec<Range<Anchor>>,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -172,6 +172,10 @@ impl EditorElement {
|
|||
.on_drag(MouseButton::Left, {
|
||||
let position_map = position_map.clone();
|
||||
move |event, editor, cx| {
|
||||
if event.end {
|
||||
return;
|
||||
}
|
||||
|
||||
if !Self::mouse_dragged(
|
||||
editor,
|
||||
event.platform_event,
|
||||
|
@ -542,8 +546,20 @@ impl EditorElement {
|
|||
});
|
||||
}
|
||||
|
||||
let scroll_left =
|
||||
layout.position_map.snapshot.scroll_position().x() * layout.position_map.em_width;
|
||||
|
||||
for (wrap_position, active) in layout.wrap_guides.iter() {
|
||||
let x = text_bounds.origin_x() + wrap_position + layout.position_map.em_width / 2.;
|
||||
let x =
|
||||
(text_bounds.origin_x() + wrap_position + layout.position_map.em_width / 2.)
|
||||
- scroll_left;
|
||||
|
||||
if x < text_bounds.origin_x()
|
||||
|| (layout.show_scrollbars && x > self.scrollbar_left(&bounds))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let color = if *active {
|
||||
self.style.active_wrap_guide
|
||||
} else {
|
||||
|
@ -1032,6 +1048,10 @@ impl EditorElement {
|
|||
scene.pop_layer();
|
||||
}
|
||||
|
||||
fn scrollbar_left(&self, bounds: &RectF) -> f32 {
|
||||
bounds.max_x() - self.style.theme.scrollbar.width
|
||||
}
|
||||
|
||||
fn paint_scrollbar(
|
||||
&mut self,
|
||||
scene: &mut SceneBuilder,
|
||||
|
@ -1050,7 +1070,7 @@ impl EditorElement {
|
|||
let top = bounds.min_y();
|
||||
let bottom = bounds.max_y();
|
||||
let right = bounds.max_x();
|
||||
let left = right - style.width;
|
||||
let left = self.scrollbar_left(&bounds);
|
||||
let row_range = &layout.scrollbar_row_range;
|
||||
let max_row = layout.max_row as f32 + (row_range.end - row_range.start);
|
||||
|
||||
|
@ -1087,8 +1107,6 @@ impl EditorElement {
|
|||
if layout.is_singleton && scrollbar_settings.selections {
|
||||
let start_anchor = Anchor::min();
|
||||
let end_anchor = Anchor::max();
|
||||
let mut start_row = None;
|
||||
let mut end_row = None;
|
||||
let color = scrollbar_theme.selections;
|
||||
let border = Border {
|
||||
width: 1.,
|
||||
|
@ -1099,54 +1117,32 @@ impl EditorElement {
|
|||
bottom: false,
|
||||
left: true,
|
||||
};
|
||||
let mut push_region = |start, end| {
|
||||
if let (Some(start_display), Some(end_display)) = (start, end) {
|
||||
let start_y = y_for_row(start_display as f32);
|
||||
let mut end_y = y_for_row(end_display as f32);
|
||||
if end_y - start_y < 1. {
|
||||
end_y = start_y + 1.;
|
||||
}
|
||||
let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y));
|
||||
|
||||
scene.push_quad(Quad {
|
||||
bounds,
|
||||
background: Some(color),
|
||||
border,
|
||||
corner_radius: style.thumb.corner_radius,
|
||||
})
|
||||
let mut push_region = |start: DisplayPoint, end: DisplayPoint| {
|
||||
let start_y = y_for_row(start.row() as f32);
|
||||
let mut end_y = y_for_row(end.row() as f32);
|
||||
if end_y - start_y < 1. {
|
||||
end_y = start_y + 1.;
|
||||
}
|
||||
let bounds = RectF::from_points(vec2f(left, start_y), vec2f(right, end_y));
|
||||
|
||||
scene.push_quad(Quad {
|
||||
bounds,
|
||||
background: Some(color),
|
||||
border,
|
||||
corner_radius: style.thumb.corner_radius,
|
||||
})
|
||||
};
|
||||
for (row, _) in &editor
|
||||
.background_highlights_in_range_for::<crate::items::BufferSearchHighlights>(
|
||||
let background_ranges = editor
|
||||
.background_highlight_row_ranges::<crate::items::BufferSearchHighlights>(
|
||||
start_anchor..end_anchor,
|
||||
&layout.position_map.snapshot,
|
||||
&theme,
|
||||
)
|
||||
{
|
||||
let start_display = row.start;
|
||||
let end_display = row.end;
|
||||
|
||||
if start_row.is_none() {
|
||||
assert_eq!(end_row, None);
|
||||
start_row = Some(start_display.row());
|
||||
end_row = Some(end_display.row());
|
||||
continue;
|
||||
}
|
||||
if let Some(current_end) = end_row.as_mut() {
|
||||
if start_display.row() > *current_end + 1 {
|
||||
push_region(start_row, end_row);
|
||||
start_row = Some(start_display.row());
|
||||
end_row = Some(end_display.row());
|
||||
} else {
|
||||
// Merge two hunks.
|
||||
*current_end = end_display.row();
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
50000,
|
||||
);
|
||||
for row in background_ranges {
|
||||
let start = row.start();
|
||||
let end = row.end();
|
||||
push_region(*start, *end);
|
||||
}
|
||||
// We might still have a hunk that was not rendered (if there was a search hit on the last line)
|
||||
push_region(start_row, end_row);
|
||||
}
|
||||
|
||||
if layout.is_singleton && scrollbar_settings.git_diff {
|
||||
|
@ -1235,6 +1231,10 @@ impl EditorElement {
|
|||
})
|
||||
.on_drag(MouseButton::Left, {
|
||||
move |event, editor: &mut Editor, cx| {
|
||||
if event.end {
|
||||
return;
|
||||
}
|
||||
|
||||
let y = event.prev_mouse_position.y();
|
||||
let new_y = event.position.y();
|
||||
if thumb_top < y && y < thumb_bottom {
|
||||
|
@ -2978,10 +2978,12 @@ mod tests {
|
|||
fn test_layout_line_numbers(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let (_, editor) = cx.add_window(|cx| {
|
||||
let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
|
||||
Editor::new(EditorMode::Full, buffer, None, None, cx)
|
||||
});
|
||||
let editor = cx
|
||||
.add_window(|cx| {
|
||||
let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
|
||||
Editor::new(EditorMode::Full, buffer, None, None, cx)
|
||||
})
|
||||
.root(cx);
|
||||
let element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx)));
|
||||
|
||||
let layouts = editor.update(cx, |editor, cx| {
|
||||
|
@ -2997,10 +2999,12 @@ mod tests {
|
|||
fn test_layout_with_placeholder_text_and_blocks(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let (_, editor) = cx.add_window(|cx| {
|
||||
let buffer = MultiBuffer::build_simple("", cx);
|
||||
Editor::new(EditorMode::Full, buffer, None, None, cx)
|
||||
});
|
||||
let editor = cx
|
||||
.add_window(|cx| {
|
||||
let buffer = MultiBuffer::build_simple("", cx);
|
||||
Editor::new(EditorMode::Full, buffer, None, None, cx)
|
||||
})
|
||||
.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.set_placeholder_text("hello", cx);
|
||||
|
@ -3214,10 +3218,12 @@ mod tests {
|
|||
info!(
|
||||
"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);
|
||||
Editor::new(editor_mode, buffer, None, None, cx)
|
||||
});
|
||||
let editor = cx
|
||||
.add_window(|cx| {
|
||||
let buffer = MultiBuffer::build_simple(&input_text, cx);
|
||||
Editor::new(editor_mode, buffer, None, None, cx)
|
||||
})
|
||||
.root(cx);
|
||||
|
||||
let mut element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx)));
|
||||
let (_, layout_state) = editor.update(cx, |editor, cx| {
|
||||
|
|
|
@ -571,7 +571,6 @@ fn new_update_task(
|
|||
if let Some(buffer) =
|
||||
refresh_multi_buffer.buffer(pending_refresh_query.buffer_id)
|
||||
{
|
||||
drop(refresh_multi_buffer);
|
||||
editor.inlay_hint_cache.update_tasks.insert(
|
||||
pending_refresh_query.excerpt_id,
|
||||
UpdateTask {
|
||||
|
@ -1136,7 +1135,9 @@ mod tests {
|
|||
)
|
||||
.await;
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -1836,7 +1837,9 @@ mod tests {
|
|||
.await;
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -1989,7 +1992,9 @@ mod tests {
|
|||
project.update(cx, |project, _| {
|
||||
project.languages().add(Arc::clone(&language))
|
||||
});
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -2075,8 +2080,9 @@ mod tests {
|
|||
|
||||
deterministic.run_until_parked();
|
||||
cx.foreground().run_until_parked();
|
||||
let (_, editor) =
|
||||
cx.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx));
|
||||
let editor = cx
|
||||
.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx))
|
||||
.root(cx);
|
||||
let editor_edited = Arc::new(AtomicBool::new(false));
|
||||
let fake_server = fake_servers.next().await.unwrap();
|
||||
let closure_editor_edited = Arc::clone(&editor_edited);
|
||||
|
@ -2328,7 +2334,9 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
|||
project.update(cx, |project, _| {
|
||||
project.languages().add(Arc::clone(&language))
|
||||
});
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -2373,8 +2381,9 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
|||
|
||||
deterministic.run_until_parked();
|
||||
cx.foreground().run_until_parked();
|
||||
let (_, editor) =
|
||||
cx.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx));
|
||||
let editor = cx
|
||||
.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx))
|
||||
.root(cx);
|
||||
let editor_edited = Arc::new(AtomicBool::new(false));
|
||||
let fake_server = fake_servers.next().await.unwrap();
|
||||
let closure_editor_edited = Arc::clone(&editor_edited);
|
||||
|
@ -2562,7 +2571,9 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
|||
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
|
|
@ -28,7 +28,10 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
use text::Selection;
|
||||
use util::{paths::FILE_ROW_COLUMN_DELIMITER, ResultExt, TryFutureExt};
|
||||
use util::{
|
||||
paths::{PathExt, FILE_ROW_COLUMN_DELIMITER},
|
||||
ResultExt, TryFutureExt,
|
||||
};
|
||||
use workspace::item::{BreadcrumbText, FollowableItemHandle};
|
||||
use workspace::{
|
||||
item::{FollowableItem, Item, ItemEvent, ItemHandle, ProjectItem},
|
||||
|
@ -546,9 +549,7 @@ impl Item for Editor {
|
|||
.and_then(|f| f.as_local())?
|
||||
.abs_path(cx);
|
||||
|
||||
let file_path = util::paths::compact(&file_path)
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
let file_path = file_path.compact().to_string_lossy().to_string();
|
||||
|
||||
Some(file_path.into())
|
||||
}
|
||||
|
|
|
@ -69,7 +69,8 @@ impl<'a> EditorLspTestContext<'a> {
|
|||
.insert_tree("/root", json!({ "dir": { file_name.clone(): "" }}))
|
||||
.await;
|
||||
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
project.find_or_create_local_worktree("/root", true, cx)
|
||||
|
@ -98,7 +99,7 @@ impl<'a> EditorLspTestContext<'a> {
|
|||
Self {
|
||||
cx: EditorTestContext {
|
||||
cx,
|
||||
window_id,
|
||||
window: window.into(),
|
||||
editor,
|
||||
},
|
||||
lsp,
|
||||
|
|
|
@ -3,7 +3,8 @@ use crate::{
|
|||
};
|
||||
use futures::Future;
|
||||
use gpui::{
|
||||
keymap_matcher::Keystroke, AppContext, ContextHandle, ModelContext, ViewContext, ViewHandle,
|
||||
keymap_matcher::Keystroke, AnyWindowHandle, AppContext, ContextHandle, ModelContext,
|
||||
ViewContext, ViewHandle,
|
||||
};
|
||||
use indoc::indoc;
|
||||
use language::{Buffer, BufferSnapshot};
|
||||
|
@ -21,7 +22,7 @@ use super::build_editor;
|
|||
|
||||
pub struct EditorTestContext<'a> {
|
||||
pub cx: &'a mut gpui::TestAppContext,
|
||||
pub window_id: usize,
|
||||
pub window: AnyWindowHandle,
|
||||
pub editor: ViewHandle<Editor>,
|
||||
}
|
||||
|
||||
|
@ -32,16 +33,14 @@ impl<'a> EditorTestContext<'a> {
|
|||
let buffer = project
|
||||
.update(cx, |project, cx| project.create_buffer("", None, cx))
|
||||
.unwrap();
|
||||
let (window_id, editor) = cx.update(|cx| {
|
||||
cx.add_window(Default::default(), |cx| {
|
||||
cx.focus_self();
|
||||
build_editor(MultiBuffer::build_from_buffer(buffer, cx), cx)
|
||||
})
|
||||
let window = cx.add_window(|cx| {
|
||||
cx.focus_self();
|
||||
build_editor(MultiBuffer::build_from_buffer(buffer, cx), cx)
|
||||
});
|
||||
|
||||
let editor = window.root(cx);
|
||||
Self {
|
||||
cx,
|
||||
window_id,
|
||||
window: window.into(),
|
||||
editor,
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +112,8 @@ impl<'a> EditorTestContext<'a> {
|
|||
let keystroke_under_test_handle =
|
||||
self.add_assertion_context(format!("Simulated Keystroke: {:?}", keystroke_text));
|
||||
let keystroke = Keystroke::parse(keystroke_text).unwrap();
|
||||
self.cx.dispatch_keystroke(self.window_id, keystroke, false);
|
||||
|
||||
self.cx.dispatch_keystroke(self.window, keystroke, false);
|
||||
keystroke_under_test_handle
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue