Skip to content

Keep following text visible when opening previews with wrapped lines - #81

Open
denny0223 wants to merge 2 commits into
delphinus:mainfrom
denny0223:fix/preview-wrapped-context
Open

denny0223 wants to merge 2 commits into
delphinus:mainfrom
denny0223:fix/preview-wrapped-context

Conversation

@denny0223

@denny0223 denny0223 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Opening a preview near the end of a document with wrapped lines can put the cursor on the bottom row and hide the next paragraph. This change keeps that following text visible in this case while preserving #80's protection against scrolling past the end.

#80 prevents unnecessary scrolling when a document fits in the window, and avoids excess blank rows below the end of longer documents. Its EOF limit uses buffer line counts, but a buffer line can occupy several screen rows. The limit can therefore pull the view too far toward the start of the document. Neovim then scrolls only enough to bring the mapped cursor back into view at the bottom.

This change measures the screen rows remaining from the proposed starting position. If they fill the window, it applies that position; otherwise it uses Neovim's native bottom alignment. It then places the cursor on the same mapped line. The height query and bottom-alignment command are already used by split synchronization.

The new test case for wrapped lines attaches its own 120×40 UI and checks that the following paragraph is actually drawn and the end of the document aligns with the bottom of the window. It fails on #80 and passes with this change on Neovim 0.12.0 and 0.12.5. The test file also covers short-document behavior, unwrapped EOF alignment, and cursor/source preservation.

Run from this PR's repository root:

nvim --headless -u NONE --noplugin -l tests/preview_scroll_test.lua
Verify the failure on #80 and the fix with the same test

Run these commands from this PR's repository root. Both runs use the PR version of the test; the baseline worktree supplies the unchanged plugin code. The baseline run is expected to exit with status 1 and report the paragraph after the cursor is off screen.

pr_dir=$PWD
base_dir=$(mktemp -d)
git worktree add --detach "$base_dir" 4f6d73a276356bc23dbffa594d2a54dc978e98bb
(cd "$base_dir" && nvim --headless -u NONE --noplugin -l "$pr_dir/tests/preview_scroll_test.lua")
nvim --headless -u NONE --noplugin -l tests/preview_scroll_test.lua
git worktree remove "$base_dir"
Plugin version Result with the same PR test
#80 / 4f6d73a 8 passed, 1 failed: following paragraph off screen
This change 9 passed, 0 failed

The test creates its own UI, so its result does not depend on your terminal size.

Validation against that upstream base:

  • make -k test passes on Neovim 0.12.0 and 0.12.5 (28 Lua test files). The optional PlantUML renderer test is skipped because no renderer is available locally.
  • StyLua 2.5.2 and Luacheck 1.2.0 pass.

The change retains the existing initial centering estimate and leaves the floating-window height issue noted in #80 separate.

Reproduce the visible behavior interactively

Save this snippet as a temporary .vim file outside the repository. It generates 13 numbered test paragraphs; Para12 and Para13 are simply the labels for paragraphs 12 and 13:

enew
setlocal filetype=markdown
set scrolloff=0 laststatus=2
lua << EOF
local lines = {}
for i = 1, 13 do
  lines[#lines + 1] = ("Para%02d "):format(i) .. string.rep("x", 145)
  lines[#lines + 1] = ""
end
vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
vim.api.nvim_win_set_cursor(0, { 23, 0 })
EOF
MdRender tab

From the repository root of each revision listed below, start a fresh Neovim:

nvim --clean --cmd 'set runtimepath^=.'

Resize the terminal so :echo &columns &lines reports 120 40, then run :source /path/to/your/repro.vim. The script places the source cursor in paragraph 12, the second-to-last paragraph, and opens the tab preview. Look for paragraph 13 below the cursor and any unused rows below the end of the document.

With the same snippet, terminal size, and operation:

Version Observed behavior
Before #80 (a10f025) The final paragraph is visible, but unused rows remain below the end of the document.
With #80 (4f6d73a) The cursor is on the bottom row and the final paragraph is off screen.
This PR The final paragraph is visible and the end of the document reaches the bottom row.

Repeat in the other checkouts at the same terminal size. Exit each reproduction with :qa!.

Capping the topline by buffer line count moves the cursor to the bottom
when following wrapped content already fills the screen. Measure the
remaining screen rows, stopping before later buffer lines once a window
is filled, and use the existing native EOF alignment only when those
rows would leave a gap.

Keep the original centering path when enough screen rows remain. Add EOF
and attached-UI wrapping regressions alongside the upstream tests.

Upstream-PR: delphinus#80
(cherry picked from commit 86c7c95)
Move the wrapped preview fixture to the penultimate paragraph so the same
case demonstrates both following-text visibility and EOF alignment.

Assert that the document's last line reaches the window's last screen row
using the actual window geometry. Preserve the cursor mapping and source
checks.

The additional assertion catches wrapped previews that show the following
paragraph but still leave unused rows below the end of the document.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant