From 919f5af0bcccf38f735c96fc2970f73698d9a31a Mon Sep 17 00:00:00 2001 From: CedricMeu Date: Wed, 27 Sep 2023 10:05:28 +0200 Subject: [PATCH] Opinionated to scrolling --- book/src/configuration.md | 15 +------ helix-term/src/ui/editor.rs | 88 ++++++++++++++----------------------- helix-view/src/editor.rs | 25 +---------- 3 files changed, 34 insertions(+), 94 deletions(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index 588c16c19..14e9baa7c 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -59,26 +59,13 @@ Its settings will be merged with the configuration directory `config.toml` and t | `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative | `false` | | `undercurl` | Set to `true` to override automatic detection of terminal undercurl support in the event of a false negative | `false` | | `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file | `[]` | +| `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` | | `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` | | `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap-at-text-width` is set | `80` | | `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml` | `[]` | | `default-line-ending` | The line ending to use for new documents. Can be `native`, `lf`, `crlf`, `ff`, `cr` or `nel`. `native` uses the platform's native line ending (`crlf` on Windows, otherwise `lf`). | `native` | | `insert-final-newline` | Whether to automatically insert a trailing line-ending on write if missing | `true` | -### `[editor.bufferline]` Section - -Allows configuring the bufferline at the top of the editor. - -```toml -[editor.bufferline] -show = "always" -style = "scroll" -``` - -| Key | Description | Default | -| --- | --- | --- | -| `show` | Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `never` | -| `style` | Can be `overflow`, `wrap` or `scroll`. | `overflow` | ### `[editor.statusline]` Section diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 94ffc725e..9ef1ea9f5 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::{BufferLine, BufferLineStyle, CompleteAction, CursorShapeConfig}, + editor::{BufferLine, CompleteAction, CursorShapeConfig}, graphics::{Color, CursorKind, Modifier, Rect, Style}, input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind}, keyboard::{KeyCode, KeyModifiers}, @@ -64,7 +64,6 @@ pub struct BufferTab { text: String, width: u16, x: i32, - y: i32, style: Style, } @@ -530,24 +529,7 @@ impl EditorView { } /// Render bufferline at the top - pub fn render_bufferline( - editor: &Editor, - viewport: Rect, - surface: &mut Surface, - config: BufferLine, - ) -> u16 { - // check if bufferline should be rendered - use helix_view::editor::BufferLineShow; - let use_bufferline = match config.show { - BufferLineShow::Always => true, - BufferLineShow::Multiple if editor.documents.len() > 1 => true, - _ => false, - }; - - if !use_bufferline { - return 0; - } - + pub fn render_bufferline(editor: &Editor, viewport: Rect, surface: &mut Surface) { // Define styles let bufferline_active = editor .theme @@ -560,7 +542,6 @@ impl EditorView { .unwrap_or_else(|| editor.theme.get("ui.statusline.inactive")); let mut x = viewport.x as i32; - let mut y = viewport.y as i32; let current_doc = view!(editor).doc; // Gather info on buffertabs @@ -587,28 +568,16 @@ impl EditorView { let text = format!(" {}{} ", fname, if doc.is_modified() { "[+]" } else { "" }); let text_width = text.grapheme_indices(true).count(); - if config.style == BufferLineStyle::Wrap - && x.saturating_add(text_width as i32) >= viewport.right() as i32 - { - y = y.saturating_add(1); - x = viewport.x as _; - } - buffertabs.push(BufferTab { active, text, width: text_width as _, x, - y, style, }); x = x.saturating_add(text_width as _); } - let height = - (if x != 0 { y.saturating_add(1) } else { y } as u16).saturating_sub(viewport.y); - - let viewport = viewport.with_height(height); surface.clear_with( viewport, editor @@ -617,31 +586,29 @@ impl EditorView { .unwrap_or_else(|| editor.theme.get("ui.statusline")), ); - if config.style == BufferLineStyle::Scroll { - let viewport_center = (viewport.width as f64 / 2.).floor() as i32 + viewport.x as i32; + // Scroll the tabs correctly + let viewport_center = (viewport.width as f64 / 2.).floor() as i32 + viewport.x as i32; - let active_buffertab = buffertabs.iter().find(|tab| tab.active).unwrap(); + let active_buffertab = buffertabs.iter().find(|tab| tab.active).unwrap(); - let active_buffertab_center = - (active_buffertab.width as f64 / 2.).floor() as i32 + active_buffertab.x; + let active_buffertab_center = + (active_buffertab.width as f64 / 2.).floor() as i32 + active_buffertab.x; - let right_of_center = active_buffertab_center as i32 - viewport_center as i32; + let right_of_center = active_buffertab_center as i32 - viewport_center as i32; - if right_of_center > 0 { - let rightmost = buffertabs.last().unwrap(); - let full_width = rightmost.x + rightmost.width as i32; + if right_of_center > 0 { + let rightmost = buffertabs.last().unwrap(); + let full_width = rightmost.x + rightmost.width as i32; - let max_displacement = (full_width - viewport.width as i32).max(0); - let displacement = right_of_center.min(max_displacement); + let max_displacement = (full_width - viewport.width as i32).max(0); + let displacement = right_of_center.min(max_displacement); - for tab in buffertabs.iter_mut() { - tab.x = tab.x.saturating_sub(displacement.abs()); - } - } // If on center, or left of center, nothing to do - } + for tab in buffertabs.iter_mut() { + tab.x = tab.x.saturating_sub(displacement.abs()); + } + } // If on center, or left of center, nothing to do // Itterate over buffertabs, skip or slice them if left off screen, stop if right of screen. - // If wrapping no buffers will go off screen and all are drawn. for tab in buffertabs.iter_mut() { if tab.x < viewport.x as i32 { if tab.x + tab.width as i32 > viewport.x as i32 { @@ -671,15 +638,13 @@ impl EditorView { let _ = surface .set_stringn( tab.x as _, - tab.y as _, + viewport.y, tab.text.clone(), (viewport.right() as usize).saturating_sub(tab.x as _), tab.style, ) .0; } - - height } pub fn render_gutter<'d>( @@ -1511,15 +1476,26 @@ impl Component for EditorView { surface.set_style(area, cx.editor.theme.get("ui.background")); let config = cx.editor.config(); + // check if bufferline should be rendered + let use_bufferline = match config.bufferline { + BufferLine::Always => true, + BufferLine::Multiple if cx.editor.documents.len() > 1 => true, + _ => false, + }; + // -1 for commandline and -1 for bufferline let mut editor_area = area.clip_bottom(1); - let buffer_line_height = - Self::render_bufferline(cx.editor, area, surface, config.bufferline.clone()); - editor_area = editor_area.clip_top(buffer_line_height); + if use_bufferline { + editor_area = editor_area.clip_top(1); + } // if the terminal size suddenly changed, we need to trigger a resize cx.editor.resize(editor_area); + if use_bufferline { + Self::render_bufferline(cx.editor, area.with_height(1), surface); + } + for (view, is_focused) in cx.editor.tree.views() { let doc = cx.editor.document(view.doc).unwrap(); self.render_view(cx.editor, doc, view, area, surface, is_focused); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 3ca06cd5b..2265633df 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -576,20 +576,10 @@ impl Default for CursorShapeConfig { } } -/// bufferline configuration -#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case", default, deny_unknown_fields)] -pub struct BufferLine { - // Set when to show the bufferline - pub show: BufferLineShow, - // Set how to handle overflowing - pub style: BufferLineStyle, -} - /// bufferline render modes #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] -pub enum BufferLineShow { +pub enum BufferLine { /// Don't render bufferline #[default] Never, @@ -599,19 +589,6 @@ pub enum BufferLineShow { Multiple, } -/// bufferline render style -#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub enum BufferLineStyle { - /// Overflow bufferline on the right - #[default] - Overflow, - /// Wrap when the bufferline overflows - Wrap, - /// Scroll active buffer as centered in the bufferline as possible - Scroll, -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum LineNumber {