-
Notifications
You must be signed in to change notification settings - Fork 251
feat(filesystem): Implement shared clipboard #1594
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
21eb9a9
6325e1c
fb695b3
ca48964
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 | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,79 @@ | ||||||
local fs_watch = require("neo-tree.sources.filesystem.lib.fs_watch") | ||||||
local manager = require("neo-tree.sources.manager") | ||||||
local events = require("neo-tree.events") | ||||||
local renderer = require("neo-tree.ui.renderer") | ||||||
local log = require("neo-tree.log") | ||||||
|
||||||
local M = {} | ||||||
|
||||||
local clipboard_state_dir_path = vim.fn.stdpath("state") .. "/neo-tree/" | ||||||
local clipboard_file_path = clipboard_state_dir_path .. "filesystem-clipboard.json" | ||||||
local clipboard_file_change_triggered_by_cur_neovim_instance = false | ||||||
|
||||||
M.save_clipboard = function(clipboard) | ||||||
local file = io.open(clipboard_file_path, "w+") | ||||||
-- We want to erase data in the file if clipboard is nil instead writing null | ||||||
if not clipboard or not file then | ||||||
return | ||||||
end | ||||||
|
||||||
local is_success, data = pcall(vim.json.encode, clipboard) | ||||||
if not is_success then | ||||||
log.error("Failed to save clipboard. JSON serialization error") | ||||||
return | ||||||
end | ||||||
file:write(data) | ||||||
file:flush() | ||||||
M._update_all_cilpboards(clipboard) | ||||||
clipboard_file_change_triggered_by_cur_neovim_instance = true | ||||||
end | ||||||
|
||||||
M._load_clipboard = function() | ||||||
local file = io.open(clipboard_file_path, "r") | ||||||
if not file then | ||||||
return nil | ||||||
end | ||||||
local content = file:read("*a") | ||||||
local is_success, clipboard = pcall(vim.json.decode, content) | ||||||
if not is_success then | ||||||
return nil | ||||||
end | ||||||
return clipboard | ||||||
end | ||||||
|
||||||
M._update_all_cilpboards = function(clipboard) | ||||||
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. Typo:
Suggested change
|
||||||
manager._for_each_state("filesystem", function(state) | ||||||
state.clipboard = clipboard | ||||||
vim.schedule(function() | ||||||
renderer.redraw(state) | ||||||
end) | ||||||
end) | ||||||
end | ||||||
|
||||||
M.init = function() | ||||||
if vim.fn.isdirectory(clipboard_state_dir_path) == 0 then | ||||||
vim.fn.mkdir(clipboard_state_dir_path) | ||||||
end | ||||||
|
||||||
events.subscribe({ | ||||||
event = events.STATE_CREATED, | ||||||
handler = function(state) | ||||||
if state.name ~= "filesystem" then | ||||||
return | ||||||
end | ||||||
vim.schedule(function() | ||||||
M._update_all_cilpboards(M._load_clipboard()) | ||||||
end) | ||||||
end, | ||||||
}) | ||||||
|
||||||
-- Using watch_folder because we haven't "watch_file" :) | ||||||
fs_watch.watch_folder(clipboard_state_dir_path, function() | ||||||
if not clipboard_file_change_triggered_by_cur_neovim_instance then | ||||||
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. This is a bad idea. You can't say for sure that a file event came from this instance just because you wrote a file recently. This is fertile ground for hard to recreate bugs. Between this and the modified time based check I would rather use the first solution where you just process every write, even your own. I think I have a better idea:
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. Actually I can't understand why we can't be sure about this. Can you give me an example, please?
Why can't we be sure that the write occurred in the current instance? We are not performing any other actions between these two steps, are we? 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. We do not have exclusive access to this folder. Another program could write a file in this folder for some reason. For that matter, neo-tree itself might write a file here. It doesn't do that now, but someone else may do so in the future and they likely won't know that some other section of the code is naively reading every file written without checking the contents or even the file name. Finally, I don't think you should be so confident about the order of events when you are dealing with asynchronous actions. |
||||||
M._update_all_cilpboards(M._load_clipboard()) | ||||||
end | ||||||
clipboard_file_change_triggered_by_cur_neovim_instance = false | ||||||
end, true) | ||||||
end | ||||||
|
||||||
return M |
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.
I actually meant to put the error handling n the
file:write
/file:flush
code. That's where you are going to get frequent errors due to permissions, file locked, disk full, etc.