├── LICENSE ├── README.md ├── autoload └── vimbits │ ├── highlightonyank.vim │ ├── jump.vim │ └── vim9cmdline.vim ├── doc ├── easyjump.txt ├── fFtT.txt ├── tags └── vimtips.txt ├── plugin ├── easyjump.vim ├── fFtT.vim └── vimbits.vim └── test ├── highlight.vim ├── runtests.sh ├── setup.vim ├── visual.vim └── yank.vim /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 girishji 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VimBits 2 | 3 | Suite of lightweight Vim plugins. 4 | 5 | 1. [**HighlightOnYank**](#plugin-highlightonyank) - Confirm yank operation by temporarily highlighting the region. 6 | 7 | 2. [**EasyJump**](#plugin-easyjump) - Jump to any location on screen by typing two characters. 8 | 9 | 3. [**fFtT**](#plugin-fFtT) - Highlight characters reachable in one jump using `f`, `t`, `F`, and `T` commands. 10 | 11 | 4. [**Vim9Cmdline**](#plugin-vim9cmdline) - Use *vim9script* in command-line seamlessley. 12 | 13 | 5. **vimtips** from [zzapper](https://web.archive.org/web/20121104092340/http://zzapper.co.uk/vimtips.html) - `:h vimtips.txt` 14 | 15 | 16 | ## Requirements 17 | 18 | - Vim 9.0 or higher 19 | 20 | ## Installation 21 | 22 | Install it via [vim-plug](https://github.com/junegunn/vim-plug). 23 | 24 |
Show instructions 25 |
26 | 27 | Using vim9 script: 28 | 29 | ```vim 30 | vim9script 31 | plug#begin() 32 | Plug 'girishji/vimbits' 33 | plug#end() 34 | ``` 35 | 36 | Using legacy script: 37 | 38 | ```vim 39 | call plug#begin() 40 | Plug 'girishji/vimbits' 41 | call plug#end() 42 | ``` 43 | 44 |
45 | 46 | Install using Vim's built-in package manager. 47 | 48 |
Show instructions 49 |
50 | 51 | ```bash 52 | $ mkdir -p $HOME/.vim/pack/downloads/opt 53 | $ cd $HOME/.vim/pack/downloads/opt 54 | $ git clone https://github.com/girishji/vimbits.git 55 | ``` 56 | 57 | Add the following to your $HOME/.vimrc file. 58 | 59 | ```vim 60 | packadd vimbits 61 | ``` 62 | 63 |
64 | 65 | ## Configuration 66 | 67 | By default, all plugins are enabled except for Vim9Cmdline. To disable a specific plugin, set its corresponding global variable to `false`. To enable a plugin, set its corresponding global variable to `true`. 68 | 69 | ``` 70 | vim9script 71 | g:vimbits_highlightonyank = true 72 | g:vimbits_easyjump = true 73 | g:vimbits_fFtT = true 74 | g:vimbits_vim9cmdline = false 75 | ``` 76 | 77 | More configurable options pertaining to individual plugins are described below. 78 | 79 | # Plugin: HighlightOnYank 80 | 81 | Ensure the text you intended to yank is correctly selected. This feature helps avoid surprises when pasting, especially if you accidentally hit the wrong keys. 82 | 83 | The yanked region is temporarily highlighted (using `:h hl-IncSearch`) for 300 milliseconds by default. The duration and highlight group are configurable, and there's an option to disable highlighting in visual mode. 84 | 85 | To customize the default settings, add the following to your `.vimrc` file: 86 | 87 | ```vim 88 | vim9script 89 | g:vimbits_highlightonyank = false # Disables the default autocmd 90 | import autoload 'vimbits/highlightonyank.vim' as hy 91 | augroup HighlightOnYank 92 | autocmd! 93 | autocmd TextYankPost * hy.HighlightOnYank('IncSearch', 300, true) 94 | augroup END 95 | ``` 96 | 97 | `HighlightOnYank()` accepts three arguments: 98 | 99 | - `hlgroup`: The highlight group for the yanked region. 100 | - `duration`: The duration of the highlight in milliseconds. 101 | - `in_visual`: Whether to highlight the region when yanked in visual mode. 102 | 103 | This mini plugin is inspired by [this issue](https://github.com/vim/vim/issues/14848). 104 | 105 | # Plugin: EasyJump 106 | 107 | Jump to any location on screen by typing two characters. 108 | 109 | ## TL;DR 110 | 111 | - `s` + _\_ + _\_ to jump 112 | - `ds` + _\_ + _\_ to delete (similarly, `vs` for visual selection, `cs` for change, etc.) 113 | - `` and `` (or `;` and `,`) after _\_ to view additional tag characters 114 | - `2s` + _\_ + _\_ + _\_ to jump 115 | 116 | ## Features 117 | 118 | - Initially bound to `s`, but it can be reassigned to any desired trigger (e.g., `,`). 119 | - Supports essential Vim idioms such as `ds` for deletion, `cs` for change, `vs` for visual selection, and more. Here `s` is the trigger character. 120 | - Updates the jump list (`:jumps`) for easy back-navigation using ``. 121 | - Optional two-character mode, for users accustomed to targeting with two characters instead of one. 122 | - Non-disruptive: Does not modify the buffer. Crafted in vim9 script. 123 | 124 | 125 | 🚀 **Jump (`s`)**: Type `s` followed by a character (say `c`). Witness 126 | new tag characters replacing the character `c`. Typing next 127 | character initiates the jump. For instance, typing `e` 128 | navigates the cursor to the `c` under `e`. 129 | 130 | 131 | 132 | 🚀 **Jump back**: Type `` (control-O) to jump back. Type `` or `` to jump forward. 133 | 134 | 🚀 **Visual Select (`vs`)**: For visually selecting a block of text from the 135 | cursor position up to an instance of `c`, enter `vsc`, then the highlighted 136 | character (e.g., `e`). 137 | 138 | 139 | 140 | Likewise, use `ds` for deletion or `cs` for text alteration. 141 | 142 | Press `` to cancel the ongoing jump. 143 | 144 | Pictures above are based on `:colorscheme quiet`. 145 | 146 | 🔎 **What if the intended jump location is not showing a tag letter?** 147 | 148 | This scenario occurs when there aren't enough unique letters available for 149 | tagging. Simply press `` (or `;`), and new tag labels will fill the 150 | remaining spots. To cycle backwards, press `` (or `,`). 151 | 152 | 🚀 **Two-Character Mode (New)**: Activated with `2s` or simply `s` if `g:easyjump_two_chars` is configured as `true`. 153 | 154 | - Use `2s` + _\_ + _\_ to leap to your destination (when a tag character marks the spot). 155 | - If no tag label is present, type the adjacent character as well, forming `2s` + _\_ + _\_ + _\_ to execute the jump. 156 | 157 | > [!TIP] 158 | > A lazy way to navigate is by leveraging the space character as a guide. Experiment with typing `s` followed by ``. The algorithm strives to allocate one label per line. Once you're near your desired location within a line, you can [effectively employ](https://github.com/girishji/fFtT.vim) Vim's built-in `f/F, t/T` commands to reach it precisely. This is an alternative to using relative line numbers to jump. 159 | 160 | ## Trigger Key 161 | 162 | By default, `s` serves as the trigger key. To unmap `s` and restore it to the default (:h s), 163 | include the following line in your .vimrc file: 164 | 165 | ``` 166 | g:easyjump_default_keymap = false 167 | ``` 168 | 169 | To assign `,` as the trigger for jumping, add the following lines to your `.vimrc` 170 | file. You can choose any other key beside `,`. 171 | 172 | ``` 173 | nmap , EasyjumpJump; 174 | omap , EasyjumpJump; 175 | vmap , EasyjumpJump; 176 | ``` 177 | 178 | ## Case Sensitivity 179 | 180 | Options include 'case' (case sensitive), 'icase' (ignore case), or 'smart' 181 | (smart case). Add the following line to your .vimrc: 182 | 183 | ``` 184 | g:easyjump_case = 'smart' # Can be 'case', 'icase', or 'smart' (default). 185 | ``` 186 | 187 | ## Highlight Group 188 | 189 | The tag letters displayed alongside destination locations utilize the 190 | highlighted group `EasyJump`. By default, this group is linked to `IncSearch`. Modify its 191 | appearance using the `:highlight` command to change colors. 192 | 193 | ## Tag Letters 194 | 195 | Jump locations prioritize placement based on distance from cursor and 196 | preference for having at least one placement per line. 197 | Letters are picked in the following sequence. Modify the sequence (say, for 198 | Dvorak) as needed. Set the following global variable: 199 | 200 | ``` 201 | g:easyjump_letters = 'asdfgwercvhjkluiopynmbtqxzASDFGWERCVHJKLUIOPYNMBTQXZ0123456789' 202 | ``` 203 | 204 | # Plugin: fFtT 205 | 206 | Characters that are reachable with a single jump are highlighted, while others are dimmed. This enhancement enhances the accuracy of navigation using `f`, `F`, `t`, and `T` commands. Moreover, you can prefix the command with a numerical `[count]` (e.g., `3f`), which will exclusively highlight the `[count]`'th occurrence (third in this instance) of a character to the right of the cursor, while dimming the others. 207 | 208 | This plugin does not alter Vim operators or commands. It solely focuses on highlighting relevant characters without making any changes to the default key mappings. The code consists of less than 100 lines, with explanatory comments. 209 | 210 | ![](https://gist.githubusercontent.com/girishji/40e35cd669626212a9691140de4bd6e7/raw/6041405e45072a7fbc4e352cbd461e450a7af90e/fFtT-img.jpeg) 211 | 212 | The appearance of characters that are unreachable within one jump is determined by the highlight group `FfTtSubtle`, which is linked to the `Comment` group by default. 213 | 214 | # Plugin: Vim9Cmdline 215 | 216 | *vim9script* offers significant improvements over the legacy script. Although there isn't a direct way to switch the command line to parse *vim9script*, you can execute *vim9script* commands by prepending each command with `vim9`. This plugin automates that process for you. 217 | 218 | 219 | 220 | Some things to keep in mind: 221 | 222 | - Remember that execution occurs in the global context, not the script-local context. This means you need to declare variables with the `g:` prefix, like `g:foo = 'bar'`. 223 | 224 | - Common commands, such as visual range (`'<,'>`), other types of ranges, shell commands (`!`), substitution (`s//`), and global (`g//`), work as expected even when `vim9` is prepended. 225 | 226 | - Ranges to Ex commands should be prefixed with a colon. For example, `:vim9 :%s/foo/bar` (notice the `:` before `%s`). 227 | From `:h [range]`: 228 | 229 | > In Vim9 script a range needs to be prefixed with a colon to avoid ambiguity 230 | > with continuation lines. 231 | 232 | - Related to the above, if your keymap's right-hand side (rhs) starts with a range, it may throw an error. To avoid this, use `:h ` or ensure the {rhs} of your keymap begins with `silent` or `:`. For example, `nnoremap your_key :% !your_cmd` throws an error, while `nnoremap your_key % !your_cmd`, `nnoremap your_key :silent % !your_cmd` and `nnoremap your_key ::% !your_cmd` are OK. 233 | 234 | - Colorschemes may not load if they are written in legacy script. `:vim9 colorscheme foo` will not work unless `foo` is written in vim9script. 235 | 236 | - If you have defined a custom command with a completion function (`command -complete=custom,Foo() ...`), be aware that this function may not work as expected if it is designed to complete the n-th word. This is because there are now n+1 words, including the word `vim9`. You many need to adapt this function. 237 | 238 | - If you work with multi-byte UTF-8 characters, you'll appreciate the *vim9* command line. When slicing a UTF-8 string using the `[from : to]` operator, *vim9* is more predictable because it uses character-based addressing, unlike the byte-based addressing of the legacy script. 239 | 240 | - Legacy mode of addressing autoloaded functions and variables still work, even without legacy keywords like `call` and `let`. For instance, both `:vim9 g:foo#bar#baz()` and `:vim9 call g:foo#bar#baz()` work. 241 | 242 | You can keep the command line in *vim9script* mode by default and switch back to the legacy script at any time using the `:ToggleVim9Cmdline` command. 243 | 244 | ## Other Plugins to Enhance Your Workflow 245 | 246 | 1. [**vimcomplete**](https://github.com/girishji/vimcomplete) - enhances autocompletion in Vim. 247 | 248 | 2. [**devdocs.vim**](https://github.com/girishji/devdocs.vim) - browse documentation from [devdocs.io](https://devdocs.io). 249 | 250 | 3. [**scope.vim**](https://github.com/girishji/scope.vim) - fuzzy find anything. 251 | 252 | 4. [**VimSuggest**](https://github.com/girishji/vimsuggest) - autocompletion for Vim's command-line. 253 | -------------------------------------------------------------------------------- /autoload/vimbits/highlightonyank.vim: -------------------------------------------------------------------------------- 1 | vim9script 2 | 3 | # hlgroup: Highlight group used for highlighting yanked region. 4 | # duration: Duration of highlight in milliseconds. 5 | # in_visual: Whether to highlight the region if selected from visual mode. 6 | export def HighlightOnYank(hlgroup = 'IncSearch', duration = 300, in_visual = true) 7 | if v:event.operator ==? 'y' 8 | if !in_visual && visualmode() != null_string 9 | visualmode(1) 10 | return 11 | endif 12 | var [beg, end] = [getpos("'["), getpos("']")] 13 | var type = v:event.regtype ?? 'v' 14 | var pos = getregionpos(beg, end, {type: type}) 15 | var end_offset = (type == 'V' || v:event.inclusive) ? 1 : 0 16 | var m = matchaddpos(hlgroup, pos->mapnew((_, v) => { 17 | var col_beg = v[0][2] + v[0][3] 18 | var col_end = v[1][2] + v[1][3] + end_offset 19 | return [v[0][1], col_beg, col_end - col_beg] 20 | })) 21 | var winid = win_getid() 22 | timer_start(duration, (_) => { 23 | # keymap like `:vmap // y/"` (search for visually selected text) throws E803 24 | try 25 | m->matchdelete(winid) 26 | catch 27 | endtry 28 | }) 29 | endif 30 | enddef 31 | 32 | export def HighlightOnYankLegacy(hlgroup = 'IncSearch', duration = 300, in_visual = true) 33 | if v:event.operator ==? 'y' 34 | if !in_visual && visualmode() != null_string 35 | visualmode(1) 36 | return 37 | endif 38 | var [lnum_beg, col_beg, off_beg] = getpos("'[")[1 : 3] 39 | var [lnum_end, col_end, off_end] = getpos("']")[1 : 3] 40 | col_end += !v:event.inclusive ? 1 : 0 41 | var maxcol = v:maxcol - 1 42 | var visualblock = v:event.regtype[0] ==# "\" 43 | var pos = [] 44 | for lnum in range(lnum_beg, lnum_end, lnum_beg < lnum_end ? 1 : -1) 45 | var col_b = (lnum == lnum_beg || visualblock) ? (col_beg + off_beg) : 1 46 | var col_e = (lnum == lnum_end || visualblock) ? (col_end + off_end) : maxcol 47 | pos->add([lnum, col_b, min([col_e - col_b + 1, maxcol])]) 48 | endfor 49 | var m = matchaddpos(hlgroup, pos) 50 | var winid = win_getid() 51 | timer_start(duration, (_) => { 52 | try 53 | m->matchdelete(winid) 54 | catch 55 | endtry 56 | }) 57 | endif 58 | enddef 59 | -------------------------------------------------------------------------------- /autoload/vimbits/jump.vim: -------------------------------------------------------------------------------- 1 | vim9script 2 | 3 | var locations: list> = [] # A list of {line nr, column nr} to jump to 4 | var letters: string 5 | var labels: string 6 | var easyjump_case: string 7 | 8 | export def Setup() 9 | easyjump_case = get(g:, 'easyjump_case', 'smart') # case/icase/smart 10 | letters = get(g:, 'easyjump_letters', '') 11 | if letters->empty() 12 | var alpha = 'asdfgwercvhjkluiopynmbtqxz' 13 | letters = $'{alpha}{alpha->toupper()}0123456789' 14 | endif 15 | if letters->split('\zs')->sort()->uniq()->len() != letters->len() 16 | echoe 'EasyJump: Letters list has duplicates' 17 | endif 18 | # if get(g:, 'easyjump_default_keymap', true) && !hasmapto('EasyjumpJump;', 'n') && mapcheck('s', 'n') ==# '' 19 | if get(g:, 'easyjump_default_keymap', true) 20 | :nmap s EasyjumpJump; 21 | :omap s EasyjumpJump; 22 | :vmap s EasyjumpJump; 23 | endif 24 | enddef 25 | 26 | # get all line numbers in the visible area of the window ordered by distance from cursor 27 | def WindowLineNrs(): list 28 | # line('w$') does not include a long line (broken into many lines) that is only partly visible 29 | var [lstart, lend] = [max([1, line('w0')]), min([line('w$') + 1, line('$')])] # lines on screen 30 | var [curline, curcol] = getcurpos()[1 : 2] 31 | var lnums = [curline] 32 | for dist in range(1, (lend - lstart)) 33 | if curline + dist <= lend 34 | lnums->add(curline + dist) 35 | endif 36 | if curline - dist >= lstart 37 | lnums->add(curline - dist) 38 | endif 39 | endfor 40 | return lnums 41 | enddef 42 | 43 | # search for locations to jump to, starting from cursor position and searching outwards 44 | def GatherLocations(ctx: string, filter_label: bool = false) 45 | var ignorecase = (easyjump_case ==? 'icase' || (easyjump_case ==? 'smart' && ctx =~ '\U')) ? true : false 46 | var Ignorecase = (s) => ignorecase ? s->tolower() : s 47 | labels = letters->copy() 48 | locations = [] 49 | 50 | var [curline, curcol] = getcurpos()[1 : 2] 51 | var lnums = WindowLineNrs() 52 | for lnum in lnums 53 | if foldclosed(lnum) != -1 54 | continue # ignore folded lines 55 | endif 56 | var line = Ignorecase(getline(lnum)) 57 | var col = line->stridx(ctx) 58 | while col != -1 59 | col += 1 # column numbers start from 1 60 | if ctx == ' ' && !locations->empty() && locations[-1] == [lnum, col - 1] 61 | locations[-1][1] = col # one target per cluster of adjacent spaces 62 | elseif [lnum, col] != [curline, curcol] # no target on cursor position 63 | locations->add([lnum, col]) 64 | if filter_label && col < line->len() 65 | # remove character next to ctx from label chars 66 | var idx = labels->stridx(line[col]) 67 | if idx != -1 68 | labels = $'{labels->slice(0, idx)}{labels->slice(idx + 1)}' 69 | endif 70 | endif 71 | endif 72 | col = line->stridx(ctx, col) 73 | endwhile 74 | if lnum == curline # prioritize based on distance from cursor 75 | locations->sort((x, y) => abs(x[1] - curcol) - abs(y[1] - curcol)) 76 | endif 77 | endfor 78 | enddef 79 | 80 | # order locations list by keeping more locations near cursor, and at least one per line 81 | def Prioritize() 82 | var [lstart, lend] = [line('w0'), line('w$')] # lines on screen start/end 83 | var highpri = [] 84 | var lowpri = [] 85 | var expected = locations->len() 86 | var curline = line('.') 87 | def FilterLocations(tlinenr: number, tmax: number) 88 | if tlinenr < lstart || tlinenr > lend 89 | return 90 | endif 91 | var curlocations = locations->copy()->filter((_, v) => v[0] == tlinenr) 92 | locations->filter((_, v) => v[0] != tlinenr) 93 | highpri->extend(curlocations->slice(0, tmax)) 94 | lowpri->extend(curlocations->slice(tmax)) 95 | enddef 96 | 97 | FilterLocations(curline, 10) # 10 locations max 98 | if locations->len() > (lend - lstart) 99 | var excess = locations->len() - (lend - lstart) 100 | FilterLocations(curline + 1, excess / 3) 101 | FilterLocations(curline - 1, excess / 3) 102 | endif 103 | # at least one target per line 104 | for p in range(locations->len()) 105 | if locations[p][0] != locations[p - 1][0] 106 | highpri->add(locations[p]) 107 | else 108 | lowpri->add(locations[p]) 109 | endif 110 | endfor 111 | # shuffle the remaining low priority locations 112 | lowpri = lowpri->mapnew((_, v) => [v, rand()])->sort((a, b) => a[1] < b[1] ? 0 : 1)->mapnew((_, v) => v[0]) 113 | locations = highpri + lowpri 114 | # error check 115 | if expected != locations->len() 116 | echoe 'EasyJump: Locations list filter error' 117 | endif 118 | if locations->copy()->sort()->uniq()->len() != locations->len() 119 | echoe 'EasyJump: Locations list has duplicates' 120 | endif 121 | enddef 122 | 123 | def ShowTag(tag: string, lnum: number, col: number) 124 | if lnum != -1 125 | popup_create(tag, { 126 | line: lnum, 127 | col: col, 128 | highlight: 'EasyJump', 129 | wrap: false, 130 | zindex: 50 - 1, 131 | }) 132 | endif 133 | enddef 134 | 135 | # NOTE: column number (byte based) is different from screen column when tab or 136 | # utf-8 chars are present. chars like ぬ, і, etc. are 3-byte and double wide. 137 | # popup_create() expects screen column while what we have is byte column. Use 138 | # screenpos() with synconcealed(), or wincol() which requires :redraw and is slow. 139 | # Vim bug: https://github.com/vim/vim/issues/14640 140 | # concealed characters, set by matchadd() are not accounted for. 141 | # https://github.com/vim/vim/issues/14643 142 | 143 | def ScreenPos(lnum: number, col: number): list 144 | var is_invisible = {row: 0, col: 0, endcol: 0, curscol: 0} 145 | var scrpos = win_getid()->screenpos(lnum, col) 146 | if scrpos != is_invisible 147 | # screenpos has no knowledge of concealed or substituted chars 148 | var concealed_len = 0 149 | var idx = 1 150 | while idx < col 151 | var status = synconcealed(lnum, idx) 152 | if status[0] == 1 # concealed 153 | var spos = win_getid()->screenpos(lnum, idx) 154 | var clen = spos.endcol - spos.col + 1 155 | if status[1] != null_string # substitute char present 156 | echom status[1] 157 | # Vim does not allow/show as substitute char 158 | # utf-8 chars are either 1 cell or 2 cell wide 159 | clen -= status[1]->strwidth() # display width in cells 160 | endif 161 | concealed_len += clen 162 | var line = getline(lnum) 163 | idx += line->strcharpart(line->charidx(idx - 1), 1)->len() # skip by byte width of char 164 | else 165 | idx += 1 166 | endif 167 | endwhile 168 | return [scrpos.row, scrpos.col - concealed_len] 169 | endif 170 | return [-1, -1] 171 | enddef 172 | 173 | def ShowLocations(group: number) 174 | try 175 | popup_clear() 176 | var ntags = labels->len() 177 | for idx in range(min([ntags, locations->len() - group * ntags])) 178 | var [lnum, col] = locations[idx + group * ntags] 179 | var [scrlnum, scrcol] = ScreenPos(lnum, col) 180 | if scrlnum != -1 181 | ShowTag(labels[idx], scrlnum, scrcol) 182 | endif 183 | endfor 184 | finally 185 | :redraw 186 | endtry 187 | enddef 188 | 189 | def JumpTo(tgt: string, group: number) 190 | var tagidx = labels->stridx(tgt) 191 | var locidx = tagidx + group * labels->len() 192 | if tagidx != -1 && locidx < locations->len() 193 | var loc = locations[locidx] 194 | :normal! m' 195 | cursor(loc) 196 | endif 197 | popup_clear() 198 | enddef 199 | 200 | def GroupCount(): number 201 | var ngroups = locations->len() / labels->len() + 1 202 | ngroups -= (locations->len() % labels->len() == 0) ? 1 : 0 203 | if ngroups > 1 204 | Prioritize() 205 | endif 206 | return ngroups 207 | enddef 208 | 209 | # main entry point 210 | export def Jump(two_chars: bool = false) 211 | var two_chars_mode = two_chars || get(g:, 'easyjump_two_chars', false) 212 | var ch = (easyjump_case ==? 'icase') ? getcharstr()->tolower() : getcharstr() 213 | GatherLocations(ch, two_chars_mode) 214 | if locations->empty() 215 | return 216 | endif 217 | var ngroups = GroupCount() 218 | var group = 0 219 | try 220 | ShowLocations(group) 221 | var ctx = ch 222 | ch = getcharstr() 223 | if two_chars_mode 224 | if labels->stridx(ch) != -1 225 | JumpTo(ch, group) 226 | return 227 | elseif [';', ',', "\", "\"]->index(ch) != -1 # switch to 1-char mode 228 | labels = letters->copy() 229 | ngroups = GroupCount() 230 | if ngroups == 1 231 | ShowLocations(group) 232 | endif 233 | else 234 | ctx ..= (easyjump_case ==? 'icase') ? ch->tolower() : ch 235 | GatherLocations(ctx) 236 | ngroups = GroupCount() 237 | ShowLocations(group) 238 | ch = getcharstr() 239 | endif 240 | endif 241 | while true 242 | if [';', ',', "\", "\"]->index(ch) != -1 243 | if ngroups > 1 244 | if ch == ';' || ch == "\" 245 | group = (group + 1) % ngroups 246 | else 247 | group = (group + ngroups - 1) % ngroups 248 | endif 249 | ShowLocations(group) 250 | endif 251 | else 252 | JumpTo(ch, group) 253 | break 254 | endif 255 | ch = getcharstr() 256 | endwhile 257 | finally 258 | popup_clear() 259 | endtry 260 | enddef 261 | -------------------------------------------------------------------------------- /autoload/vimbits/vim9cmdline.vim: -------------------------------------------------------------------------------- 1 | vim9script 2 | 3 | export def Vim9cmdlineSet() 4 | if get(g:, 'vimbits_vim9cmdline', false) 5 | if visualmode() == null_string 6 | setcmdline('vim9 ') 7 | else 8 | setcmdline('vim9 :') 9 | visualmode(1) 10 | endif 11 | cnoremap vim9 12 | cnoremap 13 | cnoremap getcmdpos() > 6 ? "\" : "" 14 | cnoremap getcmdpos() > 6 ? "\" : "" 15 | cnoremap getcmdpos() > 6 ? "\" : "" 16 | cnoremap getcmdpos() > 6 ? "\" : "" 17 | endif 18 | enddef 19 | 20 | export def Vim9cmdlineUnset() 21 | if get(g:, 'vimbits_vim9cmdline', false) 22 | silent! cunmap 23 | silent! cunmap 24 | silent! cunmap 25 | silent! cunmap 26 | silent! cunmap 27 | silent! cunmap 28 | endif 29 | enddef 30 | -------------------------------------------------------------------------------- /doc/easyjump.txt: -------------------------------------------------------------------------------- 1 | *easyjump.txt* Vim motion on steroids 2 | 3 | Author: Girish (girishji AT gmail DOT com) 4 | For Vim version 9.0 and above 5 | 6 | ============================================================================== 7 | CONTENTS *easyjump-contents* 8 | 9 | 1. Overview ................................. |easyjump-overview| 10 | 2. Features ................................. |easyjump-features| 11 | 3. Requirements ............................. |easyjump-requirements| 12 | 4. Installation ............................. |easyjump-installation| 13 | 5. Configuration ............................ |easyjump-configuration| 14 | 15 | ============================================================================== 16 | 1. Overview *easyjump-overview* 17 | 18 | Jump to any location by typing 2 characters. 19 | 20 | Jump: Type `s` and `c` (say) and you'll see new letters (virtual text) appear 21 | next to all the occurrences of `c`. Type `d` (for instance) and cursor jumps to 22 | `c` next to `d`. 23 | 24 | Visual Select: To visually select a block of text starting from cursor position 25 | to some occurrence of `c` type `vsc` and then type the highlighted character 26 | (say `d`). 27 | 28 | What if there is no letter next to where you want to jump to?~ 29 | 30 | This scenario occurs when there aren't enough unique letters available for 31 | tagging. Simply press `` (or `;`), and new tag labels will fill the 32 | remaining spots. To cycle backwards, press `` (or `,`). 33 | 34 | Two-Character Mode (New): Activated with `2s` or simply `s` if 35 | `g:easyjump_two_chars` is configured as `true`. 36 | - Use `2s` + + to leap to your destination (when a 37 | tag character marks the spot). 38 | - If no tag label is present, type the adjacent character as well, forming 39 | `2s` + + + _tag_character_ to execute the jump. 40 | 41 | ============================================================================== 42 | 2. Features *easyjump-features* 43 | 44 | - Mapped to `s` but any other trigger (like `,`) would work. 45 | - Vim idioms supported. Use `dsxy` to delete, `csxy` to change, `vsxy` to select visually, etc. 46 | - Jump list (`:jumps`) updated so that you can jump back using ``. 47 | - Does not alter the buffer. 48 | 49 | ============================================================================== 50 | 3. Requirements *easyjump-requirements* 51 | 52 | - Vim >= 9.0 53 | 54 | ============================================================================== 55 | 4. Installation *easyjump-installation* 56 | 57 | Install using vim-plug (https://github.com/junegunn/vim-plug). 58 | > 59 | vim9script 60 | plug#begin() 61 | Plug 'girishji/easyjump.vim' 62 | plug#end() 63 | 64 | Alternately, 65 | > 66 | call plug#begin() 67 | Plug 'girishji/easyjump.vim' 68 | call plug#end() 69 | 70 | Or use Vim's builtin package manager. 71 | > 72 | $ mkdir -p $HOME/.vim/pack/downloads/opt 73 | $ cd $HOME/.vim/pack/downloads/opt 74 | $ git clone https://github.com/girishji/easyjump.git 75 | 76 | If using builtin package manager, add the following line to your $HOME/.vimrc 77 | file: 78 | > 79 | packadd easyjump 80 | 81 | ============================================================================== 82 | 5. Configuration *easyjump-configuration* 83 | 84 | Trigger Key~ 85 | 86 | By default `s` is the trigger key. To disable it put the following in `.vimrc` 87 | file. `s` will be restored to Vim original keybinding (`:h s`). 88 | > 89 | g:easyjump_default_keymap = false 90 | 91 | To make `,` (for example) trigger the jump put the following in `.vimrc` file. 92 | > 93 | nmap , EasyjumpJump; 94 | omap , EasyjumpJump; 95 | vmap , EasyjumpJump; 96 | 97 | Case~ 98 | 99 | The destination character you type is compared against visible buffer text. To 100 | make the search case sensitive (case), insensitive (icase), or smart case 101 | (smart) put the following in `.vimrc`. 102 | > 103 | g:easyjump_case = 'smart' # Can be 'case', 'icase', or 'smart' 104 | 105 | Highlight~ 106 | 107 | The tag letters that appear next to destination locations utilize highlight 108 | group `EasyJump`. It is linked to `MatchParen` by default. Set this group using 109 | `:highlight` command to change colors. 110 | 111 | Letters~ 112 | 113 | The virtual text letters that appear next to the destination you want to jump 114 | to are prioritized based on distance from the cursor, with at least one letter 115 | per line. The letters appear in the following order of decreasing priority. The 116 | letters and order can be changed by assigning to the following variable. 117 | > 118 | g:easyjump_letters = 119 | 'asdfgwercvhjkluiopynmbtqxzASDFGWERCVHJKLUIOPYNMBTQXZ0123456789' 120 | 121 | ============================================================================== 122 | 123 | vim:tw=78:ts=8:noet:ft=help:norl: 124 | -------------------------------------------------------------------------------- /doc/fFtT.txt: -------------------------------------------------------------------------------- 1 | fFtT.txt* Accurate left-right navigation in Vim 2 | 3 | Author: Girish (girishji AT gmail DOT com) 4 | For Vim version 9.0 and above 5 | 6 | ============================================================================== 7 | CONTENTS *fFtT-contents* 8 | 9 | 1. Overview ................................. |fFtT-overview| 10 | 2. Requirements ............................. |fFtT-requirements| 11 | 3. Installation ............................. |fFtT-installation| 12 | 4. Configuration............................. |fFtT-configuration| 13 | 14 | ============================================================================== 15 | 1. Overview *fFtT-overview* 16 | 17 | Characters that are reachable with a single jump are highlighted, while others 18 | are dimmed. This enhancement improves the accuracy of navigation using `f`, 19 | `F`, `t`, and `T` commands. Additionally, you can provide a numerical prefix 20 | (e.g., `3f`), which will only highlight characters that occur the third time 21 | to the right of the cursor, while others are dimmed. 22 | 23 | This plugin does not remap keys or alter the behavior of commands. It solely 24 | focuses on highlighting relevant characters without making any changes to the 25 | default key mappings. The code consists of less than 100 lines, with 26 | explanatory comments. 27 | 28 | ============================================================================== 29 | 2. Requirements *fFtT-requirements* 30 | 31 | - Vim >= 9.1 32 | 33 | ============================================================================== 34 | 3. Installation *fFtT-installation* 35 | 36 | Install using vim-plug (https://github.com/junegunn/vim-plug) 37 | > 38 | vim9script 39 | plug#begin() 40 | Plug 'girishji/fFtT.vim' 41 | plug#end() 42 | 43 | Legacy script: 44 | > 45 | call plug#begin() 46 | Plug 'girishji/fFtT.vim' 47 | call plug#end() 48 | 49 | Or use Vim's builtin package manager. 50 | 51 | ============================================================================== 52 | 4. Configuration *fFtT-configuration* 53 | 54 | The appearance of characters that are unreachable within one jump is 55 | determined by the highlight group `FfTtSubtle`, which is linked to the 56 | `Comment` group by default. 57 | 58 | ============================================================================== 59 | 60 | vim:tw=78:ts=8:noet:ft=help:norl: 61 | -------------------------------------------------------------------------------- /doc/tags: -------------------------------------------------------------------------------- 1 | /Content.IE?/ vimtips.txt /*\/Content.IE?\/* 2 | easyjump-configuration easyjump.txt /*easyjump-configuration* 3 | easyjump-contents easyjump.txt /*easyjump-contents* 4 | easyjump-features easyjump.txt /*easyjump-features* 5 | easyjump-installation easyjump.txt /*easyjump-installation* 6 | easyjump-overview easyjump.txt /*easyjump-overview* 7 | easyjump-requirements easyjump.txt /*easyjump-requirements* 8 | easyjump.txt easyjump.txt /*easyjump.txt* 9 | fFtT-configuration fFtT.txt /*fFtT-configuration* 10 | fFtT-contents fFtT.txt /*fFtT-contents* 11 | fFtT-installation fFtT.txt /*fFtT-installation* 12 | fFtT-overview fFtT.txt /*fFtT-overview* 13 | fFtT-requirements fFtT.txt /*fFtT-requirements* 14 | vimtips-absolutely-essential vimtips.txt /*vimtips-absolutely-essential* 15 | vimtips-global vimtips.txt /*vimtips-global* 16 | vimtips-global-combined-with-substitute vimtips.txt /*vimtips-global-combined-with-substitute* 17 | vimtips-searching vimtips.txt /*vimtips-searching* 18 | vimtips-substitution vimtips.txt /*vimtips-substitution* 19 | vimtips.txt vimtips.txt /*vimtips.txt* 20 | -------------------------------------------------------------------------------- /doc/vimtips.txt: -------------------------------------------------------------------------------- 1 | *vimtips.txt* For Vim version 8.0. 2 | David Rayner (zzapper) 15 Years of Vi + 7 years of Vim and still learning 3 | ------------------------------------------------------------------------------ 4 | " new items marked [N] , corrected items marked [C] 5 | " *vimtips-searching* 6 | /joe/e : cursor set to End of match 7 | 3/joe/e+1 : find 3rd joe cursor set to End of match plus 1 [C] 8 | /joe/s-2 : cursor set to Start of match minus 2 9 | /joe/+3 : find joe move cursor 3 lines down 10 | /^joe.*fred.*bill/ : find joe AND fred AND Bill (Joe at start of line) 11 | /^[A-J]/ : search for lines beginning with one or more A-J 12 | /begin\_.*end : search over possible multiple lines 13 | /fred\_s*joe/ : any whitespace including newline [C] 14 | /fred\|joe : Search for FRED OR JOE 15 | /.*fred\&.*joe : Search for FRED AND JOE in any ORDER! 16 | /\/ : search for fred but not alfred or frederick [C] 17 | /\<\d\d\d\d\> : Search for exactly 4 digit numbers 18 | /\D\d\d\d\d\D : Search for exactly 4 digit numbers 19 | /\<\d\{4}\> : same thing 20 | /\([^0-9]\|^\)%.*% : Search for absence of a digit or beginning of line 21 | " finding empty lines 22 | /^\n\{3} : find 3 empty lines 23 | /^str.*\nstr : find 2 successive lines starting with str 24 | /\(^str.*\n\)\{2} : find 2 successive lines starting with str 25 | " using regexp memory in a search find fred.*joe.*joe.*fred 26 | /\(fred\).*\(joe\).*\2.*\1 27 | " Repeating the Regexp (rather than what the Regexp finds) 28 | /^\([^,]*,\)\{8} 29 | " visual searching 30 | :vmap // y/" : search for visually highlighted text 31 | :vmap // y/=escape(@", '\\/.*$^~[]') : with spec chars 32 | " \zs and \ze regex delimiters :h /\zs 33 | /<\zs[^>]*\ze> : search for tag contents, ignoring chevrons 34 | " zero-width :h /\@= 35 | /<\@<=[^>]*>\@= : search for tag contents, ignoring chevrons 36 | /<\@<=\_[^>]*>\@= : search for tags across possible multiple lines 37 | " searching over multiple lines \_ means including newline 38 | / : search for multiple line comments 39 | /fred\_s*joe/ : any whitespace including newline 40 | /bugs\(\_.\)*bunny : bugs followed by bunny anywhere in file 41 | :h \_ : help 42 | " search for declaration of subroutine/function under cursor 43 | :nmap gx yiw/^\(sub\function\)\s\+" 44 | " multiple file search/operations 45 | :bufdo /searchstr/ : use :rewind to recommence search 46 | " multiple file search better but cheating 47 | :bufdo %s/searchstr/&/gic : say n and then a to stop 48 | :bufdo execute "normal! @a" | w : execute macro a over all buffers [N] 49 | :bufdo exe ":normal Gp" | update : Paste to the end of each buffer [N] 50 | :argdo exe '%!sort' | w [N] 51 | " How to search for a URL without backslashing 52 | ?http://www.vim.org/ : (first) search BACKWARDS!!! clever huh! 53 | " Specify what you are NOT searching for (vowels) 54 | /\c\v([^aeiou]&\a){4} : search for 4 consecutive consonants 55 | /\%>20l\%<30lgoat : Search for goat between lines 20 and 30 [N] 56 | /^.\{-}home.\{-}\zshome/e : match only the 2nd occurence in a line of "home" [ 57 | N] 58 | :%s/home.\{-}\zshome/alone : Substitute only the 2nd occurrence of home in any 59 | line [U] 60 | :%s/.*\zsone/two/ : Substitute only the LAST occurrence of one [N] 61 | " find str but not on lines containing tongue 62 | ^\(.*tongue.*\)\@!.*nose.*$ 63 | \v^((tongue)@!.)*nose((tongue)@!.)*$ 64 | .*nose.*\&^\%(\%(tongue\)\@!.\)*$ 65 | :v/tongue/s/nose/&/gic 66 | 'a,'bs/extrascost//gc : trick: restrict search to between markers (answer 67 | n) [N] 68 | /integ : Control-L to complete search term [N] 69 | "---------------------------------------- 70 | " *vimtips-substitution* 71 | :s/foo/\rfoo/g : \r will substitute a newline 72 | :%s/fred/joe/igc : general substitute command 73 | :%s//joe/igc : Substitute what you last searched for [N] 74 | :%s/~/sue/igc : Substitute your last replacement string [N] 75 | :%s/\r//g : Delete DOS returns ^M 76 | " Is your Text File jumbled onto one line? use following 77 | :%s/\r/\r/g : Turn DOS returns ^M into real returns 78 | :%s= *$== : delete end of line blanks 79 | :%s= \+$== : Same thing 80 | :%s#\s*\r\?$## : Clean both trailing spaces AND DOS returns 81 | :%s#\s*\r*$## : same thing 82 | " deleting empty lines 83 | :%s/^\n\{3}// : delete blocks of 3 empty lines 84 | :%s/^\n\+/\r/ : compressing empty lines 85 | :%s#<[^>]\+>##g : delete html tags, leave text (non-greedy) 86 | :%s#<\_.\{-1,}>##g : delete html tags possibly multi-line (non-greedy) 87 | :%s#.*\(\d\+hours\).*#\1# : Delete all but memorised string (\1) [N] 88 | " parse xml/soap 89 | %s#><\([^/]\)#>\r<\1#g : split jumbled up XML file into one tag per line [N 90 | ] 91 | %s/#\L&#gc : lowercase with optional leading characters 117 | " over possibly many lines 118 | :%s/// : delete possibly multi-line comments 119 | :help /\{-} : help non-greedy 120 | " substitute using a register 121 | :s/fred/a/g : sub "fred" with contents of register "a" 122 | :s/fred/asome_texts/g 123 | :s/fred/\=@a/g : better alternative as register not displayed (not 124 | *) [C] 125 | :s/fred/\=@*/g : replace string with contents of paste register [N] 126 | " multiple commands on one line 127 | :%s/\f\+\.gif\>/\r&\r/g | v/\.gif$/d | %s/gif/jpg/ 128 | :%s/a/but/gie|:update|:next : then use @: to repeat 129 | " ORing 130 | :%s/goat\|cow/sheep/gc : ORing (must break pipe) 131 | :'a,'bs#\[\|\]##g : remove [] from lines between markers a and b [N] 132 | :%s/\v(.*\n){5}/&\r : insert a blank line every 5 lines [N] 133 | " Calling a VIM function 134 | :s/__date__/\=strftime("%c")/ : insert datestring 135 | :inoremap \zd =strftime("%d%b%y") : insert date eg 31Jan11 [N] 136 | " Working with Columns sub any str1 in col3 137 | :%s:\(\(\w\+\s\+\)\{2}\)str1:\1str2: 138 | " Swapping first & last column (4 columns) 139 | :%s:\(\w\+\)\(.*\s\+\)\(\w\+\)$:\3\2\1: 140 | " format a mysql query 141 | :%s#\\|\\|\\|\<\inner join\>#\r&#g 142 | " filter all form elements into paste register 143 | :redir @*|sil exec 'g#<\(input\|select\|textarea\|/\=form\)\>#p'|redir END 144 | :nmap ,z :redir @*sil exec 'g@<\(input\select\textarea\/\=fo 145 | rm\)\>@p'redir END 146 | " substitute string in column 30 [N] 147 | :%s/^\(.\{30\}\)xx/\1yy/ 148 | " decrement numbers by 3 149 | :%s/\d\+/\=(submatch(0)-3)/ 150 | " increment numbers by 6 on certain lines only 151 | :g/loc\|function/s/\d/\=submatch(0)+6/ 152 | " better 153 | :%s#txtdev\zs\d#\=submatch(0)+1#g 154 | :h /\zs 155 | " increment only numbers gg\d\d by 6 (another way) 156 | :%s/\(gg\)\@<=\d\+/\=submatch(0)+6/ 157 | :h zero-width 158 | " rename a string with an incrementing number 159 | :let i=10 | 'a,'bg/Abc/s/yy/\=i/ |let i=i+1 # convert yy to 10,11,12 etc 160 | " as above but more precise 161 | :let i=10 | 'a,'bg/Abc/s/xx\zsyy\ze/\=i/ |let i=i+1 # convert xxyy to xx11,xx12, 162 | xx13 163 | " find replacement text, put in memory, then use \zs to simplify substitute 164 | :%s/"\([^.]\+\).*\zsxx/\1/ 165 | " Pull word under cursor into LHS of a substitute 166 | :nmap z :%s#\<=expand("")\># 167 | " Pull Visually Highlighted text into LHS of a substitute 168 | :vmap z :%s/\<*\>/ 169 | " substitute singular or plural 170 | :'a,'bs/bucket\(s\)*/bowl\1/gic [N] 171 | ---------------------------------------- 172 | " all following performing similar task, substitute within substitution 173 | " Multiple single character substitution in a portion of line only 174 | :%s,\(all/.*\)\@<=/,_,g : replace all / with _ AFTER "all/" 175 | " Same thing 176 | :s#all/\zs.*#\=substitute(submatch(0), '/', '_', 'g')# 177 | " Substitute by splitting line, then re-joining 178 | :s#all/#&^M#|s#/#_#g|-j! 179 | " Substitute inside substitute 180 | :%s/.*/\='cp '.submatch(0).' all/'.substitute(submatch(0),'/','_','g')/ 181 | ---------------------------------------- 182 | " *vimtips-global* command 183 | :g/gladiolli/# : display with line numbers (YOU WANT THIS!) 184 | :g/fred.*joe.*dick/ : display all lines fred,joe & dick 185 | :g/\/ : display all lines fred but not freddy 186 | :g/^\s*$/d : delete all blank lines 187 | :g!/^dd/d : delete lines not containing string 188 | :v/^dd/d : delete lines not containing string 189 | :g/joe/,/fred/d : not line based (very powerfull) 190 | :g/fred/,/joe/j : Join Lines [N] 191 | :g/-------/.-10,.d : Delete string & 10 previous lines 192 | :g/{/ ,/}/- s/\n\+/\r/g : Delete empty lines but only between {...} 193 | :v/\S/d : Delete empty lines (and blank lines ie whitespace) 194 | :v/./,/./-j : compress empty lines 195 | :g/^$/,/./-j : compress empty lines 196 | :g/ as 5 characters) 216 | :.,$g/^\d/exe "norm! \": increment numbers 217 | :'a,'bg/\d\+/norm! ^A : increment numbers 218 | " storing glob results (note must use APPEND) you need to empty reg a first with 219 | qaq. 220 | "save results to a register/paste buffer 221 | :g/fred/y A : append all lines fred to register a 222 | :g/fred/y A | :let @*=@a : put into paste buffer 223 | :g//y A | :let @*=@a : put into paste buffer # better reuses last g// [N] 224 | :g//y A | :let @*=@a : put last glob into paste buffer [N] 225 | :let @a=''|g/Barratt/y A |:let @*=@a 226 | " filter lines to a file (file must already exist) 227 | :'a,'bg/^Error/ . w >> errors.txt 228 | " duplicate every line in a file wrap a print '' around each duplicate 229 | :g/./yank|put|-1s/'/"/g|s/.*/Print '&'/ 230 | " replace string with contents of a file, -d deletes the "mark" 231 | :g/^MARK$/r tmp.txt | -d 232 | " display prettily 233 | :g//z#.5 : display with context 234 | :g//z#.5|echo "==========" : display beautifully 235 | " Combining g// with normal mode commands 236 | :g/|/norm 2f|r* : replace 2nd | with a star 237 | "send output of previous global command to a new window 238 | :nmap :redir @a:g//:redir END:new:put! a 239 | ---------------------------------------- 240 | " *vimtips-global-combined-with-substitute* (*power-editing*) 241 | :'a,'bg/fred/s/joe/susan/gic : can use memory to extend matching 242 | :/fred/,/joe/s/fred/joe/gic : non-line based (ultra) 243 | :/biz/,/any/g/article/s/wheel/bucket/gic: non-line based [N] 244 | ---------------------------------------- 245 | " Find fred before beginning search for joe [N] 246 | /fred/;/joe/ 247 | " Find fred before beginning search for joe then substitute [N] 248 | :/fred/;/joe/-2,/sid/+3s/sally/alley/gIC 249 | ---------------------------------------- 250 | " create a new file for each line of file eg 1.txt,2.txt,3,txt etc 251 | :g/^/exe ".w ".line(".").".txt" 252 | ---------------------------------------- 253 | " chain an external command 254 | :.g/^/ exe ".!sed 's/N/X/'" | s/I/Q/ [N] 255 | ---------------------------------------- 256 | " Operate until string found [N] 257 | d/fred/ :delete until fred 258 | y/fred/ :yank until fred 259 | c/fred/e :change until fred end 260 | v12| : visualise/change/delete to column 12 [N 261 | ] 262 | ---------------------------------------- 263 | " Summary of editing repeats [N] 264 | . last edit (magic dot) 265 | :& last substitute 266 | :%& last substitute every line 267 | :%&gic last substitute every line confirm 268 | g% normal mode repeat last substitute 269 | g& last substitute on all lines 270 | @@ last recording 271 | @: last command-mode command 272 | :!! last :! command 273 | :~ last substitute 274 | :help repeating 275 | ---------------------------------------- 276 | " Summary of repeated searches 277 | ; last f, t, F or T 278 | , last f, t, F or T in opposite direction 279 | n last / or ? search 280 | N last / or ? search in opposite direction 281 | ---------------------------------------- 282 | " *vimtips-absolutely-essential* 283 | ---------------------------------------- 284 | * # g* g# : find word under cursor () (forwards/backwards) 285 | % : match brackets {}[]() 286 | . : repeat last modification 287 | @: : repeat last : command (then @@) 288 | matchit.vim : % now matches tags