Opinionated to scrolling

pull/8362/head
CedricMeu 1 year ago
parent 0415401285
commit 919f5af0bc

@ -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` | | `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` | | `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 | `[]` | | `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` | | `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` | | `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` | `[]` | | `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` | | `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` | | `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 ### `[editor.statusline]` Section

@ -23,7 +23,7 @@ use helix_core::{
}; };
use helix_view::{ use helix_view::{
document::{Mode, SavePoint, SCRATCH_BUFFER_NAME}, document::{Mode, SavePoint, SCRATCH_BUFFER_NAME},
editor::{BufferLine, BufferLineStyle, CompleteAction, CursorShapeConfig}, editor::{BufferLine, CompleteAction, CursorShapeConfig},
graphics::{Color, CursorKind, Modifier, Rect, Style}, graphics::{Color, CursorKind, Modifier, Rect, Style},
input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind}, input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind},
keyboard::{KeyCode, KeyModifiers}, keyboard::{KeyCode, KeyModifiers},
@ -64,7 +64,6 @@ pub struct BufferTab {
text: String, text: String,
width: u16, width: u16,
x: i32, x: i32,
y: i32,
style: Style, style: Style,
} }
@ -530,24 +529,7 @@ impl EditorView {
} }
/// Render bufferline at the top /// Render bufferline at the top
pub fn render_bufferline( pub fn render_bufferline(editor: &Editor, viewport: Rect, surface: &mut Surface) {
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;
}
// Define styles // Define styles
let bufferline_active = editor let bufferline_active = editor
.theme .theme
@ -560,7 +542,6 @@ impl EditorView {
.unwrap_or_else(|| editor.theme.get("ui.statusline.inactive")); .unwrap_or_else(|| editor.theme.get("ui.statusline.inactive"));
let mut x = viewport.x as i32; let mut x = viewport.x as i32;
let mut y = viewport.y as i32;
let current_doc = view!(editor).doc; let current_doc = view!(editor).doc;
// Gather info on buffertabs // Gather info on buffertabs
@ -587,28 +568,16 @@ impl EditorView {
let text = format!(" {}{} ", fname, if doc.is_modified() { "[+]" } else { "" }); let text = format!(" {}{} ", fname, if doc.is_modified() { "[+]" } else { "" });
let text_width = text.grapheme_indices(true).count(); 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 { buffertabs.push(BufferTab {
active, active,
text, text,
width: text_width as _, width: text_width as _,
x, x,
y,
style, style,
}); });
x = x.saturating_add(text_width as _); 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( surface.clear_with(
viewport, viewport,
editor editor
@ -617,31 +586,29 @@ impl EditorView {
.unwrap_or_else(|| editor.theme.get("ui.statusline")), .unwrap_or_else(|| editor.theme.get("ui.statusline")),
); );
if config.style == BufferLineStyle::Scroll { // Scroll the tabs correctly
let viewport_center = (viewport.width as f64 / 2.).floor() as i32 + viewport.x as i32; 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 = let active_buffertab_center =
(active_buffertab.width as f64 / 2.).floor() as i32 + active_buffertab.x; (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 { if right_of_center > 0 {
let rightmost = buffertabs.last().unwrap(); let rightmost = buffertabs.last().unwrap();
let full_width = rightmost.x + rightmost.width as i32; let full_width = rightmost.x + rightmost.width as i32;
let max_displacement = (full_width - viewport.width as i32).max(0); let max_displacement = (full_width - viewport.width as i32).max(0);
let displacement = right_of_center.min(max_displacement); let displacement = right_of_center.min(max_displacement);
for tab in buffertabs.iter_mut() { for tab in buffertabs.iter_mut() {
tab.x = tab.x.saturating_sub(displacement.abs()); tab.x = tab.x.saturating_sub(displacement.abs());
} }
} // If on center, or left of center, nothing to do } // 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. // 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() { for tab in buffertabs.iter_mut() {
if tab.x < viewport.x as i32 { if tab.x < viewport.x as i32 {
if tab.x + tab.width as i32 > viewport.x as i32 { if tab.x + tab.width as i32 > viewport.x as i32 {
@ -671,15 +638,13 @@ impl EditorView {
let _ = surface let _ = surface
.set_stringn( .set_stringn(
tab.x as _, tab.x as _,
tab.y as _, viewport.y,
tab.text.clone(), tab.text.clone(),
(viewport.right() as usize).saturating_sub(tab.x as _), (viewport.right() as usize).saturating_sub(tab.x as _),
tab.style, tab.style,
) )
.0; .0;
} }
height
} }
pub fn render_gutter<'d>( pub fn render_gutter<'d>(
@ -1511,15 +1476,26 @@ impl Component for EditorView {
surface.set_style(area, cx.editor.theme.get("ui.background")); surface.set_style(area, cx.editor.theme.get("ui.background"));
let config = cx.editor.config(); 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 // -1 for commandline and -1 for bufferline
let mut editor_area = area.clip_bottom(1); let mut editor_area = area.clip_bottom(1);
let buffer_line_height = if use_bufferline {
Self::render_bufferline(cx.editor, area, surface, config.bufferline.clone()); editor_area = editor_area.clip_top(1);
editor_area = editor_area.clip_top(buffer_line_height); }
// if the terminal size suddenly changed, we need to trigger a resize // if the terminal size suddenly changed, we need to trigger a resize
cx.editor.resize(editor_area); 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() { for (view, is_focused) in cx.editor.tree.views() {
let doc = cx.editor.document(view.doc).unwrap(); let doc = cx.editor.document(view.doc).unwrap();
self.render_view(cx.editor, doc, view, area, surface, is_focused); self.render_view(cx.editor, doc, view, area, surface, is_focused);

@ -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 /// bufferline render modes
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum BufferLineShow { pub enum BufferLine {
/// Don't render bufferline /// Don't render bufferline
#[default] #[default]
Never, Never,
@ -599,19 +589,6 @@ pub enum BufferLineShow {
Multiple, 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)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum LineNumber { pub enum LineNumber {

Loading…
Cancel
Save