Skip to content

Commit e8730ca

Browse files
aaron404sudormrfbinlazytanukisbromberger
authored
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 <[email protected]> * add ui.bufferline.background key for themes Co-authored-by: lazytanuki <[email protected]> * 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 <[email protected]> Co-authored-by: lazytanuki <[email protected]> Co-authored-by: Seth Bromberger <[email protected]>
1 parent 04a4033 commit e8730ca

File tree

3 files changed

+97
-3
lines changed

3 files changed

+97
-3
lines changed

book/src/configuration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ use helix_core::{
1616
LineEnding, Position, Range, Selection, Transaction,
1717
};
1818
use 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

2828
use 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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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")]
372392
pub 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
}

0 commit comments

Comments
 (0)