From baf4c548616ec167dbde69a3027001ca3523e84d Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Tue, 16 Nov 2010 13:19:50 -0800 Subject: initial commit --- README | 98 +++++++++ camelcasemotion.vba | 569 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 667 insertions(+) create mode 100644 README create mode 100644 camelcasemotion.vba diff --git a/README b/README new file mode 100644 index 0000000..bbbb71e --- /dev/null +++ b/README @@ -0,0 +1,98 @@ +created by +Ingo Karkat + +forked by +Kevin Le + +script type +utility + +description +DESCRIPTION +Vim provides many built-in motions, e.g. to move to the next word, or end of +the current word. Most programming languages use either CamelCase +("anIdentifier") or underscore_notation ("an_identifier") naming conventions +for identifiers. The best way to navigate inside those identifiers using Vim +built-in motions is the [count]f{char} motion, i.e. f{uppercase-char} or f_, +respectively. But we can make this easier: + +This script defines motions ',w', ',b' and ',e' (similar to 'w', 'b', 'e'), +which do not move word-wise (forward/backward), but Camel-wise; i.e. to word +boundaries and uppercase letters. The motions also work on underscore notation, +where words are delimited by underscore ('_') characters. From here on, both +CamelCase and underscore_notation entities are referred to as "words" (in double +quotes). Just like with the regular motions, a [count] can be prepended to move +over multiple "words" at once. Outside of "words" (e.g. in non-keyword +characters like // or ;), the new motions move just like the regular motions. + +Vim provides a built-in 'iw' text object called 'inner word', which works in +operator-pending and visual mode. Analog to that, this script defines inner +"word" motions 'i,w', 'i,b' and 'i,e', which select the "word" (or multiple +"words" if a [count] is given) where the cursor is located. + +USAGE +Use the new motions',w',',b' and ',e' in normal mode, operator-pending mode (cp. +:help operator), and visual mode. For example, type 'bc,w' to change 'Camel' in +'CamelCase' to something else. + +EXAMPLE: motions +Given the following CamelCase identifiers in a source code fragment: + set Script31337PathAndNameWithoutExtension11=%~dpn0 + set Script31337PathANDNameWITHOUTExtension11=%~dpn0 +and the corresponding identifiers in underscore_notation: + set script_31337_path_and_name_without_extension_11=%~dpn0 + set SCRIPT_31337_PATH_AND_NAME_WITHOUT_EXTENSION_11=%~dpn0 + +,w moves to ([x] is cursor position): [s]et, [s]cript, [3]1337, [p]ath, + [a]nd, [n]ame, [w]ithout, [e]xtension, [1]1, [d]pn0, dpn[0], [s]et +,b moves to: [d]pn0, [1]1, [e]xtension, [w]ithout, ... +,e moves to: se[t], scrip[t], 3133[7], pat[h], an[d], nam[e], withou[t], + extensio[n], 1[1], dpn[0] + +EXAMPLE: inner motions +Given the following identifier, with the cursor positioned at [x]: + script_31337_path_and_na[m]e_without_extension_11 + +v3i,w selects script_31337_path_and_[name_without_extension_]11 +v3i,b selects script_31337_[path_and_name]_without_extension_11 +v3i,e selects script_31337_path_and_[name_without_extension]_11 +Instead of visual mode, you can also use c3i,w to change, d3i,w to delete, +gU3i,w to upper-case, and so on. + +Source: Based on http://vim.wikia.com/wiki/Moving_through_camel_case_words by +Anthony Van Ham. + +install details +INSTALLATION +This script is packaged as a vimball. If you have the "gunzip" decompressor +in your PATH, simply edit the *.vba.gz package in Vim; otherwise, decompress +the archive first, e.g. using WinZip. Inside Vim, install by sourcing the +vimball or via the :UseVimball command. + vim camelcasemotion.vba.gz + :so % +To uninstall, use the :RmVimball command. + +DEPENDENCIES +- Requires Vim 7.0 or higher. + +CONFIGURATION +If you want to use different mappings, map your keys to the +CamelCaseMotion_? mapping targets _before_ sourcing this script (e.g. in +your .vimrc). + +EXAMPLE: Replace the default 'w', 'b' and 'e' mappings instead of defining +additional mappings',w', ',b' and ',e': + map w CamelCaseMotion_w + map b CamelCaseMotion_b + map e CamelCaseMotion_e + sunmap w + sunmap b + sunmap e + +EXAMPLE: Replace default 'iw' text-object and define 'ib' and 'ie' motions: + omap iw CamelCaseMotion_iw + xmap iw CamelCaseMotion_iw + omap ib CamelCaseMotion_ib + xmap ib CamelCaseMotion_ib + omap ie CamelCaseMotion_ie + xmap ie CamelCaseMotion_ie diff --git a/camelcasemotion.vba b/camelcasemotion.vba new file mode 100644 index 0000000..748166a --- /dev/null +++ b/camelcasemotion.vba @@ -0,0 +1,569 @@ +" Vimball Archiver by Charles E. Campbell, Jr., Ph.D. +UseVimball +finish +autoload/camelcasemotion.vim [[[1 +173 +" camelcasemotion.vim: Motion through CamelCaseWords and underscore_notation. +" +" DEPENDENCIES: +" - Requires Vim 7.0 or higher. +" +" Copyright: (C) 2007-2009 by Ingo Karkat +" The VIM LICENSE applies to this script; see ':help copyright'. +" +" Maintainer: Ingo Karkat +" REVISION DATE REMARKS +" 1.50.001 05-May-2009 Do not create mappings for select mode; +" according to|Select-mode|, printable character +" commands should delete the selection and insert +" the typed characters. +" Moved functions from plugin to separate autoload +" script. +" file creation + +"- functions ------------------------------------------------------------------" +function! s:Move( direction, count, mode ) + " Note: There is no inversion of the regular expression character class + " 'keyword character' (\k). We need an inversion "non-keyword" defined as + " "any non-whitespace character that is not a keyword character" (e.g. + " [!@#$%^&*()]). This can be specified via a non-whitespace character in + " whose place no keyword character matches (\k\@!\S). + + "echo "count is " . a:count + let l:i = 0 + while l:i < a:count + if a:direction == 'e' + " "Forward to end" motion. + "call search( '\>\|\(\a\|\d\)\+\ze_', 'We' ) + " end of ... + " number | ACRONYM followed by CamelCase or number | CamelCase | underscore_notation | non-keyword | word + call search( '\d\+\|\u\+\ze\%(\u\l\|\d\)\|\u\l\+\|\%(\a\|\d\)\+\ze_\|\%(\k\@!\S\)\+\|\%(_\@!\k\)\+\>', 'We' ) + " Note: word must be defined as '\k\>'; '\>' on its own somehow + " dominates over the previous branch. Plus, \k must exclude the + " underscore, or a trailing one will be incorrectly moved over: + " '\%(_\@!\k\)'. + if a:mode == 'o' + " Note: Special additional treatment for operator-pending mode + " "forward to end" motion. + " The difference between normal mode, operator-pending and visual + " mode is that in the latter two, the motion must go _past_ the + " final "word" character, so that all characters of the "word" are + " selected. This is done by appending a 'l' motion after the + " search for the next "word". + " + " In operator-pending mode, the 'l' motion only works properly + " at the end of the line (i.e. when the moved-over "word" is at + " the end of the line) when the 'l' motion is allowed to move + " over to the next line. Thus, the 'l' motion is added + " temporarily to the global 'whichwrap' setting. + " Without this, the motion would leave out the last character in + " the line. I've also experimented with temporarily setting + " "set virtualedit=onemore" , but that didn't work. + let l:save_ww = &whichwrap + set whichwrap+=l + normal! l + let &whichwrap = l:save_ww + endif + else + " Forward (a:direction == '') and backward (a:direction == 'b') + " motion. + + let l:direction = (a:direction == 'w' ? '' : a:direction) + + " CamelCase: Jump to beginning of either (start of word, Word, WORD, + " 123). + " Underscore_notation: Jump to the beginning of an underscore-separated + " word or number. + "call search( '\<\|\u', 'W' . l:direction ) + "call search( '\<\|\u\(\l\+\|\u\+\ze\u\)\|\d\+', 'W' . l:direction ) + "call search( '\<\|\u\(\l\+\|\u\+\ze\u\)\|\d\+\|_\zs\(\a\|\d\)\+', 'W' . l:direction ) + " beginning of ... + " word | empty line | non-keyword after whitespaces | non-whitespace after word | number | ACRONYM followed by CamelCase or number | CamelCase | underscore followed by ACRONYM, Camel, lowercase or number + call search( '\<\D\|^$\|\%(^\|\s\)\+\zs\k\@!\S\|\>\S\|\d\+\|\u\+\ze\%(\u\l\|\d\)\|\u\l\+\|_\zs\%(\u\+\|\u\l\+\|\l\+\|\d\+\)', 'W' . l:direction ) + " Note: word must be defined as '\<\D' to avoid that a word like + " 1234Test is moved over as [1][2]34[T]est instead of [1]234[T]est + " because \< matches with zero width, and \d\+ will then start + " matching '234'. To fix that, we make \d\+ be solely responsible + " for numbers by taken this away from \< via \<\D. (An alternative + " would be to replace \d\+ with \D\%#\zs\d\+, but that one is more + " complex.) All other branches are not affected, because they match + " multiple characters and not the same character multiple times. + endif + let l:i = l:i + 1 + endwhile +endfunction + +function! camelcasemotion#Motion( direction, count, mode ) +"******************************************************************************* +"* PURPOSE: +" Perform the motion over CamelCaseWords or underscore_notation. +"* ASSUMPTIONS / PRECONDITIONS: +" none +"* EFFECTS / POSTCONDITIONS: +" Move cursor / change selection. +"* INPUTS: +" a:direction one of 'w', 'b', 'e' +" a:count number of "words" to move over +" a:mode one of 'n', 'o', 'v', 'iv' (latter one is a special visual mode +" when inside the inner "word" text objects. +"* RETURN VALUES: +" none +"******************************************************************************* + " Visual mode needs special preparations and postprocessing; + " normal and operator-pending mode breeze through to s:Move(). + + if a:mode == 'v' + " Visual mode was left when calling this function. Reselecting the current + " selection returns to visual mode and allows to call search() and issue + " normal mode motions while staying in visual mode. + normal! gv + endif + if a:mode == 'v' || a:mode == 'iv' + + " Note_1a: + if &selection != 'exclusive' && a:direction == 'w' + normal! l + endif + endif + + call s:Move( a:direction, a:count, a:mode ) + + if a:mode == 'v' || a:mode == 'iv' + " Note: 'selection' setting. + if &selection == 'exclusive' && a:direction == 'e' + " When set to 'exclusive', the "forward to end" motion (',e') does not + " include the last character of the moved-over "word". To include that, an + " additional 'l' motion is appended to the motion; similar to the + " special treatment in operator-pending mode. + normal! l + elseif &selection != 'exclusive' && a:direction != 'e' + " Note_1b: + " The forward and backward motions move to the beginning of the next "word". + " When 'selection' is set to 'inclusive' or 'old', this is one character too far. + " The appended 'h' motion undoes this. Because of this backward step, + " though, the forward motion finds the current "word" again, and would + " be stuck on the current "word". An 'l' motion before the CamelCase + " motion (see Note_1a) fixes that. + normal! h + endif + endif +endfunction + +function! camelcasemotion#InnerMotion( direction, count ) + " If the cursor is positioned on the first character of a CamelWord, the + " backward motion would move to the previous word, which would result in a + " wrong selection. To fix this, first move the cursor to the right, so that + " the backward motion definitely will cover the current "word" under the + " cursor. + normal! l + + " Move "word" backwards, enter visual mode, then move "word" forward. This + " selects the inner "word" in visual mode; the operator-pending mode takes + " this selection as the area covered by the motion. + if a:direction == 'b' + " Do not do the selection backwards, because the backwards "word" motion + " in visual mode + selection=inclusive has an off-by-one error. + call camelcasemotion#Motion( 'b', a:count, 'n' ) + normal! v + " We decree that 'b' is the opposite of 'e', not 'w'. This makes more + " sense at the end of a line and for underscore_notation. + call camelcasemotion#Motion( 'e', a:count, 'iv' ) + else + call camelcasemotion#Motion( 'b', 1, 'n' ) + normal! v + call camelcasemotion#Motion( a:direction, a:count, 'iv' ) + endif +endfunction + +" vim: set sts=4 sw=4 noexpandtab ff=unix fdm=syntax : +plugin/camelcasemotion.vim [[[1 +204 +" camelcasemotion.vim: Motion through CamelCaseWords and underscore_notation. +" +" DEPENDENCIES: +" - Requires Vim 7.0 or higher. +" +" Copyright: (C) 2007-2009 by Ingo Karkat +" The VIM LICENSE applies to this script; see ':help copyright'. +" +" Source: Based on vimtip #1016 by Anthony Van Ham. +" Maintainer: Ingo Karkat +" REVISION DATE REMARKS +" 1.50.019 05-May-2009 Do not create mappings for select mode; +" according to|Select-mode|, printable character +" commands should delete the selection and insert +" the typed characters. +" Moved functions from plugin to separate autoload +" script. +" Split off documentation into separate help file. +" Now cleaning up Create...Mappings functions. +" 1.40.018 30-Jun-2008 Minor: Removed unnecessary