Skip to content

Commit d658bae

Browse files
aaron404sudormrfbinlazytanukisbromberger
authored andcommitted
initial implementation of bufferline (helix-editor#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 d8d8ce3 commit d658bae

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
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: 70 additions & 2 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

@@ -621,6 +621,59 @@ impl EditorView {
621621
}
622622
}
623623

624+
/// Render bufferline at the top
625+
pub fn render_bufferline(editor: &Editor, viewport: Rect, surface: &mut Surface) {
626+
let scratch = PathBuf::from(SCRATCH_BUFFER_NAME); // default filename to use for scratch buffer
627+
surface.clear_with(
628+
viewport,
629+
editor
630+
.theme
631+
.try_get("ui.bufferline.background")
632+
.unwrap_or_else(|| editor.theme.get("ui.statusline")),
633+
);
634+
635+
let bufferline_active = editor
636+
.theme
637+
.try_get("ui.bufferline.active")
638+
.unwrap_or_else(|| editor.theme.get("ui.statusline.active"));
639+
640+
let bufferline_inactive = editor
641+
.theme
642+
.try_get("ui.bufferline")
643+
.unwrap_or_else(|| editor.theme.get("ui.statusline.inactive"));
644+
645+
let mut x = viewport.x;
646+
let current_doc = view!(editor).doc;
647+
648+
for doc in editor.documents() {
649+
let fname = doc
650+
.path()
651+
.unwrap_or(&scratch)
652+
.file_name()
653+
.unwrap_or_default()
654+
.to_str()
655+
.unwrap_or_default();
656+
657+
let style = if current_doc == doc.id() {
658+
bufferline_active
659+
} else {
660+
bufferline_inactive
661+
};
662+
663+
let text = format!(" {}{} ", fname, if doc.is_modified() { "[+]" } else { "" });
664+
let used_width = viewport.x.saturating_sub(x);
665+
let rem_width = surface.area.width.saturating_sub(used_width);
666+
667+
x = surface
668+
.set_stringn(x, viewport.y, text, rem_width as usize, style)
669+
.0;
670+
671+
if x >= surface.area.right() {
672+
break;
673+
}
674+
}
675+
}
676+
624677
pub fn render_gutter(
625678
editor: &Editor,
626679
doc: &Document,
@@ -1298,6 +1351,21 @@ impl Component for EditorView {
12981351
// clear with background color
12991352
surface.set_style(area, cx.editor.theme.get("ui.background"));
13001353
let config = cx.editor.config();
1354+
1355+
// check if bufferline should be rendered
1356+
use helix_view::editor::BufferLine;
1357+
let use_bufferline = match config.bufferline {
1358+
BufferLine::Always => true,
1359+
BufferLine::Multiple if cx.editor.documents.len() > 1 => true,
1360+
_ => false,
1361+
};
1362+
1363+
// -1 for commandline and -1 for bufferline
1364+
let mut editor_area = area.clip_bottom(1);
1365+
if use_bufferline {
1366+
editor_area = editor_area.clip_top(1);
1367+
}
1368+
13011369
// if the terminal size suddenly changed, we need to trigger a resize
13021370
let mut editor_area = area.clip_bottom(1);
13031371
if self.explorer.is_some() && (config.explorer.is_embed()) {

helix-view/src/editor.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ pub struct Config {
225225
pub rulers: Vec<u16>,
226226
#[serde(default)]
227227
pub whitespace: WhitespaceConfig,
228+
/// Persistently display open buffers along the top
229+
pub bufferline: BufferLine,
228230
/// Vertical indent width guides.
229231
pub indent_guides: IndentGuidesConfig,
230232
/// Whether to color modes with different colors. Defaults to `false`.
@@ -432,6 +434,24 @@ impl Default for CursorShapeConfig {
432434
}
433435
}
434436

437+
/// bufferline render modes
438+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
439+
#[serde(rename_all = "kebab-case")]
440+
pub enum BufferLine {
441+
/// Don't render bufferline
442+
Never,
443+
/// Always render
444+
Always,
445+
/// Only if multiple buffers are open
446+
Multiple,
447+
}
448+
449+
impl Default for BufferLine {
450+
fn default() -> Self {
451+
BufferLine::Never
452+
}
453+
}
454+
435455
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
436456
#[serde(rename_all = "kebab-case")]
437457
pub enum LineNumber {
@@ -619,6 +639,7 @@ impl Default for Config {
619639
terminal: get_terminal_provider(),
620640
rulers: Vec::new(),
621641
whitespace: WhitespaceConfig::default(),
642+
bufferline: BufferLine::default(),
622643
indent_guides: IndentGuidesConfig::default(),
623644
color_modes: false,
624645
explorer: ExplorerConfig::default(),

0 commit comments

Comments
 (0)