on master help sign in
Revert "Fix precedence of ui.virtual.whitespace (#8750)"
811d62dBlaž Hrastnik
helix-term/src/ui/document.rs+24−60
@@ -97,8 +97,7 @@ pub fn render_document(
97 doc: &Document,
97 doc: &Document,
98 offset: ViewPosition,
98 offset: ViewPosition,
99 doc_annotations: &TextAnnotations,
99 doc_annotations: &TextAnnotations,
100− syntax_highlight_iter: impl Iterator<Item = HighlightEvent>,
101− overlay_highlight_iter: impl Iterator<Item = HighlightEvent>,
100+ highlight_iter: impl Iterator<Item = HighlightEvent>,
102 theme: &Theme,
101 theme: &Theme,
103 line_decoration: &mut [Box<dyn LineDecoration + '_>],
102 line_decoration: &mut [Box<dyn LineDecoration + '_>],
104 translated_positions: &mut [TranslatedPosition],
103 translated_positions: &mut [TranslatedPosition],
@@ -110,8 +109,7 @@ pub fn render_document(
110 offset,
109 offset,
111 &doc.text_format(viewport.width, Some(theme)),
110 &doc.text_format(viewport.width, Some(theme)),
112 doc_annotations,
111 doc_annotations,
113− syntax_highlight_iter,
112+ highlight_iter,
114− overlay_highlight_iter,
115 theme,
113 theme,
116 line_decoration,
114 line_decoration,
117 translated_positions,
115 translated_positions,
@@ -159,8 +157,7 @@ pub fn render_text<'t>(
159 offset: ViewPosition,
157 offset: ViewPosition,
160 text_fmt: &TextFormat,
158 text_fmt: &TextFormat,
161 text_annotations: &TextAnnotations,
159 text_annotations: &TextAnnotations,
162− syntax_highlight_iter: impl Iterator<Item = HighlightEvent>,
163− overlay_highlight_iter: impl Iterator<Item = HighlightEvent>,
160+ highlight_iter: impl Iterator<Item = HighlightEvent>,
164 theme: &Theme,
161 theme: &Theme,
165 line_decorations: &mut [Box<dyn LineDecoration + '_>],
162 line_decorations: &mut [Box<dyn LineDecoration + '_>],
166 translated_positions: &mut [TranslatedPosition],
163 translated_positions: &mut [TranslatedPosition],
@@ -181,16 +178,10 @@ pub fn render_text<'t>(
181
178
182 let (mut formatter, mut first_visible_char_idx) =
179 let (mut formatter, mut first_visible_char_idx) =
183 DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, text_annotations, offset.anchor);
180 DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, text_annotations, offset.anchor);
184− let mut syntax_styles = StyleIter {
181+ let mut styles = StyleIter {
185 text_style: renderer.text_style,
182 text_style: renderer.text_style,
186 active_highlights: Vec::with_capacity(64),
183 active_highlights: Vec::with_capacity(64),
187− highlight_iter: syntax_highlight_iter,
184+ highlight_iter,
188− theme,
189− };
190− let mut overlay_styles = StyleIter {
191− text_style: renderer.text_style,
192− active_highlights: Vec::with_capacity(64),
193− highlight_iter: overlay_highlight_iter,
194 theme,
185 theme,
195 };
186 };
196
187
@@ -202,10 +193,7 @@ pub fn render_text<'t>(
202 };
193 };
203 let mut is_in_indent_area = true;
194 let mut is_in_indent_area = true;
204 let mut last_line_indent_level = 0;
195 let mut last_line_indent_level = 0;
205− let mut syntax_style_span = syntax_styles
196+ let mut style_span = styles
206− .next()
207− .unwrap_or_else(|| (Style::default(), usize::MAX));
208− let mut overlay_style_span = overlay_styles
209 .next()
197 .next()
210 .unwrap_or_else(|| (Style::default(), usize::MAX));
198 .unwrap_or_else(|| (Style::default(), usize::MAX));
211
199
@@ -233,16 +221,9 @@ pub fn render_text<'t>(
233
221
234 // skip any graphemes on visual lines before the block start
222 // skip any graphemes on visual lines before the block start
235 if pos.row < row_off {
223 if pos.row < row_off {
236− if char_pos >= syntax_style_span.1 {
224+ if char_pos >= style_span.1 {
237− syntax_style_span = if let Some(syntax_style_span) = syntax_styles.next() {
225+ style_span = if let Some(style_span) = styles.next() {
238− syntax_style_span
226+ style_span
239− } else {
240− break;
241− }
242− }
243− if char_pos >= overlay_style_span.1 {
244− overlay_style_span = if let Some(overlay_style_span) = overlay_styles.next() {
245− overlay_style_span
246 } else {
227 } else {
247 break;
228 break;
248 }
229 }
@@ -279,15 +260,8 @@ pub fn render_text<'t>(
279 }
260 }
280
261
281 // acquire the correct grapheme style
262 // acquire the correct grapheme style
282− if char_pos >= syntax_style_span.1 {
263+ if char_pos >= style_span.1 {
283− syntax_style_span = syntax_styles
284− .next()
285− .unwrap_or((Style::default(), usize::MAX));
286− }
287− if char_pos >= overlay_style_span.1 {
288− overlay_style_span = overlay_styles
289− .next()
290− .unwrap_or((Style::default(), usize::MAX));
264+ style_span = styles.next().unwrap_or((Style::default(), usize::MAX));
291 }
265 }
292 char_pos += grapheme.doc_chars();
266 char_pos += grapheme.doc_chars();
293
267
@@ -301,25 +275,22 @@ pub fn render_text<'t>(
301 pos,
275 pos,
302 );
276 );
303
277
304− let (syntax_style, overlay_style) =
305− if let GraphemeSource::VirtualText { highlight } = grapheme.source {
278+ let grapheme_style = if let GraphemeSource::VirtualText { highlight } = grapheme.source {
306− let mut style = renderer.text_style;
279+ let style = renderer.text_style;
307− if let Some(highlight) = highlight {
280+ if let Some(highlight) = highlight {
308− style = style.patch(theme.highlight(highlight.0))
281+ style.patch(theme.highlight(highlight.0))
309− }
310− (style, Style::default())
311 } else {
282 } else {
312− (syntax_style_span.0, overlay_style_span.0)
283+ style
284+ }
285+ } else {
286+ style_span.0
313− };
287+ };
314
288
315− let is_virtual = grapheme.is_virtual();
289+ let virt = grapheme.is_virtual();
316 renderer.draw_grapheme(
290 renderer.draw_grapheme(
317 grapheme.grapheme,
291 grapheme.grapheme,
318− GraphemeStyle {
292+ grapheme_style,
319− syntax_style,
293+ virt,
320− overlay_style,
321− },
322− is_virtual,
323 &mut last_line_indent_level,
294 &mut last_line_indent_level,
324 &mut is_in_indent_area,
295 &mut is_in_indent_area,
325 pos,
296 pos,
@@ -351,11 +322,6 @@ pub struct TextRenderer<'a> {
351 pub viewport: Rect,
322 pub viewport: Rect,
352}
323}
353
324
354−pub struct GraphemeStyle {
355− syntax_style: Style,
356− overlay_style: Style,
357−}
358−
359impl<'a> TextRenderer<'a> {
325impl<'a> TextRenderer<'a> {
360 pub fn new(
326 pub fn new(
361 surface: &'a mut Surface,
327 surface: &'a mut Surface,
@@ -429,7 +395,7 @@ impl<'a> TextRenderer<'a> {
429 pub fn draw_grapheme(
395 pub fn draw_grapheme(
430 &mut self,
396 &mut self,
431 grapheme: Grapheme,
397 grapheme: Grapheme,
432− grapheme_style: GraphemeStyle,
398+ mut style: Style,
433 is_virtual: bool,
399 is_virtual: bool,
434 last_indent_level: &mut usize,
400 last_indent_level: &mut usize,
435 is_in_indent_area: &mut bool,
401 is_in_indent_area: &mut bool,
@@ -439,11 +405,9 @@ impl<'a> TextRenderer<'a> {
439 let is_whitespace = grapheme.is_whitespace();
405 let is_whitespace = grapheme.is_whitespace();
440
406
441 // TODO is it correct to apply the whitespace style to all unicode white spaces?
407 // TODO is it correct to apply the whitespace style to all unicode white spaces?
442− let mut style = grapheme_style.syntax_style;
443 if is_whitespace {
408 if is_whitespace {
444 style = style.patch(self.whitespace_style);
409 style = style.patch(self.whitespace_style);
445 }
410 }
446− style = style.patch(grapheme_style.overlay_style);
447
411
448 let width = grapheme.width();
412 let width = grapheme.width();
449 let space = if is_virtual { " " } else { &self.space };
413 let space = if is_virtual { " " } else { &self.space };
helix-term/src/ui/editor.rs+38−58
@@ -124,20 +124,16 @@ impl EditorView {
124 line_decorations.push(Box::new(line_decoration));
124 line_decorations.push(Box::new(line_decoration));
125 }
125 }
126
126
127− let syntax_highlights =
127+ let mut highlights =
128 Self::doc_syntax_highlights(doc, view.offset.anchor, inner.height, theme);
128 Self::doc_syntax_highlights(doc, view.offset.anchor, inner.height, theme);
129−
130− let mut overlay_highlights =
129+ let overlay_highlights = Self::overlay_syntax_highlights(
131− Self::empty_highlight_iter(doc, view.offset.anchor, inner.height);
132− let overlay_syntax_highlights = Self::overlay_syntax_highlights(
133 doc,
130 doc,
134 view.offset.anchor,
131 view.offset.anchor,
135 inner.height,
132 inner.height,
136 &text_annotations,
133 &text_annotations,
137 );
134 );
138− if !overlay_syntax_highlights.is_empty() {
135+ if !overlay_highlights.is_empty() {
139− overlay_highlights =
136+ highlights = Box::new(syntax::merge(highlights, overlay_highlights));
140− Box::new(syntax::merge(overlay_highlights, overlay_syntax_highlights));
141 }
137 }
142
138
143 for diagnostic in Self::doc_diagnostics_highlights(doc, theme) {
139 for diagnostic in Self::doc_diagnostics_highlights(doc, theme) {
@@ -146,12 +142,12 @@ impl EditorView {
146 if diagnostic.is_empty() {
142 if diagnostic.is_empty() {
147 continue;
143 continue;
148 }
144 }
149− overlay_highlights = Box::new(syntax::merge(overlay_highlights, diagnostic));
145+ highlights = Box::new(syntax::merge(highlights, diagnostic));
150 }
146 }
151
147
152− if is_focused {
148+ let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused {
153 let highlights = syntax::merge(
149 let highlights = syntax::merge(
154− overlay_highlights,
150+ highlights,
155 Self::doc_selection_highlights(
151 Self::doc_selection_highlights(
156 editor.mode(),
152 editor.mode(),
157 doc,
153 doc,
@@ -162,11 +158,13 @@ impl EditorView {
162 );
158 );
163 let focused_view_elements = Self::highlight_focused_view_elements(view, doc, theme);
159 let focused_view_elements = Self::highlight_focused_view_elements(view, doc, theme);
164 if focused_view_elements.is_empty() {
160 if focused_view_elements.is_empty() {
165− overlay_highlights = Box::new(highlights)
161+ Box::new(highlights)
166 } else {
162 } else {
167− overlay_highlights = Box::new(syntax::merge(highlights, focused_view_elements))
163+ Box::new(syntax::merge(highlights, focused_view_elements))
168 }
164 }
169− }
165+ } else {
166+ Box::new(highlights)
167+ };
170
168
171 let gutter_overflow = view.gutter_offset(doc) == 0;
169 let gutter_overflow = view.gutter_offset(doc) == 0;
172 if !gutter_overflow {
170 if !gutter_overflow {
@@ -199,8 +197,7 @@ impl EditorView {
199 doc,
197 doc,
200 view.offset,
198 view.offset,
201 &text_annotations,
199 &text_annotations,
202− syntax_highlights,
200+ highlights,
203− overlay_highlights,
204 theme,
201 theme,
205 &mut line_decorations,
202 &mut line_decorations,
206 &mut translated_positions,
203 &mut translated_positions,
@@ -260,39 +257,27 @@ impl EditorView {
260 .for_each(|area| surface.set_style(area, ruler_theme))
257 .for_each(|area| surface.set_style(area, ruler_theme))
261 }
258 }
262
259
263− fn viewport_byte_range(
260+ pub fn overlay_syntax_highlights(
264− text: helix_core::RopeSlice,
265− row: usize,
266− height: u16,
267− ) -> std::ops::Range<usize> {
268− // Calculate viewport byte ranges:
269− // Saturating subs to make it inclusive zero indexing.
270− let last_line = text.len_lines().saturating_sub(1);
271− let last_visible_line = (row + height as usize).saturating_sub(1).min(last_line);
272− let start = text.line_to_byte(row.min(last_line));
273− let end = text.line_to_byte(last_visible_line + 1);
274−
275− start..end
276− }
277−
278− pub fn empty_highlight_iter(
279 doc: &Document,
261 doc: &Document,
280 anchor: usize,
262 anchor: usize,
281 height: u16,
263 height: u16,
282− ) -> Box<dyn Iterator<Item = HighlightEvent>> {
264+ text_annotations: &TextAnnotations,
265+ ) -> Vec<(usize, std::ops::Range<usize>)> {
283 let text = doc.text().slice(..);
266 let text = doc.text().slice(..);
284 let row = text.char_to_line(anchor.min(text.len_chars()));
267 let row = text.char_to_line(anchor.min(text.len_chars()));
285
268
269+ let range = {
286− // Calculate viewport byte ranges:
270+ // Calculate viewport byte ranges:
287− // Saturating subs to make it inclusive zero indexing.
271+ // Saturating subs to make it inclusive zero indexing.
288− let range = Self::viewport_byte_range(text, row, height);
272+ let last_line = text.len_lines().saturating_sub(1);
289− Box::new(
273+ let last_visible_line = (row + height as usize).saturating_sub(1).min(last_line);
290− [HighlightEvent::Source {
274+ let start = text.line_to_byte(row.min(last_line));
291− start: text.byte_to_char(range.start),
275+ let end = text.line_to_byte(last_visible_line + 1);
292− end: text.byte_to_char(range.end),
276+
277+ start..end
293− }]
278+ };
294− .into_iter(),
279+
295− )
280+ text_annotations.collect_overlay_highlights(range)
296 }
281 }
297
282
298 /// Get syntax highlights for a document in a view represented by the first line
283 /// Get syntax highlights for a document in a view represented by the first line
@@ -307,7 +292,16 @@ impl EditorView {
307 let text = doc.text().slice(..);
292 let text = doc.text().slice(..);
308 let row = text.char_to_line(anchor.min(text.len_chars()));
293 let row = text.char_to_line(anchor.min(text.len_chars()));
309
294
310− let range = Self::viewport_byte_range(text, row, height);
295+ let range = {
296+ // Calculate viewport byte ranges:
297+ // Saturating subs to make it inclusive zero indexing.
298+ let last_line = text.len_lines().saturating_sub(1);
299+ let last_visible_line = (row + height as usize).saturating_sub(1).min(last_line);
300+ let start = text.line_to_byte(row.min(last_line));
301+ let end = text.line_to_byte(last_visible_line + 1);
302+
303+ start..end
304+ };
311
305
312 match doc.syntax() {
306 match doc.syntax() {
313 Some(syntax) => {
307 Some(syntax) => {
@@ -340,20 +334,6 @@ impl EditorView {
340 }
334 }
341 }
335 }
342
336
343− pub fn overlay_syntax_highlights(
344− doc: &Document,
345− anchor: usize,
346− height: u16,
347− text_annotations: &TextAnnotations,
348− ) -> Vec<(usize, std::ops::Range<usize>)> {
349− let text = doc.text().slice(..);
350− let row = text.char_to_line(anchor.min(text.len_chars()));
351−
352− let range = Self::viewport_byte_range(text, row, height);
353−
354− text_annotations.collect_overlay_highlights(range)
355− }
356−
357 /// Get highlight spans for document diagnostics
337 /// Get highlight spans for document diagnostics
358 pub fn doc_diagnostics_highlights(
338 pub fn doc_diagnostics_highlights(
359 doc: &Document,
339 doc: &Document,
helix-term/src/ui/picker.rs+3−7
@@ -736,20 +736,17 @@ impl<T: Item + 'static> Picker<T> {
736 }
736 }
737 }
737 }
738
738
739− let syntax_highlights = EditorView::doc_syntax_highlights(
739+ let mut highlights = EditorView::doc_syntax_highlights(
740 doc,
740 doc,
741 offset.anchor,
741 offset.anchor,
742 area.height,
742 area.height,
743 &cx.editor.theme,
743 &cx.editor.theme,
744 );
744 );
745−
746− let mut overlay_highlights =
747− EditorView::empty_highlight_iter(doc, offset.anchor, area.height);
748 for spans in EditorView::doc_diagnostics_highlights(doc, &cx.editor.theme) {
745 for spans in EditorView::doc_diagnostics_highlights(doc, &cx.editor.theme) {
749 if spans.is_empty() {
746 if spans.is_empty() {
750 continue;
747 continue;
751 }
748 }
752− overlay_highlights = Box::new(helix_core::syntax::merge(overlay_highlights, spans));
749+ highlights = Box::new(helix_core::syntax::merge(highlights, spans));
753 }
750 }
754 let mut decorations: Vec<Box<dyn LineDecoration>> = Vec::new();
751 let mut decorations: Vec<Box<dyn LineDecoration>> = Vec::new();
755
752
@@ -780,8 +777,7 @@ impl<T: Item + 'static> Picker<T> {
780 offset,
777 offset,
781 // TODO: compute text annotations asynchronously here (like inlay hints)
778 // TODO: compute text annotations asynchronously here (like inlay hints)
782 &TextAnnotations::default(),
779 &TextAnnotations::default(),
783− syntax_highlights,
780+ highlights,
784− overlay_highlights,
785 &cx.editor.theme,
781 &cx.editor.theme,
786 &mut decorations,
782 &mut decorations,
787 &mut [],
783 &mut [],