aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/ui/editor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src/ui/editor.rs')
-rw-r--r--helix-term/src/ui/editor.rs160
1 files changed, 60 insertions, 100 deletions
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 98462e26..21e6cd9b 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -38,8 +38,6 @@ pub struct EditorView {
autoinfo: Option<Info>,
}
-pub const GUTTER_OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
-
impl Default for EditorView {
fn default() -> Self {
Self::new(Keymaps::default())
@@ -74,15 +72,10 @@ impl EditorView {
loader: &syntax::Loader,
config: &helix_view::editor::Config,
) {
- let area = Rect::new(
- view.area.x + GUTTER_OFFSET,
- view.area.y,
- view.area.width - GUTTER_OFFSET,
- view.area.height.saturating_sub(1),
- ); // - 1 for statusline
- let height = view.area.height.saturating_sub(1); // - 1 for statusline
-
- let highlights = Self::doc_syntax_highlights(doc, view.offset, height, theme, loader);
+ let inner = view.inner_area();
+ let area = view.area;
+
+ let highlights = Self::doc_syntax_highlights(doc, view.offset, inner.height, theme, loader);
let highlights = syntax::merge(highlights, Self::doc_diagnostics_highlights(doc, theme));
let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused {
Box::new(syntax::merge(
@@ -93,11 +86,11 @@ impl EditorView {
Box::new(highlights)
};
- Self::render_text_highlights(doc, view.offset, area, surface, theme, highlights);
- Self::render_gutter(doc, view, area, surface, theme, config);
+ Self::render_text_highlights(doc, view.offset, inner, surface, theme, highlights);
+ Self::render_gutter(doc, view, view.area, surface, theme, is_focused, config);
if is_focused {
- Self::render_focused_view_elements(view, doc, area, theme, surface);
+ Self::render_focused_view_elements(view, doc, inner, theme, surface);
}
// if we're not at the edge of the screen, draw a right border
@@ -113,7 +106,7 @@ impl EditorView {
}
}
- self.render_diagnostics(doc, view, area, surface, theme);
+ self.render_diagnostics(doc, view, inner, surface, theme);
let area = Rect::new(
view.area.x,
@@ -369,7 +362,7 @@ impl EditorView {
}
}
- /// Render brace match, selected line numbers, etc (meant for the focused view only)
+ /// Render brace match, etc (meant for the focused view only)
pub fn render_focused_view_elements(
view: &View,
doc: &Document,
@@ -377,77 +370,29 @@ impl EditorView {
theme: &Theme,
surface: &mut Surface,
) {
- let text = doc.text().slice(..);
- let selection = doc.selection(view.id);
- let last_line = view.last_line(doc);
- let screen = {
- let start = text.line_to_char(view.offset.row);
- let end = text.line_to_char(last_line + 1) + 1; // +1 for cursor at end of text.
- Range::new(start, end)
- };
-
- // render selected linenr(s)
- let linenr_select: Style = theme
- .try_get("ui.linenr.selected")
- .unwrap_or_else(|| theme.get("ui.linenr"));
-
- // Whether to draw the line number for the last line of the
- // document or not. We only draw it if it's not an empty line.
- let draw_last = text.line_to_byte(last_line) < text.len_bytes();
-
- for selection in selection.iter().filter(|range| range.overlaps(&screen)) {
- let head = view.screen_coords_at_pos(
- doc,
- text,
- if selection.head > selection.anchor {
- selection.head - 1
- } else {
- selection.head
- },
- );
- if let Some(head) = head {
- // Highlight line number for selected lines.
- let line_number = view.offset.row + head.row;
- let line_number_text = if line_number == last_line && !draw_last {
- " ~".into()
- } else {
- format!("{:>5}", line_number + 1)
- };
- surface.set_stringn(
- viewport.x - GUTTER_OFFSET + 1,
- viewport.y + head.row as u16,
- line_number_text,
- 5,
- linenr_select,
- );
+ // Highlight matching braces
+ if let Some(syntax) = doc.syntax() {
+ let text = doc.text().slice(..);
+ use helix_core::match_brackets;
+ let pos = doc.selection(view.id).primary().cursor(text);
+
+ let pos = match_brackets::find(syntax, doc.text(), pos)
+ .and_then(|pos| view.screen_coords_at_pos(doc, text, pos));
+
+ if let Some(pos) = pos {
+ // ensure col is on screen
+ if (pos.col as u16) < viewport.width + view.offset.col as u16
+ && pos.col >= view.offset.col
+ {
+ let style = theme.try_get("ui.cursor.match").unwrap_or_else(|| {
+ Style::default()
+ .add_modifier(Modifier::REVERSED)
+ .add_modifier(Modifier::DIM)
+ });
- // Highlight matching braces
- // TODO: set cursor position for IME
- if let Some(syntax) = doc.syntax() {
- use helix_core::match_brackets;
- let pos = doc
- .selection(view.id)
- .primary()
- .cursor(doc.text().slice(..));
- let pos = match_brackets::find(syntax, doc.text(), pos)
- .and_then(|pos| view.screen_coords_at_pos(doc, text, pos));
-
- if let Some(pos) = pos {
- // ensure col is on screen
- if (pos.col as u16) < viewport.width + view.offset.col as u16
- && pos.col >= view.offset.col
- {
- let style = theme.try_get("ui.cursor.match").unwrap_or_else(|| {
- Style::default()
- .add_modifier(Modifier::REVERSED)
- .add_modifier(Modifier::DIM)
- });
-
- surface
- .get_mut(viewport.x + pos.col as u16, viewport.y + pos.row as u16)
- .set_style(style);
- }
- }
+ surface
+ .get_mut(viewport.x + pos.col as u16, viewport.y + pos.row as u16)
+ .set_style(style);
}
}
}
@@ -460,12 +405,15 @@ impl EditorView {
viewport: Rect,
surface: &mut Surface,
theme: &Theme,
+ is_focused: bool,
config: &helix_view::editor::Config,
) {
let text = doc.text().slice(..);
let last_line = view.last_line(doc);
let linenr = theme.get("ui.linenr");
+ let linenr_select: Style = theme.try_get("ui.linenr.selected").unwrap_or(linenr);
+
let warning = theme.get("warning");
let error = theme.get("error");
let info = theme.get("info");
@@ -478,11 +426,21 @@ impl EditorView {
let current_line = doc
.text()
.char_to_line(doc.selection(view.id).primary().anchor);
+
+ // it's used inside an iterator so the collect isn't needless:
+ // https://github.com/rust-lang/rust-clippy/issues/6164
+ #[allow(clippy::clippy::needless_collect)]
+ let cursors: Vec<_> = doc
+ .selection(view.id)
+ .iter()
+ .map(|range| range.cursor_line(text))
+ .collect();
+
for (i, line) in (view.offset.row..(last_line + 1)).enumerate() {
use helix_core::diagnostic::Severity;
if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) {
surface.set_stringn(
- viewport.x - GUTTER_OFFSET,
+ viewport.x,
viewport.y + i as u16,
"●",
1,
@@ -495,25 +453,27 @@ impl EditorView {
);
}
- // Line numbers having selections are rendered
- // differently, further below.
- let line_number_text = if line == last_line && !draw_last {
+ let selected = cursors.contains(&line);
+
+ let text = if line == last_line && !draw_last {
" ~".into()
} else {
- match config.line_number {
- LineNumber::Absolute => format!("{:>5}", line + 1),
- LineNumber::Relative => {
- let relative_line = abs_diff(current_line, line);
- format!("{:>5}", relative_line)
- }
- }
+ let line = match config.line_number {
+ LineNumber::Absolute => line + 1,
+ LineNumber::Relative => abs_diff(current_line, line),
+ };
+ format!("{:>5}", line)
};
surface.set_stringn(
- viewport.x + 1 - GUTTER_OFFSET,
+ viewport.x + 1,
viewport.y + i as u16,
- line_number_text,
+ text,
5,
- linenr,
+ if selected && is_focused {
+ linenr_select
+ } else {
+ linenr
+ },
);
}
}