From 10fa54747552ed1a22ae6eb85d02253f3967b9c3 Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Sat, 1 Feb 2025 17:48:29 +0800 Subject: [PATCH 1/3] remove useless comment --- lua/LspUI/signature/util.lua | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/lua/LspUI/signature/util.lua b/lua/LspUI/signature/util.lua index 78efada..bf3df8d 100644 --- a/lua/LspUI/signature/util.lua +++ b/lua/LspUI/signature/util.lua @@ -28,22 +28,9 @@ local build_signature_info = function(help, client_name) return nil end - -- TODO: this is some debug info, maybe remove - -- lib_util.write_message_to_file( - -- vim.inspect(help), - -- "C:\\Users\\jin\\Downloads\\log.txt" - -- ) - - local active_signature, active_parameter - -- this logic is in order to handle certain lsp specification implementations that are not standard - -- if client_name == "basedpyright" then - -- active_signature = help.activeSignature and help.activeSignature + 1 - -- or 1 - -- active_parameter = help.activeParameter and help.activeParameter or 1 - -- else - active_signature = help.activeSignature and help.activeSignature + 1 or 1 - active_parameter = help.activeParameter and help.activeParameter + 1 or 1 - -- end + local active_signature = help.activeSignature and help.activeSignature + 1 or 1 + local active_parameter = help.activeParameter and help.activeParameter + 1 or 1 + --- @type signature_info ---@diagnostic disable-next-line: missing-fields local res = {} @@ -121,15 +108,10 @@ M.request = function(buffer_id, callback) end local params = lsp.util.make_position_params() - -- TODO: this is debug info should be removed - -- lib_util.write_message_to_file( - -- vim.inspect(params), - -- "C:\\Users\\jin\\Downloads\\log1.txt" - -- ) -- NOTE: we just use one client to get the lsp signature local client = clients[1] - -- for _, client in pairs(clients or {}) do + client.request( signature_feature, params, @@ -151,7 +133,6 @@ M.request = function(buffer_id, callback) end, buffer_id ) - -- end end -- get all valid clients for lightbulb From 955f7579716d6175beafcf16c93a844ac17e33ec Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Tue, 4 Feb 2025 09:40:10 +0800 Subject: [PATCH 2/3] rename code simplify --- lua/LspUI/rename/util.lua | 138 ++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/lua/LspUI/rename/util.lua b/lua/LspUI/rename/util.lua index 166b808..833fdf2 100644 --- a/lua/LspUI/rename/util.lua +++ b/lua/LspUI/rename/util.lua @@ -7,6 +7,11 @@ local lib_notify = require("LspUI.lib.notify") local lib_util = require("LspUI.lib.util") local lib_windows = require("LspUI.lib.windows") +--- @alias LspUI_prepare_rename_res lsp.Range | { range: lsp.Range, placeholder: string } | { defaultBehavior: boolean } | nil + +-- TODO: add progress support !! +-- maybe no need to implemention, because rename is a simple operation + local M = {} -- get all valid clients of rename @@ -14,8 +19,10 @@ local M = {} --- @return vim.lsp.Client[]? clients array or nil M.get_clients = function(buffer_id) -- note: we need get lsp clients attached to current buffer - local clients = - lsp.get_clients({ bufnr = buffer_id, method = rename_feature }) + local clients = lsp.get_clients({ + bufnr = buffer_id, + method = rename_feature, + }) if vim.tbl_isempty(clients) then return nil end @@ -43,22 +50,34 @@ end --- @param client vim.lsp.Client lsp client instance, must be element of func `get_clients` --- @param buffer_id integer buffer id --- @param position_param lsp.PrepareRenameParams this param must be generated by `vim.lsp.util.make_position_params` ---- @param callback function +--- @param callback fun(result:LspUI_prepare_rename_res?) M.prepare_rename = function(client, buffer_id, position_param, callback) - vim.schedule(function() + local function __tmp() client.request( prepare_rename_feature, position_param, - function(err, result) - if err or result == nil then - callback(false) + --- @type lsp.Handler + --- @diagnostic disable-next-line: unused-local + function(err, result, ctx, _) + if err then + lib_notify.Error( + "error code:" .. err.code .. ", " .. err.message + ) + + return + end + --- @type LspUI_prepare_rename_res + local res = result + if result == nil then + callback() return end - callback(true) + callback(res) end, buffer_id ) - end) + end + vim.schedule(__tmp) end -- do rename, a wrap function for prepare_rename and rename @@ -67,45 +86,35 @@ end --- @param buffer_id integer buffer id --- @param position_param lsp.PrepareRenameParams|lsp.RenameParams this param must be generated by `vim.lsp.util.make_position_params`, has newname attribute M.do_rename = function(id, clients, buffer_id, position_param) + local function next_rename() + local next_id, _ = next(clients, id) + M.do_rename(next_id, clients, buffer_id, position_param) + end + local async = uv.new_async(function() local client = clients[id] - -- when client is nil, return if not client then return end - -- TODO: client.supports_method is not listed by document if client.supports_method(prepare_rename_feature) then M.prepare_rename( client, buffer_id, --- @cast position_param lsp.PrepareRenameParams position_param, - -- result is true, that is preparename is ok - --- @param result boolean + -- we no need to resuse the result, we just use it todetect whether we can do rename function(result) - if result then - --- @cast position_param lsp.RenameParams - M.rename(client, buffer_id, position_param, function() - local next_id, _ = next(clients, id) - M.do_rename( - next_id, - clients, - buffer_id, - position_param - ) - end) - else - local next_id, _ = next(clients, id) - M.do_rename(next_id, clients, buffer_id, position_param) + if not result then + next_rename() + return end + --- @cast position_param lsp.RenameParams + M.rename(client, buffer_id, position_param, next_rename) end ) else --- @cast position_param lsp.RenameParams - M.rename(client, buffer_id, position_param, function() - local next_id, _ = next(clients, id) - M.do_rename(next_id, clients, buffer_id, position_param) - end) + M.rename(client, buffer_id, position_param, next_rename) end end) @@ -150,15 +159,10 @@ M.render = function(clients, buffer_id, current_win, old_name) --- @cast old_name string old_name, }) - api.nvim_set_option_value("filetype", "LspUI-rename", { - buf = new_buffer, - }) - api.nvim_set_option_value("modifiable", true, { - buf = new_buffer, - }) - api.nvim_set_option_value("bufhidden", "wipe", { - buf = new_buffer, - }) + + api.nvim_set_option_value("filetype", "LspUI-rename", { buf = new_buffer }) + api.nvim_set_option_value("modifiable", true, { buf = new_buffer }) + api.nvim_set_option_value("bufhidden", "wipe", { buf = new_buffer }) local new_window_wrap = lib_windows.new_window(new_buffer) @@ -187,12 +191,14 @@ M.render = function(clients, buffer_id, current_win, old_name) }) if config.options.rename.auto_select then - vim.cmd([[normal! V]]) - api.nvim_feedkeys( - api.nvim_replace_termcodes("", true, true, true), - "n", - true - ) + api.nvim_win_call(window_id, function() + vim.cmd([[normal! V]]) + api.nvim_feedkeys( + api.nvim_replace_termcodes("", true, true, true), + "n", + true + ) + end) end -- keybinding and autocommand @@ -260,34 +266,32 @@ M.keybinding_autocmd = function( } ) - local insert_change_id = -1 - insert_change_id = api.nvim_create_autocmd( - { "TextChanged", "TextChangedI" }, - { - buffer = new_buffer, - callback = function() - local now_name = api.nvim_get_current_line() - local len = calculate_length(now_name) - api.nvim_win_set_config(window_id, { - width = len, - }) - end, + local autocmd_group_id = + vim.api.nvim_create_augroup("LspUI-rename_autocmd_group", { + clear = true, + }) - desc = lib_util.command_desc( - "automatically lengthen the rename input box" - ), - } - ) + api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, { + group = autocmd_group_id, + buffer = new_buffer, + callback = function() + local now_name = api.nvim_get_current_line() + local len = calculate_length(now_name) + api.nvim_win_set_config(window_id, { + width = len, + }) + end, + desc = lib_util.command_desc( + "automatically lengthen the rename input box" + ), + }) -- auto command: auto close window, when focus leave rename float window api.nvim_create_autocmd("WinLeave", { + group = autocmd_group_id, buffer = new_buffer, once = true, callback = function() - -- delete insert change event - pcall(api.nvim_del_autocmd, insert_change_id) - - -- close window close_window(window_id) end, desc = lib_util.command_desc( From c90f4c5bc455c0e15ced112c5576243416f8c40d Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Tue, 4 Feb 2025 13:39:13 +0800 Subject: [PATCH 3/3] rename code tidy --- lua/LspUI/rename/init.lua | 2 +- lua/LspUI/rename/util.lua | 248 +++++++++++++++++++++++--------------- 2 files changed, 149 insertions(+), 101 deletions(-) diff --git a/lua/LspUI/rename/init.lua b/lua/LspUI/rename/init.lua index f0ffa1b..b15e3ad 100644 --- a/lua/LspUI/rename/init.lua +++ b/lua/LspUI/rename/init.lua @@ -59,7 +59,7 @@ M.run = function() local old_name = fn.expand("") - util.render(clients, current_buffer, current_win, old_name --[[@as string]]) + util.done(clients, current_buffer, current_win, old_name) end return M diff --git a/lua/LspUI/rename/util.lua b/lua/LspUI/rename/util.lua index 833fdf2..ac6b03a 100644 --- a/lua/LspUI/rename/util.lua +++ b/lua/LspUI/rename/util.lua @@ -34,7 +34,7 @@ end --- @param buffer_id integer buffer id --- @param position_param lsp.RenameParams this param must be generated by `vim.lsp.util.make_position_params`, has newname attribute --- @param callback function -M.rename = function(client, buffer_id, position_param, callback) +local function rename(client, buffer_id, position_param, callback) local handler = client.handlers[rename_feature] or lsp.handlers[rename_feature] vim.schedule(function() @@ -51,7 +51,7 @@ end --- @param buffer_id integer buffer id --- @param position_param lsp.PrepareRenameParams this param must be generated by `vim.lsp.util.make_position_params` --- @param callback fun(result:LspUI_prepare_rename_res?) -M.prepare_rename = function(client, buffer_id, position_param, callback) +local function prepare_rename(client, buffer_id, position_param, callback) local function __tmp() client.request( prepare_rename_feature, @@ -63,7 +63,6 @@ M.prepare_rename = function(client, buffer_id, position_param, callback) lib_notify.Error( "error code:" .. err.code .. ", " .. err.message ) - return end --- @type LspUI_prepare_rename_res @@ -80,42 +79,79 @@ M.prepare_rename = function(client, buffer_id, position_param, callback) vim.schedule(__tmp) end +--- @param id integer +--- @param clients vim.lsp.Client[] lsp client instance, must be element of func `get_clients` +--- @param buffer_id integer buffer id +--- @param position_param lsp.PrepareRenameParams|lsp.RenameParams this param must be generated by `vim.lsp.util.make_position_params`, has newname attribute +--- @param callback fun(clients: vim.lsp.Client[]) +--- @param final_clients vim.lsp.Client[] +local function if_rename( + id, + clients, + buffer_id, + position_param, + callback, + final_clients +) + --- @param __final_clients vim.lsp.Client[] + local function __next_rename(__final_clients) + local next_id, _ = next(clients, id) + if_rename( + next_id, + clients, + buffer_id, + position_param, + callback, + __final_clients + ) + end + + if not id then + callback(final_clients) + return + end + + local client = clients[id] + + if client.supports_method(prepare_rename_feature) then + prepare_rename( + client, + buffer_id, + --- @cast position_param lsp.PrepareRenameParams + position_param, + -- we no need to resuse the result, we just use it todetect whether we can do rename + function(result) + if result then + table.insert(final_clients, client) + end + __next_rename(final_clients) + end + ) + return + end + table.insert(final_clients, client) + __next_rename(final_clients) +end + -- do rename, a wrap function for prepare_rename and rename --- @param id integer --- @param clients vim.lsp.Client[] lsp client instance, must be element of func `get_clients` --- @param buffer_id integer buffer id --- @param position_param lsp.PrepareRenameParams|lsp.RenameParams this param must be generated by `vim.lsp.util.make_position_params`, has newname attribute -M.do_rename = function(id, clients, buffer_id, position_param) +local function do_rename(id, clients, buffer_id, position_param) local function next_rename() local next_id, _ = next(clients, id) - M.do_rename(next_id, clients, buffer_id, position_param) + do_rename(next_id, clients, buffer_id, position_param) end local async = uv.new_async(function() - local client = clients[id] - if not client then + if not id then return end - if client.supports_method(prepare_rename_feature) then - M.prepare_rename( - client, - buffer_id, - --- @cast position_param lsp.PrepareRenameParams - position_param, - -- we no need to resuse the result, we just use it todetect whether we can do rename - function(result) - if not result then - next_rename() - return - end - --- @cast position_param lsp.RenameParams - M.rename(client, buffer_id, position_param, next_rename) - end - ) - else - --- @cast position_param lsp.RenameParams - M.rename(client, buffer_id, position_param, next_rename) - end + + local client = clients[id] + --- @cast position_param lsp.RenameParams + rename(client, buffer_id, position_param, next_rename) end) if async then @@ -137,81 +173,11 @@ end -- calculate display length --- @param str string -local calculate_length = function(str) +local function calculate_length(str) local len = fn.strdisplaywidth(str) + 2 return len > 10 and len or 10 end --- render the window ---- @param clients vim.lsp.Client[] ---- @param buffer_id integer ---- @param current_win integer ---- @param old_name string -M.render = function(clients, buffer_id, current_win, old_name) - local position_param = lsp.util.make_position_params(current_win) - - -- Here we need to define window - - local new_buffer = api.nvim_create_buf(false, true) - - -- note: this must set before modifiable, when modifiable is false, this function will fail - api.nvim_buf_set_lines(new_buffer, 0, -1, false, { - --- @cast old_name string - old_name, - }) - - api.nvim_set_option_value("filetype", "LspUI-rename", { buf = new_buffer }) - api.nvim_set_option_value("modifiable", true, { buf = new_buffer }) - api.nvim_set_option_value("bufhidden", "wipe", { buf = new_buffer }) - - local new_window_wrap = lib_windows.new_window(new_buffer) - - -- For aesthetics, the minimum width is 8 - local width = calculate_length(old_name) - - lib_windows.set_width_window(new_window_wrap, width) - lib_windows.set_height_window(new_window_wrap, 1) - lib_windows.set_enter_window(new_window_wrap, true) - lib_windows.set_anchor_window(new_window_wrap, "NW") - lib_windows.set_border_window(new_window_wrap, "rounded") - lib_windows.set_focusable_window(new_window_wrap, true) - lib_windows.set_relative_window(new_window_wrap, "cursor") - lib_windows.set_col_window(new_window_wrap, 1) - lib_windows.set_row_window(new_window_wrap, 1) - lib_windows.set_style_window(new_window_wrap, "minimal") - lib_windows.set_right_title_window(new_window_wrap, "rename") - - local window_id = lib_windows.display_window(new_window_wrap) - - api.nvim_set_option_value("winhighlight", "Normal:Normal", { - win = window_id, - }) - api.nvim_set_option_value("winblend", config.options.rename.transparency, { - win = window_id, - }) - - if config.options.rename.auto_select then - api.nvim_win_call(window_id, function() - vim.cmd([[normal! V]]) - api.nvim_feedkeys( - api.nvim_replace_termcodes("", true, true, true), - "n", - true - ) - end) - end - - -- keybinding and autocommand - M.keybinding_autocmd( - window_id, - old_name, - clients, - buffer_id, - new_buffer, - position_param - ) -end - -- keybinding and autocommand --- @param window_id integer rename float window's id --- @param old_name string the word's old name @@ -219,7 +185,7 @@ end --- @param old_buffer integer the buffer which word belongs to --- @param new_buffer integer the buffer which attach to rename float window --- @param position_param lsp.PrepareRenameParams|lsp.RenameParams this param must be generated by `vim.lsp.util.make_position_params` -M.keybinding_autocmd = function( +local function keybinding_autocmd( window_id, old_name, clients, @@ -241,7 +207,7 @@ M.keybinding_autocmd = function( local new_name = vim.trim(api.nvim_get_current_line()) if old_name ~= new_name then position_param.newName = new_name - M.do_rename(1, clients, old_buffer, position_param) + do_rename(1, clients, old_buffer, position_param) end close_window(window_id) end, @@ -300,4 +266,86 @@ M.keybinding_autocmd = function( }) end +-- render the window +--- @param clients vim.lsp.Client[] +--- @param buffer_id integer +--- @param old_name string +--- @param position_param lsp.PrepareRenameParams|lsp.RenameParams this param must be generated by `vim.lsp.util.make_position_params` +local function render(clients, buffer_id, old_name, position_param) + local new_buffer = api.nvim_create_buf(false, true) + + -- note: this must set before modifiable, when modifiable is false, this function will fail + api.nvim_buf_set_lines(new_buffer, 0, -1, false, { + --- @cast old_name string + old_name, + }) + + api.nvim_set_option_value("filetype", "LspUI-rename", { buf = new_buffer }) + api.nvim_set_option_value("modifiable", true, { buf = new_buffer }) + api.nvim_set_option_value("bufhidden", "wipe", { buf = new_buffer }) + + local new_window_wrap = lib_windows.new_window(new_buffer) + + -- For aesthetics, the minimum width is 8 + local width = calculate_length(old_name) + + lib_windows.set_width_window(new_window_wrap, width) + lib_windows.set_height_window(new_window_wrap, 1) + lib_windows.set_enter_window(new_window_wrap, true) + lib_windows.set_anchor_window(new_window_wrap, "NW") + lib_windows.set_border_window(new_window_wrap, "rounded") + lib_windows.set_focusable_window(new_window_wrap, true) + lib_windows.set_relative_window(new_window_wrap, "cursor") + lib_windows.set_col_window(new_window_wrap, 1) + lib_windows.set_row_window(new_window_wrap, 1) + lib_windows.set_style_window(new_window_wrap, "minimal") + lib_windows.set_right_title_window(new_window_wrap, "rename") + + local window_id = lib_windows.display_window(new_window_wrap) + + api.nvim_set_option_value("winhighlight", "Normal:Normal", { + win = window_id, + }) + api.nvim_set_option_value("winblend", config.options.rename.transparency, { + win = window_id, + }) + + if config.options.rename.auto_select then + api.nvim_win_call(window_id, function() + vim.cmd([[normal! V]]) + api.nvim_feedkeys( + api.nvim_replace_termcodes("", true, true, true), + "n", + true + ) + end) + end + + -- keybinding and autocommand + keybinding_autocmd( + window_id, + old_name, + clients, + buffer_id, + new_buffer, + position_param + ) +end + +-- render the window +--- @param clients vim.lsp.Client[] +--- @param buffer_id integer +--- @param current_win integer +--- @param old_name string +M.done = function(clients, buffer_id, current_win, old_name) + local position_param = lsp.util.make_position_params(current_win) + if_rename(1, clients, buffer_id, position_param, function(__clients) + if #__clients < 1 then + lib_notify.Info("This position can not rename!") + return + end + render(__clients, buffer_id, old_name, position_param) + end, {}) +end + return M