···9696 end)
9797end
98989999+function M.align()
100100+ local win = vim.api.nvim_get_current_win()
101101+102102+ local function step(delta, m, start, dst)
103103+ local diff = dst.row - start.row
104104+105105+ -- reached dst or overshot
106106+ -- - diff == 0: no more distance to travel
107107+ -- - diff * m: both need to be oriented in the same direction (positive product)
108108+ if diff == 0 or diff * m < 0 then
109109+ return true
110110+ end
111111+112112+ -- travel t of the current diff (ceiled), at least 1
113113+ local s = math.max(1, math.ceil(H.coillerp(math.abs(diff), delta)))
114114+ start.row = start.row + (m * s)
115115+116116+ vim._with({ win = win }, function()
117117+ for _ = 1, s do
118118+ local key = vim.api.nvim_replace_termcodes(m > 0 and "<c-y>" or "<c-e>", true, false, true)
119119+ vim.api.nvim_feedkeys(key, "n", false)
120120+ end
121121+ end)
122122+ end
123123+124124+ M.smooth(win, step, function()
125125+ local buf, lnum, col = unpack(vim.fn.getpos("."))
126126+ local start = vim.pos.cursor(buf, { lnum, col })
127127+128128+ local m
129129+ local wfirst = vim.fn.getpos("w0")[2]
130130+ local wlast = vim.fn.getpos("w$")[2]
131131+ -- no lines are visible
132132+ if wlast < wfirst then
133133+ m = 0
134134+ end
135135+ local dst = vim.pos.cursor(buf, { math.ceil(wfirst + (wlast - wfirst) / 2), col })
136136+ local diff = dst.row - start.row
137137+ m = m or diff / math.abs(diff)
138138+139139+ return { m, start, dst }
140140+ end)
141141+end
142142+99143vim.keymap.set("n", "<plug>(smoothie-ctrl-d)", function()
100144 vim._with({ win = 0 }, function()
101145 M.scroll(vim.v.count1)
···104148vim.keymap.set("n", "<plug>(smoothie-ctrl-u)", function()
105149 vim._with({ win = 0 }, function()
106150 M.scroll(-vim.v.count1)
151151+ end)
152152+end)
153153+vim.keymap.set("n", "<plug>(smoothie-zz)", function()
154154+ vim._with({ win = 0 }, function()
155155+ M.align()
107156 end)
108157end)
109158