Add line numbers in the editor
This commit is contained in:
46
src/tui.rs
46
src/tui.rs
@@ -968,6 +968,11 @@ fn render_editor(frame: &mut Frame, area: Rect, editor: &Editor, focused: bool)
|
|||||||
};
|
};
|
||||||
let block = Block::default().borders(Borders::ALL).title(title);
|
let block = Block::default().borders(Borders::ALL).title(title);
|
||||||
|
|
||||||
|
// Line numbers occupy a fixed-width left gutter. Width grows with the
|
||||||
|
// largest line number so the body never shifts as lines are added.
|
||||||
|
let gutter_width = line_number_width(editor.buffer.len());
|
||||||
|
let gutter_style = Style::default().fg(Color::DarkGray);
|
||||||
|
|
||||||
if focused {
|
if focused {
|
||||||
// Highlight the character under the cursor with explicit bg + fg
|
// Highlight the character under the cursor with explicit bg + fg
|
||||||
// colours (not `REVERSED`) so the cursor cell is filled even when
|
// colours (not `REVERSED`) so the cursor cell is filled even when
|
||||||
@@ -981,24 +986,55 @@ fn render_editor(frame: &mut Frame, area: Rect, editor: &Editor, focused: bool)
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(r, line)| {
|
.map(|(r, line)| {
|
||||||
if r == cr {
|
let body = if r == cr {
|
||||||
editor_cursor_line(line, cc, cursor_style)
|
editor_cursor_line(line, cc, cursor_style)
|
||||||
} else {
|
} else {
|
||||||
Line::from(line.clone())
|
Line::from(line.clone())
|
||||||
}
|
};
|
||||||
|
prepend_line_number(body, r + 1, gutter_width, gutter_style)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let p = Paragraph::new(lines).block(block).wrap(Wrap { trim: false });
|
let p = Paragraph::new(lines).block(block).wrap(Wrap { trim: false });
|
||||||
frame.render_widget(p, area);
|
frame.render_widget(p, area);
|
||||||
} else {
|
} else {
|
||||||
let p = Paragraph::new(editor.text())
|
let lines: Vec<Line> = editor
|
||||||
.block(block)
|
.buffer
|
||||||
.wrap(Wrap { trim: false });
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(r, line)| {
|
||||||
|
prepend_line_number(
|
||||||
|
Line::from(line.clone()),
|
||||||
|
r + 1,
|
||||||
|
gutter_width,
|
||||||
|
gutter_style,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let p = Paragraph::new(lines).block(block).wrap(Wrap { trim: false });
|
||||||
frame.render_widget(p, area);
|
frame.render_widget(p, area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn line_number_width(line_count: usize) -> usize {
|
||||||
|
let max = line_count.max(1);
|
||||||
|
let mut digits = 1;
|
||||||
|
let mut n = max;
|
||||||
|
while n >= 10 {
|
||||||
|
n /= 10;
|
||||||
|
digits += 1;
|
||||||
|
}
|
||||||
|
digits
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepend_line_number(line: Line<'static>, number: usize, width: usize, style: Style) -> Line<'static> {
|
||||||
|
let gutter = format!("{:>width$} │ ", number, width = width);
|
||||||
|
let mut spans = Vec::with_capacity(line.spans.len() + 1);
|
||||||
|
spans.push(Span::styled(gutter, style));
|
||||||
|
spans.extend(line.spans);
|
||||||
|
Line::from(spans)
|
||||||
|
}
|
||||||
|
|
||||||
/// Build the cursor-bearing line as three spans: text before, the
|
/// Build the cursor-bearing line as three spans: text before, the
|
||||||
/// highlighted character at the cursor, text after. If the cursor sits
|
/// highlighted character at the cursor, text after. If the cursor sits
|
||||||
/// past the end of the line (or on a whitespace cell), the highlight
|
/// past the end of the line (or on a whitespace cell), the highlight
|
||||||
|
|||||||
Reference in New Issue
Block a user