feat(float): open float relative to mouse #21531

Problem:
No easy way to position a LSP hover window relative to mouse.

Solution:
Introduce another option to the `relative` key in `nvim_open_win()`.

With this PR it should be possible to override the handler and do something
similar to this https://github.com/neovim/neovim/pull/19481#issuecomment-1193248674
to have hover information displayed from the mouse.

Test case:

    ```lua
    local util = require('vim.lsp.util')

    local function make_position_param(window, offset_encoding)
        window = window or 0
        local buf = vim.api.nvim_win_get_buf(window)
        local row, col

        local mouse = vim.fn.getmousepos()
        row = mouse.line
        col = mouse.column

        offset_encoding = offset_encoding or util._get_offset_encoding(buf)
        row = row - 1
        local line = vim.api.nvim_buf_get_lines(buf, row, row + 1, true)[1]
        if not line then
            return { line = 0, character = 0 }
        end
        if #line < col then
            return { line = 0, character = 0 }
        end

        col = util._str_utfindex_enc(line, col, offset_encoding)

        return { line = row, character = col }
    end

    local make_params = function(window, offset_encoding)
        window = window or 0
        local buf = vim.api.nvim_win_get_buf(window)
        offset_encoding = offset_encoding or util._get_offset_encoding(buf)
        return {
            textDocument = util.make_text_document_params(buf),
            position = make_position_param(window, offset_encoding),
        }
    end

    local hover_timer = nil
    vim.o.mousemoveevent = true

    vim.keymap.set({ '', 'i' }, '<MouseMove>', function()
        if hover_timer then
            hover_timer:close()
        end
        hover_timer = vim.defer_fn(function()
            hover_timer = nil
            local params = make_params()
            vim.lsp.buf_request(
                0,
                'textDocument/hover',
                params,
                vim.lsp.with(vim.lsp.handlers.hover, {
                    silent = true,
                    focusable = false,
                    relative = 'mouse',
                })
            )
        end, 500)
        return '<MouseMove>'
    end, { expr = true })
    ```
This commit is contained in:
Sebastian Lyng Johansen
2023-01-10 11:22:41 +01:00
committed by GitHub
parent d6cb3328f7
commit 870ca1de52
9 changed files with 53 additions and 5 deletions

View File

@@ -74,6 +74,7 @@
/// - "editor" The global editor grid
/// - "win" Window given by the `win` field, or current window.
/// - "cursor" Cursor position in current window.
/// - "mouse" Mouse position
/// - win: |window-ID| for relative="win".
/// - anchor: Decides which corner of the float to place at (row,col):
/// - "NW" northwest (default)
@@ -349,6 +350,8 @@ static bool parse_float_relative(String relative, FloatRelative *out)
*out = kFloatRelativeWindow;
} else if (striequal(str, "cursor")) {
*out = kFloatRelativeCursor;
} else if (striequal(str, "mouse")) {
*out = kFloatRelativeMouse;
} else {
return false;
}