on master help sign in
Implement cursorline (#2170)

* Implement cursorline * Binary search possible lines

commit8dc86beabd9334d013291656313cb33a88754c42 authorTobias Menzi <github@tobtobxx.net> dateMon 27 Jun 2022, 10:09 (4 years ago) parenta26943d
3 files changed+45
book/src/configuration.md+1 helix-term/src/ui/editor.rs+41 helix-view/src/editor.rs+3
book/src/configuration.md+1
@@ -37,6 +37,7 @@ hidden = false
3737| `scroll-lines` | Number of lines to scroll per scroll wheel step. | `3` |
3838| `shell` | Shell to use when running external commands. | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` |
3939| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers. | `absolute` |
40+| `cursorline` | Highlight all lines with a cursor. | `false` |
4041| `gutters` | Gutters to display: Available are `diagnostics` and `line-numbers`, note that `diagnostics` also includes other features like breakpoints | `["diagnostics", "line-numbers"]` |
4142| `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
4243| `auto-format` | Enable automatic formatting on save. | `true` |
helix-term/src/ui/editor.rs+41
@@ -112,6 +112,10 @@ impl EditorView {
112112 }
113113 }
114114
115+ if editor.config().cursorline {
116+ Self::highlight_cursorline(doc, view, surface, theme);
117+ }
118+
115119 let highlights = Self::doc_syntax_highlights(doc, view.offset, inner.height, theme);
116120 let highlights = syntax::merge(highlights, Self::doc_diagnostics_highlights(doc, theme));
117121 let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused {
@@ -686,6 +690,43 @@ impl EditorView {
686690 );
687691 }
688692
693+ /// Apply the highlighting on the lines where a cursor is active
694+ pub fn highlight_cursorline(doc: &Document, view: &View, surface: &mut Surface, theme: &Theme) {
695+ let text = doc.text().slice(..);
696+ let last_line = view.last_line(doc);
697+
698+ let primary_line = doc.selection(view.id).primary().cursor_line(text);
699+
700+ // The secondary_lines do contain the primary_line, it doesn't matter
701+ // as the else-if clause in the loop later won't test for the
702+ // secondary_lines if primary_line == line.
703+ // It's used inside a loop so the collect isn't needless:
704+ // https://github.com/rust-lang/rust-clippy/issues/6164
705+ #[allow(clippy::needless_collect)]
706+ let secondary_lines: Vec<_> = doc
707+ .selection(view.id)
708+ .iter()
709+ .map(|range| range.cursor_line(text))
710+ .collect();
711+
712+ let primary_style = theme.get("ui.cursorline.primary");
713+ let secondary_style = theme.get("ui.cursorline.secondary");
714+
715+ for line in view.offset.row..(last_line + 1) {
716+ let area = Rect::new(
717+ view.area.x,
718+ view.area.y + (line - view.offset.row) as u16,
719+ view.area.width,
720+ 1,
721+ );
722+ if primary_line == line {
723+ surface.set_style(area, primary_style);
724+ } else if secondary_lines.binary_search(&line).is_ok() {
725+ surface.set_style(area, secondary_style);
726+ }
727+ }
728+ }
729+
689730 pub fn render_statusline(
690731 &self,
691732 doc: &Document,
helix-view/src/editor.rs+3
@@ -121,6 +121,8 @@ pub struct Config {
121121 pub shell: Vec<String>,
122122 /// Line number mode.
123123 pub line_number: LineNumber,
124+ /// Highlight the lines cursors are currently on. Defaults to false.
125+ pub cursorline: bool,
124126 /// Gutters. Default ["diagnostics", "line-numbers"]
125127 pub gutters: Vec<GutterType>,
126128 /// Middle click paste support. Defaults to true.
@@ -394,6 +396,7 @@ impl Default for Config {
394396 vec!["sh".to_owned(), "-c".to_owned()]
395397 },
396398 line_number: LineNumber::Absolute,
399+ cursorline: false,
397400 gutters: vec![GutterType::Diagnostics, GutterType::LineNumbers],
398401 middle_click_paste: true,
399402 auto_pairs: AutoPairConfig::default(),