From a4aaf6bb33fd80b31fe4442b4bf5ad33191f11b1 Mon Sep 17 00:00:00 2001 From: SoraTenshi Date: Mon, 27 Feb 2023 15:28:52 +0100 Subject: [PATCH] Add simple explanation of how to continue Some improvements --- helix-term/src/ui/editor.rs | 120 ++++++++++++++++++++++-------------- languages.toml | 1 + 2 files changed, 76 insertions(+), 45 deletions(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index cbe027cea..c11c030dd 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -22,7 +22,7 @@ use helix_core::{ }; use helix_view::{ document::{Mode, SCRATCH_BUFFER_NAME}, - editor::{CompleteAction, CursorShapeConfig, LineNumber}, + editor::{CompleteAction, CursorShapeConfig}, graphics::{Color, CursorKind, Modifier, Rect, Style}, input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind}, keyboard::{KeyCode, KeyModifiers}, @@ -44,6 +44,13 @@ pub struct EditorView { spinners: ProgressSpinners, } +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] +pub struct StickyNode { + line_nr: usize, + start_byte: usize, + end_byte: usize, +} + #[derive(Debug, Clone)] pub enum InsertEvent { Key(KeyEvent), @@ -175,6 +182,12 @@ impl EditorView { Box::new(highlights) }; + let context = Self::calculate_sticky_nodes( + doc, + view, + &config + ); + if is_focused { let cursor = doc .selection(view.id) @@ -202,17 +215,16 @@ impl EditorView { ); if config.sticky_context { - let _line_nr = Self::render_sticky_context( - editor, + Self::render_sticky_context( doc, view, surface, + context, &text_annotations, &mut line_decorations, &mut translated_positions, theme, - ) - .unwrap_or_default(); + ); } Self::render_rulers(editor, doc, view, inner, surface, theme); @@ -703,22 +715,31 @@ impl EditorView { ); } - /// Render the sticky context - pub fn render_sticky_context( - editor: &Editor, + pub fn calculate_sticky_nodes( doc: &Document, view: &View, - surface: &mut Surface, - doc_annotations: &TextAnnotations, - line_decoration: &mut [Box], - translated_positions: &mut [TranslatedPosition], - theme: &Theme, - ) -> Option> { + config: &helix_view::editor::Config, + ) -> Option> { + if !config.sticky_context { + return None; + } + //TODO: split up to own logic, before it is actually rendered + // Having a pipeline there would vastly improve usability + reusability + // basically do the following pipeline: + // calculate contexts, that are required + // -> pass line numbers to gutter renderer + // -> pass to initial render document state, which doesn't render + // the reserved space + // -> and now finally render the contextes + // this might lead to solving the issue with the cursor as well as the logic is split + // maybe it's also a good idea to summarize nodes that should be together + + let syntax = doc.syntax()?; let tree = syntax.tree(); let text = doc.text().slice(..); let viewport = view.inner_area(doc); - let top_byte = text.char_to_byte(view.offset.anchor); + let top_first_byte = text.char_to_byte(view.offset.anchor); let context_nodes = doc .language_config() @@ -726,11 +747,11 @@ impl EditorView { let mut parent = tree .root_node() - .descendant_for_byte_range(top_byte, top_byte) + .descendant_for_byte_range(top_first_byte, top_first_byte) .and_then(|n| n.parent()); // context is list of numbers of lines that should be rendered in the LSP context - let mut context: Vec = Vec::new(); + let mut context: Vec = Vec::new(); while let Some(node) = parent { // if the node is smaller than half the viewport height, skip @@ -743,45 +764,70 @@ impl EditorView { let line = text.byte_to_line(node.start_byte()); // if parent of previous node is still on the same line, use the parent node - // or if the parent of previous node overlaps with the current node if let Some(&prev_line) = context.last() { - if prev_line == line { + if prev_line.line_nr == line { context.pop(); } } if context_nodes.map_or(true, |nodes| nodes.iter().any(|n| n == node.kind())) { - context.push(line); + context.push(StickyNode { + line_nr: line, + start_byte: node.start_byte(), + end_byte: node.end_byte(), + }); } parent = node.parent(); } + // context should be filled by now + if context.is_empty() { + return None; + } + // we render from top most (last in the list) context.reverse(); // allow a maximum of half the viewport height // to be occupied by the sticky context - if context.len() > viewport.height as usize / 2 { - context = context - .into_iter() - .take(viewport.height as usize / 2) - .collect(); + context = context.into_iter().take(viewport.height as usize / 2).collect(); + + Some(context) + } + + /// Render the sticky context + pub fn render_sticky_context( + doc: &Document, + view: &View, + surface: &mut Surface, + context: Option>, + doc_annotations: &TextAnnotations, + line_decoration: &mut [Box], + translated_positions: &mut [TranslatedPosition], + theme: &Theme, + ) { + if context.is_none() { + return; } + let context = context.expect("context has value"); + + let text = doc.text().slice(..); + let viewport = view.inner_area(doc); + // TODO: this probably needs it's own style, although it seems to work well even with cursorline let context_style = theme.get("ui.cursorline.primary"); let mut context_area = viewport; context_area.height = 1; - let mut line_numbers = Vec::new(); - - for line_num in &context { - let line_num_anchor = text.line_to_char(*line_num); + for node in context { + let line_num_anchor = text.line_to_char(node.line_nr); surface.clear_with(context_area, context_style); + // get all highlights from the latest points let highlights = Self::doc_syntax_highlights(doc, line_num_anchor, 1, theme); let mut renderer = TextRenderer::new( @@ -808,23 +854,7 @@ impl EditorView { ); context_area.y += 1; - let line_number = match editor.config().line_number { - LineNumber::Absolute => *line_num, - LineNumber::Relative => { - if editor.mode() == Mode::Insert { - *line_num - } else { - let res = top_byte - *line_num; - match res { - n if n < 2 => 1, - _ => res - 1, - } - } - } - }; - line_numbers.push(line_number); } - Some(line_numbers) } /// Apply the highlighting on the lines where a cursor is active diff --git a/languages.toml b/languages.toml index aade6bf26..78dfd50a9 100644 --- a/languages.toml +++ b/languages.toml @@ -11,6 +11,7 @@ auto-format = true comment-token = "//" language-server = { command = "rust-analyzer" } indent = { tab-width = 4, unit = " " } +sticky-context-nodes = ["impl_item", "function_item", "struct_item", "enum_item", "match_expression", "match_arm", "let_declaration"] [language.auto-pairs] '(' = ')'