From dc63ca686dd762680e884a55538135cb197da9b6 Mon Sep 17 00:00:00 2001 From: Iain Patterson Date: Fri, 7 Feb 2014 17:05:25 +0000 Subject: [PATCH] Space plugin. --- .vim/doc/space.txt | 252 ++++++++++++++++++ .vim/plugin/space.vim | 602 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 854 insertions(+) create mode 100644 .vim/doc/space.txt create mode 100644 .vim/plugin/space.vim diff --git a/.vim/doc/space.txt b/.vim/doc/space.txt new file mode 100644 index 0000000..4596946 --- /dev/null +++ b/.vim/doc/space.txt @@ -0,0 +1,252 @@ +*space.txt* Smart Space Key + + *space.vim* + + ______ ______ _____ _____ _____ + / _____\ | ___ \ / ___ \ / ___/ / ___/ + \ \____ | ___ / | \ / | | | | \__ + \___ \ | | | V | | |___ | /___ + /______/ \_| \_/ \_/ \____/ \____/ + + By Henrik Öhman + + + Reference Manual ~ + + + *space-toc* + +1. Intro |space-intro| +2. Usage |space-usage| +3. Hooks |space-hooks| +4. Status line integration |space-statusline| +5. Configuration |space-configuration| +6. License |space-license| + + + +============================================================================== +1. Intro *space-intro* + +space.vim is a plugin which remaps the ** key to act as a clever key +to repeat motions. To disable space.vim, set the "space_loaded" global +variable in your |vimrc| file: > + :let g:space_loaded = 1 + +space.vim hooks into several of the more complex motion commands, such as +|search-commands|, |jumpto-diffs|, |quickfix|, |tag-commands| and +|location-list| and more commands. When a command that space.vim has hooked +into is issued, it remaps the key to repeat that command, and it also +remaps and to do the reverse. + +NOTE:~Due to terminal restrictions, may not be available. For that +reason, the key is also used for reverse motions. Wherever this document +talks of , can be used in its place. + +NOTE:~When using the gVim space.vim won't remap if any previous mappings +to it already exists. When using Vim is always remapped. + +NOTE:~space.vim has some problems with the |'foldopen'| option. Since Vim +won't open folds if a command is part of a mapping, space.vim tries to +emulate this behaviour. This works well for all Normal mode mappings and for +most Visual mode mappings. Only for searches using |/| and |?| in Visual mode +is space.vim unable to emulate |'foldopen'|. + +NOTE:~Some |filetype| plugins map the section text objects ([[, [], ][, ]]) +and the method motions ([m, [M, ]m, ]M). space.vim is unable to hook into +these mappings in a well defined way. There is definitely room for +improvement here. + +============================================================================== +2. Usage *space-usage* + +Using space.vim is intuitive. Issue a command, such as a search, and the + key to go to the next match, and to go to the previous +match. Thus, the following sequence > + /foo + n + N + +is equivalent to > + /foo + + + +This works with counts, and with Visual mode too > + /foo + V + 4 + +space.vim tries to immitate Vim in its logic when specifying the direction for +the repeated movement. For the search commands, behaves like |n|, and + behaves like |N|, which means that a following a search using +|?|, will actually find the previous match. For other commands, is +configured to use the variant of the command that has the meaning of "next". +Thus, is always mapped to |:lnext|, |[[|, |zj| etc, and never the +reverse. + +The full power of space.vim will become apparent if you use |jumpto-diffs|, +in particular on non-US keyboards, or |quickfix| and |location-list| +commands. Remember all that finger stretching and keyboard dancing to quickly +browse through a series of diffs for a fast overview of what your colleague +managed to screw up this time? No more! > + ]c Jump to the next diff + Repeat the ]c motion + ... Nothing interesting, keep pressing space + Wait, there was something! Let's go back one diff + +Or why not quickly browse through all files which contain the sentence 'over +9000' in all subdirectories? > + :lvimgrep /over 9000/ **/* Find all the matches and add them to the + location-list + is now mapped to :lnext + And is mapped to :lprevious + +Neat, huh? To get an overview of all the commands space.vim hooks into, and +enables and mappings for, read on. |space-hooks| + +============================================================================== +3. Hooks *space-hooks* + +This is a list of all the commands that space.vim hooks into and provides + and navigation for. + +Character movements: |left-right-motions| + |f| |F| |t| |T| |;| |,| + +Search commands: |search-commands| + |star| |gstar| |#| |g#| |n| |N| + +Jump list jumps: |jump-motions| + |CTRL-O| |CTRL-I| + +Change list jumps: |change-list-jumps| + |g;| |g,| + +Diff jumps: |jumpto-diffs| + |]c| |[c| + +Parenthesis and bracket jumps: |various-motions| + |])| |[(| |]}| |[{| + +Method jumps: |various-motions| + |]m| |[m| |]M| |[M| + +Section jumps: |object-motions| + |]]| |[]| |][| |[[| + +Fold movements: + |zj| |zk| |]z| |[z| + +Tag movements: |tag-commands| + |CTRL-]| + |:tag| + |:tnext| + |:tprevious| + |:tNext| + |:trewind| + |:tfirst| + |:tlast| + +Undolist movements: |undo-branches| + |g-||g+| + +Quickfix commands: |quickfix| + |:make| + |:vimgrep| + |:grep| + |:cc| + |:cnext| + |:cprevious| + |:cNext| + |:cfirst| + |:clast| + |:crewind| + |:cfile| + |:cnfile| + |:cpfile| + |:cNfile| + +Location list commands: |location-list| + |:lmake| + |:lvimgrep| + |:lgrep| + |:ll| + |:lcnext| + |:lcprevious| + |:lcNext| + |:lcfirst| + |:lclast| + |:lcrewind| + |:lcfile| + |:lcnfile| + |:lcpfile| + |:lcNfile| + +============================================================================== +4. Status line integration *space-statusline* + +It is possible to display the current command assigned to in the +status line using the GetSpaceMovement() function. Here's an example: > + + function! SlSpace() + if exists("*GetSpaceMovement") + return "[" . GetSpaceMovement() . "]" + else + return "" + endif + endfunc + set statusline+=%{SlSpace()} + +============================================================================== +5. Configuration *space-configuration* + +It is possible to avoid using the key for groups of navigation +commands using global variables. For instance, you may wish to use to +repeat the last command only for diff jumps and quickfix and location list +commands. Here's a list of commands that disable the use of the key + +Disable for character movements > + let g:space_no_character_movements = 1 + +Disable for search commands > + let g:space_no_search = 1 + +Disable for jump commands > + let g:space_no_jump = 1 + +Disable for diff jumps > + let g:space_no_diff = 1 + +Disable for parenthesis and bracket jumps > + let g:space_no_brace = 1 + +Disable for method jumps > + let g:space_no_method = 1 + +Disable for section jumps > + let g:space_no_section = 1 + +Disable for fold movements > + let g:space_no_folds = 1 + +Disable for tag movements > + let g:space_no_tags = 1 + +Disable for quickfix and location list commands > + let g:space_no_quickfix = 1 + +Disable for undolist movements > + let g:space_no_undolist = 1 + +Furthermore it is possible to disable the hooks and mappings set by space.vim +to affect the select mode (these can cause problems with some snippets plugins +like snipmate.vim) > + let g:space_disable_select_mode = 1 + +============================================================================== +6. License *space-license* + +space.vim is licensed under the same terms as Vim itself. + +vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl: diff --git a/.vim/plugin/space.vim b/.vim/plugin/space.vim new file mode 100644 index 0000000..e91d9c5 --- /dev/null +++ b/.vim/plugin/space.vim @@ -0,0 +1,602 @@ +" space.vim - Smart Space key +" Author: Henrik Öhman +" URL: http://github.com/spiiph/vim-space/tree/master +" Version: 1.8 +" ReleaseDate: 2011 jun 09 +" +" Licensed under the same terms as Vim itself. +" +" NOTE: Using this script has some problems with 'foldopen', since vim won't +" open folds if a command is part of a mapping. This is possible to +" emulate in Normal mode, and in most cases in Visual mode. Only for +" searches using '/' and '?' have I been unsuccessful in finding a +" solution. +" ============================================================================ +if version < 702 + finish +endif + +" Set this variable to disable space.vim +" +" let g:space_loaded = 1 + +" Set this variable to disable select mode mappings +" +" let g:space_disable_select_mode = 1 + +" These variables disables the usage of for groups of different +" movement commands +" +" Disable for character movements, e.g. fFtT;, +" let g:space_no_character_movements = 1 +" +" Disable for searches, e.g. /?#*nN +" let g:space_no_search = 1 +" +" Disable for jump commands, e.g. Ctrl-O, Ctrl-I, g, and g; +" let g:space_no_jump = 1 +" +" Disable for diff commands, e.g. [c and ]c +" let g:space_no_diff = 1 +" +" Disable for brace movement commands, e.g. [(, ]), [{ and ]} +" let g:space_no_brace = 1 +" +" Disable for method movement commands, e.g. [m, ]m, [M and ]M +" let g:space_no_method = 1 +" +" Disable for section movement commands, e.g. [[, ]], [] and ][ +" let g:space_no_section = 1 +" +" Disable for fold movement commands, e.g. [z, ]z, zj and zk +" let g:space_no_folds = 1 +" +" Disable for tag movement commands, e.g. Ctrl-], :tag, etc. +" let g:space_no_tags = 1 +" +" Disable for quickfix and location list commands, e.g. :cc, :ll, etc. +" let g:space_no_quickfix = 1 +" +" Disable for undolist movements, e.g. g- and g+ +" let g:space_no_undolist = 1 + +" It is possible to display the current command assigned to in the +" status line using the GetSpaceMovement() function. Here's an example: +" +" function! SlSpace() +" if exists("*GetSpaceMovement") +" return "[" . GetSpaceMovement() . "]" +" else +" return "" +" endif +" endfunc +" set statusline+=%{SlSpace()} + +" TODO: Make the mapping assignments more dynamical, and allow user defined +" commands? + +if exists("g:space_debug") + let g:space_no_character_movements = 0 + let g:space_no_search = 0 + let g:space_no_jump = 0 + let g:space_no_diff = 0 + let g:space_no_brace = 0 + let g:space_no_method = 0 + let g:space_no_section = 0 + let g:space_no_folds = 0 + let g:space_no_quickfix = 0 + let g:space_no_undolist = 0 + let g:space_no_tags = 0 + echomsg "Running space.vim in debug mode." +elseif exists("g:space_loaded") + finish +endif +let g:space_loaded = 1 + +" Mapping of / and possibly +noremap do_space(0, "") +noremap do_space(1, "") + +if exists("g:space_disable_select_mode") + silent! sunmap + silent! sunmap + silent! sunmap +endif + +if mapcheck("") == "" || !has("gui_running") + noremap do_space(1, "") + if exists("g:space_disable_select_mode") + silent! sunmap + endif +endif + + +" character movement commands +if !exists("g:space_no_character_movements") || !g:space_no_character_movements + noremap f setup_space("char", "f") + noremap F setup_space("char", "F") + noremap t setup_space("char", "t") + noremap T setup_space("char", "T") + noremap ; setup_space("char", ";") + noremap , setup_space("char", ",") + + if exists("g:space_disable_select_mode") + silent! sunmap f + silent! sunmap F + silent! sunmap t + silent! sunmap T + silent! sunmap ; + silent! sunmap , + endif +endif + +" search commands +if !exists("g:space_no_search") || !g:space_no_search + + " do not override visual mappings for * and # + " because these are often used for visual search functions + if maparg('*', 'v') != '' + nnoremap * setup_space("search", "*") + onoremap * setup_space("search", "*") + nnoremap setup_space("search", "*") + onoremap setup_space("search", "*") + else + noremap * setup_space("search", "*") + noremap setup_space("search", "*") + endif + + if maparg('#', 'v') != '' + nnoremap # setup_space("search", "#") + onoremap # setup_space("search", "#") + else + noremap # setup_space("search", "#") + endif + + noremap g* setup_space("search", "g*") + noremap g# setup_space("search", "g#") + noremap n setup_space("search", "n") + noremap N setup_space("search", "N") + + if exists("g:space_disable_select_mode") + silent! sunmap * + silent! sunmap # + silent! sunmap + silent! sunmap g* + silent! sunmap g# + silent! sunmap n + silent! sunmap N + endif + + let s:search_mappings = 1 +else + let s:search_mappings = 0 +endif + +" jump commands +" NOTE: Jumps are not motions. They can't be used in Visual mode. +if !exists("g:space_no_jump") || !g:space_no_jump + nnoremap g, setup_space("cjump", "g,") + nnoremap g; setup_space("cjump", "g;") + nnoremap setup_space("jump", "\") + nnoremap setup_space("jump", "\") +endif + +" diff next/prev +if !exists("g:space_no_diff") || !g:space_no_diff + noremap ]c setup_space("diff", "]c") + noremap [c setup_space("diff", "[c") + + if exists("g:space_disable_select_mode") + silent! sunmap ]c + silent! sunmap [c + endif +endif + +" previous/next unmatched ( or [ +if !exists("g:space_no_brace") || !g:space_no_brace + noremap ]) setup_space("paren", "])") + noremap [( setup_space("paren", "[(") + + noremap ]} setup_space("curly", "]}") + noremap [{ setup_space("curly", "[{") + + if exists("g:space_disable_select_mode") + silent! sunmap ]) + silent! sunmap [( + silent! sunmap ]} + silent! sunmap [{ + endif +endif + +" start/end of a method +if !exists("g:space_no_method") || !g:space_no_method + noremap ]m setup_space("method_start", "]m") + noremap [m setup_space("method_start", "[m") + + noremap ]M setup_space("method_end", "]M") + noremap [M setup_space("method_end", "[M") + + if exists("g:space_disable_select_mode") + silent! sunmap ]m + silent! sunmap [m + silent! sunmap ]M + silent! sunmap [M + endif +endif + +" previous/next section or '}'/'{' in the first column +if !exists("g:space_no_section") || !g:space_no_section + noremap ]] setup_space("section_start", "]]") + noremap [[ setup_space("section_start", "[[") + + noremap ][ setup_space("section_end", "][") + noremap [] setup_space("section_end", "[]") + + if exists("g:space_disable_select_mode") + silent! sunmap ]] + silent! sunmap [[ + silent! sunmap ][ + silent! sunmap [] + endif +endif + +" previous/next fold +if !exists("g:space_no_folds") || !g:space_no_folds + noremap zj setup_space("fold_next", "zj") + noremap zk setup_space("fold_next", "zk") + + noremap ]z setup_space("fold_start", "]z") + noremap [z setup_space("fold_start", "[z") + + if exists("g:space_disable_select_mode") + silent! sunmap zj + silent! sunmap zk + silent! sunmap ]z + silent! sunmap [z + endif +endif + +" tag movement +if !exists("g:space_no_tags") || !g:space_no_tags + noremap setup_space("tag", "\") + + if exists("g:space_disable_select_mode") + silent! sunmap + endif + + let s:tag_mappings = 1 +else + let s:tag_mappings = 0 +endif + +" undolist movement +if !exists("g:space_no_undolist") || !g:space_no_undolist + noremap g- setup_space("undo", "g-") + noremap g+ setup_space("undo", "g+") + + if exists("g:space_disable_select_mode") + silent! sunmap g- + silent! sunmap g+ + endif +endif + +" quickfix and location list commands +if !exists("g:space_no_quickfix") || !g:space_no_quickfix + cnoremap parse_cmd_line() + let s:quickfix_mappings = 1 +else + let s:quickfix_mappings = 0 +endif + +" TODO: Have all mappings add the remapped sequence to a list, and use that +" list to remove mappings. +command! SpaceRemoveMappings call remove_space_mappings() +function! s:remove_space_mappings() + silent! unmap + silent! unmap + silent! unmap + + silent! unmap f + silent! unmap F + silent! unmap t + silent! unmap T + silent! unmap ; + silent! unmap , + + silent! unmap * + silent! unmap # + silent! unmap g* + silent! unmap g# + silent! unmap n + silent! unmap N + + silent! nunmap g, + silent! nunmap g; + silent! nunmap + silent! nunmap + + silent! unmap ]c + silent! unmap [c + + silent! unmap [( + silent! unmap ]) + silent! unmap [{ + silent! unmap ]} + + silent! unmap ]] + silent! unmap [[ + silent! unmap ][ + silent! unmap [] + + silent! unmap ]m + silent! unmap [m + silent! unmap ]M + silent! unmap [M + + silent! unmap zj + silent! unmap zk + silent! unmap ]z + silent! unmap [z + + silent! unmap + + silent! unmap g- + silent! unmap g+ + + silent! cunmap + + silent! unlet g:space_loaded +endfunction + +" TODO: Check if the '\>!\=' part of the pattern fails when 'iskeyword' +" contains '!' +" NOTE: Since Vim allows commands like ":'k,'lvim /foo/ *", it's a little +" tedious to write a perfect regexp. + +let s:pre_re = '^\%(' . + \ '\%(noa\%[utocmd]\s\+\)\=' . + \ '\%(' . + \ '\%(' . + \ '\%(\d\+\)\|' . + \ '\%(''[0-9a-zA-Z><.]\)\|' . + \ '\%(\\[/?&]\)\|' . + \ '[%$.]' . + \ '\)' . + \ '\%([-+]\d*\)\=' . + \ '\)\=' . + \ ',\=' . + \ '\%(' . + \ '\%(' . + \ '\%(\d\+\)\|' . + \ '\%(''[0-9a-zA-Z><.]\)\|' . + \ '\%(\\[/?&]\)\|' . + \ '[%$.]' . + \ '\)' . + \ '\%([-+]\d*\)\=' . + \ '\)\=' . + \ '\)\=' + +let s:qf_re = '\%(' . + \ 'mak\%[e]\|' . + \ 'v\%[imgrep]\|' . + \ 'gr\%[ep]\|' . + \ 'c\%(' . + \ 'c\|' . + \ 'p\%[revious]\|' . + \ '[nN]\%[ext]\|' . + \ '\(fir\|la\)\%[st]\|' . + \ 'r\%[ewind]\|' . + \ '\(f\|nf\|Nf\|pf\)\%[ile]' . + \ '\)' . + \ '\)\>!\=' + +let s:lf_re = 'l\%(' . + \ 'mak\%[e]\|' . + \ 'v\%[imgrep]\|' . + \ 'gr\%[ep]\|' . + \ 'l\|' . + \ 'p\%[revious]\|' . + \ 'ne\%[xt]\|N\%[ext]\|' . + \ '\(fir\|la\)\%[st]\|' . + \ 'r\%[ewind]\|' . + \ '\(f\|nf\|Nf\|pf\)\%[ile]' . + \ '\)\>!\=' + +let s:ta_re = 't\%(' . + \ 'a\%[g]\|' . + \ 'n\%[ext]\|' . + \ 'p\%[revious]\|' . + \ 'N\%[ext]\|' . + \ 'r\%[ewind]\|' . + \ 'f\%[irst]\|' . + \ 'l\%[ast]\|' . + \ '\)\>!\=' + +function! s:parse_cmd_line() + let cmd = getcmdline() + let type = getcmdtype() + + if s:search_mappings && (type == '/' || type == '?') + return setup_space("search", cmd) + elseif type == ':' + if s:quickfix_mappings + if cmd =~ s:pre_re . s:lf_re + return setup_space("lf", cmd) + elseif cmd =~ s:pre_re . s:qf_re + return setup_space("qf", cmd) + endif + endif + if s:tag_mappings && cmd =~ s:pre_re . s:ta_re + return setup_space("tag", cmd) + endif + end + return "\" +endfunc + +function! s:setup_space(type, command) + let cmd = a:command + let s:cmd_type = "undefined" + + if a:type == "char" + let s:space_move = ";" + let s:shift_space_move = "," + let s:cmd_type = "hor" + if cmd =~ "[;,]$" + let cmd = maybe_open_fold(cmd) + endif + elseif a:type == "diff" + let s:space_move = "]c" + let s:shift_space_move = "[c" + elseif a:type == "method_start" + let s:space_move = "]m" + let s:shift_space_move = "[m" + let s:cmd_type = "block" + let cmd = maybe_open_fold(cmd) + elseif a:type == "method_end" + let s:space_move = "]M" + let s:shift_space_move = "[M" + let s:cmd_type = "block" + let cmd = maybe_open_fold(cmd) + elseif a:type == "section_start" + let s:space_move = "]]" + let s:shift_space_move = "[[" + let s:cmd_type = "block" + let cmd = maybe_open_fold(cmd) + elseif a:type == "section_end" + let s:space_move = "][" + let s:shift_space_move = "[]" + let s:cmd_type = "block" + let cmd = maybe_open_fold(cmd) + elseif a:type == "paren" + let s:space_move = "])" + let s:shift_space_move = "[(" + let s:cmd_type = "block" + let cmd = maybe_open_fold(cmd) + elseif a:type == "curly" + let s:space_move = "]}" + let s:shift_space_move = "[{" + let s:cmd_type = "block" + let cmd = maybe_open_fold(cmd) + elseif a:type == "fold_next" + let s:space_move = "zj" + let s:shift_space_move = "zk" + elseif a:type == "fold_start" + let s:space_move = "]z" + let s:shift_space_move = "[z" + elseif a:type == "search" + let s:space_move = "n" + let s:shift_space_move = "N" + let s:cmd_type = "search" + let cmd = maybe_open_fold(cmd) + elseif a:type == "cjump" + let s:space_move = "g," + let s:shift_space_move = "g;" + let s:cmd_type = "jump" + let cmd = maybe_open_fold(cmd) + elseif a:type == "jump" + let s:space_move = "\" + let s:shift_space_move = "\" + let s:cmd_type = "jump" + let cmd = maybe_open_fold(cmd) + elseif a:type == "tag" + let s:space_move = "tn" + let s:shift_space_move = "tp" + let s:cmd_type = "tag" + if getcmdtype() == ':' + let cmd = maybe_open_fold(cmd) + endif + elseif a:type == "qf" + let s:space_move = "cn" + let s:shift_space_move = "cN" + let s:cmd_type = "quickfix" + let cmd = maybe_open_fold(cmd) + elseif a:type == "lf" + let s:space_move = "lne" + let s:shift_space_move = "lN" + let s:cmd_type = "quickfix" + let cmd = maybe_open_fold(cmd) + elseif a:type == "undo" + let s:space_move = "g-" + let s:shift_space_move = "g+" + let s:cmd_type = "undo" + let cmd = maybe_open_fold(cmd) + endif + call debug_msg("setup_space(type = " . a:type . + \ ", command = " . cmd . ")") + return cmd +endfunc + +function! s:do_space(shift, default) + " + if a:shift == 0 + if exists("s:space_move") + let cmd = maybe_open_fold(s:space_move) + call debug_msg("do_space(cmd = " . cmd . ")") + else + let cmd = a:default + endif + " and + else + if exists("s:shift_space_move") + let cmd = maybe_open_fold(s:shift_space_move) + call debug_msg("do_space(cmd = " . cmd . ")") + else + let cmd = a:default + endif + endif + return cmd +endfunc + +function! s:maybe_open_fold(cmd) + if !exists("g:space_no_foldopen") && &foldopen =~ s:cmd_type && v:operator != "c" + " special treatment of :ex commands + if s:cmd_type == "quickfix" || s:cmd_type == "tag" + if getcmdtype() == ':' + return "\" + else + return ":\" . (v:count ? v:count : "") . a:cmd . "\zv" + endif + " special treatment of /foo and ?foo commands + elseif s:cmd_type == "search" && getcmdtype() =~ "[/?]" + return "\zv" + else + if mode() =~ "[vV]" + " NOTE: That this works is probably a bug in vim. Let's hope + " it stays that way. ;) + return ":\normal! gv" . (v:count ? v:count : "") + \ . a:cmd . "zv\" + "return a:cmd . "zv" + else + return a:cmd . "zv" + endif + endif + else + if s:cmd_type == "quickfix" || s:cmd_type == "tag" + if getcmdtype() == ':' + return "\" + else + return ":\" . (v:count ? v:count : "") . a:cmd . "\" + endif + elseif s:cmd_type == "search" && getcmdtype() =~ "[/?]" + return "\" + else + return a:cmd + endif + endif +endfunc + +function! s:debug_msg(string) + if exists("g:space_debug") + echomsg a:string + endif +endfunc + +function! GetSpaceMovement() + if exists("s:space_move") + return s:space_move == "\" ? "^I" : s:space_move + else + return "" + end +endfunc + +" vim: et sts=4 sw=4 -- 2.20.1