From d2460ea4247e893715d18b8b3fb4e60a0ee06653 Mon Sep 17 00:00:00 2001 From: Uison Yoon Date: Wed, 29 Aug 2018 18:56:38 +0900 Subject: [PATCH 1/2] Handling continuous scroll key input. Add impulse checking the current velocity value. Without this patch, keeping pressing scroll key, it doessn't stop properly. This patch make to set a upper limit to velocity value. Add a function for distance instead of impluse. It will help to move a specific lines. But it will ignore the air_drag value. It is hard to calculate the impulse value to move a certain distance with air_drag. --- autoload/comfortable_motion.vim | 56 ++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/autoload/comfortable_motion.vim b/autoload/comfortable_motion.vim index 5aa3a23..354f261 100644 --- a/autoload/comfortable_motion.vim +++ b/autoload/comfortable_motion.vim @@ -37,6 +37,7 @@ let s:comfortable_motion_state = { \ 'impulse': 0.0, \ 'velocity': 0.0, \ 'delta': 0.0, +\ 'air_drag' : 0.0, \ } function! s:tick(timer_id) @@ -50,7 +51,7 @@ function! s:tick(timer_id) \ ? 0 \ : l:st.velocity / abs(l:st.velocity) let l:friction = -l:vel_sign * g:comfortable_motion_friction * 1 " The mass is 1 - let l:air_drag = -l:st.velocity * g:comfortable_motion_air_drag + let l:air_drag = -l:st.velocity * l:st.air_drag let l:additional_force = l:friction + l:air_drag " Update the state @@ -58,17 +59,37 @@ function! s:tick(timer_id) let l:st.velocity += l:st.impulse + (abs(l:additional_force * l:dt) > abs(l:st.velocity) ? -l:st.velocity : l:additional_force * l:dt) let l:st.impulse = 0 + " Current Position + let l:topline = line('w0') + let l:botline = line('w$') + " Scroll let l:int_delta = float2nr(l:st.delta >= 0 ? floor(l:st.delta) : ceil(l:st.delta)) let l:st.delta -= l:int_delta if l:int_delta > 0 - execute "normal! " . string(abs(l:int_delta)) . g:comfortable_motion_scroll_down_key + if l:botline == line("$") " when can see bottom line, move cursor + execute "normal! " . string(abs(l:int_delta)) . "j" + else + execute "normal! " . string(abs(l:int_delta)) . g:comfortable_motion_scroll_down_key + endif elseif l:int_delta < 0 - execute "normal! " . string(abs(l:int_delta)) . g:comfortable_motion_scroll_up_key + if l:topline == 1 + execute "normal! " . string(abs(l:int_delta)) . "k" + else + execute "normal! " . string(abs(l:int_delta)) . g:comfortable_motion_scroll_up_key + endif else " Do nothing endif redraw + + " stop at the top and bottom + let l:pos = getpos('.') + if ( l:pos[1] == 1 && l:st.velocity < 0 ) + \ || ( l:pos[1] == line('$') && l:st.velocity > 0 ) + let l:st.velocity = 0 + let l:st.delta = 0 + endif else " Stop scrolling and the thread let l:st.velocity = 0 @@ -78,13 +99,38 @@ function! s:tick(timer_id) endif endfunction -function! comfortable_motion#flick(impulse) +function! comfortable_motion#flick_impl(impulse, air_drag) + let l:st = s:comfortable_motion_state " This is just an alias for the global variable + let l:st.air_drag = a:air_drag if !exists('s:timer_id') " There is no thread, start one let l:interval = float2nr(round(g:comfortable_motion_interval)) let s:timer_id = timer_start(l:interval, function("s:tick"), {'repeat': -1}) endif - let s:comfortable_motion_state.impulse += a:impulse + + " stop if velocity and impulse is not same direction + if ( l:st.velocity > 0 && a:impulse < 0 ) + \ || ( l:st.velocity < 0 && a:impulse > 0 ) + let s:comfortable_motion_state.impulse -= l:st.velocity * 4 / 5 "stop smoothly + else + let s:comfortable_motion_state.impulse = a:impulse - l:st.velocity + endif +endfunction + +function! comfortable_motion#flick(impulse, air_drag) + call comfortable_motion#flick_impl( a:impulse, g:comfortable_motion_air_drag ) +endfunction + +function! comfortable_motion#flickDist(dist) + let l:friction = g:comfortable_motion_friction + let l:dt = g:comfortable_motion_interval / 1000.0 + let l:fdt = l:friction * l:dt + let l:fddt = l:fdt * l:dt + let l:dist_sign = a:dist == 0 ? 0 : a:dist / abs(a:dist) + + let l:impulse = l:fdt * ( sqrt( 2.0 * abs(a:dist) / l:fddt + 1.0/4.0 ) - 1.0/2.0 ) + + call comfortable_motion#flick_impl( l:impulse * l:dist_sign, 0 ) endfunction let &cpo = s:save_cpo From d8b24d7c37188094279cc1454640e31fa0a34be3 Mon Sep 17 00:00:00 2001 From: Uison Yoon Date: Thu, 22 Nov 2018 19:34:58 +0900 Subject: [PATCH 2/2] Turn off syntax for fast scrolling. --- autoload/comfortable_motion.vim | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/autoload/comfortable_motion.vim b/autoload/comfortable_motion.vim index 354f261..277114c 100644 --- a/autoload/comfortable_motion.vim +++ b/autoload/comfortable_motion.vim @@ -38,6 +38,7 @@ let s:comfortable_motion_state = { \ 'velocity': 0.0, \ 'delta': 0.0, \ 'air_drag' : 0.0, +\ 'syntax' : '' \ } function! s:tick(timer_id) @@ -91,6 +92,8 @@ function! s:tick(timer_id) let l:st.delta = 0 endif else + execute "setlocal syntax=".s:comfortable_motion_state.syntax + "let g:airline#extensions#wordcount#enabled = 1 " Stop scrolling and the thread let l:st.velocity = 0 let l:st.delta = 0 @@ -103,17 +106,25 @@ function! comfortable_motion#flick_impl(impulse, air_drag) let l:st = s:comfortable_motion_state " This is just an alias for the global variable let l:st.air_drag = a:air_drag if !exists('s:timer_id') + let s:comfortable_motion_state.syntax = &syntax + "let g:airline#extensions#wordcount#enabled = 0 " There is no thread, start one let l:interval = float2nr(round(g:comfortable_motion_interval)) let s:timer_id = timer_start(l:interval, function("s:tick"), {'repeat': -1}) + else + if l:st.velocity > a:impulse * 3 + execute "setlocal syntax=" + endif endif " stop if velocity and impulse is not same direction if ( l:st.velocity > 0 && a:impulse < 0 ) \ || ( l:st.velocity < 0 && a:impulse > 0 ) - let s:comfortable_motion_state.impulse -= l:st.velocity * 4 / 5 "stop smoothly + "let s:comfortable_motion_state.impulse -= l:st.velocity * 4 / 5 + "let s:comfortable_motion_state.impulse = a:impulse + let s:comfortable_motion_state.impulse += a:impulse else - let s:comfortable_motion_state.impulse = a:impulse - l:st.velocity + let s:comfortable_motion_state.impulse += a:impulse - l:st.velocity * 0.6 endif endfunction