on master help sign in
initial implementation of bufferline (#2759)

* initial implementation of bufferline * fixed lint * changed to 'bufferline', added enum for config modes, some cleanup * fixed lint * added file modification indicator * removed redundant code, added proper themeing with fallback, changed 'file modified' indicator * remove commented code * Update helix-term/src/ui/editor.rs simplify text and offset computation Co-authored-by: Gokul Soumya <gokulps15@gmail.com> * add ui.bufferline.background key for themes Co-authored-by: lazytanuki <43273245+lazytanuki@users.noreply.github.com> * address PR comments * Update helix-term/src/ui/editor.rs * simplify computation of editor area: * change to set_stringn to avoid overflow * Update configuration.md Updates documentation to reflect decision re: defaulting to never showing bufferline. * addressed pr comments * fix build error * address pr comments * revert accidental change Co-authored-by: Gokul Soumya <gokulps15@gmail.com> Co-authored-by: lazytanuki <43273245+lazytanuki@users.noreply.github.com> Co-authored-by: Seth Bromberger <sbromberger@users.noreply.github.com>

commite8730ca5fd72e3bb275b4d825de40475eabea174 authoraaron404 <54856541+aaron404@users.noreply.github.com> dateThu 1 Sep 2022, 22:39 (4 years ago) parent04a4033
3 files changed+97−3
book/src/configuration.md+1 helix-term/src/ui/editor.rs+75−3 helix-view/src/editor.rs+21
book/src/configuration.md+1
@@ -49,6 +49,7 @@ You may also specify a file to use for configuration with the `-c` or
4949| `auto-info` | Whether to display infoboxes | `true` |
5050| `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative. | `false` |
5151| `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file. | `[]` |
52+| `bufferline` | Renders a line at the top of the editor displaying open buffers. Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `never` |
5253| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` |
5354
5455### `[editor.statusline]` Section
helix-term/src/ui/editor.rs+75−3
@@ -16,14 +16,14 @@ use helix_core::{
1616 LineEnding, Position, Range, Selection, Transaction,
1717};
1818use helix_view::{
19− document::Mode,
19+ document::{Mode, SCRATCH_BUFFER_NAME},
2020 editor::{CompleteAction, CursorShapeConfig},
2121 graphics::{Color, CursorKind, Modifier, Rect, Style},
2222 input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
2323 keyboard::{KeyCode, KeyModifiers},
2424 Document, Editor, Theme, View,
2525};
26−use std::borrow::Cow;
26+use std::{borrow::Cow, path::PathBuf};
2727
2828use tui::buffer::Buffer as Surface;
2929
@@ -619,6 +619,59 @@ impl EditorView {
619619 }
620620 }
621621
622+ /// Render bufferline at the top
623+ pub fn render_bufferline(editor: &Editor, viewport: Rect, surface: &mut Surface) {
624+ let scratch = PathBuf::from(SCRATCH_BUFFER_NAME); // default filename to use for scratch buffer
625+ surface.clear_with(
626+ viewport,
627+ editor
628+ .theme
629+ .try_get("ui.bufferline.background")
630+ .unwrap_or_else(|| editor.theme.get("ui.statusline")),
631+ );
632+
633+ let bufferline_active = editor
634+ .theme
635+ .try_get("ui.bufferline.active")
636+ .unwrap_or_else(|| editor.theme.get("ui.statusline.active"));
637+
638+ let bufferline_inactive = editor
639+ .theme
640+ .try_get("ui.bufferline")
641+ .unwrap_or_else(|| editor.theme.get("ui.statusline.inactive"));
642+
643+ let mut x = viewport.x;
644+ let current_doc = view!(editor).doc;
645+
646+ for doc in editor.documents() {
647+ let fname = doc
648+ .path()
649+ .unwrap_or(&scratch)
650+ .file_name()
651+ .unwrap_or_default()
652+ .to_str()
653+ .unwrap_or_default();
654+
655+ let style = if current_doc == doc.id() {
656+ bufferline_active
657+ } else {
658+ bufferline_inactive
659+ };
660+
661+ let text = format!(" {}{} ", fname, if doc.is_modified() { "[+]" } else { "" });
662+ let used_width = viewport.x.saturating_sub(x);
663+ let rem_width = surface.area.width.saturating_sub(used_width);
664+
665+ x = surface
666+ .set_stringn(x, viewport.y, text, rem_width as usize, style)
667+ .0;
668+
669+ if x >= surface.area.right() {
670+ break;
671+ }
672+ }
673+ }
674+
622675 pub fn render_gutter(
623676 editor: &Editor,
624677 doc: &Document,
@@ -1291,8 +1344,27 @@ impl Component for EditorView {
12911344 // clear with background color
12921345 surface.set_style(area, cx.editor.theme.get("ui.background"));
12931346 let config = cx.editor.config();
1347+
1348+ // check if bufferline should be rendered
1349+ use helix_view::editor::BufferLine;
1350+ let use_bufferline = match config.bufferline {
1351+ BufferLine::Always => true,
1352+ BufferLine::Multiple if cx.editor.documents.len() > 1 => true,
1353+ _ => false,
1354+ };
1355+
1356+ // -1 for commandline and -1 for bufferline
1357+ let mut editor_area = area.clip_bottom(1);
1358+ if use_bufferline {
1359+ editor_area = editor_area.clip_top(1);
1360+ }
1361+
12941362 // if the terminal size suddenly changed, we need to trigger a resize
1295− cx.editor.resize(area.clip_bottom(1)); // -1 from bottom for commandline
1363+ cx.editor.resize(editor_area);
1364+
1365+ if use_bufferline {
1366+ Self::render_bufferline(cx.editor, area.with_height(1), surface);
1367+ }
12961368
12971369 for (view, is_focused) in cx.editor.tree.views() {
12981370 let doc = cx.editor.document(view.doc).unwrap();
helix-view/src/editor.rs+21
@@ -162,6 +162,8 @@ pub struct Config {
162162 pub rulers: Vec<u16>,
163163 #[serde(default)]
164164 pub whitespace: WhitespaceConfig,
165+ /// Persistently display open buffers along the top
166+ pub bufferline: BufferLine,
165167 /// Vertical indent width guides.
166168 pub indent_guides: IndentGuidesConfig,
167169 /// Whether to color modes with different colors. Defaults to `false`.
@@ -367,6 +369,24 @@ impl Default for CursorShapeConfig {
367369 }
368370}
369371
372+/// bufferline render modes
373+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
374+#[serde(rename_all = "kebab-case")]
375+pub enum BufferLine {
376+ /// Don't render bufferline
377+ Never,
378+ /// Always render
379+ Always,
380+ /// Only if multiple buffers are open
381+ Multiple,
382+}
383+
384+impl Default for BufferLine {
385+ fn default() -> Self {
386+ BufferLine::Never
387+ }
388+}
389+
370390#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
371391#[serde(rename_all = "kebab-case")]
372392pub enum LineNumber {
@@ -554,6 +574,7 @@ impl Default for Config {
554574 terminal: get_terminal_provider(),
555575 rulers: Vec::new(),
556576 whitespace: WhitespaceConfig::default(),
577+ bufferline: BufferLine::default(),
557578 indent_guides: IndentGuidesConfig::default(),
558579 color_modes: false,
559580 }