Last active
April 19, 2018 22:03
-
-
Save icarofreire/d84e7fb660867a0cf0002b4c20435376 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| " EasyMotion - Vim motions on speed! | |
| " | |
| " Author: Kim Silkebækken <[email protected]> | |
| " Source repository: https://github.com/Lokaltog/vim-easymotion | |
| " Default configuration functions {{{ | |
| function! EasyMotion_InitOptions(options) " {{{ | |
| for [key, value] in items(a:options) | |
| if ! exists('g:EasyMotion_' . key) | |
| exec 'let g:EasyMotion_' . key . ' = ' . string(value) | |
| endif | |
| endfor | |
| endfunction " }}} | |
| function! EasyMotion_InitHL(group, colors) " {{{ | |
| let group_default = a:group . 'Default' | |
| " Prepare highlighting variables | |
| let guihl = printf('guibg=%s guifg=%s gui=%s', a:colors.gui[0], a:colors.gui[1], a:colors.gui[2]) | |
| if !exists('g:CSApprox_loaded') | |
| let ctermhl = &t_Co == 256 | |
| \ ? printf('ctermbg=%s ctermfg=%s cterm=%s', a:colors.cterm256[0], a:colors.cterm256[1], a:colors.cterm256[2]) | |
| \ : printf('ctermbg=%s ctermfg=%s cterm=%s', a:colors.cterm[0], a:colors.cterm[1], a:colors.cterm[2]) | |
| else | |
| let ctermhl = '' | |
| endif | |
| " Create default highlighting group | |
| execute printf('hi default %s %s %s', group_default, guihl, ctermhl) | |
| " Check if the hl group exists | |
| if hlexists(a:group) | |
| redir => hlstatus | exec 'silent hi ' . a:group | redir END | |
| " Return if the group isn't cleared | |
| if hlstatus !~ 'cleared' | |
| return | |
| endif | |
| endif | |
| " No colors are defined for this group, link to defaults | |
| execute printf('hi default link %s %s', a:group, group_default) | |
| endfunction " }}} | |
| function! EasyMotion_InitMappings(motions) "{{{ | |
| for motion in keys(a:motions) | |
| call EasyMotion_InitOptions({ 'mapping_' . motion : g:EasyMotion_leader_key . motion }) | |
| endfor | |
| if g:EasyMotion_do_mapping | |
| for [motion, fn] in items(a:motions) | |
| if empty(g:EasyMotion_mapping_{motion}) | |
| continue | |
| endif | |
| silent exec 'nnoremap <silent> ' . g:EasyMotion_mapping_{motion} . ' :call EasyMotion_' . fn.name . '(0, ' . fn.dir . ')<CR>' | |
| silent exec 'onoremap <silent> ' . g:EasyMotion_mapping_{motion} . ' :call EasyMotion_' . fn.name . '(0, ' . fn.dir . ')<CR>' | |
| silent exec 'vnoremap <silent> ' . g:EasyMotion_mapping_{motion} . ' :<C-U>call EasyMotion_' . fn.name . '(1, ' . fn.dir . ')<CR>' | |
| endfor | |
| endif | |
| endfunction "}}} | |
| " }}} | |
| " Motion functions {{{ | |
| function! EasyMotion_F(visualmode, direction) " {{{ | |
| let char = s:GetSearchChar(a:visualmode) | |
| if empty(char) | |
| return | |
| endif | |
| let re = '\C' . escape(char, '.$^~') | |
| call s:EasyMotion(re, a:direction, a:visualmode ? visualmode() : '', mode(1)) | |
| endfunction " }}} | |
| function! EasyMotion_T(visualmode, direction) " {{{ | |
| let char = s:GetSearchChar(a:visualmode) | |
| if empty(char) | |
| return | |
| endif | |
| if a:direction == 1 | |
| let re = '\C' . escape(char, '.$^~') . '\zs.' | |
| else | |
| let re = '\C.' . escape(char, '.$^~') | |
| endif | |
| call s:EasyMotion(re, a:direction, a:visualmode ? visualmode() : '', mode(1)) | |
| endfunction " }}} | |
| function! EasyMotion_WB(visualmode, direction) " {{{ | |
| call s:EasyMotion('\(\<.\|^$\)', a:direction, a:visualmode ? visualmode() : '', '') | |
| endfunction " }}} | |
| function! EasyMotion_WBW(visualmode, direction) " {{{ | |
| call s:EasyMotion('\(\(^\|\s\)\@<=\S\|^$\)', a:direction, a:visualmode ? visualmode() : '', '') | |
| endfunction " }}} | |
| function! EasyMotion_E(visualmode, direction) " {{{ | |
| call s:EasyMotion('\(.\>\|^$\)', a:direction, a:visualmode ? visualmode() : '', mode(1)) | |
| endfunction " }}} | |
| function! EasyMotion_EW(visualmode, direction) " {{{ | |
| call s:EasyMotion('\(\S\(\s\|$\)\|^$\)', a:direction, a:visualmode ? visualmode() : '', mode(1)) | |
| endfunction " }}} | |
| function! EasyMotion_JK(visualmode, direction) " {{{ | |
| call s:EasyMotion('^\(\w\|\s*\zs\|$\)', a:direction, a:visualmode ? visualmode() : '', '') | |
| endfunction " }}} | |
| function! EasyMotion_Search(visualmode, direction) " {{{ | |
| call s:EasyMotion(@/, a:direction, a:visualmode ? visualmode() : '', '') | |
| endfunction " }}} | |
| " }}} | |
| " Helper functions {{{ | |
| function! s:Message(message) " {{{ | |
| echo 'EasyMotion: ' . a:message | |
| endfunction " }}} | |
| function! s:Prompt(message) " {{{ | |
| echohl Question | |
| echo a:message . ': ' | |
| echohl None | |
| endfunction " }}} | |
| function! s:VarReset(var, ...) " {{{ | |
| if ! exists('s:var_reset') | |
| let s:var_reset = {} | |
| endif | |
| let buf = bufname("") | |
| if a:0 == 0 && has_key(s:var_reset, a:var) | |
| " Reset var to original value | |
| call setbufvar(buf, a:var, s:var_reset[a:var]) | |
| elseif a:0 == 1 | |
| let new_value = a:0 == 1 ? a:1 : '' | |
| " Store original value | |
| let s:var_reset[a:var] = getbufvar(buf, a:var) | |
| " Set new var value | |
| call setbufvar(buf, a:var, new_value) | |
| endif | |
| endfunction " }}} | |
| function! s:SetLines(lines, key) " {{{ | |
| try | |
| " Try to join changes with previous undo block | |
| undojoin | |
| catch | |
| endtry | |
| for [line_num, line] in a:lines | |
| call setline(line_num, line[a:key]) | |
| endfor | |
| endfunction " }}} | |
| function! s:GetChar() " {{{ | |
| let char = getchar() | |
| if char == 27 | |
| " Escape key pressed | |
| redraw | |
| call s:Message('Cancelled') | |
| return '' | |
| endif | |
| return nr2char(char) | |
| endfunction " }}} | |
| function! s:GetSearchChar(visualmode) " {{{ | |
| call s:Prompt('Search for character') | |
| let char = s:GetChar() | |
| " Check that we have an input char | |
| if empty(char) | |
| " Restore selection | |
| if ! empty(a:visualmode) | |
| silent exec 'normal! gv' | |
| endif | |
| return '' | |
| endif | |
| return char | |
| endfunction " }}} | |
| " }}} | |
| " Grouping algorithms {{{ | |
| let s:grouping_algorithms = { | |
| \ 1: 'SCTree' | |
| \ , 2: 'Original' | |
| \ } | |
| " Single-key/closest target priority tree {{{ | |
| " This algorithm tries to assign one-key jumps to all the targets closest to the cursor. | |
| " It works recursively and will work correctly with as few keys as two. | |
| function! s:GroupingAlgorithmSCTree(targets, keys) | |
| " Prepare variables for working | |
| let targets_len = len(a:targets) | |
| let keys_len = len(a:keys) | |
| let groups = {} | |
| let keys = reverse(copy(a:keys)) | |
| " Semi-recursively count targets {{{ | |
| " We need to know exactly how many child nodes (targets) this branch will have | |
| " in order to pass the correct amount of targets to the recursive function. | |
| " Prepare sorted target count list {{{ | |
| " This is horrible, I know. But dicts aren't sorted in vim, so we need to | |
| " work around that. That is done by having one sorted list with key counts, | |
| " and a dict which connects the key with the keys_count list. | |
| let keys_count = [] | |
| let keys_count_keys = {} | |
| let i = 0 | |
| for key in keys | |
| call add(keys_count, 0) | |
| let keys_count_keys[key] = i | |
| let i += 1 | |
| endfor | |
| " }}} | |
| let targets_left = targets_len | |
| let level = 0 | |
| let i = 0 | |
| while targets_left > 0 | |
| " Calculate the amount of child nodes based on the current level | |
| let childs_len = (level == 0 ? 1 : (keys_len - 1) ) | |
| for key in keys | |
| " Add child node count to the keys_count array | |
| let keys_count[keys_count_keys[key]] += childs_len | |
| " Subtract the child node count | |
| let targets_left -= childs_len | |
| if targets_left <= 0 | |
| " Subtract the targets left if we added too many too | |
| " many child nodes to the key count | |
| let keys_count[keys_count_keys[key]] += targets_left | |
| break | |
| endif | |
| let i += 1 | |
| endfor | |
| let level += 1 | |
| endwhile | |
| " }}} | |
| " Create group tree {{{ | |
| let i = 0 | |
| let key = 0 | |
| call reverse(keys_count) | |
| for key_count in keys_count | |
| if key_count > 1 | |
| " We need to create a subgroup | |
| " Recurse one level deeper | |
| let groups[a:keys[key]] = s:GroupingAlgorithmSCTree(a:targets[i : i + key_count - 1], a:keys) | |
| elseif key_count == 1 | |
| " Assign single target key | |
| let groups[a:keys[key]] = a:targets[i] | |
| else | |
| " No target | |
| continue | |
| endif | |
| let key += 1 | |
| let i += key_count | |
| endfor | |
| " }}} | |
| " Finally! | |
| return groups | |
| endfunction | |
| " }}} | |
| " Original {{{ | |
| function! s:GroupingAlgorithmOriginal(targets, keys) | |
| " Split targets into groups (1 level) | |
| let targets_len = len(a:targets) | |
| let keys_len = len(a:keys) | |
| let groups = {} | |
| let i = 0 | |
| let root_group = 0 | |
| try | |
| while root_group < targets_len | |
| let groups[a:keys[root_group]] = {} | |
| for key in a:keys | |
| let groups[a:keys[root_group]][key] = a:targets[i] | |
| let i += 1 | |
| endfor | |
| let root_group += 1 | |
| endwhile | |
| catch | endtry | |
| " Flatten the group array | |
| if len(groups) == 1 | |
| let groups = groups[a:keys[0]] | |
| endif | |
| return groups | |
| endfunction | |
| " }}} | |
| " Coord/key dictionary creation {{{ | |
| function! s:CreateCoordKeyDict(groups, ...) | |
| " Dict structure: | |
| " 1,2 : a | |
| " 2,3 : b | |
| let sort_list = [] | |
| let coord_keys = {} | |
| let group_key = a:0 == 1 ? a:1 : '' | |
| for [key, item] in items(a:groups) | |
| let key = ( ! empty(group_key) ? group_key : key) | |
| if type(item) == 3 | |
| " Destination coords | |
| " The key needs to be zero-padded in order to | |
| " sort correctly | |
| let dict_key = printf('%05d,%05d', item[0], item[1]) | |
| let coord_keys[dict_key] = key | |
| " We need a sorting list to loop correctly in | |
| " PromptUser, dicts are unsorted | |
| call add(sort_list, dict_key) | |
| else | |
| " Item is a dict (has children) | |
| let coord_key_dict = s:CreateCoordKeyDict(item, key) | |
| " Make sure to extend both the sort list and the | |
| " coord key dict | |
| call extend(sort_list, coord_key_dict[0]) | |
| call extend(coord_keys, coord_key_dict[1]) | |
| endif | |
| unlet item | |
| endfor | |
| return [sort_list, coord_keys] | |
| endfunction | |
| " }}} | |
| " }}} | |
| "{{{ function! LinesInRange(lines_prev, lines_next) | |
| function! LinesInRange(lines_prev, lines_next) | |
| let all_lines = filter( range(line('w0'), line('w$')), 'foldclosed(v:val) == -1' ) | |
| let current = index(all_lines, line('.')) | |
| let lines_prev = a:lines_prev == -1 ? current : a:lines_prev | |
| let lines_next = a:lines_next == -1 ? len(all_lines) : a:lines_next | |
| let lines_prev_i = max( [0, current - lines_prev] ) | |
| let lines_next_i = min( [len(all_lines), current + lines_next] ) | |
| return all_lines[ lines_prev_i : lines_next_i ] | |
| endfunction | |
| "}}} | |
| "{{{ function! FindTargets(re, line_numbers) | |
| function! FindTargets(re, line_numbers) | |
| let targets = [] | |
| for l in a:line_numbers | |
| let n = 1 | |
| let match_start = match(getline(l), a:re, 0, 1) | |
| while match_start != -1 | |
| call add(targets, [l, match_start + 1]) | |
| let n += 1 | |
| let match_start = match(getline(l), a:re, 0, n) | |
| endwhile | |
| endfor | |
| return targets | |
| endfunction | |
| "}}} | |
| " Core functions {{{ | |
| function! s:PromptUser(groups) "{{{ | |
| " If only one possible match, jump directly to it {{{ | |
| let group_values = values(a:groups) | |
| if len(group_values) == 1 | |
| redraw | |
| return group_values[0] | |
| endif | |
| " }}} | |
| " Prepare marker lines {{{ | |
| let lines = {} | |
| let hl_coords = [] | |
| let coord_key_dict = s:CreateCoordKeyDict(a:groups) | |
| for dict_key in sort(coord_key_dict[0]) | |
| let target_key = coord_key_dict[1][dict_key] | |
| let [line_num, col_num] = split(dict_key, ',') | |
| let line_num = str2nr(line_num) | |
| let col_num = str2nr(col_num) | |
| " Add original line and marker line | |
| if ! has_key(lines, line_num) | |
| let current_line = getline(line_num) | |
| let lines[line_num] = { 'orig': current_line, 'marker': current_line, 'mb_compensation': 0 } | |
| endif | |
| " Compensate for byte difference between marker | |
| " character and target character | |
| " | |
| " This has to be done in order to match the correct | |
| " column; \%c matches the byte column and not display | |
| " column. | |
| let target_char_len = strlen(matchstr(lines[line_num]['marker'], '\%' . col_num . 'c.')) | |
| let target_key_len = strlen(target_key) | |
| " Solve multibyte issues by matching the byte column | |
| " number instead of the visual column | |
| let col_num -= lines[line_num]['mb_compensation'] | |
| if strlen(lines[line_num]['marker']) > 0 | |
| " Substitute marker character if line length > 0 | |
| let lines[line_num]['marker'] = substitute(lines[line_num]['marker'], '\%' . col_num . 'c.', target_key, '') | |
| else | |
| " Set the line to the marker character if the line is empty | |
| let lines[line_num]['marker'] = target_key | |
| endif | |
| " Add highlighting coordinates | |
| call add(hl_coords, '\%' . line_num . 'l\%' . col_num . 'c') | |
| " Add marker/target lenght difference for multibyte | |
| " compensation | |
| let lines[line_num]['mb_compensation'] += (target_char_len - target_key_len) | |
| endfor | |
| let lines_items = items(lines) | |
| " }}} | |
| " Highlight targets {{{ | |
| let target_hl_id = matchadd(g:EasyMotion_hl_group_target, join(hl_coords, '\|'), 1) | |
| " }}} | |
| try | |
| " Set lines with markers | |
| call s:SetLines(lines_items, 'marker') | |
| redraw | |
| " Get target character {{{ | |
| call s:Prompt('Target key') | |
| let char = s:GetChar() | |
| " }}} | |
| finally | |
| " Restore original lines | |
| call s:SetLines(lines_items, 'orig') | |
| " Un-highlight targets {{{ | |
| if exists('target_hl_id') | |
| call matchdelete(target_hl_id) | |
| endif | |
| " }}} | |
| redraw | |
| endtry | |
| " Check if we have an input char {{{ | |
| if empty(char) | |
| throw 'Cancelled' | |
| endif | |
| " }}} | |
| " Check if the input char is valid {{{ | |
| if ! has_key(a:groups, char) | |
| throw 'Invalid target' | |
| endif | |
| " }}} | |
| let target = a:groups[char] | |
| if type(target) == 3 | |
| " Return target coordinates | |
| return target | |
| else | |
| " Prompt for new target character | |
| return s:PromptUser(target) | |
| endif | |
| endfunction "}}} | |
| function! s:EasyMotion(regexp, direction, visualmode, mode) " {{{ | |
| let orig_pos = [line('.'), col('.')] | |
| let targets = [] | |
| try | |
| " Reset properties {{{ | |
| call s:VarReset('&scrolloff', 0) | |
| call s:VarReset('&modified', 0) | |
| call s:VarReset('&modifiable', 1) | |
| call s:VarReset('&readonly', 0) | |
| call s:VarReset('&spell', 0) | |
| call s:VarReset('&virtualedit', '') | |
| " }}} | |
| " Find motion targets {{{ | |
| " let search_direction = (a:direction == 1 ? 'b' : '') | |
| " let search_stopline = line(a:direction == 1 ? 'w0' : 'w$') | |
| " while 1 | |
| " let pos = searchpos(a:regexp, search_direction, search_stopline) | |
| " " Reached end of search range | |
| " if pos == [0, 0] | |
| " break | |
| " endif | |
| " " Skip folded lines | |
| " if foldclosed(pos[0]) != -1 | |
| " continue | |
| " endif | |
| " call add(targets, pos) | |
| " endwhile | |
| let lnums = LinesInRange(-1, -1) | |
| let targets = FindTargets(a:regexp, lnums) | |
| let targets_len = len(targets) | |
| if targets_len == 0 | |
| throw 'No matches' | |
| endif | |
| " }}} | |
| let GroupingFn = function('s:GroupingAlgorithm' . s:grouping_algorithms[g:EasyMotion_grouping]) | |
| let groups = GroupingFn(targets, split(g:EasyMotion_keys, '\zs')) | |
| " Shade inactive source {{{ | |
| if g:EasyMotion_do_shade | |
| let shade_hl_pos = '\%' . orig_pos[0] . 'l\%'. orig_pos[1] .'c' | |
| if a:direction == 1 | |
| " Backward | |
| let shade_hl_re = '\%'. line('w0') .'l\_.*' . shade_hl_pos | |
| else | |
| " Forward | |
| let shade_hl_re = shade_hl_pos . '\_.*\%'. line('w$') .'l' | |
| endif | |
| let shade_hl_id = matchadd(g:EasyMotion_hl_group_shade, shade_hl_re, 0) | |
| endif | |
| " }}} | |
| " Prompt user for target group/character | |
| let coords = s:PromptUser(groups) | |
| " Update selection {{{ | |
| if ! empty(a:visualmode) | |
| keepjumps call cursor(orig_pos[0], orig_pos[1]) | |
| exec 'normal! ' . a:visualmode | |
| endif | |
| " }}} | |
| " Handle operator-pending mode {{{ | |
| if a:mode == 'no' | |
| " This mode requires that we eat one more | |
| " character to the right if we're using | |
| " a forward motion | |
| if a:direction != 1 | |
| let coords[1] += 1 | |
| endif | |
| endif | |
| " }}} | |
| " Update cursor position | |
| call cursor(orig_pos[0], orig_pos[1]) | |
| mark ' | |
| call cursor(coords[0], coords[1]) | |
| call s:Message('Jumping to [' . coords[0] . ', ' . coords[1] . ']') | |
| catch | |
| redraw | |
| " Show exception message | |
| call s:Message(v:exception) | |
| " Restore original cursor position/selection {{{ | |
| if ! empty(a:visualmode) | |
| silent exec 'normal! gv' | |
| else | |
| keepjumps call cursor(orig_pos[0], orig_pos[1]) | |
| endif | |
| " }}} | |
| finally | |
| " Restore properties {{{ | |
| call s:VarReset('&scrolloff') | |
| call s:VarReset('&modified') | |
| call s:VarReset('&modifiable') | |
| call s:VarReset('&readonly') | |
| call s:VarReset('&spell') | |
| call s:VarReset('&virtualedit') | |
| " }}} | |
| " Remove shading {{{ | |
| if g:EasyMotion_do_shade && exists('shade_hl_id') | |
| call matchdelete(shade_hl_id) | |
| endif | |
| " }}} | |
| endtry | |
| endfunction " }}} | |
| " }}} | |
| " vim: fdm=marker:noet:ts=4:sw=4:sts=4 | |
| "----------------------------------------------------------------------- | |
| " EasyMotion - Vim motions on speed! | |
| " | |
| " Author: Kim Silkebækken <[email protected]> | |
| " Source repository: https://github.com/Lokaltog/vim-easymotion | |
| " Script initialization {{{ | |
| if exists('g:EasyMotion_loaded') || &compatible || version < 702 | |
| finish | |
| endif | |
| let g:EasyMotion_loaded = 1 | |
| " }}} | |
| " Default configuration {{{ | |
| " Default options {{{ | |
| call EasyMotion_InitOptions({ | |
| \ 'leader_key' : '<Leader><Leader>' | |
| \ , 'keys' : 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' | |
| \ , 'do_shade' : 1 | |
| \ , 'do_mapping' : 1 | |
| \ , 'grouping' : 1 | |
| \ | |
| \ , 'hl_group_target' : 'EasyMotionTarget' | |
| \ , 'hl_group_shade' : 'EasyMotionShade' | |
| \ }) | |
| " }}} | |
| " Default highlighting {{{ | |
| let s:target_hl_defaults = { | |
| \ 'gui' : ['NONE', '_ff0000' , 'bold'] | |
| \ , 'cterm256': ['NONE', '196' , 'bold'] | |
| \ , 'cterm' : ['NONE', 'red' , 'bold'] | |
| \ } | |
| let s:shade_hl_defaults = { | |
| \ 'gui' : ['NONE', '_777777' , 'NONE'] | |
| \ , 'cterm256': ['NONE', '242' , 'NONE'] | |
| \ , 'cterm' : ['NONE', 'grey' , 'NONE'] | |
| \ } | |
| call EasyMotion_InitHL(g:EasyMotion_hl_group_target, s:target_hl_defaults) | |
| call EasyMotion_InitHL(g:EasyMotion_hl_group_shade, s:shade_hl_defaults) | |
| " Reset highlighting after loading a new color scheme {{{ | |
| augroup EasyMotionInitHL | |
| autocmd! | |
| autocmd ColorScheme * call EasyMotion_InitHL(g:EasyMotion_hl_group_target, s:target_hl_defaults) | |
| autocmd ColorScheme * call EasyMotion_InitHL(g:EasyMotion_hl_group_shade, s:shade_hl_defaults) | |
| augroup end | |
| " }}} | |
| " }}} | |
| " Default key mapping {{{ | |
| call EasyMotion_InitMappings({ | |
| \ 'f' : { 'name': 'F' , 'dir': 0 } | |
| \ , 'F' : { 'name': 'F' , 'dir': 1 } | |
| \ , 't' : { 'name': 'T' , 'dir': 0 } | |
| \ , 'T' : { 'name': 'T' , 'dir': 1 } | |
| \ , 'w' : { 'name': 'WB' , 'dir': 0 } | |
| \ , 'W' : { 'name': 'WBW', 'dir': 0 } | |
| \ , 'b' : { 'name': 'WB' , 'dir': 1 } | |
| \ , 'B' : { 'name': 'WBW', 'dir': 1 } | |
| \ , 'e' : { 'name': 'E' , 'dir': 0 } | |
| \ , 'E' : { 'name': 'EW' , 'dir': 0 } | |
| \ , 'ge': { 'name': 'E' , 'dir': 1 } | |
| \ , 'gE': { 'name': 'EW' , 'dir': 1 } | |
| \ , 'j' : { 'name': 'JK' , 'dir': 0 } | |
| \ , 'k' : { 'name': 'JK' , 'dir': 1 } | |
| \ , 'n' : { 'name': 'Search' , 'dir': 0 } | |
| \ , 'N' : { 'name': 'Search' , 'dir': 1 } | |
| \ }) | |
| " }}} | |
| " }}} | |
| " vim: fdm=marker:noet:ts=4:sw=4:sts=4 | |
| "map <C-j> :call EasyMotion_JK('', 0)<CR> | |
| map <C-j> :call EasyMotion_F('', 0)<CR> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment