Detailed changes
@@ -5,16 +5,17 @@ use collections::{BTreeMap, HashSet};
use editor::{
diagnostic_block_renderer,
display_map::{BlockDisposition, BlockId, BlockProperties, RenderBlock},
- highlight_diagnostic_message, Autoscroll, Editor, ExcerptId, MultiBuffer, ToOffset,
+ highlight_diagnostic_message, Autoscroll, Editor, ExcerptId, ExcerptRange, MultiBuffer,
+ ToOffset,
};
use gpui::{
- actions, elements::*, fonts::TextStyle, impl_internal_actions, platform::CursorStyle,
- serde_json, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext,
- Task, View, ViewContext, ViewHandle, WeakViewHandle,
+ actions, elements::*, fonts::TextStyle, impl_internal_actions, serde_json, AnyViewHandle,
+ AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext,
+ ViewHandle, WeakViewHandle,
};
use language::{
Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection,
- SelectionGoal, ToPoint,
+ SelectionGoal,
};
use project::{DiagnosticSummary, Project, ProjectPath};
use serde_json::json;
@@ -27,7 +28,7 @@ use std::{
path::PathBuf,
sync::Arc,
};
-use util::{ResultExt, TryFutureExt};
+use util::TryFutureExt;
use workspace::{ItemHandle as _, ItemNavHistory, Workspace};
actions!(diagnostics, [Deploy]);
@@ -38,7 +39,6 @@ const CONTEXT_LINE_COUNT: u32 = 1;
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ProjectDiagnosticsEditor::deploy);
- cx.add_action(ProjectDiagnosticsEditor::jump);
items::init(cx);
}
@@ -194,30 +194,6 @@ impl ProjectDiagnosticsEditor {
}
}
- fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
- let editor = workspace.open_path(action.path.clone(), true, cx);
- let position = action.position;
- let anchor = action.anchor;
- cx.spawn_weak(|_, mut cx| async move {
- let editor = editor.await.log_err()?.downcast::<Editor>()?;
- editor.update(&mut cx, |editor, cx| {
- let buffer = editor.buffer().read(cx).as_singleton()?;
- let buffer = buffer.read(cx);
- let cursor = if buffer.can_resolve(&anchor) {
- anchor.to_point(buffer)
- } else {
- buffer.clip_point(position, Bias::Left)
- };
- editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
- s.select_ranges([cursor..cursor]);
- });
- Some(())
- })?;
- Some(())
- })
- .detach()
- }
-
fn update_excerpts(&mut self, language_server_id: Option<usize>, cx: &mut ViewContext<Self>) {
let mut paths = Vec::new();
self.paths_to_update.retain(|path, server_id| {
@@ -348,7 +324,10 @@ impl ProjectDiagnosticsEditor {
.insert_excerpts_after(
&prev_excerpt_id,
buffer.clone(),
- [excerpt_start..excerpt_end],
+ [ExcerptRange {
+ context: excerpt_start..excerpt_end,
+ primary: Some(range.clone()),
+ }],
excerpts_cx,
)
.pop()
@@ -363,20 +342,13 @@ impl ProjectDiagnosticsEditor {
is_first_excerpt_for_group = false;
let mut primary =
group.entries[group.primary_ix].diagnostic.clone();
- let anchor = group.entries[group.primary_ix].range.start;
- let position = anchor.to_point(&snapshot);
primary.message =
primary.message.split('\n').next().unwrap().to_string();
group_state.block_count += 1;
blocks_to_add.push(BlockProperties {
position: header_position,
height: 2,
- render: diagnostic_header_renderer(
- primary,
- path.clone(),
- position,
- anchor,
- ),
+ render: diagnostic_header_renderer(primary),
disposition: BlockDisposition::Above,
});
}
@@ -633,18 +605,10 @@ impl workspace::Item for ProjectDiagnosticsEditor {
}
}
-fn diagnostic_header_renderer(
- diagnostic: Diagnostic,
- path: ProjectPath,
- position: Point,
- anchor: Anchor,
-) -> RenderBlock {
- enum JumpIcon {}
-
+fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
let (message, highlights) = highlight_diagnostic_message(&diagnostic.message);
Arc::new(move |cx| {
let settings = cx.global::<Settings>();
- let tooltip_style = settings.theme.tooltip.clone();
let theme = &settings.theme.editor;
let style = theme.diagnostic_header.clone();
let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
@@ -685,43 +649,6 @@ fn diagnostic_header_renderer(
.aligned()
.boxed()
}))
- .with_child(
- MouseEventHandler::new::<JumpIcon, _, _>(diagnostic.group_id, cx, |state, _| {
- let style = style.jump_icon.style_for(state, false);
- Svg::new("icons/jump.svg")
- .with_color(style.color)
- .constrained()
- .with_width(style.icon_width)
- .aligned()
- .contained()
- .with_style(style.container)
- .constrained()
- .with_width(style.button_width)
- .with_height(style.button_width)
- .boxed()
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_click({
- let path = path.clone();
- move |_, _, cx| {
- cx.dispatch_action(Jump {
- path: path.clone(),
- position,
- anchor,
- });
- }
- })
- .with_tooltip(
- diagnostic.group_id,
- "Jump to diagnostic".to_string(),
- Some(Box::new(editor::OpenExcerpts)),
- tooltip_style,
- cx,
- )
- .aligned()
- .flex_float()
- .boxed(),
- )
.contained()
.with_style(style.container)
.with_padding_left(x_padding)
@@ -2,7 +2,7 @@ use super::{
wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot},
TextHighlights,
};
-use crate::{Anchor, ToPoint as _};
+use crate::{Anchor, ExcerptRange, ToPoint as _};
use collections::{Bound, HashMap, HashSet};
use gpui::{ElementBox, RenderContext};
use language::{BufferSnapshot, Chunk, Patch};
@@ -97,8 +97,9 @@ struct Transform {
pub enum TransformBlock {
Custom(Arc<Block>),
ExcerptHeader {
+ key: usize,
buffer: BufferSnapshot,
- range: Range<text::Anchor>,
+ range: ExcerptRange<text::Anchor>,
height: u8,
starts_new_buffer: bool,
},
@@ -126,7 +127,7 @@ impl Debug for TransformBlock {
Self::Custom(block) => f.debug_struct("Custom").field("block", block).finish(),
Self::ExcerptHeader { buffer, .. } => f
.debug_struct("ExcerptHeader")
- .field("path", &buffer.path())
+ .field("path", &buffer.file().map(|f| f.path()))
.finish(),
}
}
@@ -359,6 +360,7 @@ impl BlockMap {
.from_point(Point::new(excerpt_boundary.row, 0), Bias::Left)
.row(),
TransformBlock::ExcerptHeader {
+ key: excerpt_boundary.key,
buffer: excerpt_boundary.buffer,
range: excerpt_boundary.range,
height: if excerpt_boundary.starts_new_buffer {
@@ -36,10 +36,11 @@ use language::{
};
use multi_buffer::MultiBufferChunks;
pub use multi_buffer::{
- Anchor, AnchorRangeExt, ExcerptId, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint,
+ Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
+ ToPoint,
};
use ordered_float::OrderedFloat;
-use project::{HoverBlock, Project, ProjectTransaction};
+use project::{HoverBlock, Project, ProjectPath, ProjectTransaction};
use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
use serde::{Deserialize, Serialize};
use settings::Settings;
@@ -85,6 +86,13 @@ pub struct HoverAt {
point: Option<DisplayPoint>,
}
+#[derive(Clone, Debug, PartialEq)]
+pub struct Jump {
+ path: ProjectPath,
+ position: Point,
+ anchor: language::Anchor,
+}
+
#[derive(Clone, Deserialize, PartialEq)]
pub struct Input(pub String);
@@ -215,7 +223,7 @@ impl_actions!(
]
);
-impl_internal_actions!(editor, [Scroll, Select, HoverAt]);
+impl_internal_actions!(editor, [Scroll, Select, HoverAt, Jump]);
enum DocumentHighlightRead {}
enum DocumentHighlightWrite {}
@@ -305,6 +313,7 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(Editor::hover);
cx.add_action(Editor::hover_at);
cx.add_action(Editor::open_excerpts);
+ cx.add_action(Editor::jump);
cx.add_action(Editor::restart_language_server);
cx.add_async_action(Editor::confirm_completion);
cx.add_async_action(Editor::confirm_code_action);
@@ -2833,11 +2842,11 @@ impl Editor {
let start = highlight
.range
.start
- .max(&excerpt_range.start, cursor_buffer_snapshot);
+ .max(&excerpt_range.context.start, cursor_buffer_snapshot);
let end = highlight
.range
.end
- .min(&excerpt_range.end, cursor_buffer_snapshot);
+ .min(&excerpt_range.context.end, cursor_buffer_snapshot);
if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
continue;
}
@@ -5825,6 +5834,34 @@ impl Editor {
nav_history.borrow_mut().enable();
});
}
+
+ fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
+ let editor = workspace.open_path(action.path.clone(), true, cx);
+ let position = action.position;
+ let anchor = action.anchor;
+ cx.spawn_weak(|_, mut cx| async move {
+ let editor = editor.await.log_err()?.downcast::<Editor>()?;
+ editor.update(&mut cx, |editor, cx| {
+ let buffer = editor.buffer().read(cx).as_singleton()?;
+ let buffer = buffer.read(cx);
+ let cursor = if buffer.can_resolve(&anchor) {
+ language::ToPoint::to_point(&anchor, buffer)
+ } else {
+ buffer.clip_point(position, Bias::Left)
+ };
+
+ let nav_history = editor.nav_history.take();
+ editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
+ s.select_ranges([cursor..cursor]);
+ });
+ editor.nav_history = nav_history;
+
+ Some(())
+ })?;
+ Some(())
+ })
+ .detach()
+ }
}
impl EditorSnapshot {
@@ -7718,12 +7755,18 @@ mod tests {
let mut multibuffer = MultiBuffer::new(0);
multibuffer.push_excerpts(
toml_buffer.clone(),
- [Point::new(0, 0)..Point::new(2, 0)],
+ [ExcerptRange {
+ context: Point::new(0, 0)..Point::new(2, 0),
+ primary: None,
+ }],
cx,
);
multibuffer.push_excerpts(
rust_buffer.clone(),
- [Point::new(0, 0)..Point::new(1, 0)],
+ [ExcerptRange {
+ context: Point::new(0, 0)..Point::new(1, 0),
+ primary: None,
+ }],
cx,
);
multibuffer
@@ -9595,8 +9638,14 @@ mod tests {
multibuffer.push_excerpts(
buffer.clone(),
[
- Point::new(0, 0)..Point::new(0, 4),
- Point::new(1, 0)..Point::new(1, 4),
+ ExcerptRange {
+ context: Point::new(0, 0)..Point::new(0, 4),
+ primary: None,
+ },
+ ExcerptRange {
+ context: Point::new(1, 0)..Point::new(1, 4),
+ primary: None,
+ },
],
cx,
);
@@ -9634,6 +9683,10 @@ mod tests {
[aaaa
(bbbb]
cccc)"});
+ let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
+ context,
+ primary: None,
+ });
let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
let multibuffer = cx.add_model(|cx| {
let mut multibuffer = MultiBuffer::new(0);
@@ -9687,8 +9740,14 @@ mod tests {
.push_excerpts(
buffer.clone(),
[
- Point::new(0, 0)..Point::new(1, 4),
- Point::new(1, 0)..Point::new(2, 4),
+ ExcerptRange {
+ context: Point::new(0, 0)..Point::new(1, 4),
+ primary: None,
+ },
+ ExcerptRange {
+ context: Point::new(1, 0)..Point::new(2, 4),
+ primary: None,
+ },
],
cx,
)
@@ -9771,8 +9830,14 @@ mod tests {
.push_excerpts(
buffer.clone(),
[
- Point::new(0, 0)..Point::new(1, 4),
- Point::new(1, 0)..Point::new(2, 4),
+ ExcerptRange {
+ context: Point::new(0, 0)..Point::new(1, 4),
+ primary: None,
+ },
+ ExcerptRange {
+ context: Point::new(1, 0)..Point::new(2, 4),
+ primary: None,
+ },
],
cx,
)
@@ -27,6 +27,7 @@ use gpui::{
};
use json::json;
use language::{Bias, DiagnosticSeverity, Selection};
+use project::ProjectPath;
use settings::Settings;
use smallvec::SmallVec;
use std::{
@@ -795,6 +796,7 @@ impl EditorElement {
return Default::default();
};
+ let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
let scroll_x = snapshot.scroll_position.x();
snapshot
.blocks_in_range(rows.clone())
@@ -827,10 +829,60 @@ impl EditorElement {
})
}
TransformBlock::ExcerptHeader {
+ key,
buffer,
+ range,
starts_new_buffer,
..
} => {
+ let jump_icon = project::File::from_dyn(buffer.file()).map(|file| {
+ let jump_position = range
+ .primary
+ .as_ref()
+ .map_or(range.context.start, |primary| primary.start);
+ let jump_action = crate::Jump {
+ path: ProjectPath {
+ worktree_id: file.worktree_id(cx),
+ path: file.path.clone(),
+ },
+ position: language::ToPoint::to_point(&jump_position, buffer),
+ anchor: jump_position,
+ };
+
+ enum JumpIcon {}
+ cx.render(&editor, |_, cx| {
+ MouseEventHandler::new::<JumpIcon, _, _>(*key, cx, |state, _| {
+ let style = style.jump_icon.style_for(state, false);
+ Svg::new("icons/jump.svg")
+ .with_color(style.color)
+ .constrained()
+ .with_width(style.icon_width)
+ .aligned()
+ .contained()
+ .with_style(style.container)
+ .constrained()
+ .with_width(style.button_width)
+ .with_height(style.button_width)
+ .boxed()
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_click({
+ move |_, _, cx| cx.dispatch_action(jump_action.clone())
+ })
+ .with_tooltip(
+ *key,
+ "Jump to Buffer".to_string(),
+ Some(Box::new(crate::OpenExcerpts)),
+ tooltip_style.clone(),
+ cx,
+ )
+ .aligned()
+ .flex_float()
+ .boxed()
+ })
+ });
+
+ let padding = gutter_padding + scroll_x * em_width;
if *starts_new_buffer {
let style = &self.style.diagnostic_path_header;
let font_size =
@@ -838,7 +890,8 @@ impl EditorElement {
let mut filename = None;
let mut parent_path = None;
- if let Some(path) = buffer.path() {
+ if let Some(file) = buffer.file() {
+ let path = file.path();
filename =
path.file_name().map(|f| f.to_string_lossy().to_string());
parent_path =
@@ -853,6 +906,7 @@ impl EditorElement {
)
.contained()
.with_style(style.filename.container)
+ .aligned()
.boxed(),
)
.with_children(parent_path.map(|path| {
@@ -862,20 +916,25 @@ impl EditorElement {
)
.contained()
.with_style(style.path.container)
+ .aligned()
.boxed()
}))
- .aligned()
- .left()
+ .with_children(jump_icon)
.contained()
.with_style(style.container)
- .with_padding_left(gutter_padding + scroll_x * em_width)
+ .with_padding_left(padding)
+ .with_padding_right(padding)
.expanded()
.named("path header block")
} else {
let text_style = self.style.text.clone();
- Label::new("…".to_string(), text_style)
+ Flex::row()
+ .with_child(Label::new("…".to_string(), text_style).boxed())
+ .with_children(jump_icon)
.contained()
- .with_padding_left(gutter_padding + scroll_x * em_width)
+ .with_padding_left(padding)
+ .with_padding_right(padding)
+ .expanded()
.named("collapsed context")
}
}
@@ -272,7 +272,7 @@ pub fn surrounding_word(map: &DisplaySnapshot, position: DisplayPoint) -> Range<
#[cfg(test)]
mod tests {
use super::*;
- use crate::{test::marked_display_snapshot, Buffer, DisplayMap, MultiBuffer};
+ use crate::{test::marked_display_snapshot, Buffer, DisplayMap, ExcerptRange, MultiBuffer};
use language::Point;
use settings::Settings;
@@ -494,8 +494,14 @@ mod tests {
multibuffer.push_excerpts(
buffer.clone(),
[
- Point::new(0, 0)..Point::new(1, 4),
- Point::new(2, 0)..Point::new(3, 2),
+ ExcerptRange {
+ context: Point::new(0, 0)..Point::new(1, 4),
+ primary: None,
+ },
+ ExcerptRange {
+ context: Point::new(2, 0)..Point::new(3, 2),
+ primary: None,
+ },
],
cx,
);
@@ -31,6 +31,7 @@ use text::{
Edit, Point, PointUtf16, TextSummary,
};
use theme::SyntaxTheme;
+use util::post_inc;
const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize];
@@ -40,6 +41,7 @@ pub struct MultiBuffer {
snapshot: RefCell<MultiBufferSnapshot>,
buffers: RefCell<HashMap<usize, BufferState>>,
used_excerpt_ids: SumTree<ExcerptId>,
+ next_excerpt_key: usize,
subscriptions: Topic,
singleton: bool,
replica_id: ReplicaId,
@@ -102,23 +104,31 @@ pub struct MultiBufferSnapshot {
pub struct ExcerptBoundary {
pub id: ExcerptId,
+ pub key: usize,
pub row: u32,
pub buffer: BufferSnapshot,
- pub range: Range<text::Anchor>,
+ pub range: ExcerptRange<text::Anchor>,
pub starts_new_buffer: bool,
}
#[derive(Clone)]
struct Excerpt {
id: ExcerptId,
+ key: usize,
buffer_id: usize,
buffer: BufferSnapshot,
- range: Range<text::Anchor>,
+ range: ExcerptRange<text::Anchor>,
max_buffer_row: u32,
text_summary: TextSummary,
has_trailing_newline: bool,
}
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ExcerptRange<T> {
+ pub context: Range<T>,
+ pub primary: Option<Range<T>>,
+}
+
#[derive(Clone, Debug, Default)]
struct ExcerptSummary {
excerpt_id: ExcerptId,
@@ -161,6 +171,7 @@ impl MultiBuffer {
snapshot: Default::default(),
buffers: Default::default(),
used_excerpt_ids: Default::default(),
+ next_excerpt_key: Default::default(),
subscriptions: Default::default(),
singleton: false,
replica_id,
@@ -198,7 +209,8 @@ impl MultiBuffer {
Self {
snapshot: RefCell::new(self.snapshot.borrow().clone()),
buffers: RefCell::new(buffers),
- used_excerpt_ids: Default::default(),
+ used_excerpt_ids: self.used_excerpt_ids.clone(),
+ next_excerpt_key: self.next_excerpt_key,
subscriptions: Default::default(),
singleton: self.singleton,
replica_id: self.replica_id,
@@ -215,7 +227,14 @@ impl MultiBuffer {
pub fn singleton(buffer: ModelHandle<Buffer>, cx: &mut ModelContext<Self>) -> Self {
let mut this = Self::new(buffer.read(cx).replica_id());
this.singleton = true;
- this.push_excerpts(buffer, [text::Anchor::MIN..text::Anchor::MAX], cx);
+ this.push_excerpts(
+ buffer,
+ [ExcerptRange {
+ context: text::Anchor::MIN..text::Anchor::MAX,
+ primary: None,
+ }],
+ cx,
+ );
this.snapshot.borrow_mut().singleton = true;
this
}
@@ -343,8 +362,12 @@ impl MultiBuffer {
}
let start_excerpt = cursor.item().expect("start offset out of bounds");
let start_overshoot = range.start - cursor.start();
- let buffer_start =
- start_excerpt.range.start.to_offset(&start_excerpt.buffer) + start_overshoot;
+ let buffer_start = start_excerpt
+ .range
+ .context
+ .start
+ .to_offset(&start_excerpt.buffer)
+ + start_overshoot;
cursor.seek(&range.end, Bias::Right, &());
if cursor.item().is_none() && range.end == *cursor.start() {
@@ -352,7 +375,12 @@ impl MultiBuffer {
}
let end_excerpt = cursor.item().expect("end offset out of bounds");
let end_overshoot = range.end - cursor.start();
- let buffer_end = end_excerpt.range.start.to_offset(&end_excerpt.buffer) + end_overshoot;
+ let buffer_end = end_excerpt
+ .range
+ .context
+ .start
+ .to_offset(&end_excerpt.buffer)
+ + end_overshoot;
if start_excerpt.id == end_excerpt.id {
buffer_edits
@@ -360,10 +388,18 @@ impl MultiBuffer {
.or_insert(Vec::new())
.push((buffer_start..buffer_end, new_text, true));
} else {
- let start_excerpt_range =
- buffer_start..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
- let end_excerpt_range =
- end_excerpt.range.start.to_offset(&end_excerpt.buffer)..buffer_end;
+ let start_excerpt_range = buffer_start
+ ..start_excerpt
+ .range
+ .context
+ .end
+ .to_offset(&start_excerpt.buffer);
+ let end_excerpt_range = end_excerpt
+ .range
+ .context
+ .start
+ .to_offset(&end_excerpt.buffer)
+ ..buffer_end;
buffer_edits
.entry(start_excerpt.buffer_id)
.or_insert(Vec::new())
@@ -383,7 +419,7 @@ impl MultiBuffer {
.entry(excerpt.buffer_id)
.or_insert(Vec::new())
.push((
- excerpt.range.to_offset(&excerpt.buffer),
+ excerpt.range.context.to_offset(&excerpt.buffer),
new_text.clone(),
false,
));
@@ -523,8 +559,8 @@ impl MultiBuffer {
break;
}
- let mut start = excerpt.range.start.clone();
- let mut end = excerpt.range.end.clone();
+ let mut start = excerpt.range.context.start.clone();
+ let mut end = excerpt.range.context.end.clone();
if excerpt.id == selection.start.excerpt_id {
start = selection.start.text_anchor.clone();
}
@@ -644,7 +680,7 @@ impl MultiBuffer {
pub fn push_excerpts<O>(
&mut self,
buffer: ModelHandle<Buffer>,
- ranges: impl IntoIterator<Item = Range<O>>,
+ ranges: impl IntoIterator<Item = ExcerptRange<O>>,
cx: &mut ModelContext<Self>,
) -> Vec<ExcerptId>
where
@@ -692,7 +728,10 @@ impl MultiBuffer {
}
}
- excerpt_ranges.push(excerpt_start..excerpt_end);
+ excerpt_ranges.push(ExcerptRange {
+ context: excerpt_start..excerpt_end,
+ primary: Some(range),
+ });
range_counts.push(ranges_in_excerpt);
}
@@ -722,7 +761,7 @@ impl MultiBuffer {
&mut self,
prev_excerpt_id: &ExcerptId,
buffer: ModelHandle<Buffer>,
- ranges: impl IntoIterator<Item = Range<O>>,
+ ranges: impl IntoIterator<Item = ExcerptRange<O>>,
cx: &mut ModelContext<Self>,
) -> Vec<ExcerptId>
where
@@ -786,10 +825,17 @@ impl MultiBuffer {
if let Err(ix) = buffer_state.excerpts.binary_search(&id) {
buffer_state.excerpts.insert(ix, id.clone());
}
- let range = buffer_snapshot.anchor_before(&range.start)
- ..buffer_snapshot.anchor_after(&range.end);
+ let range = ExcerptRange {
+ context: buffer_snapshot.anchor_before(&range.context.start)
+ ..buffer_snapshot.anchor_after(&range.context.end),
+ primary: range.primary.map(|primary| {
+ buffer_snapshot.anchor_before(&primary.start)
+ ..buffer_snapshot.anchor_after(&primary.end)
+ }),
+ };
let excerpt = Excerpt::new(
id.clone(),
+ post_inc(&mut self.next_excerpt_key),
buffer_id,
buffer_snapshot.clone(),
range,
@@ -846,7 +892,7 @@ impl MultiBuffer {
&self,
buffer: &ModelHandle<Buffer>,
cx: &AppContext,
- ) -> Vec<(ExcerptId, Range<text::Anchor>)> {
+ ) -> Vec<(ExcerptId, ExcerptRange<text::Anchor>)> {
let mut excerpts = Vec::new();
let snapshot = self.read(cx);
let buffers = self.buffers.borrow();
@@ -894,7 +940,7 @@ impl MultiBuffer {
.unwrap()
.buffer
.clone(),
- excerpt.range.clone(),
+ excerpt.range.context.clone(),
)
})
}
@@ -914,7 +960,7 @@ impl MultiBuffer {
}
cursor.item().map(|excerpt| {
- let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
+ let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
let buffer_point = excerpt_start + offset - *cursor.start();
let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
@@ -943,7 +989,7 @@ impl MultiBuffer {
if excerpt.has_trailing_newline {
end_before_newline -= 1;
}
- let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
+ let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
@@ -1234,7 +1280,7 @@ impl MultiBuffer {
buffer
.edits_since_in_range::<usize>(
old_excerpt.buffer.version(),
- old_excerpt.range.clone(),
+ old_excerpt.range.context.clone(),
)
.map(|mut edit| {
let excerpt_old_start = cursor.start().1;
@@ -1249,6 +1295,7 @@ impl MultiBuffer {
new_excerpt = Excerpt::new(
id.clone(),
+ old_excerpt.key,
buffer_id,
buffer.snapshot(),
old_excerpt.range.clone(),
@@ -1384,7 +1431,10 @@ impl MultiBuffer {
let end_ix =
buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Right);
let start_ix = buffer.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
- start_ix..end_ix
+ ExcerptRange {
+ context: start_ix..end_ix,
+ primary: None,
+ }
})
.collect::<Vec<_>>();
log::info!(
@@ -1393,7 +1443,7 @@ impl MultiBuffer {
ranges,
ranges
.iter()
- .map(|range| &buffer_text[range.clone()])
+ .map(|range| &buffer_text[range.context.clone()])
.collect::<Vec<_>>()
);
@@ -1465,7 +1515,7 @@ impl MultiBufferSnapshot {
cursor.seek(&offset, Bias::Left, &());
let mut excerpt_chunks = cursor.item().map(|excerpt| {
let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
- let start = excerpt.range.start.to_offset(&excerpt.buffer);
+ let start = excerpt.range.context.start.to_offset(&excerpt.buffer);
let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
excerpt.buffer.reversed_chunks_in_range(start..end)
});
@@ -1476,7 +1526,7 @@ impl MultiBufferSnapshot {
excerpt_chunks = Some(
excerpt
.buffer
- .reversed_chunks_in_range(excerpt.range.clone()),
+ .reversed_chunks_in_range(excerpt.range.context.clone()),
);
}
@@ -1581,7 +1631,7 @@ impl MultiBufferSnapshot {
let mut cursor = self.excerpts.cursor::<usize>();
cursor.seek(&offset, Bias::Right, &());
let overshoot = if let Some(excerpt) = cursor.item() {
- let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
+ let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
let buffer_offset = excerpt
.buffer
.clip_offset(excerpt_start + (offset - cursor.start()), bias);
@@ -1600,7 +1650,7 @@ impl MultiBufferSnapshot {
let mut cursor = self.excerpts.cursor::<Point>();
cursor.seek(&point, Bias::Right, &());
let overshoot = if let Some(excerpt) = cursor.item() {
- let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
+ let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.clip_point(excerpt_start + (point - cursor.start()), bias);
@@ -1621,7 +1671,7 @@ impl MultiBufferSnapshot {
let overshoot = if let Some(excerpt) = cursor.item() {
let excerpt_start = excerpt
.buffer
- .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
+ .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
let buffer_point = excerpt
.buffer
.clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
@@ -1690,8 +1740,8 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_offset, start_point) = cursor.start();
let overshoot = offset - start_offset;
- let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
- let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
+ let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
+ let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.offset_to_point(excerpt_start_offset + overshoot);
@@ -1711,8 +1761,8 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_offset, start_point) = cursor.start();
let overshoot = offset - start_offset;
- let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
- let excerpt_start_point = excerpt.range.start.to_point_utf16(&excerpt.buffer);
+ let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
+ let excerpt_start_point = excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.offset_to_point_utf16(excerpt_start_offset + overshoot);
@@ -1732,8 +1782,9 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_offset, start_point) = cursor.start();
let overshoot = point - start_offset;
- let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
- let excerpt_start_point_utf16 = excerpt.range.start.to_point_utf16(&excerpt.buffer);
+ let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
+ let excerpt_start_point_utf16 =
+ excerpt.range.context.start.to_point_utf16(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.point_to_point_utf16(excerpt_start_point + overshoot);
@@ -1753,8 +1804,8 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_point, start_offset) = cursor.start();
let overshoot = point - start_point;
- let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
- let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
+ let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
+ let excerpt_start_point = excerpt.range.context.start.to_point(&excerpt.buffer);
let buffer_offset = excerpt
.buffer
.point_to_offset(excerpt_start_point + overshoot);
@@ -1774,10 +1825,10 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_point, start_offset) = cursor.start();
let overshoot = point - start_point;
- let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
+ let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
let excerpt_start_point = excerpt
.buffer
- .offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
+ .offset_to_point_utf16(excerpt.range.context.start.to_offset(&excerpt.buffer));
let buffer_offset = excerpt
.buffer
.point_utf16_to_offset(excerpt_start_point + overshoot);
@@ -1811,8 +1862,8 @@ impl MultiBufferSnapshot {
cursor.seek(&Point::new(row, 0), Bias::Right, &());
if let Some(excerpt) = cursor.item() {
let overshoot = row - cursor.start().row;
- let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
- let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
+ let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer);
+ let excerpt_end = excerpt.range.context.end.to_point(&excerpt.buffer);
let buffer_row = excerpt_start.row + overshoot;
let line_start = Point::new(buffer_row, 0);
let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
@@ -1847,7 +1898,7 @@ impl MultiBufferSnapshot {
end_before_newline -= 1;
}
- let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
+ let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
let start_in_excerpt = excerpt_start + (range.start - cursor.start());
let end_in_excerpt =
excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
@@ -1881,7 +1932,7 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
range.end = cmp::max(*cursor.start(), range.end);
- let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
+ let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
let end_in_excerpt = excerpt_start + (range.end - cursor.start());
summary.add_assign(
&excerpt
@@ -1907,8 +1958,9 @@ impl MultiBufferSnapshot {
let mut position = D::from_text_summary(&cursor.start().text);
if let Some(excerpt) = cursor.item() {
if excerpt.id == anchor.excerpt_id {
- let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
- let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
+ let excerpt_buffer_start =
+ excerpt.range.context.start.summary::<D>(&excerpt.buffer);
+ let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(&excerpt.buffer);
let buffer_position = cmp::min(
excerpt_buffer_end,
anchor.text_anchor.summary::<D>(&excerpt.buffer),
@@ -1954,8 +2006,10 @@ impl MultiBufferSnapshot {
let position = D::from_text_summary(&cursor.start().text);
if let Some(excerpt) = cursor.item() {
if excerpt.id == *excerpt_id {
- let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
- let excerpt_buffer_end = excerpt.range.end.summary::<D>(&excerpt.buffer);
+ let excerpt_buffer_start =
+ excerpt.range.context.start.summary::<D>(&excerpt.buffer);
+ let excerpt_buffer_end =
+ excerpt.range.context.end.summary::<D>(&excerpt.buffer);
summaries.extend(
excerpt
.buffer
@@ -2036,10 +2090,14 @@ impl MultiBufferSnapshot {
anchor = if let Some(excerpt) = next_excerpt {
let mut text_anchor = excerpt
.range
+ .context
.start
.bias(anchor.text_anchor.bias, &excerpt.buffer);
- if text_anchor.cmp(&excerpt.range.end, &excerpt.buffer).is_gt() {
- text_anchor = excerpt.range.end.clone();
+ if text_anchor
+ .cmp(&excerpt.range.context.end, &excerpt.buffer)
+ .is_gt()
+ {
+ text_anchor = excerpt.range.context.end.clone();
}
Anchor {
buffer_id: Some(excerpt.buffer_id),
@@ -2049,13 +2107,14 @@ impl MultiBufferSnapshot {
} else if let Some(excerpt) = prev_excerpt {
let mut text_anchor = excerpt
.range
+ .context
.end
.bias(anchor.text_anchor.bias, &excerpt.buffer);
if text_anchor
- .cmp(&excerpt.range.start, &excerpt.buffer)
+ .cmp(&excerpt.range.context.start, &excerpt.buffer)
.is_lt()
{
- text_anchor = excerpt.range.start.clone();
+ text_anchor = excerpt.range.context.start.clone();
}
Anchor {
buffer_id: Some(excerpt.buffer_id),
@@ -2106,7 +2165,7 @@ impl MultiBufferSnapshot {
bias = Bias::Right;
}
- let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
+ let buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
let text_anchor =
excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
Anchor {
@@ -2196,6 +2255,7 @@ impl MultiBufferSnapshot {
let starts_new_buffer = Some(excerpt.buffer_id) != prev_buffer_id;
let boundary = ExcerptBoundary {
id: excerpt.id.clone(),
+ key: excerpt.key,
row: cursor.start().1.row,
buffer: excerpt.buffer.clone(),
range: excerpt.range.clone(),
@@ -2239,8 +2299,11 @@ impl MultiBufferSnapshot {
return None;
}
- let excerpt_buffer_start =
- start_excerpt.range.start.to_offset(&start_excerpt.buffer);
+ let excerpt_buffer_start = start_excerpt
+ .range
+ .context
+ .start
+ .to_offset(&start_excerpt.buffer);
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
let start_in_buffer =
@@ -2340,8 +2403,11 @@ impl MultiBufferSnapshot {
return None;
}
- let excerpt_buffer_start =
- start_excerpt.range.start.to_offset(&start_excerpt.buffer);
+ let excerpt_buffer_start = start_excerpt
+ .range
+ .context
+ .start
+ .to_offset(&start_excerpt.buffer);
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
let start_in_buffer =
@@ -2427,7 +2493,8 @@ impl MultiBufferSnapshot {
cursor
.take_while(move |excerpt| excerpt.id <= range.end.excerpt_id)
.flat_map(move |excerpt| {
- let mut query_range = excerpt.range.start.clone()..excerpt.range.end.clone();
+ let mut query_range =
+ excerpt.range.context.start.clone()..excerpt.range.context.end.clone();
if excerpt.id == range.start.excerpt_id {
query_range.start = range.start.text_anchor.clone();
}
@@ -2617,15 +2684,18 @@ impl History {
impl Excerpt {
fn new(
id: ExcerptId,
+ key: usize,
buffer_id: usize,
buffer: BufferSnapshot,
- range: Range<text::Anchor>,
+ range: ExcerptRange<text::Anchor>,
has_trailing_newline: bool,
) -> Self {
Excerpt {
id,
- max_buffer_row: range.end.to_point(&buffer).row,
- text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
+ key,
+ max_buffer_row: range.context.end.to_point(&buffer).row,
+ text_summary: buffer
+ .text_summary_for_range::<TextSummary, _>(range.context.to_offset(&buffer)),
buffer_id,
buffer,
range,
@@ -2638,7 +2708,7 @@ impl Excerpt {
range: Range<usize>,
language_aware: bool,
) -> ExcerptChunks<'a> {
- let content_start = self.range.start.to_offset(&self.buffer);
+ let content_start = self.range.context.start.to_offset(&self.buffer);
let chunks_start = content_start + range.start;
let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
@@ -2660,7 +2730,7 @@ impl Excerpt {
}
fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
- let content_start = self.range.start.to_offset(&self.buffer);
+ 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.bytes);
let footer_height = if self.has_trailing_newline
@@ -2680,10 +2750,16 @@ impl Excerpt {
}
fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
- if text_anchor.cmp(&self.range.start, &self.buffer).is_lt() {
- self.range.start.clone()
- } else if text_anchor.cmp(&self.range.end, &self.buffer).is_gt() {
- self.range.end.clone()
+ if text_anchor
+ .cmp(&self.range.context.start, &self.buffer)
+ .is_lt()
+ {
+ self.range.context.start.clone()
+ } else if text_anchor
+ .cmp(&self.range.context.end, &self.buffer)
+ .is_gt()
+ {
+ self.range.context.end.clone()
} else {
text_anchor
}
@@ -2693,11 +2769,13 @@ impl Excerpt {
Some(self.buffer_id) == anchor.buffer_id
&& self
.range
+ .context
.start
.cmp(&anchor.text_anchor, &self.buffer)
.is_le()
&& self
.range
+ .context
.end
.cmp(&anchor.text_anchor, &self.buffer)
.is_ge()
@@ -2802,7 +2880,7 @@ impl<'a> MultiBufferRows<'a> {
if let Some(excerpt) = self.excerpts.item() {
let overshoot = row - self.excerpts.start().row;
- let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
+ let excerpt_start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
self.buffer_row_range.start = excerpt_start + overshoot;
self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
}
@@ -2822,7 +2900,7 @@ impl<'a> Iterator for MultiBufferRows<'a> {
self.excerpts.item()?;
self.excerpts.next(&());
let excerpt = self.excerpts.item()?;
- self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
+ self.buffer_row_range.start = excerpt.range.context.start.to_point(&excerpt.buffer).row;
self.buffer_row_range.end =
self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
}
@@ -3079,7 +3157,14 @@ mod tests {
let subscription = multibuffer.update(cx, |multibuffer, cx| {
let subscription = multibuffer.subscribe();
- multibuffer.push_excerpts(buffer_1.clone(), [Point::new(1, 2)..Point::new(2, 5)], cx);
+ multibuffer.push_excerpts(
+ buffer_1.clone(),
+ [ExcerptRange {
+ context: Point::new(1, 2)..Point::new(2, 5),
+ primary: None,
+ }],
+ cx,
+ );
assert_eq!(
subscription.consume().into_inner(),
[Edit {
@@ -3088,8 +3173,22 @@ mod tests {
}]
);
- multibuffer.push_excerpts(buffer_1.clone(), [Point::new(3, 3)..Point::new(4, 4)], cx);
- multibuffer.push_excerpts(buffer_2.clone(), [Point::new(3, 1)..Point::new(3, 3)], cx);
+ multibuffer.push_excerpts(
+ buffer_1.clone(),
+ [ExcerptRange {
+ context: Point::new(3, 3)..Point::new(4, 4),
+ primary: None,
+ }],
+ cx,
+ );
+ multibuffer.push_excerpts(
+ buffer_2.clone(),
+ [ExcerptRange {
+ context: Point::new(3, 1)..Point::new(3, 3),
+ primary: None,
+ }],
+ cx,
+ );
assert_eq!(
subscription.consume().into_inner(),
[Edit {
@@ -3253,7 +3352,7 @@ mod tests {
boundary.row,
boundary
.buffer
- .text_for_range(boundary.range)
+ .text_for_range(boundary.range.context)
.collect::<String>(),
boundary.starts_new_buffer,
)
@@ -3334,8 +3433,22 @@ mod tests {
let buffer_2 = cx.add_model(|cx| Buffer::new(0, "efghi", cx));
let multibuffer = cx.add_model(|cx| {
let mut multibuffer = MultiBuffer::new(0);
- multibuffer.push_excerpts(buffer_1.clone(), [0..4], cx);
- multibuffer.push_excerpts(buffer_2.clone(), [0..5], cx);
+ multibuffer.push_excerpts(
+ buffer_1.clone(),
+ [ExcerptRange {
+ context: 0..4,
+ primary: None,
+ }],
+ cx,
+ );
+ multibuffer.push_excerpts(
+ buffer_2.clone(),
+ [ExcerptRange {
+ context: 0..5,
+ primary: None,
+ }],
+ cx,
+ );
multibuffer
});
let old_snapshot = multibuffer.read(cx).snapshot(cx);
@@ -3385,7 +3498,14 @@ mod tests {
buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], cx));
let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
multibuffer
- .push_excerpts(buffer_1.clone(), [0..7], cx)
+ .push_excerpts(
+ buffer_1.clone(),
+ [ExcerptRange {
+ context: 0..7,
+ primary: None,
+ }],
+ cx,
+ )
.pop()
.unwrap()
});
@@ -3397,7 +3517,24 @@ mod tests {
let (excerpt_id_2, excerpt_id_3) = multibuffer.update(cx, |multibuffer, cx| {
multibuffer.remove_excerpts([&excerpt_id_1], cx);
let mut ids = multibuffer
- .push_excerpts(buffer_2.clone(), [0..4, 6..10, 12..16], cx)
+ .push_excerpts(
+ buffer_2.clone(),
+ [
+ ExcerptRange {
+ context: 0..4,
+ primary: None,
+ },
+ ExcerptRange {
+ context: 6..10,
+ primary: None,
+ },
+ ExcerptRange {
+ context: 12..16,
+ primary: None,
+ },
+ ],
+ cx,
+ )
.into_iter();
(ids.next().unwrap(), ids.next().unwrap())
});
@@ -3437,7 +3574,15 @@ mod tests {
let excerpt_id_5 = multibuffer.update(cx, |multibuffer, cx| {
multibuffer.remove_excerpts([&excerpt_id_3], cx);
multibuffer
- .insert_excerpts_after(&excerpt_id_3, buffer_2.clone(), [5..8], cx)
+ .insert_excerpts_after(
+ &excerpt_id_3,
+ buffer_2.clone(),
+ [ExcerptRange {
+ context: 5..8,
+ primary: None,
+ }],
+ cx,
+ )
.pop()
.unwrap()
});
@@ -3584,7 +3729,10 @@ mod tests {
.insert_excerpts_after(
&prev_excerpt_id,
buffer_handle.clone(),
- [start_ix..end_ix],
+ [ExcerptRange {
+ context: start_ix..end_ix,
+ primary: None,
+ }],
cx,
)
.pop()
@@ -3893,8 +4041,22 @@ mod tests {
let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
let group_interval = multibuffer.read(cx).history.group_interval;
multibuffer.update(cx, |multibuffer, cx| {
- multibuffer.push_excerpts(buffer_1.clone(), [0..buffer_1.read(cx).len()], cx);
- multibuffer.push_excerpts(buffer_2.clone(), [0..buffer_2.read(cx).len()], cx);
+ multibuffer.push_excerpts(
+ buffer_1.clone(),
+ [ExcerptRange {
+ context: 0..buffer_1.read(cx).len(),
+ primary: None,
+ }],
+ cx,
+ );
+ multibuffer.push_excerpts(
+ buffer_2.clone(),
+ [ExcerptRange {
+ context: 0..buffer_2.read(cx).len(),
+ primary: None,
+ }],
+ cx,
+ );
});
let mut now = Instant::now();
@@ -49,7 +49,7 @@ lazy_static! {
pub struct Buffer {
text: TextBuffer,
- file: Option<Box<dyn File>>,
+ file: Option<Arc<dyn File>>,
saved_version: clock::Global,
saved_mtime: SystemTime,
language: Option<Arc<Language>>,
@@ -72,7 +72,7 @@ pub struct Buffer {
pub struct BufferSnapshot {
text: text::BufferSnapshot,
tree: Option<Tree>,
- path: Option<Arc<Path>>,
+ file: Option<Arc<dyn File>>,
diagnostics: DiagnosticSet,
diagnostics_update_count: usize,
file_update_count: usize,
@@ -152,7 +152,7 @@ pub enum Event {
Closed,
}
-pub trait File {
+pub trait File: Send + Sync {
fn as_local(&self) -> Option<&dyn LocalFile>;
fn is_local(&self) -> bool {
@@ -306,7 +306,7 @@ impl Buffer {
pub fn from_file<T: Into<Arc<str>>>(
replica_id: ReplicaId,
base_text: T,
- file: Box<dyn File>,
+ file: Arc<dyn File>,
cx: &mut ModelContext<Self>,
) -> Self {
Self::build(
@@ -322,7 +322,7 @@ impl Buffer {
pub fn from_proto(
replica_id: ReplicaId,
message: proto::BufferState,
- file: Option<Box<dyn File>>,
+ file: Option<Arc<dyn File>>,
cx: &mut ModelContext<Self>,
) -> Result<Self> {
let buffer = TextBuffer::new(
@@ -403,7 +403,7 @@ impl Buffer {
self
}
- fn build(buffer: TextBuffer, file: Option<Box<dyn File>>) -> Self {
+ fn build(buffer: TextBuffer, file: Option<Arc<dyn File>>) -> Self {
let saved_mtime;
if let Some(file) = file.as_ref() {
saved_mtime = file.mtime();
@@ -438,7 +438,7 @@ impl Buffer {
BufferSnapshot {
text: self.text.snapshot(),
tree: self.syntax_tree(),
- path: self.file.as_ref().map(|f| f.path().clone()),
+ file: self.file.clone(),
remote_selections: self.remote_selections.clone(),
diagnostics: self.diagnostics.clone(),
diagnostics_update_count: self.diagnostics_update_count,
@@ -496,7 +496,7 @@ impl Buffer {
&mut self,
version: clock::Global,
mtime: SystemTime,
- new_file: Option<Box<dyn File>>,
+ new_file: Option<Arc<dyn File>>,
cx: &mut ModelContext<Self>,
) {
self.saved_mtime = mtime;
@@ -550,7 +550,7 @@ impl Buffer {
pub fn file_updated(
&mut self,
- new_file: Box<dyn File>,
+ new_file: Arc<dyn File>,
cx: &mut ModelContext<Self>,
) -> Task<()> {
let old_file = if let Some(file) = self.file.as_ref() {
@@ -1980,8 +1980,8 @@ impl BufferSnapshot {
self.selections_update_count
}
- pub fn path(&self) -> Option<&Arc<Path>> {
- self.path.as_ref()
+ pub fn file(&self) -> Option<&dyn File> {
+ self.file.as_deref()
}
pub fn file_update_count(&self) -> usize {
@@ -1994,7 +1994,7 @@ impl Clone for BufferSnapshot {
Self {
text: self.text.clone(),
tree: self.tree.clone(),
- path: self.path.clone(),
+ file: self.file.clone(),
remote_selections: self.remote_selections.clone(),
diagnostics: self.diagnostics.clone(),
selections_update_count: self.selections_update_count,
@@ -4013,7 +4013,7 @@ impl Project {
})
.log_err();
}
- buffer.file_updated(Box::new(new_file), cx).detach();
+ buffer.file_updated(Arc::new(new_file), cx).detach();
}
});
} else {
@@ -4565,7 +4565,7 @@ impl Project {
.and_then(|b| b.upgrade(cx))
.ok_or_else(|| anyhow!("no such buffer"))?;
buffer.update(cx, |buffer, cx| {
- buffer.file_updated(Box::new(file), cx).detach();
+ buffer.file_updated(Arc::new(file), cx).detach();
});
Ok(())
})
@@ -5089,8 +5089,8 @@ impl Project {
anyhow!("no worktree found for id {}", file.worktree_id)
})?;
buffer_file =
- Some(Box::new(File::from_proto(file, worktree.clone(), cx)?)
- as Box<dyn language::File>);
+ Some(Arc::new(File::from_proto(file, worktree.clone(), cx)?)
+ as Arc<dyn language::File>);
buffer_worktree = Some(worktree);
Ok::<_, anyhow::Error>(())
})?;
@@ -519,7 +519,7 @@ impl LocalWorktree {
let (file, contents) = this
.update(&mut cx, |t, cx| t.as_local().unwrap().load(&path, cx))
.await?;
- Ok(cx.add_model(|cx| Buffer::from_file(0, contents, Box::new(file), cx)))
+ Ok(cx.add_model(|cx| Buffer::from_file(0, contents, Arc::new(file), cx)))
})
}
@@ -648,7 +648,7 @@ impl LocalWorktree {
};
buffer_handle.update(&mut cx, |buffer, cx| {
- buffer.did_save(version, file.mtime, Some(Box::new(file)), cx);
+ buffer.did_save(version, file.mtime, Some(Arc::new(file)), cx);
});
Ok(())
@@ -485,7 +485,7 @@ impl BufferSearchBar {
);
} else {
for excerpt in buffer.excerpt_boundaries_in_range(0..buffer.len()) {
- let excerpt_range = excerpt.range.to_offset(&excerpt.buffer);
+ let excerpt_range = excerpt.range.context.to_offset(&excerpt.buffer);
let rope = excerpt.buffer.as_rope().slice(excerpt_range.clone());
ranges.extend(query.search(&rope).await.into_iter().map(|range| {
let start = excerpt
@@ -454,6 +454,7 @@ pub struct Editor {
pub code_actions_indicator: Color,
pub unnecessary_code_fade: f32,
pub hover_popover: HoverPopover,
+ pub jump_icon: Interactive<IconButton>,
}
#[derive(Clone, Deserialize, Default)]
@@ -473,7 +474,6 @@ pub struct DiagnosticHeader {
pub code: ContainedText,
pub text_scale_factor: f32,
pub icon_width_factor: f32,
- pub jump_icon: Interactive<IconButton>,
}
#[derive(Clone, Deserialize, Default)]
@@ -101,14 +101,6 @@ export default function editor(theme: Theme) {
background: backgroundColor(theme, 300),
iconWidthFactor: 1.5,
textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these.
- jumpIcon: {
- color: iconColor(theme, "primary"),
- iconWidth: 10,
- buttonWidth: 10,
- hover: {
- color: iconColor(theme, "active")
- }
- },
border: border(theme, "secondary", {
bottom: true,
top: true,
@@ -147,6 +139,14 @@ export default function editor(theme: Theme) {
invalidInformationDiagnostic: diagnostic(theme, "muted"),
invalidWarningDiagnostic: diagnostic(theme, "muted"),
hover_popover: hoverPopover(theme),
+ jumpIcon: {
+ color: iconColor(theme, "primary"),
+ iconWidth: 10,
+ buttonWidth: 10,
+ hover: {
+ color: iconColor(theme, "active")
+ }
+ },
syntax,
};
}