Code Monkey home page Code Monkey logo

vim-yadi's Introduction

yadi.vim

Yet Another Detect Indent. Here is how it works in my .vimrc:

" Try to auto detect and use the indentation of a file when opened. 
autocmd BufRead * DetectIndent

" Otherwise use file type specific indentation. E.g. tabs for Makefiles
" and 4 spaces for Python. This is optional.
filetype plugin indent on

" Set a fallback here in case detection fails and there is no file type
" plugin available. You can also omit this, then Vim defaults to tabs.
set expandtab shiftwidth=4 softtabstop=4

" You stay in control of your tabstop setting.
set tabstop=4

The plugin is built on the following principles:

  • Ignore outliers. A few bad whitespace should not stop the plugin from working. But as a user I don't want to be warned of or worse required to fix those inconsistencies. That's not in the scope of this plugin.
  • Leave settings unchanged if detection fails. The users .vimrc or file type plugins should then determine the indentation style.
  • Only ever touch the 3 settings relevant to indentation: expandtab, shiftwidth and softtabstop
  • Be a single, short and easy to comprehend Vimscript file.

Not convinced yet? Take a look at the code, it fits on a single page.

Commands

The :DetectIndent command tries to auto detect the indentation style in the current buffer. If it finds tabs it sets noexpandtab shiftwidth=0 softtabstop=0, if it finds n spaces it sets expandtab shiftwidth=n softtabstop=n. If the algorithm can't confidently determine the indentation style no settings are changed. It comes naturally to set this as an autocommand as can be seen above.

The :IndentTabs and :IndentSpaces <n> commands explicitly apply the settings for tabs and spaces respectively. The argument to :IndentSpaces can be omitted in which case your tabstop setting will be used.

The algorithm

The developers of the Firefox dev tools wrote a great article where they compare different indentation detection strategies for Firefox's built-in source editor. yadi.vim uses the "comparing lines" strategy from the article because it performs well and is easy to implement. The article explains it well:

This method compares the indentation of each line with the previous line, and adds the difference to a tally. So if a line is indented by 10 spaces, and the previous by 8, one more vote would be added for 2-space indentation.

Mixed tabs and spaces as well as 1-space indentation are not supported. This is a deliberate choice as these indentation styles are rare and would complicate the algorithm considerably.

Furthermore there is a heuristic in place to prevent misdetection. More than 80% of the file must be either tabs or spaces for the detection to succeed. Additionally in the case of spaces the most common indentation level must make up more than 60% of all indentations.

Integration with statuslines

To display the current indentation settings in your statusline you could use this expression:

let &statusline = '%{&expandtab?shiftwidth()." sp":"tabs"}'

Or with lightline.vim:

let g:lightline = {
      \ 'active': {
      \   'right': [ [ 'lineinfo' ],
      \              [ 'percent' ],
      \              [ 'fileformat', 'fileencoding', 'filetype', 'indentstyle' ] ]
      \ },
      \ 'component': {
      \   'indentstyle': '%{&expandtab?shiftwidth()." sp":"tabs"}'
      \ },
      \ }

Why yet another clone of DetectIndent?

There are a bunch of plugins with DetectIndent-like functionality:

But none of them let you fall back to file type plugins if detection fails. Most of them force you to set a fallback indentation style. sleuth.vim is more sophisticated and tries to guess the indentation from surrounding files. It's a different approach which comes at the cost of greater complexity and makes the result rather unpredictable.

vim-yadi's People

Contributors

konfekt avatar timakro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

vim-yadi's Issues

Continuation indent

AFAIU, the algorithm currently doesn't distinguish regular indentation and continuation indentation.

For example, one may want the former to be 2 and the latter to be 4:

public class SomeClass {
  public void doSomething() {               // 2
    if (true                                // 2
        && false) {                         // 4
      someMethodWithALotOfArguments(arg1,   // 2
          arg2.formatWith("XYZ",            // 4
              true),                        // 4
          arg3.formatWith("ABC",            // 4
              false));                      // 4
    }
  }
}

In this case, it seems vim-yadi thinks the file is indented with 4 spaces but actually 2.

I wonder if it's possible to cater for this scenario?

minimal line count

Continuing with the example of #4, if the buffer initially has too few lines, for example only 2, maybe vim-yadi should refrain from changing the defaults;
instead a minimal line count (> 5 ?) is required.

disregard line continuations

Continuning in a way the previous discussions starting with #4, maybe vim-yadi could be made aware of line continuation characters such as in

autocmd vimrc BufWinEnter <buffer> ++nested if exists('syntax_on') &&
      \ ! empty(&l:filetype) &&
      \ filereadable($VIMRUNTIME . "/syntax/" . &l:filetype . ".vim")
      \ | syntax enable | endif

if argc() > 0
  let argidx=argidx()
endif

Currently, this sets &shiftwidth to 6, which is not intended

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.