helix
helix copied to clipboard
[WIP] View based refactoring in workspace
This implements a new command: global_refactor, where one inputs a search regex and a new window shows up with all the lines in different files matching the search.
One can then do edits on the lines and afterwards apply those changes to the documents. If a file was not opened in the editor from before it will be opened and the change added as a transaction. This means that the refactoring can be undone in their respective documents.
- Demo:
https://user-images.githubusercontent.com/114359560/196932067-dda9118c-dcfe-416d-971a-d8612349ef01.mp4
There is still a lot of work to be done but I opened a draft pr to get some feedback:
- Is this something you want in core?
- What should be the default keybind for this?
- Suggestions / Ideas / Something that should be done different?
Is this something you want in core?
Yes! I tried to find a plugin in neovim for global searched text replacement, but failed. I know some tricks to do it in neovim with built-in commands and popular plugins like telescope (via sending live grep to quickfix window).
This means that the refactoring can be undone in their respective documents.
This is the one of the key and important function in my opinion. I can share the experience in nvim:
“ all mds under all dirs
:args **/*.md
:argdo %s/pat/replacement/ | update
" or forbid autocmd
:silent! noautocmd argdo %s/pat/replacement/ | update
" restore contents
:argdo undo | update
Oh cool! This reminds me of Zed's multi-buffers: https://www.youtube.com/watch?v=egI75sLT164
Very cool! Would also address #4335 beautifully :100:
I love this! Can't wait to have this in core.
I'm not quite happy with using the enum to separate from a normal file-buffer. I think a better way would be to separate different "UI elements" into their own components and also separate commands for those components, so I might do that in other PR's before continuing on this.
There are potentially more features that would benefit from custom views (like diff-mode) so there is some overlap there.
Also this PR could provide a provide a better UI (I think Zeds multi-buffers are a great reference).
I thank it would be better to abstract over View
rather than Document
.
To me a Document
really represents a single file and a View
is a display of that Document
where the user can edit it.
This already applies for splits but also fits diff-mode and global refactoring.
This approach does however mean that we need commands that behave differently based upon what view is visible. I was thinking of just having a callback called when a command is dispatched. `AbstractView::execute_command<T>(&mut self, name: &str, f: impl FnMut(&mut View) ; which would allow custom views to either just forward to their sub-views or hook for commands they want to "special case" (for example scrolling/movement in diff-mode should affect both views but all other commands are treated as normal).
The approach is kind of tricky for this PR because you would have to special case selection commands and introduce a notion of a view without selection but that's it.
Ideally you should not have to touch the document or text rendering/positioning itself at all (especially because #5420 will almost fully replace the old rendering/positioning code). Simply calculate the height and offset of each sub-view upfront (and keep it fixed even if text is removed) and then use a simple row-based offset into the view and use a binary search of views to find which views to render (and which not).
Since #5420 is mostly done now I might work on such an abstraction next in my quest to get diff-mode working :D
Yes, one of the main issues here is that the text edit commands use the current document. My thoughts was that in a more component based layout one could have a component "text buffer" that had all the commands for editing text in it. Then there could be a "file view" or something that used this component and added its own commands for file specific things. "Global refactor view" could then also use "text buffer" as a sub component and add its own specific things.
When more and more things get added to the editor, for example "file-tree view" it makes sense that those things are separate components with their own commands and can have separate key bindings and we can avoid squashing everything into EditorView
Very cool to see this WIP! I was searching to see if there were any plans for something similar to ZEDs multibuffers, and here it is.
Hello, just to note that before of ZED, vim-esearch was doing that. I used it a lot and is one of my preferred plugins. Maybe give a look into that for ideas :)
Hope to see this PR merged asap!
@pascalkuthe Hi! I'm just a new user but I've found the cursor paradigm extremely powerful and unique so far in Helix. When you say...
This approach does however mean that we need commands that behave differently based upon what view is visible.
and that a View
may lose some selection capabilities, would you lose some benefit of how flexible cursors are in your standard editing session. For example suppose we open all those buffers we want to refactor as in the video example. If we are given cursors that appear in all of those views we can refactor as expected but implicitly we would also have access to a selection removal similar to (y/n/a/q)? in many text editors. We could simply cycle through primary selection/view with (
or )
and even drop selections we don't want to change with Alt-,
. This is like your standard editor prompt replace but in the reverse order; decide if you want to drop anything then perform the change for the rest of the selections. I'm gathering from this thread that might be a technical challenge so no worries if it's not possible.
Hi! Could someone describe what needs to be done to merge this PR? Maybe some of the authors can share a vision of how the feature should look. I can try to take it on and implement it.
Very good demo. I hope this will be merged to the core.
@pathwave, are you alive? What happened to this PR ?
Hi! Could someone describe what needs to be done to merge this PR? Maybe some of the authors can share a vision of how the feature should look. I can try to take it on and implement it.
You can check the code . And start new PR based on this PR.
It seems this one was abandoned .