paradigm / SkyBison

Vim plugin to expedite use of cmdline commands
73 stars 9 forks source link

SkyBison

If you'd like to skip the whole "reading" nonsense and watch a nice, wholesome video which explains SkyBison instead, see here.

Description

It is well established that some of Vim's cmdline commands can be a bit awkward to use, especially in comparison to how keystroke-efficient most of the rest of Vim's functionality is, and as a result there are a plethora of plugins designed to make functionality such as :b and :tag more accessible.

SkyBison is another attempt at tackling this problem. It differs from other options in two key ways:

  1. It is intended to have a clean, simple and small code base.
  2. It is designed to alleviate the awkwardness of the cmdline itself rather than targeting specific commands. SkyBison has no code specifically for :b, for :tag, etc - it supports them as a side-effect of making the cmdline more comfortable.

More specifically, SkyBison alleviates three issues where the author felt Vim's cmdline was both obviously lacking during normal usage and easily capable of remedying:

  1. If Vim knows likely values for the term the user is typing (such as from its cmdline-completion), it should print them constantly. It seems silly to require the user input c_ctrl-d when he or she wishes to see completion options when it could just show them all the time.
  2. If Vim (again through the cmdline-completion) narrows down the possibilities for the term the user is typing to a single one, it seems silly to require the user to hit cctrl-l or c<tab> (or even worse, finish typing the whole thing) in order to accept it when the user enters c_<cr>. Vim already knows what is going on - just accept the term the user is in the process of typing.
  3. As an extension of (2) above, if Vim has a way of knowing the number of terms that will be on the cmdline, why have the user hit c<cr> at all? When only one possibility remains, skip the c-ctrl-lc<cr> and immediate accept it.

For example:

If Vim has three (listed) buffers, ".vimrc", ".bashrc" and ".zshrc", and the user calls SkyBison("b "), the user will see the following:

1 .vimrc
2 .bashrc
3 .zshrc
:b 

If the user inputs "v", SkyBison will recognize that the user wants ".vimrc" and select it (or prompt the user to hit <cr> to select it). However, if the user inputs "s" (which is in both .bashrc and .zshrc, but not in .vimrc), the user will see the following:

1 .bashrc
2 .zshrc
:b s

SkyBison recognizes that .vimrc is no longer an option and drops it from the possibilities. However, all of the remaining characters after "s" are shared in the remaining options. Here, the user could enter "1" or "2" to select an option. In fact, the user could have entered "1", "2" or "3" earlier to select a buffer when all three were possibilities.

This works wherever cmdline-completion works, including at a empty cmdline prompt and after :bar, including (but not limited to) :b for buffers, :tag (for jumping to a tag), :e (for editing a file), :h (for help), and many others.

Setup

Note that as of 0.3, SkyBison's configuration is slightly different from how it was in previous versions (as a result of added functionality).

SkyBison can be installed like most other Vim plugins. On a Unixy system without a plugin manager, the skybison.vim file should be located at:

~/.vim/plugin/skybison.vim

On a Unixy system with pathogen, the skybison.vim file should be located at:

~/.vim/bundle/skybison/plugin/skybison.vim

On a Windows system without a plugin manager, the skybison.vim file should be located at:

%USERPROFILE%\vimfiles\plugin\skybison.vim

On a Windows system with pathogen, the skybison.vim file should be located at:

%USERPROFILE%\vimfiles\bundle\skybison\plugin\skybison.vim

If you are using a plugin manager other than pathogen, see its documentation for how to install skybison - it should be comparable to other plugins.

If you would like the documentation to also be installed, include skybison.txt into the relevant directory described above, replacing "plugin" with "doc".

SkyBison can be called via:

:call SkyBison({string})

Where {string} is a string containing the characters you would like to be in the prompt when it starts. Rather than going to the cmdline to run it, you could make a mapping, like so:

nnoremap {keys} {count}:<c-u>call SkyBison({string})<cr>

Here, {keys} are the keys you would like to use to launch SkyBison, {count} is an optional number you could use to tell SkyBison how many terms to expect (at which it will automatically accept the cmdline without waiting for <cr>), and {string} is the same as it was above.

Note: If you do not include {count} in the mapping, you can type it before you type the map {keys} to manually set it before each launch of SkyBison. Or simply do not include or type it to opt out of the functionality if you do prefer to always have Vim wait for you to hit <cr>.

For example:

nnoremap <leader>s :<c-u>call SkyBison("")<cr>

Or, if you find you much prefer SkyBison to the normal cmdline, you could map it over the default:

nnoremap : :<c-u>call SkyBison("")<cr>

Be sure you know another way to get to the cmdline, just in case there are problems with SkyBison.

If you would like to further expedite access to specific cmdline commands, you can make mappings which launch SkyBison with the command already in the prompt. For example:

nnoremap <leader>b 2:<c-u>call SkyBison("b ")<cr>
nnoremap <leader>t 2:<c-u>call SkyBison("tag ")<cr>
nnoremap <leader>h 2:<c-u>call SkyBison("h ")<cr>
nnoremap <leader>e :<c-u>call SkyBison("e ")<cr>

Note: The space after the command is necessary to let SkyBison know to start looking for an argument for the command rather than to continue looking for possible commands.

Note: For commands which browse the filesystem, such as :e, it is recommended not to include a {count} so that SkyBison does not immediately accept a directory when you want the argument to be a file in that directory.

With those mappings:

With the above mappings, if the user had several buffers open, but only one starting with "v", the user could select that buffer in three keystrokes: <leader>bv. It could be further reduced to two keystrokes if a shorter mapping was used (e.g.: just <space> or <cr>)

You can also include more than just the command in SkyBison's argument, but also a starting string, if you'd like. For example, if you regularly edit files in ~/projects/, you could use the following:

nnoremap <leader>p :<c-u>call SkyBison("e ~/projects/")<cr>

Moreover, you can have SkyBison take over from an in-progress cmdline, with a mapping like so:

cnoremap {keys} <c-r>=SkyBison("")<cr><cr>

where {keys} is replaced with what you want to type, such as "<c-l>"

Usage

Once a mapping (as described in skybison-setup) is called, the user will see the what Vim considers as possible arguments to the current cmdline's prompt. From here, the user may:

Due to the way SkyBison parses possible options from Vim's cmdline-completion, items with non-escaped spaces in them will appear as multiple items, split at the whitespace. To select one, give enough information to uniquely identify the first part of it, then use either ctrl-l or <tab> and SkyBison will fill out the rest, at which point you can hit <cr>.

Options

SkyBison supports two variations of fuzzy matching. To use no fuzzy matching, either set:

let g:skybison_fuzz = 0

or simply leave that variable unset. To use "full" fuzzy matching, where SkyBison will only care that the possible match includes the characters you've entered in order (irrelevant of what is or is not between them, set:

let g:skybison_fuzz = 1

To use substring matching, where SkyBison will ignore characters before and after the string you've entered, but require that all of the characters you've entered are available in the possible match in order with nothing in between them, set:

let g:skybison_fuzz = 2

By default, if you press a number 1-9 and at least that many items exist in the output, that item will be selected. This can be disabled by default by setting the following:

let g:skybison_numberselect = 0

You can also toggle this setting for the duration of a given SkyBison session by pressing ctrl-g.

SkyBison has two input methods, each of which has a advantages and disadvantages. You can set

g:skybison_input = 0

or

g:skybison_input = 1

to pick which one you'd like. If you leave the variable unset, g:skybison_input=0 is the default.

With g:skybison_input empty or set to "0", SkyBison will use getchar(). The advantages of this are:

With g:skybison_input set to "1", SkyBison will use a while loop waiting for getchar(1). The advantages of this are:

Miscellaneous

SkyBison uses Vim's cmdline-completion under-the-hood. This allows SkyBison to support a wide variety of commands without requiring logic per command, and thus allows SkyBison to be quite lightweight in comparison to other plugins.

Globbing with * and ** work as one would typically expect. For example, :e **/*.vim could be used to prompt for every file ending in .vim in the current directory or any subdirectory. See starstar for details.

SkyBison works just fine as a general cmdline, not just for specific commands. It handles things like pipes properly.

The downside to using Vim's cmdline-completion under-the-hood is that requests which can take Vim's cmdline-completion a while to complete will also choke SkyBison. This is particularly noticeable in situations such as:

When using commands which browse the filesystem, such as :e, directories will be recognized as valid/selectable options before SkyBison realizes that they can be expanded to generate new completion options. Hence using a {count} on such items will select the directory, which is often not desirable. It is probably possible to have SkyBison double-check that a given input only has one option before automatically selecting it to remedy this should the time be taken to investigate it.

Running :e on a directory does not currently bring up the netrw window. This can probably be fixed should the time be taken to investigate it.

Changelog

0.9 (2013-09-18):

0.8 (2013-09-09):

0.7 (2013-06-19):

0.6 (2012-12-18):

0.5 (2012-11-07):

0.4 (2012-11-07):

0.3 (2012-11-05):

0.2 (2012-11-04):

0.1 (2012-10-31):