filemanager-plugin icon indicating copy to clipboard operation
filemanager-plugin copied to clipboard

Replace current file in buffer instead of splitting into new pane

Open GavinRay97 opened this issue 5 years ago • 7 comments

First of all, thank you for making this. Stellar plugin for a really great lightweight editor.

One thing I really wish I could do is open the selected file and replace the current buffer (and ideally maybe shift + click for new pane) instead of always splitting it into a new pane.

Maybe it is possible to do this already and I am just a bit slow.

GavinRay97 avatar Jan 25 '20 04:01 GavinRay97

Current design is to always open in a new buffer, so no it's not possible at the moment.

I suppose it's not the hardest thing, but I would need a way to do it non-destructively. I don't want it to just throw away whatever you have open. Maybe checking if the pane has changed since last save, then offering to save if needed before actually opening a file in its place.

sum01 avatar Jan 25 '20 20:01 sum01

I have a really hacked-together rough draft of something like this. It has a few bugs, namely that if you close a buffer for a file, and it was the last one you clicked, you need to click to open something else before you can open the original closed buffer again.

-- Tries to open the current index
-- If it's the top dir indicator, or separator, nothing happens
-- If it's ".." then it tries to go back a dir
-- If it's a dir then it moves into the dir and refreshes
-- If it's actually a file, open it in a new vsplit
-- THIS EXPECTS ZERO-BASED Y
-- Store a reference to the last opened file
last_opened_file = nil
local function try_open_at_y(y)
	-- 2 is the zero-based index of ".."
	if y == 2 then
		go_back_dir()
	elseif y > 2 and not scanlist_is_empty() then
		-- -2 to conform to our scanlist "missing" first 3 indicies
		y = y - 2
		if scanlist[y].dirmsg ~= "" then
			-- if passed path is a directory, update the current dir to be one deeper..
			update_current_dir(scanlist[y].abspath)
			-- If the targeted file is already open in the buffer, do not re-open
    elseif last_opened_file == scanlist[y].abspath then 
        messenger:Error("File already open")
    else
			-- If it's a file, then open it
			messenger:Message("Filemanager opened ", scanlist[y].abspath)
			-- Opens the absolute path in new vertical view
			CurView():VSplitIndex(NewBufferFromFile(scanlist[y].abspath), 1)
			-- Resizes all views after opening a file
			tabs[curTab + 1]:Resize()
			-- Update the last opened file to be this one
			last_opened_file = scanlist[y].abspath
		end
	else
		messenger:Error("Can't open that")
	end
end

GavinRay97 avatar Jan 26 '20 03:01 GavinRay97

Okay I got it.

I just store a table of opened files:

-- Store a reference to the last opened file
open_files ={}

And then in try_open_at_y() I handle adding new file entries into the table and preventing opening duplicate views of files:

if scanlist[y].dirmsg ~= "" then
	-- if passed path is a directory, update the current dir to be one deeper..
	update_current_dir(scanlist[y].abspath)
	-- If the targeted file is already open in a buffer, do not re-open
elseif open_files[scanlist[y].abspath] then 
	messenger:Error("File already open")
else
	-- If it's a file, then open it
	messenger:Message("Filemanager opened ", scanlist[y].abspath)
	-- Opens the absolute path in new vertical view
	CurView():VSplitIndex(NewBufferFromFile(scanlist[y].abspath), 1)
	-- Resizes all views after opening a file
	tabs[curTab + 1]:Resize()
	-- Add the file to the open files table
	local filepath = scanlist[y].abspath
	-- Set the value to true so we can just do a table lookup
	-- Instead of a "pairs(table)" iteration to check for it
	open_files[filepath] = true
end

In preQuit() hook, handle removal of table entries:

-- Close current
function preQuit(view)
	-- Remove the current file from the open files table
	open_files[view.Buf.path] = nil
	if view == tree_view then
		-- A fake quit function
		close_tree()
		-- Don't actually "quit", otherwise it closes everything without saving for some reason
		return false
	end
end

:+1:

GavinRay97 avatar Feb 03 '20 01:02 GavinRay97

It's not a bad idea, but this won't work if a file is opened in a way other than using the filemanager.

Sidenote: make open_files local to avoid conflicts with other plugins.


I personally don't care, but people might be annoyed at this type of change without it being behind an option. It's minor, but someone might open 1 file side-by-side, which this doesn't allow for.

sum01 avatar Feb 03 '20 19:02 sum01

@GavinRay97 do you have a fork somewhere available with this functionality? I'd love to pull it to play with it.

lcmen avatar Feb 24 '21 17:02 lcmen

@lowski Hey, I would absolutely share the finished file with you but I've since re-installed my OS and have lost this =(

Sorry. Maybe you can copy-paste those customizations from the code snippets into the plugin lua (if they still work)?

GavinRay97 avatar Feb 24 '21 19:02 GavinRay97

@GavinRay97 thanks for the reply! Unfortunately, I don't think this code will work with micro 2. There is a separate repo for updated plugins.

I analyzed your code and I don't see a change to replace existing buffer - the line to open a file in a new buffer (CurView():VSplitIndex(NewBufferFromFile(scanlist[y].abspath), 1)) is still there. Am I missing something?

lcmen avatar Feb 27 '21 00:02 lcmen