helix
helix copied to clipboard
vim/neovim style tabs
closes #2295
This is a pretty highly requested feature which also is important to me which is why I took it upon myself to start the implementation of it. The implementation is very simple and basically just instead of a single view tree per editor we get a map of trees, which are represented as tabs. While this makes it very easy to implement this does pose some limitations - mainly that all state is still managed within the editor which makes it impossible to have, say, per-tab working directory.
So while I will update and clean up what I have right now, I also want to take feedback from the maintainers and users about whether this is the direction I should take this PR or maybe make each tab more independant.
Other unresolved questions:
- [ ] Should buffers be global or per-tab
- [ ] Should bufferline and tabline be mutually exclusive
Just wanted to say I've cherry picked these commits onto my working branch, and even with the rough edges this feels great! I mapped gt
and gT
to next and prev tab for some vim-style tab jumping (I don't use the helix default gt
at all, so this works for me).
For the two questions:
- Should buffers be global or per-tab: I would vote for global so that editing a buffer in one place updates it everywhere
- Should bufferline and tabline be mutually exclusive: If the tabline showed the focused filename, I think I'd be happy with this.
Awesome to see this being worked on 😄
Just wanted to say I've cherry picked these commits onto my working branch, and even with the rough edges this feels great! I mapped gt and gT to next and prev tab for some vim-style tab jumping (I don't use the helix default gt at all, so this works for me).
This has been mostly my experience as well -- thanks to the original author for this great prototype! I have given this a spin on my local fork, and the only things I've noticed are the following:
- I wish there was a
tab-prev
command, but alas my Rust-fu is insufficient to contribute the feature myself; - I wish the tabs reported the name of the file (even though it's still readily available in the bufferline) rather than a generic "Tab 0", "Tab 1", etc;
-
Most importantly, there seems to be some weird interaction between this patch and LSP; if I create multiple tabs, all of the sudden the LSP server gets confused (I'm using
haskell-language-server
for my daily job) and it starts reporting wrong diagnostics (like a given constructor not in scope, when clearly is). If I kill all the tabs, then LSP resumes emitting the correct diagnostics.
@adinapoli thanks for trying it out! I'm gonna be honest, I haven't tried the LSP yet so thank you for reporting that, I'll definitely investigate it. tab-previous
is also definitely coming.
As for tab names - since they don't represent files but instead a specific arrangement of panes, by default I thought a generic name will be the way to go but I will also add the ability to rename them and possibly re-arrange them but I'm open to any suggestions you might have!
I'm gonna be honest, I haven't tried the LSP yet so thank you for reporting that, I'll definitely investigate it.
Mind, this could be just as well a bug in haskell-language-server
or the way it interacts with Helix, so perhaps don't spend too much time on that, if that proves to be chasing ghosts 😉 Thanks again!
Tabs is the one feature preventing me from entirely switching to helix. This is an exciting possibility.
@nrabulinski
As for tab names - since they don't represent files but instead a specific arrangement of panes, by default I thought a generic name will be the way to go
Why nest panes inside tabs? Why not nest tabs inside panes? If you nest tabs in panes, tab naming becomes a non-issue and you would allow for tab groups. It's incredibly useful to have groups of tabs where you can switch back and forth.
best thing with vim tabs are local working directory, with each tab can have either its own working directory with :tcd /local/working/directory/per/tab/
or the same global working directory of the vim instant with :cd /global/working/directory/
, hope helix get that soon. Thanks so much @nrabulinski
After rebasing and cleaning up the history a little bit I'm changing the draft status as I feel like the PR is in a state at least partially ready for review, or at least to see if that's an implementation the helix team would consider merging. Some stuff I'd still like to add/confirm before merging though:
- opening a new tab with a specific file (a'la h/vsplit)
- separate cwd per tab(?)
- making sure the tabs play nicely with all the current helix functionality
I love this feature and expecting the PR to be merged as soon as possible.
I rebased my changes on current master, feel free to test
@pascalkuthe @the-mikedavis @archseer This has been open for quite some time without any form of maintainer feedback. Is the reason for that lack of bandwidth or unclarity/disagreement if this feature is wanted?
I rebased the changes again, making sure there's no conflicts and that the functionality still works
*cough* ship it *cough*
*cough* ship it *cough*
I asked about it on matrix a while back and currently the team isn't interested, there's a bunch of code refactors they want to get around first in areas my PR touches, on top of in general there not being consensus whether this feature should be implemented like this
not being consensus whether this feature should be implemented like this
Damn. Though, I'm not exactly surprised based on some early remarks in #2295. The "one true workflow" stance. Of course, then everyone hops on their favorite browser afterwards and opens twenty tabs.
A solid and ergonomic tab implementation allows Vim-style editing to integrate nicely into IDEs using plugins. VS Code and IntelliJ's Vim extensions work great. imo This is what is needed if it's going to be worth the learning curve of switching away from Vim and Neovim.
Also, none of that CTL+ crap.
Yeah, it seems that the team refused the idea of a feature-rich editor and put all stakes on the Steel plugin system. I do not understand this. This project got 30k stars for aiming to be a complete editor with good defaults and most needed stuff implemented as first-party features, but now they are making a 180-degree turn by relying on a plugin system for essential functionalities. In the end, we will get a copy of nvim with dozens of plugins incompatible with each other, requiring tons of lines to configure. Btw, they also want to replace the beautiful, minimalistic and readable toml configuration with scheme based one. This all diverges with most of the things that got me into Helix initially.
We're a small team with limited time and I've always emphasized that helix is just one version of a tool and it's perfectly fine if there's a better alternative for some users. Someone with a fully customized neovim setup is probably going to have a better time just using their existing setup rather than getting helix to work the same way. [1]
[1] https://news.ycombinator.com/item?id=40934717
cough ship it cough
I asked about it on matrix a while back and currently the team isn't interested, there's a bunch of code refactors they want to get around first in areas my PR touches, on top of in general there not being consensus whether this feature should be implemented like this
I don't understand the argument against this implementation? How could implementing this functionality as an optional plugin be better in any way, shape, or form? Seems pretty integral to a post-modern text editor, especially vim-inspired.
We're a small team with limited time and I've always emphasized that helix is just one version of a tool and it's perfectly fine if there's a better alternative for some users. Someone with a fully customized neovim setup is probably going to have a better time just using their existing setup rather than getting helix to work the same way. [1]
[1] https://news.ycombinator.com/item?id=40934717
This has nothing to do with neovim customization preferences though. This PR is implementing a built in feature that comes with vim by default, that is currently not included in helix. There are plenty of examples of copycat features from vim integrated in helix, which are all welcome and thematic inclusions. Why would tabs be any different?
Seems pretty integral
We have different definitions of essential, tabs are completely unnecessary in my workflow and often misused in vim. The project is not just a vim clone. Either way, this discussion should probably take place elsewhere than this feature PR.
(To clarify, I'm not saying no to the PR, but this discussion is getting rather heated.)
Guys, please, if you want to show how important this feature is to you - just react to this PR and the issue which asks for this feature. I don't hold anything against the helix team, nor do I feel entitled to them merging or even reviewing the PR and neither should you. I'll do my best to keep this PR up to date so feel free to bring it into your fork or depend on it directly. This would also help me know how to develop this feature further as it's very barebones as it is :)
Could it make sense to add a binding in the picker to open a file in a new tab? Similar to the existing horizontal and vertical split bindings. ctrl-t
is already used (for the preview toggle) but any other key would be fine.
often misused in vim
okay, i'll bite: how are tabs "often misused in vim"?
@cornmonger I can't find the more detailed explanation that used to live on StackOverflow but https://github.com/helix-editor/helix/issues/2295#issuecomment-1826118276 shows an example of how vim tabs were developed: they are different view pane layouts. But users often try to turn them into tabs similar to vscode: where a single buffer lives in a single tab. But that requires some workarounds since a buffer technically lives on a global list and is able to exist in multiple panes at once. Closing a buffer also typically won't close a tab, but will instead swap to a different document for that view.
@curtisault and I'm calling you out for being rude.
https://gist.github.com/richhickey/1563cddea1002958f96e7ba9519972d9
the project isn't licensed under your name.
assert your own personal preferences
https://github.com/helix-editor/helix/blob/079f544260f4f5eaff08104bf07abd57bfb7b611/Cargo.toml#L48
Well.. given that I created the project to suit my personal needs, spent hundreds of hours working on it, maintaining and growing it, I do get to have a say on features.
"The project is not just a vim clone"
This was a response to "helix implements vim features, and tabs are a vim feature, tabs should be added"
Show some empathy and/or understanding the world is a diverse place with diverse workflows.
Have you read any of my other responses on this topic? I specifically acknowledge that there are different workflows and different needs, but we just can't fit them all without significantly growing the codebase and making it hard to maintain for us.
Every feature is essential to someone, but sadly we have to make hard decisions and draw the line somewhere... And no matter what choice we make, there's going to be some users on the other side of the decision that will be disappointed. (For example: Similar to Braam's realization that lead to vimscript (it's impossible to support every need in core, but we can at least give users a solution), we decided on a plugin system. But now Helix isn't no-plugin no-config anymore! Then what about Scheme? Why not Lua? If we pick Lua, then what about those that dislike Lua? What about WASM or Rust? Well, now users don't want to deal with compilation and the ecosystem is split into sub-systems based on the language used, etc. etc.)
This then often leads to users demanding that tabs/file tree/remote API/ssh support/copilot/LLM support/other feature is absolutely essential, that we're single-handedly destroying our marketshare and that I must be unreasonable to even consider saying no. (On the other hand sometimes this drives innovation, shout out to @silasmarvin for developing https://github.com/SilasMarvin/lsp-ai to work around us not directly supporting LLMs!)
Every decision gets second guessed, and as is often the case with open source, users will be more vocal when something is broken or a decision is made they disagree with (since it's a bug tracker, why would they open an issue to say everything works fine?) With a project this size, that results in getting negative/angry github comments straight to my inbox weekly! And it's honestly quite draining and demotivating. (I just spent half an hour drafting this reply that I could have used to write up today's release's website update. Or reviewed this PR.) I usually avoid responding but this is a good PR that the author has spent some time maintaining, and I disliked how the discussion spiraled into plugin system and our decision-making rather than the PR itself.
where a single buffer lives in a single tab
@archseer interesting. i've always assumed that was how it functioned under the hood. i think of that usage as its own valid use-case, though. not so much of a misuse unless something is available that better provides what they want.
in playing around with the demonstrated bufferline usage, i think that set bufferline always
might be what a lot of people are actually looking for in helix when they talk about tabs.