mirror of https://github.com/helix-editor/helix
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 argumentpull/592/head
parent
aaccc9419a
commit
78923496a6
|
@ -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…
Reference in New Issue