An always-on highlight for a unique character in every word on a line to help you use f, F and family.
This plugin should help you get to any word on a line in two or three keystrokes with Vim's built-in f<char> (which moves your cursor to <char>).
When moving across a line, the f, F, t and T motions combined with ; and , should be your go-to options for many reasons. Quick-scope fixes their only drawback: it is difficult to consistently choose the right characters to target.
-
Quick-scope highlights the first occurrences of characters to the left and right of your cursor (green in the screencast), once per word, every time your cursor moves.
-
If a word does not contain a first occurrence of a character but contains a second occurrence of a character, that character is highlighted in another color (blue in the screencast).
-
Quick-scope takes extra measures to avoid bombarding you with superfluous colors:
- Highlighting is done automatically.
- You already know what character to target before pressing any keys.
- No more guesswork or slowing down to reason about the character motions.
- This plugin neither introduces new motions nor overrides built-in ones.
- You don't have to learn any new commands or mappings.
- This helps you to become a better user of vanilla Vim.
Use your favorite plugin manager.
" Your .vimrc
Plug 'unblevable/quick-scope' " Plug
NeoBundle 'unblevable/quick-scope' " xor NeoBundle
Plugin 'unblevable/quick-scope' " xor Vundle
$ git clone https://github.com/unblevable/quick-scope ~/.vim/bundle/quick-scope # xor Pathogen
" Your .vimrc
" Trigger a highlight in the appropriate direction when pressing these keys:
let g:qs_highlight_on_keys = ['f', 'F', 't', 'T']
" Trigger a highlight only when pressing f and F.
let g:qs_highlight_on_keys = ['f', 'F']
Quick-scope determines the highlighting mode (always on, vs highlight on key
press) when the plugin is initialized. This means that if you want highlight on
keys functionality this value must be set before the plugin/quick_scope.vim
file is sourced. For more details about it or details about symptoms you may
encounter see discussion in issues
#72 and
#98.
Quick-scope directly makes use of highlight groups called QuickScopePrimary
and QuickScopeSecondary
. By default QuickScopePrimary
is linked to the
Function
group and QuickScopeSecondary
is linked to the Define
group. You
can customize them by adding your own :highlight
commands.
" Your .vimrc
highlight QuickScopePrimary guifg='#afff5f' gui=underline ctermfg=155 cterm=underline
highlight QuickScopeSecondary guifg='#5fffff' gui=underline ctermfg=81 cterm=underline
However, it is recommended to put them in an autocmd
so that they are updated
if and when the colorscheme changes. To achieve this you should put the
following block before you set colorscheme <colorsname>
(Note: if you do
it after you will not see your colors).
" Your .vimrc
augroup qs_colors
autocmd!
autocmd ColorScheme * highlight QuickScopePrimary guifg='#afff5f' gui=underline ctermfg=155 cterm=underline
autocmd ColorScheme * highlight QuickScopeSecondary guifg='#5fffff' gui=underline ctermfg=81 cterm=underline
augroup END
The highlight groups are applied using a priority (see: :help :syn-priority
and :help matchadd()
for more detail). The default priority used is 1
but
you can override this if needed by setting it yourself using:
let g:qs_hi_priority = 2
Turn the highlighting on and off with a user command:
:QuickScopeToggle
Or create a custom mapping for the toggle.
" Your .vimrc
" Map the leader key q to toggle quick-scope's highlighting in normal/visual mode.
" Note that you must use nmap/xmap instead of their non-recursive versions (nnoremap/xnoremap).
nmap <leader>q <plug>(QuickScopeToggle)
xmap <leader>q <plug>(QuickScopeToggle)
Setting g:qs_enable
equal to zero will start the plugin disabled. (default: 1)
" Your .vimrc
let g:qs_enable=0
Additionally, setting the buffer local variable b:qs_local_disable
will have
the same effect on a specific buffer.
let b:qs_local_disable=1
Turn off this plugin when the length of line is longer than g:qs_max_chars
.
(default: 1000)
" Your .vimrc
let g:qs_max_chars=80
Setting g:qs_buftype_blacklist
to a list of buffer types disables the plugin when
entering certain buftype
's. For example, to disable this plugin when for terminals and
floating windows without filetypes set, put the following in your vimrc
:
let g:qs_buftype_blacklist = ['terminal', 'nofile']
Setting g:qs_filetype_blacklist
to a list of file types disables the plugin when
entering certain filetypes
's. For example, to disable this plugin for
dashboard-nvim and
vim-startify, put the following in your vimrc
:
let g:qs_filetype_blacklist = ['dashboard', 'startify']
The option g:qs_accepted_chars
is a list of characters that quick-scope will
highlight. (default: a list of a-z, A-Z, 0-9
)
" Your .vimrc
let g:qs_accepted_chars = [ 'a', 'b', ... etc ]
The option g:qs_lazy_highlight
can be used to change the vanilla highlight
mode autocmd event from CursorMoved
to CursorHold
. This option is provided
to reduce the slowdown caused by vanilla highlight mode in large terminals.
(default: 0
)
" Your .vimrc
let g:qs_lazy_highlight = 1
The option g:qs_delay
can be used to set the delay duration after which the
highlighting starts if the cursor is not moved. This option increases
performance. Taken into account only if g:qs_lazy_highlight
and
g:qs_highlight_on_keys
are not enabled. If you set this to 0, the
highlighting will be synchronous. It requires has('timers')
. (default: 50
)
let g:qs_delay = 0
This section provides a detailed look at the most common and useful options for moving your cursor across a line in Vim. When you are aware of the existing tools available to you and their trade-offs, you can better understand the benefits of this plugin.
I unofficially refer to f, F, t, T, ; and , as the character motions. They form your swiss army knife for moving across a line:
- The motions are easy to reason about. Simply choose a character and then move your cursor to it. (And with quick-scope, the best characters to choose are always identified for you.)
- They are versatile. You can usually move your cursor to any word on a line in a single motion.
- Yet they are also precise. You specify an exact location to move your cursor.
- The key combinations are quick to execute and efficient in terms of number of key presses. It should only take 2 or 3 key presses to move your cursor to where you want it to be.
- The f key in particular sits comfortably on home row of the keyboard.
- Vim includes a set of two dedicated keys, ; and ,, just to make it easier to repeat the character motions and offset bad character targets.
You can also consult Vim's excellent help docs for information about any
command using :h <command>
.
f<char> moves your cursor to the first occurrence of <char> to the right.
fg
It's just like the story of the grasshopper and the octopus.
^ > > > > > > > > > > > > > > > ^
F<char> moves your cursor to the first occurrence of <char> to the left.
Fl
All year long, the grasshopper kept burying acorns for winter,
^ < < < < < < < < < < ^
t and T can be just as useful. Notice how tf
is the most optimal way to reach the word off
in the example below.
t<char> moves your cursor right before the first occurrence of <char> to the right.
tf
while the octopus mooched off his girlfriend and watched TV.
^ > > > > > > > > > ^
T<char> moves your cursor right before the first occurrence of <char> to the left.
Ts
But then the winter came, and the grasshopper died, and the octopus ate all his acorns.
^ < < < < ^
The character motions can take a preceding count
, but in practice, Vim users
tend to use the ; and , to repeat a character motion any
number of times.
; repeats the last character motion in the original direction.
fa;;
And also he got a racecar.
^ > ^
And also he got a racecar.
^ > > > > > ^
, repeats the last character motion in the opposite direction.
fs,
Is any of this getting through to you?
^ > > > > ^
Is any of this getting through to you?
^ < < < < < ^
-
Note that many of Vim's motions can take a preceding
count
, e.g. 2w moves your cursor two words to the right. However, in most cases I would advise you not to use acount
:- The number keys tend to be awkward to reach.
- It is silly to waste time counting things before using a motion.
- There are probably more effective ways to get to where you want in one or two keystrokes anyway (usually with f and co. or simply by repeating the motion).
-
b, B, w, W, ge, gE, e, E
The word motions. They are usually the optimal choices for moving your cursor a distance of one or two words. (See
:h word
for Vim's definition of a word.) Take advantage of the fact that some of these keys ignore special characters or target the beginning or end of words. -
0, ^, $
These keys let you skip to the beginning or end of a line. They are especially useful for repositioning your cursor for another motion on long lines.
You might want to map 0 to ^ because ^ tends to be the preferred functionality but 0 is easier to reach.
" Your .vimrc " Move across wrapped lines like regular lines noremap 0 ^ " Go to the first non-blank character of a line noremap ^ 0 " Just in case you need to go to the very beginning of a line
-
h, l
Try to avoid spamming these keys at all costs, but bear in mind that they are the most optimal ways to move your cursor one or two spaces.
-
?, /
The search keys. They are overkill for moving across a line.
- Much of their behavior overlaps with that of the superior character motions.
- /
pattern
Return amounts to a wildly inefficient number of keystrokes. - Searches pollute your buffer with lingering highlights.
-
(, )
These keys let you move across sentences. (See
:h sentence
for Vim's definition of a sentence.) They can also be convenient when working with programming languages that occasionally have!
or?
at the end of words, e.g. Ruby and Elixir.