diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 0b6ab04654b45..c0acf56b0666c 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -23,7 +23,7 @@ use helix_core::{ }; use helix_view::{ document::{Mode, SavePoint, SCRATCH_BUFFER_NAME}, - editor::{CompleteAction, CursorShapeConfig}, + editor::{BufferLineAlignment, CompleteAction, CursorShapeConfig}, graphics::{Color, CursorKind, Modifier, Rect, Style}, input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind}, keyboard::{KeyCode, KeyModifiers}, @@ -545,25 +545,52 @@ impl EditorView { .try_get("ui.bufferline") .unwrap_or_else(|| editor.theme.get("ui.statusline.inactive")); - let mut x = viewport.x; let current_doc = view!(editor).doc; - for doc in editor.documents() { - let fname = doc - .path() - .unwrap_or(&scratch) - .file_name() - .unwrap_or_default() - .to_str() - .unwrap_or_default(); - - let style = if current_doc == doc.id() { - bufferline_active - } else { - bufferline_inactive - }; + let mut total_width_needed = 0; + + let entries: Vec<(String, Style)> = editor + .documents() + .map(|doc| { + let fname = doc + .path() + .unwrap_or(&scratch) + .file_name() + .unwrap_or_default() + .to_str() + .unwrap_or_default(); + + let style = if current_doc == doc.id() { + bufferline_active + } else { + bufferline_inactive + }; + + let text = format!(" {}{} ", fname, if doc.is_modified() { "[+]" } else { "" }); + + total_width_needed += text.len(); + + (text, style) + }) + .collect(); + + // Figure out the X offset into the view depending on the requested bufferline alignment. + let x_offset = match editor.config().bufferline_alignment { + BufferLineAlignment::Left => 0u16, + BufferLineAlignment::Center => surface + .area + .width + .saturating_sub(total_width_needed.min(surface.area.width as usize) as u16) + .div_euclid(2), + BufferLineAlignment::Right => surface + .area + .width + .saturating_sub(total_width_needed.min(surface.area.width as usize) as u16), + }; + + let mut x = viewport.x + x_offset; - let text = format!(" {}{} ", fname, if doc.is_modified() { "[+]" } else { "" }); + for (text, style) in entries { let used_width = viewport.x.saturating_sub(x); let rem_width = surface.area.width.saturating_sub(used_width); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 7207baf38a2e0..0cf7c89dddb1f 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -276,6 +276,8 @@ pub struct Config { pub whitespace: WhitespaceConfig, /// Persistently display open buffers along the top pub bufferline: BufferLine, + /// Align the bufferline contents. Defaults to `left`. + pub bufferline_alignment: BufferLineAlignment, /// Vertical indent width guides. pub indent_guides: IndentGuidesConfig, /// Whether to color modes with different colors. Defaults to `false`. @@ -549,6 +551,24 @@ impl Default for BufferLine { } } +/// Where to align the bufferline contents +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum BufferLineAlignment { + /// Align items to the left + Left, + /// Align items to the center + Center, + /// Align items to the right + Right, +} + +impl Default for BufferLineAlignment { + fn default() -> Self { + Self::Left + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum LineNumber { @@ -746,6 +766,7 @@ impl Default for Config { rulers: Vec::new(), whitespace: WhitespaceConfig::default(), bufferline: BufferLine::default(), + bufferline_alignment: BufferLineAlignment::default(), indent_guides: IndentGuidesConfig::default(), color_modes: false, soft_wrap: SoftWrap::default(),