-
Notifications
You must be signed in to change notification settings - Fork 293
feat(mini.files): make file system actions LSP aware #2340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2bb3806
489a29d
2bdbe07
4bebe2f
9ce04e1
6f18571
18ca59f
a28c7f8
4dd5d2e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2734,10 +2734,37 @@ H.fs_actions_to_lines = function(fs_actions) | |
| end | ||
|
|
||
| H.fs_actions_apply = function(fs_actions) | ||
| local filtered_create = vim.tbl_filter( | ||
| function(diff) return diff.from and diff.action == 'create' and not H.fs_is_present_path(diff.from) end, | ||
| fs_actions | ||
| ) | ||
| local filtered_delete = vim.tbl_filter(function(diff) return diff.action == 'delete' end, fs_actions) | ||
| local filtered_rename = vim.tbl_filter( | ||
| function(diff) return diff.from and diff.action == 'rename' and not H.fs_is_present_path(diff.to) end, | ||
| fs_actions | ||
| ) | ||
|
|
||
| H.lsp_fs_hook('willCreate', { | ||
| files = vim.tbl_map(H.get_lsp_file_create_from_action, filtered_create), | ||
| }) | ||
| H.lsp_fs_hook('willDelete', { | ||
| files = vim.tbl_map(H.get_lsp_file_delete_from_action, filtered_delete), | ||
| }) | ||
| H.lsp_fs_hook('willRename', { | ||
| files = vim.tbl_map(H.get_lsp_file_rename_from_action, filtered_rename), | ||
| }) | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All these three and the H.lsp_fs_hook = function(method, diffs)
-- Compute LSP params
local files, to_uri = {}, vim.uri_from_fname
for _, d in ipairs(diffs) do
local file = {}
file[d.to ~= nil and 'oldUri' or 'uri'] = d.from ~= nil and to_uri(d.from) or nil
file[d.from ~= nil and 'newUri' or 'uri'] = d.to ~= nil and to_uri(d.to) or nil
table.insert(files, file)
end
local params = { files = files }
-- ... |
||
| local successfull_create = {} | ||
| local successfull_delete = {} | ||
| local successfull_rename = {} | ||
|
Comment on lines
+2757
to
+2759
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With shorter names, fitting them on the same line will be very readable. |
||
| for i = 1, #fs_actions do | ||
| local diff, action = fs_actions[i], fs_actions[i].action | ||
| local ok, success = pcall(H.fs_do[action], diff.from, diff.to) | ||
| if ok and success then | ||
| if diff.from and diff.action == 'create' then table.insert(successfull_create, diff) end | ||
| if diff.from and diff.action == 'delete' then table.insert(successfull_delete, diff) end | ||
| if diff.from and diff.action == 'rename' then table.insert(successfull_rename, diff) end | ||
|
|
||
| -- Trigger event | ||
| local to = action == 'create' and diff.to:gsub('/$', '') or diff.to | ||
| local data = { action = action, from = diff.from, to = to } | ||
|
|
@@ -2749,6 +2776,94 @@ H.fs_actions_apply = function(fs_actions) | |
| if has_moved then H.adjust_after_move(diff.from, to, fs_actions, i + 1) end | ||
| end | ||
| end | ||
|
|
||
| H.lsp_fs_hook('didCreate', { | ||
| files = vim.tbl_map(H.get_lsp_file_create_from_action, successfull_create), | ||
| }) | ||
| H.lsp_fs_hook('didDelete', { | ||
| files = vim.tbl_map(H.get_lsp_file_delete_from_action, successfull_delete), | ||
| }) | ||
| H.lsp_fs_hook('didRename', { | ||
| files = vim.tbl_map(H.get_lsp_file_rename_from_action, successfull_rename), | ||
| }) | ||
| end | ||
|
|
||
| H.lsp_fs_hook = function(method, params) | ||
| local full_method = 'workspace/' .. method .. 'Files' | ||
| local clients = vim.lsp.get_clients({ method = full_method }) | ||
|
|
||
| -- TODO(TheLeoP): configurable timeout | ||
TheLeoP marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| local timeout = 1000 | ||
| for _, client in ipairs(clients) do | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am sorry I don't have a more actionable direction for now, but could you please make it less nested (it is currently way too nested) and easier to read? |
||
| local filters = client.server_capabilities.workspace.fileOperations[method].filters --[=[@as lsp.FileOperationFilter[]]=] | ||
| local grouped_matching_functions = {} | ||
| for _, filter in ipairs(filters) do | ||
| local ignore_case = filter.pattern.options and filter.pattern.options.ignoreCase | ||
| local glob = filter.pattern.glob | ||
| if ignore_case then glob = vim.fn.tolower(glob) end | ||
|
|
||
| local matching_functions = {} | ||
| table.insert(matching_functions, function(uri) | ||
| local path = vim.uri_to_fname(uri) | ||
| return vim.glob.to_lpeg(glob):match(path) ~= nil | ||
| end) | ||
| if filter.scheme then | ||
| table.insert(matching_functions, function(uri) return uri:find('^' .. filter.scheme .. ':') ~= nil end) | ||
| end | ||
| if filter.pattern.matches then | ||
| table.insert(matching_functions, function(uri) | ||
| local path = vim.uri_to_fname(uri) | ||
| local type = H.fs_get_type(path) | ||
| if filter.pattern.matches == 'folder' then return type == 'directory' end | ||
| if filter.pattern.matches == 'file' then return type == 'file' end | ||
| end) | ||
| end | ||
| table.insert(grouped_matching_functions, matching_functions) | ||
| end | ||
|
|
||
| local filtered_params = { | ||
| files = {}, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't create multiline tables if they can fit in a single line. |
||
| } | ||
| for _, file in ipairs(params.files) do | ||
| local uri = file.uri or file.oldUri | ||
| local matches_any_filter = false | ||
| for _, matching_functions in ipairs(grouped_matching_functions) do | ||
| if not matches_any_filter then | ||
| local matches_current_filter = true | ||
| for _, matching_function in ipairs(matching_functions) do | ||
| matches_current_filter = matches_current_filter and matching_function(uri) | ||
| end | ||
| matches_any_filter = matches_any_filter or matches_current_filter | ||
| end | ||
| end | ||
| if matches_any_filter then table.insert(filtered_params.files, file) end | ||
| end | ||
|
|
||
| if method:sub(1, 3) == 'did' then | ||
| client:notify(full_method, filtered_params) | ||
| else | ||
| local response, err = client:request_sync(full_method, filtered_params, timeout) | ||
| -- TODO(TheLeoP): show error to user? | ||
| if response and response.result then | ||
| vim.lsp.util.apply_workspace_edit(response.result, client.offset_encoding) | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| H.get_lsp_file_create_from_action = function(action) | ||
| return { | ||
| uri = vim.uri_from_fname(action.from), | ||
| } | ||
| end | ||
|
|
||
| H.get_lsp_file_delete_from_action = H.get_lsp_file_create_from_action | ||
|
|
||
| H.get_lsp_file_rename_from_action = function(action) | ||
| return { | ||
| oldUri = vim.uri_from_fname(action.from), | ||
| newUri = vim.uri_from_fname(action.to), | ||
| } | ||
| end | ||
|
|
||
| H.fs_do = {} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not filter any create actions. The logic of
fs_actionsis like this:to.from(the possibletowhen moving to trash is not relevant).fromandto(as it is copy plus delete).So I don't think there should be any checks for
fromandtowhen there is a check foraction. Otherwise, it should be fixed in diff computation.