zed/assets/themes/dark.toml 🔗
@@ -14,7 +14,6 @@ modal_match_border = 0x000000
modal_match_text = 0xcccccc
modal_match_text_highlight = 0x18a3ff
-
[editor]
background = 0x1c1d1e
gutter_background = 0x1c1d1e
Antonio Scandurra created
zed/assets/themes/dark.toml | 1
zed/src/editor.rs | 49 +++++++++++++++++++++--------
zed/src/editor/element.rs | 65 +++++++++++++++++++++++++-------------
3 files changed, 78 insertions(+), 37 deletions(-)
@@ -14,7 +14,6 @@ modal_match_border = 0x000000
modal_match_text = 0xcccccc
modal_match_text_highlight = 0x18a3ff
-
[editor]
background = 0x1c1d1e
gutter_background = 0x1c1d1e
@@ -5,6 +5,7 @@ pub mod movement;
use crate::{
settings::{Settings, StyleId, Theme},
+ time::ReplicaId,
util::{post_inc, Bias},
workspace,
worktree::{File, Worktree},
@@ -26,6 +27,7 @@ use smallvec::SmallVec;
use smol::Timer;
use std::{
cmp::{self, Ordering},
+ collections::HashSet,
fmt::Write,
iter::FromIterator,
mem,
@@ -461,6 +463,10 @@ impl Editor {
}
}
+ pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
+ self.buffer.read(cx).replica_id()
+ }
+
pub fn buffer(&self) -> &ModelHandle<Buffer> {
&self.buffer
}
@@ -2350,27 +2356,28 @@ impl Snapshot {
pub fn layout_line_numbers(
&self,
- viewport_height: f32,
+ rows: Range<u32>,
+ active_rows: &HashSet<u32>,
font_cache: &FontCache,
layout_cache: &TextLayoutCache,
theme: &Theme,
) -> Result<Vec<Option<text_layout::Line>>> {
let font_id = font_cache.select_font(self.font_family, &FontProperties::new())?;
- let start_row = self.scroll_position().y() as usize;
- let end_row = cmp::min(
- self.display_snapshot.max_point().row() as usize,
- start_row + (viewport_height / self.line_height(font_cache)).ceil() as usize,
- );
- let line_count = end_row - start_row + 1;
-
- let mut layouts = Vec::with_capacity(line_count);
+ let mut layouts = Vec::with_capacity(rows.len());
let mut line_number = String::new();
- for (buffer_row, soft_wrapped) in self
+ for (ix, (buffer_row, soft_wrapped)) in self
.display_snapshot
- .buffer_rows(start_row as u32)
- .take(line_count)
+ .buffer_rows(rows.start)
+ .take((rows.end - rows.start) as usize)
+ .enumerate()
{
+ let display_row = rows.start + ix as u32;
+ let color = if active_rows.contains(&display_row) {
+ theme.editor.line_number_active.0
+ } else {
+ theme.editor.line_number.0
+ };
if soft_wrapped {
layouts.push(None);
} else {
@@ -2379,7 +2386,7 @@ impl Snapshot {
layouts.push(Some(layout_cache.layout_str(
&line_number,
self.font_size,
- &[(line_number.len(), font_id, theme.editor.line_number.0)],
+ &[(line_number.len(), font_id, color)],
)));
}
}
@@ -2482,6 +2489,14 @@ impl Snapshot {
)],
))
}
+
+ pub fn prev_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
+ self.display_snapshot.prev_row_boundary(point)
+ }
+
+ pub fn next_row_boundary(&self, point: DisplayPoint) -> (DisplayPoint, Point) {
+ self.display_snapshot.next_row_boundary(point)
+ }
}
fn compute_scroll_position(
@@ -2792,7 +2807,13 @@ mod tests {
let layouts = editor.update(cx, |editor, cx| {
editor
.snapshot(cx)
- .layout_line_numbers(1000.0, &font_cache, &layout_cache, &settings.borrow().theme)
+ .layout_line_numbers(
+ 0..6,
+ &Default::default(),
+ &font_cache,
+ &layout_cache,
+ &settings.borrow().theme,
+ )
.unwrap()
});
assert_eq!(layouts.len(), 6);
@@ -14,7 +14,7 @@ use gpui::{
};
use json::json;
use smallvec::SmallVec;
-use std::{cmp::Ordering, ops::Range};
+use std::{cmp::Ordering, collections::HashSet, ops::Range};
use std::{
cmp::{self},
collections::HashMap,
@@ -387,6 +387,46 @@ impl Element for EditorElement {
(autoscroll_horizontally, snapshot)
});
+ let scroll_position = snapshot.scroll_position();
+ let start_row = scroll_position.y() as u32;
+ let scroll_top = scroll_position.y() * line_height;
+ let end_row = ((scroll_top + size.y()) / line_height).ceil() as u32 + 1; // Add 1 to ensure selections bleed off screen
+
+ let mut selections = HashMap::new();
+ let mut active_rows = HashSet::new();
+ self.update_view(cx.app, |view, cx| {
+ let replica_id = view.replica_id(cx);
+ for selection_set_id in view.active_selection_sets(cx).collect::<Vec<_>>() {
+ let mut set = Vec::new();
+ for selection in view.selections_in_range(
+ selection_set_id,
+ DisplayPoint::new(start_row, 0)..DisplayPoint::new(end_row, 0),
+ cx,
+ ) {
+ set.push(selection.clone());
+ if selection_set_id.replica_id == replica_id {
+ let mut selection_start;
+ let mut selection_end;
+ if selection.start < selection.end {
+ selection_start = selection.start;
+ selection_end = selection.end;
+ } else {
+ selection_start = selection.end;
+ selection_end = selection.start;
+ };
+ selection_start = snapshot.prev_row_boundary(selection_start).0;
+ selection_end = snapshot.next_row_boundary(selection_end).0;
+ active_rows.extend(
+ cmp::max(selection_start.row(), start_row)
+ ..=cmp::min(selection_end.row(), end_row),
+ );
+ }
+ }
+
+ selections.insert(selection_set_id.replica_id, set);
+ }
+ });
+
let line_number_layouts = if snapshot.gutter_visible {
let settings = self
.view
@@ -396,7 +436,8 @@ impl Element for EditorElement {
.settings
.borrow();
match snapshot.layout_line_numbers(
- size.y(),
+ start_row..end_row,
+ &active_rows,
cx.font_cache,
cx.text_layout_cache,
&settings.theme,
@@ -411,11 +452,6 @@ impl Element for EditorElement {
Vec::new()
};
- let scroll_position = snapshot.scroll_position();
- let start_row = scroll_position.y() as u32;
- let scroll_top = scroll_position.y() * line_height;
- let end_row = ((scroll_top + size.y()) / line_height).ceil() as u32 + 1; // Add 1 to ensure selections bleed off screen
-
let mut max_visible_line_width = 0.0;
let line_layouts = match snapshot.layout_lines(start_row..end_row, font_cache, layout_cache)
{
@@ -434,21 +470,6 @@ impl Element for EditorElement {
}
};
- let mut selections = HashMap::new();
- self.update_view(cx.app, |view, cx| {
- for selection_set_id in view.active_selection_sets(cx).collect::<Vec<_>>() {
- selections.insert(
- selection_set_id.replica_id,
- view.selections_in_range(
- selection_set_id,
- DisplayPoint::new(start_row, 0)..DisplayPoint::new(end_row, 0),
- cx,
- )
- .collect(),
- );
- }
- });
-
let mut layout = LayoutState {
size,
gutter_size,