tpope / vim-sleuth

sleuth.vim: Heuristically set buffer options
https://www.vim.org/scripts/script.php?script_id=4375
1.92k stars 86 forks source link

Added a configuration option for the default tabstop width, so it can be changed from 8 #17

Closed brandonocasey closed 2 years ago

brandonocasey commented 10 years ago

I was not happy that the default was 8, so rather than just changing the default I kept the default at 8 and made it configurable using g:SleuthDefaultWidth, giving the user the power. I also added to the README for this change.

tpope commented 10 years ago

Purely tabbed files already respect the global 'tabstop', and mixed files are generally either broken or using tabs as a shorthand for 8 spaces. What are you actually trying to accomplish?

brandonocasey commented 10 years ago

I was seeing tabs of 8 with tabstop, shiftwidth, and softabstop set to 4, I was trying to make it 4 by default rather than 8.

tpope commented 10 years ago

But in what situation? Existing file? New file? Are there other files of the same file type?

brandonocasey commented 10 years ago

An existing file that started out with tabs equal to 4 spaces became a file with equal to 8 spaces. I have not seen it happen with a new file. I have seen it happen with files of the same type. Perl and PHP mostly

peterstace commented 8 years ago

I would also like this feature.

It's useful for me in the case where I'm editing an existing file that contains mixed tabs/spaces (mostly tabs, but might have a single indent made from spaces instead of tabs).

While 8 might be a historical tabstop size, in all of the code bases that I edit, 4 is assumed. I.e. if someone accidentally uses spaces instead of tabs to indent a line, they will always 4 spaces instead of 8 spaces. Yes, these files are technically 'broken', but it's not feasible for me to go around 'fixing' all of the miss-tabbed files that I have to work on.

xeyownt commented 7 years ago

I'm also in favor of this option. I forked the repo this morning to add this feature, and just noticed now that the feature was implemented exactly the same way here.

I'm also working in a big code base where default tab stop is assumed to be 4 but where some developers use space instead of tabs to manually indent the code. Adjusting tabstop in those situation is the less intrusive I can think of.

Looking at the changes needed for this feature, this is very lightweight, and fully backward compatible. So I warmly recommend accepting this pull request ;-)

duganchen commented 7 years ago

Just noting that merging this would resolve #32

tpope commented 7 years ago

So my general attitude (and I really need to write something up about this) is that the best config is no config, and the worst config is global config. If the problem is that some projects are problematic, I'd much rather have a solution that solves for those projects, rather than one that punishes the good ones.

I propose we start with a buffer local variable. Then you can easily achieve things on a per-project basis:

autocmd BufReadPost ~/my/project/**/*.js let b:sleuth_mixed_tabstop = 8

Obviously, you can still do * if you really want to, but at least now you're not boxed into an all or nothing approach.

tpope commented 7 years ago

To be clear, if someone wraps that up in a pull request and verifies it works for them, I'll merge. You can document in doc/ if you want or ignore docs for now until we confirm it's a viable solution.

duganchen commented 7 years ago

Purely tabbed files already respect the global 'tabstop', and mixed files are generally either broken or using tabs as a shorthand for 8 spaces. What are you actually trying to accomplish?

The use case for this?

Code files with code for other languages embedded in them. BASH scripts with Perl or Python scripts as Heredocs, Python with SQL embedded as multi-line strings, etc.

tpope commented 7 years ago

We have several guards for that, and presumably heredocs would be pretty easy to add.

ludovicchabant commented 7 years ago

Hey so I'm having this problem with a perfectly "non broken" codebase (unless I'm missing something). That is, all the files in the codebase are indented with only tabs... so vim-sleuth sets my tabstop to 8. But I want 4, because I like it better cosmetically speaking.

It seems that with purely space-indented codebases, vim-sleuth respects your already set tabstop. It only overwrites it to 8 for purely tab-indented codebases (see this line). Why is that? Why not preserve the value I set in my vimrc?

tpope commented 7 years ago

If the file has no lines beginning with spaces, and at least one beginning with a tab, then heuristics.hard && !heuristics.spaces will be true, and the first half of the outer conditional will run. The line you've called out only runs in mixed files.

ludovicchabant commented 7 years ago

Ah you're right, I did miss something -- several files have one or two lines that are incorrectly indented with spaces, which is why it goes in the "mixed" case.... only "mixed" is a bit incorrect here, since we're talking about something like 300 lines with tab indents, and 1 line with spaces.

The solution is obviously to fix the broken files, but I'm still wondering why vim-sleuth would ever set the tabstop? You said something earlier:

mixed files are generally either broken or using tabs as a shorthand for 8 spaces

That second part ("shorthand for 8 spaces") seems awfully arbitrary to me.

tpope commented 7 years ago

Basically every project over 20 years old, plus many modern ones, mandates tabs as 8 spaces. Linux does it. Vim itself does it. The original Java indenting standards very explicitly called for this mixing behavior. Why? Because disk space used to be a lot more expensive, and 8 space tabs used to be a universal constant.

Really it's still a universal constant, once you leave the world of text editors. Haven't y'all ever looked at a file with less, or browsed it on GitHub?

ludovicchabant commented 7 years ago

I had never heard about this, but I'm maybe not old enough :)

What I'm currently experimenting with (locally) is a heuristic (controlled by a... cough cough global configuration setting cough cough) that tries to figure out the 2 cases you outlined: whether we're looking at a broken file, or at a 20 year old thing.

Right now it's very simple, it just looks at the ratio between hard and soft indents -- if the ratio is below a given threshold, then it ignores the outlier lines and acts as if the file was 100% one way or the other. I set the default to 2%, but setting it to 0% would preserve existing behaviour. Would that be acceptable?

I'm also thinking about adding an opt-in auto-fixer that would replace the minority indents with the other type of indent (so replace spaces with tabs, or tabs with spaces, for those <2% lines), but you could argue this may not belong in vim-sleuth (but I have already too many plugins).

tpope commented 7 years ago

On that note see https://github.com/tpope/vim-sleuth/issues/12#issuecomment-49119436

ludovicchabant commented 7 years ago

Ah interesting, thanks... I'm not sure where we should be discussing this but I'll keep it here for now.

So I read that other thread and it sounds like the "fuzz" heuristic would mostly work -- I mean it can be set to 0 and it would be effectively disabled so it's not like it would be a problem for anything I think.

The other idea to check the other files to figure out if the current (potentially broken) file is an outlier or not sounds like it could work but I'm not sure if it's worth the coding and performance hit? But it could potentially let you avoid having a global setting threshold, if you don't like that.

Which way do you want to go?