on master help sign in
Make gutters padding optional (#2996)

If all gutters are removed, there are still an extra one padding, would be nice to remove that to save some space.

commite8214fb1e6009d44a4b7094c6e5297a19f18f549 authorIvan Tham <pickfire@riseup.net> dateMon 18 Jul 2022, 09:13 (4 years ago) parent2a8d38c
5 files changed+66−20
book/src/configuration.md+1−1 helix-term/src/ui/editor.rs+1−1 helix-view/src/editor.rs+7−1 helix-view/src/gutter.rs+11 helix-view/src/view.rs+46−17
book/src/configuration.md+1−1
@@ -38,7 +38,7 @@ hidden = false
3838| `shell` | Shell to use when running external commands. | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` |
3939| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers. | `absolute` |
4040| `cursorline` | Highlight all lines with a cursor. | `false` |
41−| `gutters` | Gutters to display: Available are `diagnostics` and `line-numbers`, note that `diagnostics` also includes other features like breakpoints | `["diagnostics", "line-numbers"]` |
41+| `gutters` | Gutters to display: Available are `diagnostics` and `line-numbers` and `padding`, note that `diagnostics` also includes other features like breakpoints | `["diagnostics", "line-numbers", "padding"]` |
4242| `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
4343| `auto-format` | Enable automatic formatting on save. | `true` |
4444| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
helix-term/src/ui/editor.rs+1−1
@@ -615,7 +615,7 @@ impl EditorView {
615615 // avoid lots of small allocations by reusing a text buffer for each line
616616 let mut text = String::with_capacity(8);
617617
618− for (constructor, width) in &view.gutters {
618+ for (constructor, width) in view.gutters() {
619619 let gutter = constructor(editor, doc, view, theme, is_focused, *width);
620620 text.reserve(*width); // ensure there's enough space for the gutter
621621 for (i, line) in (view.offset.row..(last_line + 1)).enumerate() {
helix-view/src/editor.rs+7−1
@@ -314,6 +314,8 @@ pub enum GutterType {
314314 Diagnostics,
315315 /// Show line numbers
316316 LineNumbers,
317+ /// Show one blank space
318+ Padding,
317319}
318320
319321impl std::str::FromStr for GutterType {
@@ -450,7 +452,11 @@ impl Default for Config {
450452 },
451453 line_number: LineNumber::Absolute,
452454 cursorline: false,
453− gutters: vec![GutterType::Diagnostics, GutterType::LineNumbers],
455+ gutters: vec![
456+ GutterType::Diagnostics,
457+ GutterType::LineNumbers,
458+ GutterType::Padding,
459+ ],
454460 middle_click_paste: true,
455461 auto_pairs: AutoPairConfig::default(),
456462 auto_completion: true,
helix-view/src/gutter.rs+11
@@ -102,6 +102,17 @@ pub fn line_numbers<'doc>(
102102 })
103103}
104104
105+pub fn padding<'doc>(
106+ _editor: &'doc Editor,
107+ _doc: &'doc Document,
108+ _view: &View,
109+ _theme: &Theme,
110+ _is_focused: bool,
111+ _width: usize,
112+) -> GutterFn<'doc> {
113+ Box::new(|_line: usize, _selected: bool, _out: &mut String| None)
114+}
115+
105116#[inline(always)]
106117const fn abs_diff(a: usize, b: usize) -> usize {
107118 if a > b {
helix-view/src/view.rs+46−17
@@ -75,7 +75,11 @@ pub struct View {
7575 pub last_modified_docs: [Option<DocumentId>; 2],
7676 /// used to store previous selections of tree-sitter objects
7777 pub object_selections: Vec<Selection>,
78− pub gutters: Vec<(Gutter, usize)>,
78+ /// Gutter (constructor) and width of gutter, used to calculate
79+ /// `gutter_offset`
80+ gutters: Vec<(Gutter, usize)>,
81+ /// cached total width of gutter
82+ gutter_offset: u16,
7983}
8084
8185impl fmt::Debug for View {
@@ -91,12 +95,23 @@ impl fmt::Debug for View {
9195impl View {
9296 pub fn new(doc: DocumentId, gutter_types: Vec<crate::editor::GutterType>) -> Self {
9397 let mut gutters: Vec<(Gutter, usize)> = vec![];
98+ let mut gutter_offset = 0;
9499 use crate::editor::GutterType;
95100 for gutter_type in &gutter_types {
96− match gutter_type {
97− GutterType::Diagnostics => gutters.push((gutter::diagnostics_or_breakpoints, 1)),
98− GutterType::LineNumbers => gutters.push((gutter::line_numbers, 5)),
99− }
101+ let width = match gutter_type {
102+ GutterType::Diagnostics => 1,
103+ GutterType::LineNumbers => 5,
104+ GutterType::Padding => 1,
105+ };
106+ gutter_offset += width;
107+ gutters.push((
108+ match gutter_type {
109+ GutterType::Diagnostics => gutter::diagnostics_or_breakpoints,
110+ GutterType::LineNumbers => gutter::line_numbers,
111+ GutterType::Padding => gutter::padding,
112+ },
113+ width as usize,
114+ ));
100115 }
101116 Self {
102117 id: ViewId::default(),
@@ -108,6 +123,7 @@ impl View {
108123 last_modified_docs: [None, None],
109124 object_selections: Vec::new(),
110125 gutters,
126+ gutter_offset,
111127 }
112128 }
113129
@@ -119,14 +135,12 @@ impl View {
119135 }
120136
121137 pub fn inner_area(&self) -> Rect {
122− // TODO: cache this
123− let offset = self
124− .gutters
125− .iter()
126− .map(|(_, width)| *width as u16)
127− .sum::<u16>()
128− + 1; // +1 for some space between gutters and line
129− self.area.clip_left(offset).clip_bottom(1) // -1 for statusline
138+ // TODO add abilty to not use cached offset for runtime configurable gutter
139+ self.area.clip_left(self.gutter_offset).clip_bottom(1) // -1 for statusline
140+ }
141+
142+ pub fn gutters(&self) -> &[(Gutter, usize)] {
143+ &self.gutters
130144 }
131145
132146 //
@@ -327,7 +341,11 @@ mod tests {
327341 fn test_text_pos_at_screen_coords() {
328342 let mut view = View::new(
329343 DocumentId::default(),
330− vec![GutterType::Diagnostics, GutterType::LineNumbers],
344+ vec![
345+ GutterType::Diagnostics,
346+ GutterType::LineNumbers,
347+ GutterType::Padding,
348+ ],
331349 );
332350 view.area = Rect::new(40, 40, 40, 40);
333351 let rope = Rope::from_str("abc\n\tdef");
@@ -374,7 +392,10 @@ mod tests {
374392
375393 #[test]
376394 fn test_text_pos_at_screen_coords_without_line_numbers_gutter() {
377− let mut view = View::new(DocumentId::default(), vec![GutterType::Diagnostics]);
395+ let mut view = View::new(
396+ DocumentId::default(),
397+ vec![GutterType::Diagnostics, GutterType::Padding],
398+ );
378399 view.area = Rect::new(40, 40, 40, 40);
379400 let rope = Rope::from_str("abc\n\tdef");
380401 let text = rope.slice(..);
@@ -400,7 +421,11 @@ mod tests {
400421 fn test_text_pos_at_screen_coords_cjk() {
401422 let mut view = View::new(
402423 DocumentId::default(),
403− vec![GutterType::Diagnostics, GutterType::LineNumbers],
424+ vec![
425+ GutterType::Diagnostics,
426+ GutterType::LineNumbers,
427+ GutterType::Padding,
428+ ],
404429 );
405430 view.area = Rect::new(40, 40, 40, 40);
406431 let rope = Rope::from_str("Hi! こんにちは皆さん");
@@ -440,7 +465,11 @@ mod tests {
440465 fn test_text_pos_at_screen_coords_graphemes() {
441466 let mut view = View::new(
442467 DocumentId::default(),
443− vec![GutterType::Diagnostics, GutterType::LineNumbers],
468+ vec![
469+ GutterType::Diagnostics,
470+ GutterType::LineNumbers,
471+ GutterType::Padding,
472+ ],
444473 );
445474 view.area = Rect::new(40, 40, 40, 40);
446475 let rope = Rope::from_str("Hèl̀l̀ò world!");