tpope / vim-sleuth Goto Github PK
View Code? Open in Web Editor NEWsleuth.vim: Heuristically set buffer options
Home Page: https://www.vim.org/scripts/script.php?script_id=4375
sleuth.vim: Heuristically set buffer options
Home Page: https://www.vim.org/scripts/script.php?script_id=4375
I’ve been running vim-sleuth with this patch all day:
diff --git a/plugin/sleuth.vim b/plugin/sleuth.vim
index 560135e..9d25d03 100644
--- a/plugin/sleuth.vim
+++ b/plugin/sleuth.vim
@@ -159,9 +159,9 @@ endfunction
setglobal smarttab
-if !exists('g:did_indent_on')
- filetype indent on
-endif
+" if !exists('g:did_indent_on')
+" filetype indent on
+" endif
augroup sleuth
autocmd!
It has detected the indentatition of all files I’ve worked with perfectly.
I want :filetype indent off
.
Here are three alternate suggestions:
:filetype indent on
enforcement.g:sleuth_enforce_filetype_indent_on
.Thanks for the best indentation detector I’ve come across so far!
@tpope Plugin is working awesome.
But default it is considering tab (\t) width to 8 for tab indent files, and there is no config provided to change it to 4.
Currently I override it inside plugin source.
We should have a configurable option to make ts=4 & sw=4
Given the following file:
# vim:sw=8:ft=votl
Bla:
- bla
- bla
foobar
some
- space
- indented
- text
I get sw=2,ts=8
in SleuthIndicator()
:
:echo &modeline | :echo &modelines | :echo SleuthIndicator()
1
5
sw=2,ts=8
I'm using vim-sleuth ea3f065 and neovim v0.4.3
I found that if I open a certain markdown file vim takes forever:
$ time vim doc/ats-feed-docs/README.md +quit
vim doc/ats-feed-docs/README.md +quit 0.396s user 0.916s system 76% cpu 1.714 total
I can reproduce the issue with a vimrc of simply:
set rtp+=~/code/dotfiles/vim/bundle/polyglot
set rtp+=~/code/dotfiles/vim/bundle/sleuth
" Pretend to be pathogen
filetype off
filetype on
Removing any of the above fixes the problem. I suspect that there is some weird thing about polyglot that makes detecting filetypes really slow, though I don't really see why that would involve sleuth. If there is anything else I can do to assist here I'm happy to. If you look at polyglot (it's huge) and see something obviously wrong I am also happy to pass along anything you find.
This should allow for not running it automatically, but letting the user invoke it manually, in case it's needed.
My preferences for go (golang) files don't always mesh well with this plugin, which I otherwise really like. See #28 for a concrete example. It could be nice to be able to do something like this:
let g:vim_sleuth_exclude_languages = "go"
The script seems to assume physical tabs are 8 spaces. Wouldn't it be better if it read the user set tabstop
and used that value?
This plugin will, for whatever reason, detect ts=8
for the following go
file, when ts=2
for go in my settings:
package lutzky
const k = `
multiline
interestingline1
`
func main() {
interestingline2 := 5
}
Note that this file is formatted by gofmt
. interestingline1
is manually indented by 2 spaces, whereas intererestingline2
is gofmt
-indented by a tab.
This might be a super-weird edge case, feel free to close as WONTFIX. (I'll be referencing this issue in another one)
diff --git a/.vim/plugin/sleuth.vim b/.vim/plugin/sleuth.vim
--- a/.vim/plugin/sleuth.vim
+++ b/.vim/plugin/sleuth.vim
@@ -118,7 +118,9 @@
for pattern in patterns
for neighbor in split(glob(dir.'/'.pattern), "\n")
if neighbor !=# expand('%:p')
- call extend(options, s:guess(readfile(neighbor, '', 1024)), 'keep')
+ if (filereadable(neighbor))
+ call extend(options, s:guess(readfile(neighbor, '', 1024)), 'keep')
+ endif
endif
if s:apply_if_ready(options)
return
Vim-sleuth isn't using the formatting from neighboring .cpp or .h files. Detection does work for other filetypes like .rs. I've double checked that the files are in fact being recognized correctly (filetype=cpp) and can reproduce the issue in both neovim (v0.3.1) and a fresh vim install (8.1.333). Installed using vim-plugged, the complete vimrc file used for vim8 is below.
call plug#begin('~/.vim/plugged')
Plug 'tpope/vim-sleuth'
call plug#end()
I notice a significant startup delay when other files detection is used. Profiling shows the culprit is building a filetype->patterns dictionary at ~100ms which is costly especially for short session workflows. At the same time current file detection on it's own is fast and often good enough for practical use, hence I don't want to disable automatic detection completely.
It would be great to have a "lightweight" auto-detection mode which doesn't cause costly patterns initialisation and therefore only look at the current file. But it would happily use existing patterns (after manual :Sleuth
). It could be enabled by let g:sleuth_automatic = 2
.
I have the following problem, I normally use spaces instead of tabs, but some projects still use them. It looks like the vim-sleuth could help me to ease the setup. After installing it, I removed the tabstop
, softtabstop
, expandtab
and shiftwidth
from my vimrc
.
Problem is while it seems to work quite fine on my own files, and new ones from my own projects, it sets tabstop
to 8
(which I believe is vim default). I normally work using a laptop with a tiling window manager so the "width" of the window for me is somewhat critical. And, for example open json tabbed files, results in something hard to wield.
Setting tabstop
to 4
, it seems to improve the file a lot, but I'm not sure if this could interfer with the plugin itself (vim documentation states having set to something different to 8 it could led to issues while printing, but honestly, I have never used vim for printing, so it's a non-issue for me).
So, tl; dr → is it acceptable to the plugin, only include set tabstop=4
from the vimrc
while removing, expandtab
, shiftwidth
, expandtab
and softtabstop
? (I still have set smarttab
on, and seems ok...)
Hello! I recently started using this plugin and I've found it quite convenient, but it seems it's configured a bit too much for my taste. I have autoindent
set in my vimrc so that when I press Enter in insert mode I start the new line at the same indentation level as the current line. This seems to have changed since adding vim-sleuth, as now indentation is automatically added in a few places it wasn't before. The automatic indentation doesn't agree with my code style, so I'd rather not have vim try to indent any more intelligently than autoindent
.
I think what's causing this behavior is indentexpr
being set, but looking at the plugin source I don't think vim-sleuth is doing it directly. Can someone explain how this is getting set and how I can restore the original indentation behavior? I wonder if this may also be considered a bug, since the readme for this project seems to only indicate that the plugin affects shiftwidth
, expandtab
, softtabstop
, and smarttab
, and doesn't document that autoindent behavior is affected.
The plugin seems not to take a modeline into account if it is available. Could you provide an option or integrate by default?
When I enable vim-lsp's g:lsp_diagnostics_float_cursor
and move to one of the highlighted issues in my source, I get an error from vim-sleuth:
Error detected while processing function <SNR>130_debounceTimeTimerCallback[1]..<SNR>130_mapFSourceCallback[1]..<SNR>130_distinctUntilChangedSourceCallback[14]..<SNR>130_filterSourceCallback[6]..<SNR>130_filterSourceCallback[6]..<SNR>130_mapFSourceCallback[1]..<SNR>130_subscribeSourceCallback[2]..<lambda>8[1]..<SNR>137_show_float[3]..lsp#ui#vim#output#preview[45]..lsp#ui#vim#output#setcontent[4]..FileType Autocommands for "*"..function <SNR>68_detect[10]..<SNR>68_patterns_for:
line 5:
E930: Cannot use :redir inside execute()
The corresponding script numbers in that backtrace are:
68: ~/.vim/bundle/sleuth/plugin/sleuth.vim
130: ~/.vim/bundle/lsp/autoload/lsp/callbag.vim
137: ~/.vim/bundle/lsp/autoload/lsp/internal/diagnostics/float.vim
This is on Fedora 32, VIM version 8.2.1551.
Please let me know if there's more info I should provide. Maybe this is ultimately vim-lsp's error, I'm not sure.
I'd like to be able to set an option to only search up one or two directories (though best would be to only traverse up until you find a .git,.svn,etc). I know little of vim scripting, so I'm just gonna leave this here...
In a legacy project I work on, hard tabs are the standard, but occasionally, there will be a line that starts with spaces.
Currently, vim Sleuth handles inconsistent indenting here:
https://github.com/tpope/vim-sleuth/blob/master/plugin/sleuth.vim#L84
This effectively overwrites the (correct) tabstop settting I already have in my vimrc, while leaving the shiftwidth unchanged.
What is the use case where you'd want to change the user's tabstop to 8 (rather than leaving it as their default) when there are spaces mixed in with mostly tabs?
Executing :verbose set shiftwidth
returns:
shiftwidth=7
Last set from ~/.cache/dein/.cache/init.vim/.dein/plugin/sleuth.vim
So that value looks very weird to me. It does not matter if sw/ts/sts has being set in my configuration file.
I have also tested it with a very clean configuration file, including only my plugin manager and vim-sleuth.
If buftype
== terminal
/ prompt
/ popup
there's no need to run sleuth on them. Maybe can add check in autocmd
for buftype
?
Background:
I often use terminals in vim, and sometimes, if terminal buffer name contains special characters (such as '['
, ']'
, '='
) I get error message:
Error detected while processing function BufFilePost Autocommands for "*"..function <SNR>60_Init[7]..<SNR>60_Detect:
E944: Reverse range in character class
vim-sleuth version: commit b14a41a07
Vim version: 8.2.3517 GTK3 GUI
OS: Manjaro Gnome
I have a project I'm working on which contains javascript files indented with 4 spaces. When I try and use vim-sleuth with these it sets my indentation to 3 spaces.
The only file I can find that contains 3 space indent in the project is a LICENCE file in my root dir (where I usually launch vim from). Removing this file appears to result in my indentation being set to the desired 4 spaces. But since all my javascript files appear to be indented with 4 spaces, I would expect vim-sleuth to detect filetype and follow suit. Is this not the desired behaviour?
When I disable vim-sleuth my old default settings kick in and give me 4 space indentation, so I don't think it's another plugin affecting things.
I open this file: https://raw.githubusercontent.com/pulumi/examples/master/kubernetes-ts-guestbook/index.ts
When I go to a random spot and hit enter, it drops me on an incorrectly idented line (tabs, not spaces).
The notes for sleuth are quite clear: if a file is indented by tabs, then shiftwidth is set to 0. This creates a problem when I want to use vim-javascript. It seems that it wants to use the shiftwidth to indent, hence no indent at all.
So this is partly an issue, and partly a question. Which is the correct behavior? vim-javascript, or vim-sleuth? I don't know myself, but looking here: http://vim.wikia.com/wiki/Indenting_source_code suggests that shiftwidth should be the same value as tabstop (see section "Indentation purely with hard tabs").
Incidentally, I have ts=4 and sw=4 in my vimrc, but sleuth overwrites this value for the js file I'm trying to edit.
Thank you for your attention.
on line 19th why not use ^\s*$
to skip empty line?
A shell script of mine starts with
#!/bin/dash
# FIXME awk: fatal: can't open source file `./checksum.awk' for reading (No such file or directory)
and continues with a few more comments then hard-tab indented commands.
Because the FIXME line matches the pattern that detects the beginning of a backtick block, and no subsequent line matches the pattern that detects the end of a backtick block, function guess
slurps the whole file as a very long backtick, never detecting spaces, hard tabs or even incrementing any heuristics counter.
What happens next depends on the contents of neighboring files. In my case one of them was indented with spaces, and sleuth based its guess on that file. Therefore, it ended up setting expandtabs
on the first script --the one indented with hard tabs.
So that FIXME line trips heuristic detection. Of course I will delete that line. It's unfortunate that most *nix utilities print the "No file or directory" error message quoting the filename between a backtick and a straight tick.
The moral of this story is, don't place shell comments before an indented line (strict moral) or, if you do, ensure that no comment line includes a single backtick (soft moral).
Morals apart, I'm not sure if anything can be done to fix this issue conclusively, if heuristics could ever be conclusive, but perhaps adding a comment to the docs?
Or perhaps modifying guess
to take a second look at the file when it's about to exit with all heuristics counters set to zero and a comment/backtick flag still on, which was exactly my case.
Thanks for this plugin. By installing this plugin, I was able to remove all indenting related configuration from my vimrc and after files. Spot on!
I'm having some issues with this plugin properly identifying python files as 2-space indented (perhaps because continuation lines are indented with 4 spaces? I haven't dug into the algorithm). I'd like to disable the plugin for all python files for now. I don't see an option for this, is it possible?
I'm not sure if this is the case but many files (that use tabs) are opened with tab set to 8 spaces while my default setting is 4. Perhaps there should be a setting for sleuth to fallback to if no possible indentation can be deduced?
Anyway, thanks Tim for a nice plugin.
If a file has both spaces AND tabs as indentation it would be very handy if vim-slueth would pop up some sort of warning that indentation is inconsistent, so that I know I need to fix it.
Exiting vim causes the prompt in my terminal (macOS, default terminal) to appear at the bottom of the window.
vim-sleuth was identified as the culprit after commenting every line on my .vimrc
I'm not sure how correct or not im with this but, seems like my spaces and tabs are mixed in the indenting, actually i have a setting that shows me tabs very visually:
"====[ Make tabs, trailing whitespace, and non-breaking spaces visible ]======
exec "set listchars=tab:\uBB\uBB,trail:\uB7,nbsp:~"
set list
So with the bash source codes, the first indenting looks to be spaces and in the second level tabs, try with this demo file: https://gist.github.com/Thanatermesis/9791996
This is the file in question:
https://github.com/eLvErDe/museek-plus/blob/master/python-clients/museekcontrol
It seems consistently indented to me.
Setting tabstop to 4 after opening the file works just fine, but I have to do it every time as it seems that set tabstop=4
in my vimrc is not working.
I don't have any other indent-settings in vimrc as far as I can tell. Here's the config: https://da.gd/GqXOa
Here's the file:
https://raw.githubusercontent.com/git/git/master/git-add--interactive.perl
I was expecting sw=4, ts=4
(preferred) or a least sw=8, ts=8
.
Summary:
:Sleuth
manually works, as does adding autocmd BufEnter * :Sleuth
to my .vimrcGists:
After updating to the latest change, I started getting this error E121: Undefined variable: capture
version:
NVIM v0.7.0-dev+nightly-975-gd3585e0ec
Build type: Release
LuaJIT 2.1.0-beta3
Compiled by [email protected]
Features: +acl +iconv +tui
See ":help feature-compile"
system vimrc file: "$VIM/sysinit.vim"
fall-back for $VIM: "/opt/homebrew/Cellar/neovim/HEAD-d3585e0/share/nvim"
Run :checkhealth for more info
I can't decide if this is a bug in the detection algorithm, or my own misunderstanding of how I should be using sleuth.
I currently have in my vimrc:
set tabstop=2 shiftwidth=2 expandtab
I then edit a file with the following contents:
public class Test {
public Test() {
}
}
(note that this file uses tabs rather than spaces for indenting).
When opening this file, tabstop=2 as expected. Additionally noexpandtab is set, also as expected. But shiftwidth=8 whereas I would have expected it to be 2.
You mention in the readme that your intention is to remove the need for any tab configuration in a user's vimrc. However, when I do that, tabstop=8. That now matches the shiftwidth value so everything works fine, and it's the expected result. But I prefer having tabs displayed with width of 2, and can't quite figure out the best way to do.
(btw, I'm really glad you're working on this. I've long wanted something like this, mainly for working on various open source projects that have different style guides. I guess it just never bothered me enough to seek out and find DetectIndent or anything like it)
I believe this is inconsistent with readme?
module Main where
import Lib
main :: IO ()
main = someFunc
Hi Tim - thanks for all the amazing plugins!
I think it would be helpful to have some kind of indication of whether Sleuth succeeded in detecting and setting indentation. In existing projects Sleuth always works great for me, but when I start a new project sometimes I want to use indentation settings that differ from the defaults in my vimrc. It would be cool if I could set up some sort of fallback mechanism that could run in such a case.
I played around with the following tweak to Sleuth which generally works ok for what I'm trying to do:
function! s:apply_if_ready(options) abort
if !has_key(a:options, 'expandtab') || !has_key(a:options, 'shiftwidth')
+ let b:_sleuth_set = 0
return 0
else
for [option, value] in items(a:options)
call setbufvar('', '&'.option, value)
endfor
+ let b:_sleuth_set = 1
return 1
endif
endfunction
and then in my vimrc (SetIndent
is a command I have set up to automatically set indentation levels for different filetypes):
autocmd BufNewFile,BufReadPost * if !get(b:, '_sleuth_set', 1) | SetIndent | endif
But I'm sure something more elegant could be implemented, maybe with a doautocmd
? I'd be willing to take a crack at this if you're amenable to the feature. No big deal if not.
Thanks!
Configuration
nvim
v0.2.2
init.vim
call plug#begin('~/.local/share/nvim/plugged')
Plug 'tpope/vim-sensible'
Plug 'tpope/vim-sleuth'
call plug#end()
set tabstop=4
set list
Steps
$ nvim
)i
<tab>
Expected
One tab character is inserted (either shiftwidth
is set to 4 or tabstop
is set to 8).
Actual
Two tab characters are inserted (shiftwidth=8
and tabstop=4
).
I loaded slueth as I was trying to get one last thing in vim that I was having trouble with and that is indenting for css
so I loaded a styles.css file which is indented such as this.
div {
margin:0;
padding:0;
}
div div {
background: #A4CA39;
position: relative;
}
.android {
height: 404px; width: 334px;
margin: 100px auto;
}
But when I edited to contiue I still didn't get correct indentation i got this, is there a way to get it right?
.body {
}
Go files (that are gofmt'ed) are indented with tabs. It used to be that tabstop was 2 (I believe), either from sleuth.vim or from somewhere in my config. Now sleut.vim forces 8, which is a bit too much.
Why don't you add some configurable variables for heuristics.hard? For example, something like below:
" at line 73 in sleuth.vim
if heuristics.hard
let options.tabstop = sleuth_tabstop
endif
In addition, I think let options.shiftwidth = 8
is missing at line 74.
Thanks!
If you have sleuth.vim installed, you will always have filetype indent
enabled when plugin/sleuth.vim loads.
It may seem obvious that enabling an indentation-related plugin would enable extra indent settings on you, but since it loads after vimrc time and there's no :verbose filetype
variant to troubleshoot what's overriding :filetype
on you, it's pretty painful tracking down why you're not able to disable filetype indent from your vimrc if you decide to try it.
I'm currently working on an horrible legacy php application written in Joomla. It stores files in the php format, in order to do something like this :
#
#<?php die('Forbidden.'); ?>
#Date: 2014-02-07 10:59:14 UTC
#Software: Joomla Platform 11.4.0 Stable [ Brian Kernighan ] 03-Jan-2012 00:00 GMT
I know, it is stupid.
Some of its neighbours are huge (there are 2 files over 10M), and they are numerous 1176 files. When I try to open one of them (even a very small one), vim hangs because of sleuth (I know it is sleuth because I disabled it and it worked fine).
It would be good if there is documentation on how to use default indentation settings combined with this plugin. For example, show an example where the default settings for ruby are set to 2 spaces, and mention that this plugin will override the setting if the current file has four spaces indenting. (By the way is that last statement correct?)
Given the following file:
<script>
// vim: ft=html
// script indent
// indent two spaces
// up to some level
</script>
I open the file in Vim, I run :Sleuth
. It should set my indentation to two spaces.
When I indent a line once more than in the example, i get a tab character, mixing spaces and tabs. Something I'd like to avoid. Indentation settings is detected as ts=8 sts=-1 sw=2 et=0 ai=1
Removing the modeline makes it work (indentation setting is detected as ts=8 sts=-1 sw=2 et=1 ai=1
).
Looks like opening even small YAML files under WSL1 (Ubuntu 20.04) with vim-sleuth
enabled takes more time than it should.
Without:
time vim site.yaml
________________________________________________________
Executed in 1.84 secs fish external
usr time 93.75 millis 0.00 micros 93.75 millis
sys time 156.25 millis 0.00 micros 156.25 millis
With:
time vim site.yaml
________________________________________________________
Executed in 3.56 secs fish external
usr time 0.44 secs 0.00 micros 0.44 secs
sys time 1.83 secs 0.00 micros 1.83 secs
vim site.yml --startuptime vim.log
: https://gist.github.com/shmileee/3183bd6225ddc11a6c0b55abbfa62d9c
.vimrc
for reference: https://github.com/shmileee/dotfiles/blob/3037be9b6828d2a590d2a3cb1bc1582977626419/.vimrc
Vim version: VIM - Vi IMproved 8.1 (2018 May 18, compiled Apr 15 2020 06:40:31)
YAML file for referecnce:
---
- hosts: k3s_cluster
gather_facts: yes
become: yes
roles:
- role: prereq
- role: download
environment: "{{ proxy_env }}"
- hosts: master
gather_facts: no
become: yes
roles:
- role: k3s/master
- hosts: node
gather_facts: no
become: yes
roles:
- role: k3s/node
- hosts: master
gather_facts: no
become: yes
roles:
- role: addons/common
tags: common
- role: addons/metallb
- role: addons/traefik
environment: "{{ proxy_env }}"
tags: addons
Hey, thanks for your script, I've been using it for a long time. I've almost never had to think about indentation again.
Since I wanted to install it globally for all users, I'm creating an Archlinux package for it. Would it be possible to do a new release? The last one (1.1) is seven years old and there have been plenty of commits since then.
I have a shell script file that is tab indented. It contains a heredoc that is manually aligned with spaces.
Sleuth erroneously thinks the spaces inside the heredoc are part of the indentation of my code, so it sets tabstop to 8, which is the default for files that contain mixed tabs and spaces for indentation.
Instead, Sleuth should ignore the contents of the heredoc and recognize that my shell script is exclusively tab indented.
As mentioned in #17 (comment), heredocs could be added to the list of guards:
Lines 25 to 61 in b6347df
For me markdown files takes a good 20 seconds to load. This seems to be derived from the fact that sleuth traverses the tree to find indentation in other files when it cannot immediately infer it from the opened file.
I suspect that since markdown files seldom uses indentation, sleuth will never find a match and block the file from loading until it has traversed the entire tree.
I don't know what would be a good solution for this. Maybe a timeout?
I don't know the specifics about markdown. If they all have the same indentation characters maybe you could even blacklist md files?
I changed to the Detectindent plugin and have not had problems since.
Is there a way to ignore comment lines when computing shiftwidth?
Putting the code below in a file (in an otherwise empty directory) results in a shiftwidth=2. Note that the indent in the docstring is 2, and 4 in the actual code. If you wonder why i use only an indent of two in the docstring, this was in a case where the docstring was ment as input for docopt. Below is just a short and simpified example.
"""
A docstring.
Some items:
* item1
* item2
"""
def myfunc1(a, b):
return a + b
def myfunc2(a, b):
return a - b
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.