vim-classic: Long-term maintenance of Vim 8.x
92 points by Aks
92 points by Aks
See also Drew's announcement blogpost.
I submitted this repo here earlier today... and immediately removed it, because 1. I didn't want to deliberately avoid Drew's domain ban, 2. I realized I was being a bit hypocritical, because when EVi was posted here I agreed with the top comment there saying that forking news should be put on cooldown - and vim-classic was literally born today.
That being said - I'm much more optimistic about this than about EVi. I trust Drew to do a good job here, and I think basing it on Vim 8.2 is a good idea. I messed around with it a bit, and it doesn't seem like the lack of Vim9 script breaks too much - in particular vim-fugitive and fzf.vim[1] work just fine. The thing I miss most from Vim9 are the new colorschemes, but they'll probably (?) be included in Vim Classic down the road too (Drew doesn't seem opposed to Vim9, he's just pulling in its changes piecemeal).
[1] Drew's article points it out as the only plugin he was using that broke - but that's not really correct. It's working fine, just hitting a fallback compatibility mode that makes it work as it did in 2020, before Vim got popup window support. But that's irrelevant anyways; I have a personal branch with the few extra patches needed to make it work exactly as it does on modern Vim. I'm hoping Drew will upstream it soon.
As a sidenote: I looked through all the commits that were cherry-picked on top of Vim 8.2. Most of them are memory safety fixes... and, uh, they also tend to be kinda janky. For example, 8.2.3402 fixes an invalid memory access that happens when you manage to set your tabstop width to a negative value. It doesn't do that by actually fixing the function where that out-of-bounds read happens, but by ensuring the tabstop width is between 0 and 9999. The actual bug's still there (even if the out-of-bounds read seems pretty benign).
I'm glad he's doing this. I think when it comes to vim, his taste is more aligned with my taste than the current maintainers' is.
I hadn't made friends with vim 9 yet anyway. I've used neovim and don't hate it, and in a gui I think zed and IDEAvim are quite good. But I think vim-classic is, if it ages well for a little while, likely to be the one that winds up as vim in my system path and goes in my $EDITOR.
For example, 8.2.3402 fixes an invalid memory access that happens when you manage to set your tabstop width to a negative value. It doesn't do that by actually fixing the function where that out-of-bounds read happens, but by ensuring the tabstop width is between 0 and 9999.
This doesn't sound that bad? It's common in C to define a function's preconditions and let unsafe stuff happen if you don't follow those preconditions. For example, it's common to say "this pointer parameter must not be null as a precondition" and accept that you'll invoke undefined behavior if you pass in null anyway. Or "this index parameter must be smaller than the length" and accept that you'll be doing an out of bounds access if you break that precondition. It's sometimes nice to throw in asserts which check those preconditions, but violating them are in the category of "the state of the program is nonsensical" not "an error occurred, let's handle it gracefully".
The right fix is to prevent the program from ending up in a nonsensical state (negative tab width). A nice bonus would be to add a debug assert to help with debugging.
I agree, but the preconditions are not actually defined anywhere - let alone are there any asserts to catch the cases where they aren't met.
The out of bounds read happens here:
/*
* Check if the attributes are correct without additionally
* stopping highlighting.
*/
// [lobste.rs: ScreenAttrs is a global array, LineOffset[0] == 0]
p = ScreenAttrs + LineOffset[row] + wouldbe_col;
while (i && *p++ == attr)
--i;
when wouldbe_col is negative. This can happen when col is negative. There are actually some checks for if col,row are in range:
// Check for valid position.
if (row < 0) // window without text lines?
row = 0;
if (row >= screen_Rows)
row = screen_Rows - 1;
if (col >= screen_Columns)
col = screen_Columns - 1;
with the notable omission of ensuring that col is nonnegative. To be honest I'm not even sure if col>=0 is an intentional precondition, if col<0 is meant to be supported and the out of bounds read is a bug, or if someone just forgot the if (col < 0) check.
I mean it's a bit of a meritocratic thing.
If a person you have seen lead a project (or do some good work before) does something like this, then the assumption is they probably will not drop it the next week.
Forking is cheap and most people are just wary of people announcing their big fork but they have zero proven credibility to be a good steward. They have to build the trust in their fork first.
And I guess in the last years we've seen to many "Oh surely forking is a good idea" things gone wrong or just going silent.
i agree with your comment wholly. i mentioned on the EVi thread similar things.
however, IMO your sidenote is in poor taste, as most drive-by reviews are. you are critiquing Bram's code posthumously (years after it was written), on a project he maintained for life, in a forum that is not about code review. it would be more productive to submit a patch or a code review in the appropriate place.
Sorry, I did not mean to be disrespectful to Bram. I think Vim is brilliant. I've been using it for years - I think it's evident (including from the source) that it's a labor of love. Bram had a focused vision for Vim, and he did a great job curating its feature set - in particular, I can be very productive in it without changing the default config at all (as opposed to some alternatives ;) ).
However - I've spent most of yesterday browsing Vim's source code because of the fork, and it struck me as... not exactly written to the current standards for C code that might handle untrusted data. That's what I meant to convey. This is relevant in this context, because it does affect maintenance burden, and also means that you can't just take a single random old Vim version and use it forever.
But also, yeah, in hindsight I shouldn't have added that :/ I was just writing out my thoughts at the end of the day without really editing it.
because when EVi was posted here I agreed with the top comment there saying that forking news should be put on cooldown - and vim-classic was literally born today.
Did not know this, just saw the release on my feeds and thought it would be nice to share.
I don't think that starting with an older release is a good starting point. It means that every distribution that has shipped a newer release cannot switch. Even adding the package in parallel would be painful. And of course, every user may face troubles while "downgrading", especially because of addons.
The goal of the project is to avoid the inclusion of AI-generated code. It's literally impossible to do that by forking the project off the current upstream version.
I also don't really see why adding the package in parallel would be painful; Debian already packages Vim alongside Neovim, for one, and it has architecture for packaging plugins in a way that works with both.
(I plan to create an unofficial Debian package for vim-classic in the near future).
Isn't there a more recent cutoff ? 9.x started almost 5 years ago. It seemed to me that there were many various improvements with 9.x versions.
That being said, now that I think more about it, a fork is defined by a single clear point in development and I'm not sure I could decide of one after 9.0 was released which means it "has" to be before.
About distributions, you can obviously add the package in parallel but you can't make it an alternative and certainly not replace it. This makes large adoption by distros more difficult. The package can be available but it will have a lower status and migrations will be one by one and manual.
I'm not familiar with the pluging packaging and how it handles compatibility in Debian. If it works well and can be adapted here when needed then it will definitely make things easier. The need to check and adapt .vimrc files will remain however.
Isn't there a more recent cutoff?
Well, if you want distributions to be able to switch without downgrading, Debian sid is packaging 9.2.0218. That's, uh, from last week. And then they'd also need to immediately stop accepting any new versions from upstream - all in the name of maybe being able to switch to a brand new, as of yet unproven, fork.
Even if we decide it's fine to revert to the latest version that's in Debian stable - 9.1.1230 - that's from March of last year. At least git log v9.1.1230 --grep claude yields nothing, so that's good, I guess - but it's too late anyways.
RPM has the Epoch field to reset versioning for this reason.
I'm not familiar with RPM but Debian packaging has epoch too and it's definitely something to think a lot about before using because by definition, it's for ever. It's also used to correct mistakes with package versions; it's not something used to go back in versions. Unless RPM does things wildly different (and that means different semantics about versioning), I'm not sure it would have a use here.
distributions would not ship this as "vi", it's a new project that happens to have the same codebase as an older vi version. so there's no need to switch. I do not see what issues you expect with adding the package in parallel along with the dozens of other text editors already in the repositories.
To be honest, even Vim 8 feels too recent. Most of the config changes I do in a .vimrc are to undo Vim 8 defaults (i.e. automatic expansion of spaces into tabs mangles most codebases where spaces are in use).
What do you mean by "automatic expansion of spaces into tabs"? Do you mean collapse? We usually talk about expanding tabs into spaces because it takes one tab character and expands it to 4 or 8 space characters.
Does vim automatically convert all spaces into tabs for the whole file for you by default? And you're saying this is a recent-ish change? Do you have a link to a changelog where this is mentioned?
No, it only converts spaces into tabs on the line you're editing (or above or below). This is what I want for my own projects actually, but with other people's projects, they rarely add the vim settings to a file, so I have to fight vim on this every time.
copyindent? I agree that it definitely should be set by default; the nocopyindent behaviour makes no sense.
Nice to see someone taking the “keep it simple and stable” path.
Not every tool needs to evolve forever, sometimes the best thing you can do is maintain a solid base well. Vim 8.2 is already mature, and long-term maintenance makes a lot of sense for people who just want a reliable editor without surprises.
The use of these tools is an endorsement of these externalities.
Boycotting evil products is very popular among programmers. To me, this misses the mark; it ignores the fundamental power inbalances that time and again lead to these evils and the must be organized against.
Boycotting is hyper individualistic and, plays into the hands of the powerful, because it doesn't question any of the underlying assumptions of the way our economy is organized. It embraces the liberal idea that consumer choice is the best way of expressing popular opinion. But ask yourself: how many technologies have you decided against using on a political/ideological bases (microsoft products, various social networks, now AI)? Did this ever do anything?
Don't get me wrong, boycot has its place, but it can't be the only action you take if you're upset with the points listed in the README of vim-classic.
Personally, the reason I don't buy anything from Amazon (or Microsoft, OpenAI, etc.) isn't that I think this will put a dent in Amazon's economy, or even inconvenience them. It is for the simple reason that my conscience won't allow me to knowingly put money in Amazon's pockets. I know full well that one person making that decision has no effect on a tech giant, but it is still the right decision.
It's for similar reasons I'm vegetarian, avoid air travel, avoid fast fashion, and don't drive a car. I don't think either of those will "change the world", but they're still the right things to do for me, in my position. I also support the appropriate political movements and sometimes participate in various protests and other activities. I don't really think that voting and going to protests "absolves" me of trying to live by my principles (to the best of my abilities) day-to-day.
(Footnote: I think the difference between a consumer choice and a boycott is precisely that a boycott is a collective and at least semi-coordinated action, whereas a consumer choice is individual and uncoordinated.)
A boycott is the minimum you can do. You can't ask everyone else to make ethical decisions if you aren't willing to do it personally.
Organizing and demanding consequences for harm done is also important.
If a person you have seen lead a project (or do some good work before) does something like this, then the assumption is they probably will not drop it the next week.
I know Drew personally, and I can vouch that he does more than just a boycott fwiw
And I 100% agree with you, btw
To bad this doesn't support the Vim9 scripting language. I wrote several plugins in it, and liked it more than legacy VimL or Lua.
I agree. I find vim9script to be the best thing about vim in the past 5-10 years. It is like the golang of typescript, which feels like the sweet spot for editor extension. Types but not so much you need to accommodate error states that you know you won't personally encounter. Simple enough to be compiled very fast.
I've had very similar feelings, but I don't know if I actually like vim.
In the last decade there hasn't been a day I've used a computer where I haven't also used vi (most probably vim), but I constantly accidentally hit features I don't know why they exist. (like the help, or whatever I do in visual mode that feeds every word to man).
I'm quite close to adding the few missing features I need to a small vi and just keeping it myself. The thing stopping me is that this feels life folly, but with sensible history, a little syntax highlighting and a visual mode nvi (which freebsd ships) would be enough for me.
Go for it! If you learn something and use it I don't see any folly. FWIW, other than a couple omitted lines that enable persistent unlimited undo this is my entire vimrc:
syntax off
set mouse=a
nnoremap <space> :
vnoremap <space> :
map q <Nop>
disclaimer: I use vim like a visual ed where I can mouse-select things ranges to perform the regex on, i.e. sort of a makeshift sam.
vis
Try vis : it’s vim without all the stuff I don’t use (except EX mode, that I’m still learning)
Just waiting to see a MacVim variant picking up one of these forks.
If it ends up being MacVim Classic, its name would have the bonus of harkening back to a certain still-fondly-remembered OS…