Add simple explanation of how to continue

Some improvements
pull/6118/merge^2
SoraTenshi 1 year ago
parent 37c8df5f5c
commit a4aaf6bb33

@ -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<dyn LineDecoration + '_>],
translated_positions: &mut [TranslatedPosition],
theme: &Theme,
) -> Option<Vec<usize>> {
config: &helix_view::editor::Config,
) -> Option<Vec<StickyNode>> {
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<usize> = Vec::new();
let mut context: Vec<StickyNode> = 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<Vec<StickyNode>>,
doc_annotations: &TextAnnotations,
line_decoration: &mut [Box<dyn LineDecoration + '_>],
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

@ -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]
'(' = ')'

Loading…
Cancel
Save