vim-smooth-scroll icon indicating copy to clipboard operation
vim-smooth-scroll copied to clipboard

Incorrect behaviour with wrapped text

Open manu0600 opened this issue 5 years ago • 1 comments

When a line is too long to fit the screen and wrap to the next visible line (it appears as multiple lines on the screen, even though there is only one line number), as seen on the attached screenshot, the command Ctrl-e and Ctrl-y on which the plugin is based make a jump of more than one visible line. The result is when I have many wrapped lines in a text, the smooth scroll scrolls much more than intended, rendering it useless. Screenshot_20200923_102613

Is there a way to change this behavior to the command Ctrl-e and Ctrl-y in the vimrc ? or any other command that can replace it ?

manu0600 avatar Sep 23 '20 08:09 manu0600

this is the basic fix. if you were integrating it in the production plugin you'd do a few things better.

nmap <silent> <c-u> :call <SID>wrapped_smooth_scroll_page('u',1,4)<CR>
nmap <silent> <c-d> :call <SID>wrapped_smooth_scroll_page('d',1,4)<CR>
nmap <silent> <c-b> :call <SID>wrapped_smooth_scroll_page('u',0,4)<CR>
nmap <silent> <c-f> :call <SID>wrapped_smooth_scroll_page('d',0,4)<CR>


function! s:wrapped_smooth_scroll_page(...)
  " kcl: 2021.10.12 scroll smoothly in the presence of `wrap`
  " Idea: It's actually "logical screen units" so c-f and c-b want to move you to the next one, which will depend on the lines you can't see (and their length/wrapping, and folds) (consider also a case where one line spans multiple screens, but vim cannot put a partial visible line at the top of the screen. minimum 1 line works.) Idea: go up until [what was] the top line is past the bottom, stop at zero, simple `while()`.
  " Remark: It would be better if we could pre-calculate the total lines and pass the total as a batch command to smooth_scroll, or handle ourselves. I suspect any pending delay after a long scroll is due to this, from incorrect buildup

  let lines = 1
  let frames = 1
  let msdelay = 4

  let updown = 'd'
  let half = 0

  if a:0 > 0
    let updown = a:1
  endif

  if a:0 > 1
    let half = a:2
  endif

  if a:0 > 2
    let msdelay = a:3
  endif

  if 'ud' !~# updown
    echom 'Error: Mode string must be either [u]p or [d]own.'
    return
  endif

  let top = line('w0')
  let bottom = line('w$')

  let middle = top + ((bottom - top) / 2)

  let i = 0
  let minimal = 1

  if updown ==# 'u'

    let target = half ? middle : top

    while (line('.') > 1 ) && (i < minimal || target <= line('w$') - &scrolloff)
      call smooth_scroll#up(lines, msdelay, frames)
      let i += 1
    endwhile

  else

    let target = half ? middle : bottom

    while (line('.') <= line('$') ) && (i < minimal || line('w0') + &scrolloff <= target)
      call smooth_scroll#down(lines, msdelay, frames)
      let i += 1
    endwhile

  endif

endfunction

kevinlawler avatar Oct 25 '21 16:10 kevinlawler