diff --git a/Cargo.lock b/Cargo.lock index ff1041695e1f1e95bcbc05798d1a1e0f953533ff..5de8cdd6a648e5ab1f43f8ddfc2c0e37983b279f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18097,6 +18097,7 @@ dependencies = [ "language", "log", "lsp", + "markdown_preview", "menu", "multi_buffer", "nvim-rs", diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 1fb02e6c1f1bf41349af7af0a38d41ba2e260072..0bcbb455b502642237347cf9fc36b91eab83f20b 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -1192,8 +1192,12 @@ { "context": "MarkdownPreview", "bindings": { - "pageup": "markdown::MovePageUp", - "pagedown": "markdown::MovePageDown" + "pageup": "markdown::ScrollPageUp", + "pagedown": "markdown::ScrollPageDown", + "up": "markdown::ScrollUp", + "down": "markdown::ScrollDown", + "alt-up": "markdown::ScrollUpByItem", + "alt-down": "markdown::ScrollDownByItem" } }, { diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 9edfaa03f8d7c9609d7b642ee7ddf61973f75e76..65ac280ba7f782cef417aef220dacd7f32f9e6ff 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -1296,8 +1296,12 @@ { "context": "MarkdownPreview", "bindings": { - "pageup": "markdown::MovePageUp", - "pagedown": "markdown::MovePageDown" + "pageup": "markdown::ScrollPageUp", + "pagedown": "markdown::ScrollPageDown", + "up": "markdown::ScrollUp", + "down": "markdown::ScrollDown", + "alt-up": "markdown::ScrollUpByItem", + "alt-down": "markdown::ScrollDownByItem" } }, { diff --git a/assets/keymaps/default-windows.json b/assets/keymaps/default-windows.json index a4211e3c25a58f0ca485cae82c39d0018fc5ed46..990902df14ad0beccc0c79db2a006368017f5965 100644 --- a/assets/keymaps/default-windows.json +++ b/assets/keymaps/default-windows.json @@ -1220,8 +1220,12 @@ "context": "MarkdownPreview", "use_key_equivalents": true, "bindings": { - "pageup": "markdown::MovePageUp", - "pagedown": "markdown::MovePageDown" + "pageup": "markdown::ScrollPageUp", + "pagedown": "markdown::ScrollPageDown", + "up": "markdown::ScrollUp", + "down": "markdown::ScrollDown", + "alt-up": "markdown::ScrollUpByItem", + "alt-down": "markdown::ScrollDownByItem" } }, { diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 7e5bc30c1ff64a637aeefbb92063d2abed7e56cd..533db14a5f7bba4196f6a45cabfbe5d9052f796a 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -1046,5 +1046,14 @@ "g g": "settings_editor::FocusFirstNavEntry", "shift-g": "settings_editor::FocusLastNavEntry" } + }, + { + "context": "MarkdownPreview", + "bindings": { + "ctrl-u": "markdown::ScrollPageUp", + "ctrl-d": "markdown::ScrollPageDown", + "ctrl-y": "markdown::ScrollUp", + "ctrl-e": "markdown::ScrollDown" + } } ] diff --git a/crates/markdown_preview/src/markdown_preview.rs b/crates/markdown_preview/src/markdown_preview.rs index 77bad89a629cbb1f660e1cd16158d4dbca03361e..61c99764add0a96135730d3cccfe4ef744a63d40 100644 --- a/crates/markdown_preview/src/markdown_preview.rs +++ b/crates/markdown_preview/src/markdown_preview.rs @@ -11,9 +11,19 @@ actions!( markdown, [ /// Scrolls up by one page in the markdown preview. - MovePageUp, + #[action(deprecated_aliases = ["markdown::MovePageUp"])] + ScrollPageUp, /// Scrolls down by one page in the markdown preview. - MovePageDown, + #[action(deprecated_aliases = ["markdown::MovePageDown"])] + ScrollPageDown, + /// Scrolls up by approximately one visual line. + ScrollUp, + /// Scrolls down by approximately one visual line. + ScrollDown, + /// Scrolls up by one markdown element in the markdown preview + ScrollUpByItem, + /// Scrolls down by one markdown element in the markdown preview + ScrollDownByItem, /// Opens a markdown preview for the current file. OpenPreview, /// Opens a markdown preview in a split pane. diff --git a/crates/markdown_preview/src/markdown_preview_view.rs b/crates/markdown_preview/src/markdown_preview_view.rs index df8201dc7a3dad18c279582d668304ce9e1cf77b..20613b112eeccf76ec8be12bddc49c12b600ff9b 100644 --- a/crates/markdown_preview/src/markdown_preview_view.rs +++ b/crates/markdown_preview/src/markdown_preview_view.rs @@ -1,3 +1,4 @@ +use std::cmp::min; use std::sync::Arc; use std::time::Duration; use std::{ops::Range, path::PathBuf}; @@ -20,11 +21,12 @@ use workspace::{Pane, Workspace}; use crate::markdown_elements::ParsedMarkdownElement; use crate::markdown_renderer::CheckboxClickedEvent; use crate::{ - MovePageDown, MovePageUp, OpenFollowingPreview, OpenPreview, OpenPreviewToTheSide, + OpenFollowingPreview, OpenPreview, OpenPreviewToTheSide, ScrollPageDown, ScrollPageUp, markdown_elements::ParsedMarkdown, markdown_parser::parse_markdown, markdown_renderer::{RenderContext, render_markdown_block}, }; +use crate::{ScrollDown, ScrollDownByItem, ScrollUp, ScrollUpByItem}; const REPARSE_DEBOUNCE: Duration = Duration::from_millis(200); @@ -425,7 +427,7 @@ impl MarkdownPreviewView { !(current_block.is_list_item() && next_block.map(|b| b.is_list_item()).unwrap_or(false)) } - fn scroll_page_up(&mut self, _: &MovePageUp, _window: &mut Window, cx: &mut Context) { + fn scroll_page_up(&mut self, _: &ScrollPageUp, _window: &mut Window, cx: &mut Context) { let viewport_height = self.list_state.viewport_bounds().size.height; if viewport_height.is_zero() { return; @@ -435,7 +437,12 @@ impl MarkdownPreviewView { cx.notify(); } - fn scroll_page_down(&mut self, _: &MovePageDown, _window: &mut Window, cx: &mut Context) { + fn scroll_page_down( + &mut self, + _: &ScrollPageDown, + _window: &mut Window, + cx: &mut Context, + ) { let viewport_height = self.list_state.viewport_bounds().size.height; if viewport_height.is_zero() { return; @@ -444,6 +451,56 @@ impl MarkdownPreviewView { self.list_state.scroll_by(viewport_height); cx.notify(); } + + fn scroll_up(&mut self, _: &ScrollUp, window: &mut Window, cx: &mut Context) { + let scroll_top = self.list_state.logical_scroll_top(); + if let Some(bounds) = self.list_state.bounds_for_item(scroll_top.item_ix) { + let item_height = bounds.size.height; + // Scroll no more than the rough equivalent of a large headline + let max_height = window.rem_size() * 2; + let scroll_height = min(item_height, max_height); + self.list_state.scroll_by(-scroll_height); + } + cx.notify(); + } + + fn scroll_down(&mut self, _: &ScrollDown, window: &mut Window, cx: &mut Context) { + let scroll_top = self.list_state.logical_scroll_top(); + if let Some(bounds) = self.list_state.bounds_for_item(scroll_top.item_ix) { + let item_height = bounds.size.height; + // Scroll no more than the rough equivalent of a large headline + let max_height = window.rem_size() * 2; + let scroll_height = min(item_height, max_height); + self.list_state.scroll_by(scroll_height); + } + cx.notify(); + } + + fn scroll_up_by_item( + &mut self, + _: &ScrollUpByItem, + _window: &mut Window, + cx: &mut Context, + ) { + let scroll_top = self.list_state.logical_scroll_top(); + if let Some(bounds) = self.list_state.bounds_for_item(scroll_top.item_ix) { + self.list_state.scroll_by(-bounds.size.height); + } + cx.notify(); + } + + fn scroll_down_by_item( + &mut self, + _: &ScrollDownByItem, + _window: &mut Window, + cx: &mut Context, + ) { + let scroll_top = self.list_state.logical_scroll_top(); + if let Some(bounds) = self.list_state.bounds_for_item(scroll_top.item_ix) { + self.list_state.scroll_by(bounds.size.height); + } + cx.notify(); + } } impl Focusable for MarkdownPreviewView { @@ -496,6 +553,10 @@ impl Render for MarkdownPreviewView { .track_focus(&self.focus_handle(cx)) .on_action(cx.listener(MarkdownPreviewView::scroll_page_up)) .on_action(cx.listener(MarkdownPreviewView::scroll_page_down)) + .on_action(cx.listener(MarkdownPreviewView::scroll_up)) + .on_action(cx.listener(MarkdownPreviewView::scroll_down)) + .on_action(cx.listener(MarkdownPreviewView::scroll_up_by_item)) + .on_action(cx.listener(MarkdownPreviewView::scroll_down_by_item)) .size_full() .bg(cx.theme().colors().editor_background) .p_4() diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index a5834f855034ef97b7d0d34b01a7d13f50369a1e..74409a6c255645378b0b2829f4d0045776bfa019 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -63,6 +63,7 @@ indoc.workspace = true language = { workspace = true, features = ["test-support"] } project = { workspace = true, features = ["test-support"] } lsp = { workspace = true, features = ["test-support"] } +markdown_preview.workspace = true parking_lot.workspace = true project_panel.workspace = true release_channel.workspace = true diff --git a/crates/vim/src/test/vim_test_context.rs b/crates/vim/src/test/vim_test_context.rs index 80208fb23ee229c4dc90a7d792ce0348f59ed950..acd77839f2d8cc09ed72993638ff4ec66f79d3fc 100644 --- a/crates/vim/src/test/vim_test_context.rs +++ b/crates/vim/src/test/vim_test_context.rs @@ -28,6 +28,7 @@ impl VimTestContext { search::init(cx); theme::init(theme::LoadThemes::JustBase, cx); settings_ui::init(cx); + markdown_preview::init(cx); }); }