Add support for clicking on the bufferline to select a buffer
Co-authored-by: Kyle Smith <kyle.smith@salsify.com>
This commit is contained in:
parent
5ba97ba41e
commit
3af529d868
1 changed files with 63 additions and 9 deletions
|
@ -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};
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -72,6 +73,7 @@ impl EditorView {
|
|||
last_insert: (commands::MappableCommand::normal_mode, Vec::new()),
|
||||
completion: None,
|
||||
spinners: ProgressSpinners::default(),
|
||||
bufferline_info: BufferLineInfo::default(),
|
||||
terminal_focused: true,
|
||||
}
|
||||
}
|
||||
|
@ -593,7 +595,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,
|
||||
|
@ -616,6 +618,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()
|
||||
|
@ -635,9 +639,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;
|
||||
|
@ -1139,6 +1148,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);
|
||||
|
@ -1480,12 +1497,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);
|
||||
|
@ -1497,7 +1509,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() {
|
||||
|
@ -1592,6 +1604,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(_),
|
||||
|
|
Loading…
Reference in a new issue