feat: relative numbers (#485)

* feat(helix-view): configuring line-number

* feat(helix-term): relative line numbers

* feat(helix-term): passing editor::Config to render

* fix(helix-view): remove LineNumber::None

* feat(helix-term): rendering line-number according to configuration

* fix(term): put calculating current line above line iteration

* fix: add abs_diff function

* deps: cargo update

* fix: pass config argument
imgbot
Grzegorz Baranski 3 years ago committed by GitHub
parent aaccc9419a
commit 78923496a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -17,6 +17,7 @@ use helix_core::{
}; };
use helix_view::{ use helix_view::{
document::Mode, document::Mode,
editor::LineNumber,
graphics::{CursorKind, Modifier, Rect, Style}, graphics::{CursorKind, Modifier, Rect, Style},
info::Info, info::Info,
input::KeyEvent, input::KeyEvent,
@ -71,6 +72,7 @@ impl EditorView {
theme: &Theme, theme: &Theme,
is_focused: bool, is_focused: bool,
loader: &syntax::Loader, loader: &syntax::Loader,
config: &helix_view::editor::Config,
) { ) {
let area = Rect::new( let area = Rect::new(
view.area.x + GUTTER_OFFSET, view.area.x + GUTTER_OFFSET,
@ -93,7 +95,7 @@ impl EditorView {
}; };
Self::render_text_highlights(doc, offset, area, surface, theme, highlights); Self::render_text_highlights(doc, offset, area, surface, theme, highlights);
Self::render_gutter(doc, view, area, surface, theme); Self::render_gutter(doc, view, area, surface, theme, config);
if is_focused { if is_focused {
Self::render_focused_view_elements(view, doc, area, theme, surface); Self::render_focused_view_elements(view, doc, area, theme, surface);
@ -459,6 +461,7 @@ impl EditorView {
viewport: Rect, viewport: Rect,
surface: &mut Surface, surface: &mut Surface,
theme: &Theme, theme: &Theme,
config: &helix_view::editor::Config,
) { ) {
let text = doc.text().slice(..); let text = doc.text().slice(..);
let last_line = view.last_line(doc); let last_line = view.last_line(doc);
@ -473,6 +476,9 @@ impl EditorView {
// document or not. We only draw it if it's not an empty line. // 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(); let draw_last = text.line_to_byte(last_line) < text.len_bytes();
let current_line = doc
.text()
.char_to_line(doc.selection(view.id).primary().anchor);
for (i, line) in (view.first_line..(last_line + 1)).enumerate() { for (i, line) in (view.first_line..(last_line + 1)).enumerate() {
use helix_core::diagnostic::Severity; use helix_core::diagnostic::Severity;
if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) { if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) {
@ -495,7 +501,13 @@ impl EditorView {
let line_number_text = if line == last_line && !draw_last { let line_number_text = if line == last_line && !draw_last {
" ~".into() " ~".into()
} else { } else {
format!("{:>5}", line + 1) match config.line_number {
LineNumber::Absolute => format!("{:>5}", line + 1),
LineNumber::Relative => {
let relative_line = abs_diff(current_line, line);
format!("{:>5}", relative_line)
}
}
}; };
surface.set_stringn( surface.set_stringn(
viewport.x + 1 - GUTTER_OFFSET, viewport.x + 1 - GUTTER_OFFSET,
@ -1042,6 +1054,7 @@ impl Component for EditorView {
&cx.editor.theme, &cx.editor.theme,
is_focused, is_focused,
loader, loader,
&cx.editor.config,
); );
} }
@ -1115,3 +1128,12 @@ fn canonicalize_key(key: &mut KeyEvent) {
key.modifiers.remove(KeyModifiers::SHIFT) key.modifiers.remove(KeyModifiers::SHIFT)
} }
} }
#[inline]
fn abs_diff(a: usize, b: usize) -> usize {
if a > b {
a - b
} else {
b - a
}
}

@ -33,16 +33,29 @@ pub struct Config {
pub scroll_lines: isize, pub scroll_lines: isize,
/// Mouse support. Defaults to true. /// Mouse support. Defaults to true.
pub mouse: bool, pub mouse: bool,
/// Line number mode.
pub line_number: LineNumber,
/// Middle click paste support. Defaults to true /// Middle click paste support. Defaults to true
pub middle_click_paste: bool, pub middle_click_paste: bool,
} }
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum LineNumber {
/// Show absolute line number
Absolute,
/// Show relative line number to the primary cursor
Relative,
}
impl Default for Config { impl Default for Config {
fn default() -> Self { fn default() -> Self {
Self { Self {
scrolloff: 5, scrolloff: 5,
scroll_lines: 3, scroll_lines: 3,
mouse: true, mouse: true,
line_number: LineNumber::Absolute,
middle_click_paste: true, middle_click_paste: true,
} }
} }

Loading…
Cancel
Save