diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 01ea617fa..9cd9ee7e4 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -80,7 +80,12 @@ impl Application { let syn_loader_conf = toml::from_slice(lang_conf).expect("Could not parse languages.toml"); let syn_loader = std::sync::Arc::new(syntax::Loader::new(syn_loader_conf)); - let mut editor = Editor::new(size, theme_loader.clone(), syn_loader.clone()); + let mut editor = Editor::new( + size, + theme_loader.clone(), + syn_loader.clone(), + config.editor.clone(), + ); let editor_view = Box::new(ui::EditorView::new(std::mem::take(&mut config.keys))); compositor.push(editor_view); @@ -489,7 +494,7 @@ impl Application { terminal::enable_raw_mode()?; let mut stdout = stdout(); execute!(stdout, terminal::EnterAlternateScreen)?; - if self.config.terminal.mouse { + if self.config.editor.mouse { execute!(stdout, EnableMouseCapture)?; } Ok(()) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 612a89abc..29be5ccd0 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -12,12 +12,8 @@ use helix_core::{ }; use helix_view::{ - document::Mode, - editor::Action, - input::KeyEvent, - keyboard::KeyCode, - view::{View, PADDING}, - Document, DocumentId, Editor, ViewId, + document::Mode, editor::Action, input::KeyEvent, keyboard::KeyCode, view::View, Document, + DocumentId, Editor, ViewId, }; use anyhow::{anyhow, bail, Context as _}; @@ -452,7 +448,11 @@ fn goto_first_nonwhitespace(cx: &mut Context) { fn goto_window(cx: &mut Context, align: Align) { let (view, doc) = current!(cx.editor); - let scrolloff = PADDING.min(view.area.height as usize / 2); // TODO: user pref + let scrolloff = cx + .editor + .config + .scrolloff + .min(view.area.height as usize / 2); // TODO: user pref let last_line = view.last_line(doc); @@ -890,7 +890,11 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) { return; } - let scrolloff = PADDING.min(view.area.height as usize / 2); // TODO: user pref + let scrolloff = cx + .editor + .config + .scrolloff + .min(view.area.height as usize / 2); // TODO: user pref view.first_line = match direction { Forward => view.first_line + offset, @@ -3927,10 +3931,9 @@ fn align_view_middle(cx: &mut Context) { .cursor(doc.text().slice(..)); let pos = coords_at_pos(doc.text().slice(..), pos); - const OFFSET: usize = 7; // gutters - view.first_col = pos - .col - .saturating_sub(((view.area.width as usize).saturating_sub(OFFSET)) / 2); + view.first_col = pos.col.saturating_sub( + ((view.area.width as usize).saturating_sub(crate::ui::editor::GUTTER_OFFSET as usize)) / 2, + ); } fn scroll_up(cx: &mut Context) { diff --git a/helix-term/src/config.rs b/helix-term/src/config.rs index 38cd3bfbd..13917656a 100644 --- a/helix-term/src/config.rs +++ b/helix-term/src/config.rs @@ -10,7 +10,7 @@ pub struct Config { #[serde(default)] pub keys: Keymaps, #[serde(default)] - pub terminal: TerminalConfig, + pub editor: helix_view::editor::Config, } #[derive(Debug, Default, Clone, PartialEq, Deserialize)] @@ -19,18 +19,6 @@ pub struct LspConfig { pub display_messages: bool, } -#[derive(Debug, Clone, PartialEq, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub struct TerminalConfig { - pub mouse: bool, -} - -impl Default for TerminalConfig { - fn default() -> Self { - Self { mouse: true } - } -} - #[test] fn parsing_keymaps_config_file() { use crate::keymap; diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index a2b169ed4..496edf42e 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -36,7 +36,7 @@ pub struct EditorView { pub autoinfo: Option, } -const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter +pub const GUTTER_OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter impl Default for EditorView { fn default() -> Self { @@ -72,9 +72,9 @@ impl EditorView { loader: &syntax::Loader, ) { let area = Rect::new( - view.area.x + OFFSET, + view.area.x + GUTTER_OFFSET, view.area.y, - view.area.width - OFFSET, + view.area.width - GUTTER_OFFSET, view.area.height.saturating_sub(1), ); // - 1 for statusline @@ -339,7 +339,7 @@ impl EditorView { use helix_core::diagnostic::Severity; if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) { surface.set_stringn( - viewport.x - OFFSET, + viewport.x - GUTTER_OFFSET, viewport.y + i as u16, "●", 1, @@ -360,7 +360,7 @@ impl EditorView { format!("{:>5}", line + 1) }; surface.set_stringn( - viewport.x + 1 - OFFSET, + viewport.x + 1 - GUTTER_OFFSET, viewport.y + i as u16, line_number_text, 5, @@ -401,7 +401,7 @@ impl EditorView { format!("{:>5}", line_number + 1) }; surface.set_stringn( - viewport.x + 1 - OFFSET, + viewport.x + 1 - GUTTER_OFFSET, viewport.y + head.row as u16, line_number_text, 5, @@ -778,7 +778,7 @@ impl Component for EditorView { } let (view, doc) = current!(cx.editor); - view.ensure_cursor_in_view(doc); + view.ensure_cursor_in_view(doc, cx.editor.config.scrolloff); // mode transitions match (mode, doc.mode()) { diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 9e71cfe73..f68ad0a74 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -1,5 +1,5 @@ mod completion; -mod editor; +pub(crate) mod editor; mod info; mod markdown; mod menu; @@ -63,7 +63,7 @@ pub fn regex_prompt( fun(view, doc, registers, regex); - view.ensure_cursor_in_view(doc); + view.ensure_cursor_in_view(doc, cx.editor.config.scrolloff); } Err(_err) => (), // TODO: mark command line as error } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 7e8548e73..e5ba0d512 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -18,6 +18,26 @@ pub use helix_core::register::Registers; use helix_core::syntax; use helix_core::Position; +use serde::Deserialize; + +#[derive(Debug, Clone, PartialEq, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct Config { + /// Padding to keep between the edge of the screen and the cursor when scrolling. Defaults to 5. + pub scrolloff: usize, + /// Mouse support. Defaults to true. + pub mouse: bool, +} + +impl Default for Config { + fn default() -> Self { + Self { + scrolloff: 5, + mouse: true, + } + } +} + #[derive(Debug)] pub struct Editor { pub tree: Tree, @@ -33,6 +53,8 @@ pub struct Editor { pub theme_loader: Arc, pub status_msg: Option<(String, Severity)>, + + pub config: Config, } #[derive(Debug, Copy, Clone)] @@ -48,6 +70,7 @@ impl Editor { mut area: Rect, themes: Arc, config_loader: Arc, + config: Config, ) -> Self { let language_servers = helix_lsp::Registry::new(); @@ -66,6 +89,7 @@ impl Editor { registers: Registers::default(), clipboard_provider: get_clipboard_provider(), status_msg: None, + config, } } @@ -108,7 +132,7 @@ impl Editor { fn _refresh(&mut self) { for (view, _) in self.tree.views_mut() { let doc = &self.documents[view.doc]; - view.ensure_cursor_in_view(doc) + view.ensure_cursor_in_view(doc, self.config.scrolloff) } } @@ -267,7 +291,7 @@ impl Editor { pub fn ensure_cursor_in_view(&mut self, id: ViewId) { let view = self.tree.get_mut(id); let doc = &self.documents[view.doc]; - view.ensure_cursor_in_view(doc) + view.ensure_cursor_in_view(doc, self.config.scrolloff) } pub fn document(&self, id: DocumentId) -> Option<&Document> { diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 62ab26424..25efbde53 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -8,8 +8,6 @@ use helix_core::{ Position, RopeSlice, Selection, }; -pub const PADDING: usize = 5; - type Jump = (DocumentId, Selection); #[derive(Debug)] @@ -84,7 +82,7 @@ impl View { } } - pub fn ensure_cursor_in_view(&mut self, doc: &Document) { + pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) { let cursor = doc .selection(self.id) .primary() @@ -95,7 +93,7 @@ impl View { let height = self.area.height.saturating_sub(1); // - 1 for statusline let last_line = (self.first_line + height as usize).saturating_sub(1); - let scrolloff = PADDING.min(self.area.height as usize / 2); // TODO: user pref + let scrolloff = scrolloff.min(self.area.height as usize / 2); // TODO: not ideal const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter