Skip to content

Commit

Permalink
Add support for clicking on the bufferline to select a buffer
Browse files Browse the repository at this point in the history
Co-authored-by: Kyle Smith <[email protected]>
  • Loading branch information
irh and askreet committed Jan 17, 2025
1 parent 64d73d0 commit e613cf2
Showing 1 changed file with 63 additions and 9 deletions.
72 changes: 63 additions & 9 deletions helix-term/src/ui/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use helix_view::{
graphics::{Color, CursorKind, Modifier, Rect, Style},
input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
keyboard::{KeyCode, KeyModifiers},
Document, Editor, Theme, View,
Document, DocumentId, Editor, Theme, View,
};
use std::{mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc, sync::Arc};

Expand All @@ -42,6 +42,7 @@ pub struct EditorView {
pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
pub(crate) completion: Option<Completion>,
spinners: ProgressSpinners,
bufferline_info: BufferLineInfo,
/// Tracks if the terminal window is focused by reaction to terminal focus events
terminal_focused: bool,
}
Expand All @@ -66,6 +67,7 @@ impl EditorView {
last_insert: (commands::MappableCommand::normal_mode, Vec::new()),
completion: None,
spinners: ProgressSpinners::default(),
bufferline_info: BufferLineInfo::default(),
terminal_focused: true,
}
}
Expand Down Expand Up @@ -608,7 +610,7 @@ impl EditorView {
}

/// Render bufferline at the top
pub fn render_bufferline(editor: &Editor, viewport: Rect, surface: &mut Surface) {
pub fn render_bufferline(&mut self, editor: &Editor, viewport: Rect, surface: &mut Surface) {
let scratch = PathBuf::from(SCRATCH_BUFFER_NAME); // default filename to use for scratch buffer
surface.clear_with(
viewport,
Expand All @@ -631,6 +633,8 @@ impl EditorView {
let mut x = viewport.x;
let current_doc = view!(editor).doc;

self.bufferline_info.clear();

for doc in editor.documents() {
let fname = doc
.path()
Expand All @@ -650,9 +654,14 @@ impl EditorView {
let used_width = viewport.x.saturating_sub(x);
let rem_width = surface.area.width.saturating_sub(used_width);

let start_x = x;
x = surface
.set_stringn(x, viewport.y, text, rem_width as usize, style)
.0;
let end_x = x.min(surface.area.right());

self.bufferline_info
.add_buffer_info(doc.id(), start_x..end_x);

if x >= surface.area.right() {
break;
Expand Down Expand Up @@ -1173,6 +1182,14 @@ impl EditorView {
MouseEventKind::Down(MouseButton::Left) => {
let editor = &mut cxt.editor;

if is_bufferline_visible(editor) && row == 0 {
if let Some(buffer_info) = self.bufferline_info.get_clicked_buffer(column) {
editor.switch(buffer_info.document_id, helix_view::editor::Action::Replace);
}

return EventResult::Consumed(None);
}

if let Some((pos, view_id)) = pos_and_view(editor, row, column, true) {
let prev_view_id = view!(editor).id;
let doc = doc_mut!(editor, &view!(editor, view_id).doc);
Expand Down Expand Up @@ -1537,12 +1554,7 @@ impl Component for EditorView {
let config = cx.editor.config();

// check if bufferline should be rendered
use helix_view::editor::BufferLine;
let use_bufferline = match config.bufferline {
BufferLine::Always => true,
BufferLine::Multiple if cx.editor.documents.len() > 1 => true,
_ => false,
};
let use_bufferline = is_bufferline_visible(cx.editor);

// -1 for commandline and -1 for bufferline
let mut editor_area = area.clip_bottom(1);
Expand All @@ -1554,7 +1566,7 @@ impl Component for EditorView {
cx.editor.resize(editor_area);

if use_bufferline {
Self::render_bufferline(cx.editor, area.with_height(1), surface);
self.render_bufferline(cx.editor, area.with_height(1), surface);
}

for (view, is_focused) in cx.editor.tree.views() {
Expand Down Expand Up @@ -1649,6 +1661,48 @@ impl Component for EditorView {
}
}

#[derive(Debug, Default)]
struct BufferLineInfo {
visible_buffers: Vec<BufferInfo>,
}

impl BufferLineInfo {
fn clear(&mut self) {
self.visible_buffers.clear();
}

fn add_buffer_info(&mut self, document_id: DocumentId, columns: std::ops::Range<u16>) {
self.visible_buffers.push(BufferInfo {
document_id,
columns,
});
}

fn get_clicked_buffer(&self, column: u16) -> Option<&BufferInfo> {
self.visible_buffers
.iter()
.find(|cell| cell.columns.contains(&column))
}
}

#[derive(Debug)]
struct BufferInfo {
document_id: DocumentId,
// The bufferline column span used to show the document name
columns: std::ops::Range<u16>,
}

fn is_bufferline_visible(editor: &Editor) -> bool {
use helix_view::editor::BufferLine;
let config = editor.config();

match config.bufferline {
BufferLine::Always => true,
BufferLine::Multiple if editor.documents.len() > 1 => true,
_ => false,
}
}

fn canonicalize_key(key: &mut KeyEvent) {
if let KeyEvent {
code: KeyCode::Char(_),
Expand Down

0 comments on commit e613cf2

Please sign in to comment.