diff --git a/lua/hop/init.lua b/lua/hop/init.lua index b82c87cd..4f5c9a5e 100644 --- a/lua/hop/init.lua +++ b/lua/hop/init.lua @@ -116,11 +116,20 @@ local function set_unmatched_lines(buf_handle, hl_ns, top_line, bottom_line, cur priority = prio.DIM_PRIO } - if end_col then - local current_line = vim.api.nvim_buf_get_lines(buf_handle, cursor_pos[1] - 1, cursor_pos[1], true)[1] - local current_width = vim.fn.strdisplaywidth(current_line) + local current_line = vim.api.nvim_buf_get_lines(buf_handle, cursor_pos[1] - 1, cursor_pos[1], true)[1] + local current_width = vim.fn.strdisplaywidth(current_line) - if end_col > current_width then + -- keep start_col within valid range + if current_width == 0 then + start_col = 0 + elseif start_col >= current_width then + start_col = current_width - 1 + end + if end_col then + -- keep end_col within valid range + if current_width == 0 then + end_col = 0 + elseif end_col >= current_width then end_col = current_width - 1 end diff --git a/lua/hop/window.lua b/lua/hop/window.lua index 289b04ad..d4ab1c0a 100644 --- a/lua/hop/window.lua +++ b/lua/hop/window.lua @@ -3,35 +3,37 @@ local hint = require'hop.hint' local M = {} local function window_context(win_handle, cursor_pos) - -- get a bunch of information about the window and the cursor - vim.api.nvim_set_current_win(win_handle) - local win_info = vim.fn.getwininfo(win_handle)[1] - local win_view = vim.fn.winsaveview() - local top_line = win_info.topline - 1 - local bot_line = win_info.botline - - -- NOTE: due to an (unknown yet) bug in neovim, the sign_width is not correctly reported when shifting the window - -- view inside a non-wrap window, so we can’t rely on this; for this reason, we have to implement a weird hack that - -- is going to disable the signs while hop is running (I’m sorry); the state is restored after jump - -- local left_col_offset = win_info.variables.context.number_width + win_info.variables.context.sign_width - local win_width = nil - - -- hack to get the left column offset in nowrap - if not vim.wo.wrap then - vim.api.nvim_win_set_cursor(win_handle, { cursor_pos[1], 0 }) - local left_col_offset = vim.fn.wincol() - 1 - vim.fn.winrestview(win_view) - win_width = win_info.width - left_col_offset - end + -- get window context without changing current window + return vim.api.nvim_win_call(win_handle, function() + -- get a bunch of information about the window and the cursor + local win_info = vim.fn.getwininfo(win_handle)[1] + local win_view = vim.fn.winsaveview() + local top_line = win_info.topline - 1 + local bot_line = win_info.botline + + -- NOTE: due to an (unknown yet) bug in neovim, the sign_width is not correctly reported when shifting the window + -- view inside a non-wrap window, so we can’t rely on this; for this reason, we have to implement a weird hack that + -- is going to disable the signs while hop is running (I’m sorry); the state is restored after jump + -- local left_col_offset = win_info.variables.context.number_width + win_info.variables.context.sign_width + local win_width = nil + + -- hack to get the left column offset in nowrap + if not vim.wo.wrap then + vim.api.nvim_win_set_cursor(win_handle, { cursor_pos[1], 0 }) + local left_col_offset = vim.fn.wincol() - 1 + vim.fn.winrestview(win_view) + win_width = win_info.width - left_col_offset + end - return { - hwin = win_handle, - cursor_pos = cursor_pos, - top_line = top_line, - bot_line = bot_line, - win_width = win_width, - col_offset = win_view.leftcol - } + return { + hwin = win_handle, + cursor_pos = cursor_pos, + top_line = top_line, + bot_line = bot_line, + win_width = win_width, + col_offset = win_view.leftcol + } + end) end -- Collect all multi-windows's context: @@ -64,9 +66,9 @@ function M.get_window_context(multi_windows) end for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do - local b = vim.api.nvim_win_get_buf(w) - if w ~= cur_hwin then - + -- suppress error "Invalid buffer id: N" when this is a floating window + local b = vim.F.npcall(vim.api.nvim_win_get_buf, w) + if w ~= cur_hwin and b then -- check duplicated buffers; the way this is done is by accessing all the already known contexts and checking that -- the buffer we are accessing is already present in; if it is, we then append the window context to that buffer local bctx = nil