mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 01:10:05 +08:00
439 lines
11 KiB
VimL
439 lines
11 KiB
VimL
"=============================================================================
|
|
" mapping.vim --- mapping functions in SpaceVim
|
|
" Copyright (c) 2016-2022 Wang Shidong & Contributors
|
|
" Author: Wang Shidong < wsdjeg@outlook.com >
|
|
" URL: https://spacevim.org
|
|
" License: GPLv3
|
|
"=============================================================================
|
|
|
|
scriptencoding utf-8
|
|
|
|
let s:BUFFER = SpaceVim#api#import('vim#buffer')
|
|
let s:WIN = SpaceVim#api#import('vim#window')
|
|
let s:VIM = SpaceVim#api#import('vim')
|
|
|
|
|
|
let g:unite_source_menu_menus =
|
|
\ get(g:,'unite_source_menu_menus',{})
|
|
let g:unite_source_menu_menus.CustomKeyMaps = {'description':
|
|
\ 'Custom mapped keyboard shortcuts [unite]<SPACE>'}
|
|
let g:unite_source_menu_menus.CustomKeyMaps.command_candidates =
|
|
\ get(g:unite_source_menu_menus.CustomKeyMaps,'command_candidates', [])
|
|
|
|
function! SpaceVim#mapping#_def(type,key,value,desc,...) abort
|
|
exec a:type . ' ' . a:key . ' ' . a:value
|
|
let description = '➤ '
|
|
\. a:desc
|
|
\. repeat(' ', 80 - len(a:desc) - len(a:key))
|
|
\. a:key
|
|
let cmd = len(a:000) > 0 ? a:000[0] : a:value
|
|
call add(g:unite_source_menu_menus.CustomKeyMaps.command_candidates, [description,cmd])
|
|
endfunction
|
|
|
|
" a:1 unite desc
|
|
" a:2 unite cmd
|
|
" a:3 guide desc
|
|
" example call SpaceVim#mapping#def('nnoremap <silent>', 'gf', ':call SpaceVim#mapping#gf()<CR>', 'Jump to a file under cursor', '')
|
|
function! SpaceVim#mapping#def(type, key, value, ...) abort
|
|
let feedkeys_mode = 'm'
|
|
let map = split(a:type)[0]
|
|
if map =~# 'nore'
|
|
let feedkeys_mode = 'n'
|
|
endif
|
|
" TODO parse lhs and rhs, return list of key
|
|
"let lhs = a:key
|
|
"let rhs = a:value
|
|
let gexe = a:value
|
|
if a:value =~? '^<plug>'
|
|
let gexe = '\' . a:value
|
|
elseif a:value =~? ':.\+<cr>$'
|
|
let gexe = substitute(gexe, '<cr>', "\<cr>", 'g')
|
|
let gexe = substitute(gexe, '<CR>', "\<CR>", 'g')
|
|
let gexe = substitute(gexe, '<Esc>', "\<Esc>", 'g')
|
|
else
|
|
endif
|
|
if get(g:, 'spacevim_enable_key_frequency', 0)
|
|
exec a:type . ' <expr> ' . a:key . " SpaceVim#mapping#frequency#update('" . a:key . "', '" . a:value . "')"
|
|
else
|
|
exec a:type . ' ' . a:key . ' ' . a:value
|
|
endif
|
|
if a:0 > 0
|
|
let desc = a:1
|
|
let description = '➤ '
|
|
\ . desc
|
|
\ . repeat(' ', 80 - len(desc) - len(a:key))
|
|
\ . a:key
|
|
let cmd = a:0 == 2 ? a:2 : a:value
|
|
call add(g:unite_source_menu_menus.CustomKeyMaps.command_candidates, [description,cmd])
|
|
if a:0 == 3
|
|
" enable guide
|
|
if a:key =~? '^<leader>'
|
|
if len(a:key) > 9
|
|
let group = a:key[8:8]
|
|
if !has_key(g:_spacevim_mappings, group)
|
|
let g:_spacevim_mappings[group] = {'name': 'new group'}
|
|
endif
|
|
call extend(g:_spacevim_mappings[group], {
|
|
\ a:key[9:] : ['call feedkeys("' . gexe . '", "'
|
|
\ . feedkeys_mode . '")', a:3]
|
|
\ })
|
|
elseif len(a:key) == 9
|
|
call extend(g:_spacevim_mappings, {
|
|
\ a:key[8:] : ['call feedkeys("' . gexe . '", "'
|
|
\ . feedkeys_mode . '")', a:3]
|
|
\ })
|
|
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
if get(g:, 'spacevim_snippet_engine', 'neosnippet') ==# 'neosnippet'
|
|
function! SpaceVim#mapping#shift_tab() abort
|
|
return pumvisible() ? "\<C-p>" : "\<Plug>delimitMateS-Tab"
|
|
endfunction
|
|
elseif get(g:, 'spacevim_snippet_engine', 'neosnippet') ==# 'ultisnips'
|
|
function! SpaceVim#mapping#shift_tab() abort
|
|
return pumvisible() ? "\<C-p>" : "\<C-R>=UltiSnips#JumpForwards()\<CR>\<C-R>=cmp#ultisnips#JumpForward()\<CR>"
|
|
endfunction
|
|
endif
|
|
|
|
function! SpaceVim#mapping#tab() abort
|
|
return SpaceVim#mapping#tab#i_tab()
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#enter() abort
|
|
return SpaceVim#mapping#enter#i_enter()
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#g_capital_d() abort
|
|
if !empty(SpaceVim#mapping#g_capital_d#get())
|
|
call call(SpaceVim#mapping#g_capital_d#get(), [])
|
|
else
|
|
normal! gD
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#gd() abort
|
|
if !empty(SpaceVim#mapping#gd#get())
|
|
call call(SpaceVim#mapping#gd#get(), [])
|
|
else
|
|
normal! gd
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#clear_buffers() abort
|
|
if confirm('Kill all other buffers?', "&Yes\n&No\n&Cancel") == 1
|
|
let blisted = filter(range(1, bufnr('$')), 'buflisted(v:val)')
|
|
for i in blisted
|
|
if i != bufnr('%')
|
|
try
|
|
exe 'bw ' . i
|
|
catch
|
|
endtry
|
|
endif
|
|
endfor
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#kill_buffer_expr() abort
|
|
let regexp = input('kill buffer by regexp:',
|
|
\ '')
|
|
if !empty(regexp)
|
|
let blisted = filter(range(1, bufnr('$')), 'bufname(v:val) =~ regexp')
|
|
for i in blisted
|
|
if i != bufnr('%')
|
|
try
|
|
exe 'bw ' . i
|
|
catch
|
|
endtry
|
|
endif
|
|
endfor
|
|
noautocmd normal! :
|
|
echo printf('killed buffers done(%s)', regexp)
|
|
else
|
|
noautocmd normal! :
|
|
echo 'canceled!'
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#split_previous_buffer() abort
|
|
if bufnr('#') == -1
|
|
call SpaceVim#util#echoWarn('There is no previous buffer')
|
|
else
|
|
split
|
|
wincmd w
|
|
e#
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#vertical_split_previous_buffer(...) abort
|
|
if bufnr('#') == -1
|
|
call SpaceVim#util#echoWarn('There is no previous buffer')
|
|
else
|
|
vsplit
|
|
wincmd w
|
|
e#
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#close_current_buffer(...) abort
|
|
if index(
|
|
\ ['startify', 'defx'],
|
|
\ &filetype) !=# -1
|
|
return
|
|
endif
|
|
let buffers = get(g:, '_spacevim_list_buffers', [])
|
|
let bn = bufnr('%')
|
|
let f = ''
|
|
if getbufvar(bn, '&modified', 0)
|
|
redraw
|
|
echohl WarningMsg
|
|
if len(a:000) > 0
|
|
let rs = get(a:000, 0)
|
|
else
|
|
echon 'save changes to "' . bufname(bn) . '"? Yes/No/Cancel'
|
|
let rs = s:VIM.getchar()
|
|
endif
|
|
echohl None
|
|
if rs ==? 'y'
|
|
write
|
|
elseif rs ==? 'n'
|
|
let f = '!'
|
|
redraw
|
|
echohl ModeMsg
|
|
echon 'discarded!'
|
|
echohl None
|
|
else
|
|
redraw
|
|
echohl ModeMsg
|
|
echon 'canceled!'
|
|
echohl None
|
|
return
|
|
endif
|
|
endif
|
|
|
|
if &buftype ==# 'terminal'
|
|
exe 'bd!'
|
|
return
|
|
endif
|
|
|
|
let cmd_close_buf = 'bd' . f
|
|
let index = index(buffers, bn)
|
|
if index == 0
|
|
if len(buffers) > 1
|
|
exe 'b' . buffers[1]
|
|
exe cmd_close_buf . bn
|
|
else
|
|
exe cmd_close_buf . bn
|
|
if exists(':Startify') ==# 2
|
|
Startify
|
|
endif
|
|
endif
|
|
elseif index > 0
|
|
if index + 1 == len(buffers)
|
|
exe 'b' . buffers[index - 1]
|
|
exe cmd_close_buf . bn
|
|
else
|
|
exe 'b' . buffers[index + 1]
|
|
exe cmd_close_buf . bn
|
|
endif
|
|
else
|
|
if len(buffers) > 1
|
|
exe 'bp'
|
|
exe cmd_close_buf . bn
|
|
elseif len(buffers) ==# 1
|
|
if exists(':Startify') ==# 2
|
|
Startify
|
|
endif
|
|
try
|
|
exe cmd_close_buf . bn
|
|
catch
|
|
endtry
|
|
else
|
|
exe cmd_close_buf . bn
|
|
if exists(':Startify') ==# 2
|
|
Startify
|
|
endif
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#close_term_buffer(...) abort
|
|
let buffers = get(g:, '_spacevim_list_buffers', [])
|
|
let abuf = str2nr(g:_spacevim_termclose_abuf)
|
|
let index = index(buffers, abuf)
|
|
if get(w:, 'shell_layer_win', 0) == 1
|
|
if bufexists(abuf)
|
|
exe 'bd!' . abuf
|
|
endif
|
|
" can not close the terminal windows
|
|
" close again
|
|
if get(w:, 'shell_layer_win', 0) == 1
|
|
close
|
|
endif
|
|
return
|
|
endif
|
|
if index != -1
|
|
if index == 0
|
|
if len(buffers) > 1
|
|
exe 'b' . buffers[1]
|
|
exe 'bd!' . abuf
|
|
else
|
|
exe 'bd! ' . abuf
|
|
endif
|
|
elseif index > 0
|
|
if index + 1 == len(buffers)
|
|
exe 'b' . buffers[index - 1]
|
|
exe 'bd!' . abuf
|
|
else
|
|
exe 'b' . buffers[index + 1]
|
|
exe 'bd!' . abuf
|
|
endif
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#kill_visible_buffer_choosewin() abort
|
|
ChooseWin
|
|
let nr = bufnr('%')
|
|
for i in range(1, winnr('$'))
|
|
if winbufnr(i) == nr
|
|
exe i . 'wincmd w'
|
|
enew
|
|
endif
|
|
endfor
|
|
exe 'bwipeout ' . nr
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#menu(desc, key, cmd) abort
|
|
let description = '➤ '
|
|
\. a:desc
|
|
\. repeat(' ', 80 - len(a:desc) - len(a:key))
|
|
\. a:key
|
|
call add(g:unite_source_menu_menus.CustomKeyMaps.command_candidates,
|
|
\ [description ,
|
|
\ a:cmd])
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#clear_saved_buffers() abort
|
|
call s:BUFFER.filter_do(
|
|
\ {
|
|
\ 'expr' : [
|
|
\ 'buflisted(v:val)',
|
|
\ 'index(tabpagebuflist(), v:val) == -1',
|
|
\ 'getbufvar(v:val, "&mod") == 0',
|
|
\ ],
|
|
\ 'do' : 'noautocmd bd %d'
|
|
\ }
|
|
\ )
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#format() abort
|
|
let save_cursor = getpos('.')
|
|
normal! gg=G
|
|
call setpos('.', save_cursor)
|
|
endfunction
|
|
|
|
function! SpaceVim#mapping#BufferEmpty() abort
|
|
let l:current = bufnr('%')
|
|
if ! getbufvar(l:current, '&modified')
|
|
enew
|
|
silent! execute 'bdelete '.l:current
|
|
endif
|
|
endfunction
|
|
|
|
fu! SpaceVim#mapping#SmartClose() abort
|
|
let ignorewin = get(g:,'spacevim_smartcloseignorewin',[])
|
|
let ignoreft = get(g:, 'spacevim_smartcloseignoreft',[])
|
|
let num = winnr('$')
|
|
for i in range(1,num)
|
|
if index(ignorewin , bufname(winbufnr(i))) != -1 || index(ignoreft, getbufvar(bufname(winbufnr(i)),'&filetype')) != -1
|
|
let num = num - 1
|
|
elseif getbufvar(winbufnr(i),'&buftype') ==# 'quickfix'
|
|
let num = num - 1
|
|
elseif getwinvar(i, '&previewwindow') == 1 && winnr() !=# i
|
|
let num = num - 1
|
|
elseif exists('*win_getid') && s:WIN.is_float(win_getid(i))
|
|
" in vim winnr('$') do not include popup.
|
|
let num = num - 1
|
|
endif
|
|
endfor
|
|
if num == 1
|
|
else
|
|
quit
|
|
endif
|
|
endf
|
|
|
|
function! SpaceVim#mapping#gf() abort
|
|
if &filetype isnot# 'vim'
|
|
return 0
|
|
endif
|
|
let isk = &l:iskeyword
|
|
setlocal iskeyword+=:,<,>,#
|
|
try
|
|
let line = getline('.')
|
|
let start = s:find_start(line, col('.'))
|
|
if line[start :] =~? '\%(s:\|<SNR>\|<SID>\)'
|
|
let line = substitute(line, '<\%(SNR\|SID\)>', 's:', '')
|
|
let path = expand('%')
|
|
else
|
|
for base_dir in [getcwd()] + split(finddir('autoload', expand('%:p:h') . ';')) + [&runtimepath]
|
|
let path = s:autoload_path(base_dir, line[start : ])
|
|
if !empty(path)
|
|
break
|
|
endif
|
|
endfor
|
|
endif
|
|
if !empty(path)
|
|
let line = s:search_line(path, matchstr(line[start :], '\k\+'))
|
|
let col = start
|
|
exe 'e ' . path
|
|
call cursor(line, col)
|
|
endif
|
|
finally
|
|
let &l:iskeyword = isk
|
|
endtry
|
|
endfunction
|
|
|
|
|
|
if has('patch-7.4.279')
|
|
function! s:globpath(path, expr) abort "{{{
|
|
return globpath(a:path, a:expr, 1, 1)
|
|
endfunction "}}}
|
|
else
|
|
function! s:globpath(path, expr) abort "{{{
|
|
return split(globpath(a:path, a:expr), '\n')
|
|
endfunction "}}}
|
|
endif
|
|
|
|
|
|
function! s:autoload_path(base_dir, function_name) abort "{{{
|
|
let match = matchstr(a:function_name, '\k\+\ze#')
|
|
let fname = expand('autoload/' . substitute(match, '#', '/', 'g') . '.vim')
|
|
let paths = s:globpath(a:base_dir, fname)
|
|
return len(paths) > 0 ? paths[0] : ''
|
|
endfunction "}}}
|
|
|
|
|
|
function! s:find_start(line, cursor_index) abort "{{{
|
|
for i in range(a:cursor_index, 0, -1)
|
|
if a:line[i] !~# '\k'
|
|
return i+1
|
|
endif
|
|
endfor
|
|
return 0
|
|
endfunction "}}}
|
|
|
|
|
|
function! s:search_line(path, term) abort "{{{
|
|
let line = match(readfile(a:path), '\s*fu\%[nction]!\?\s*' . a:term . '\>')
|
|
if line >= 0
|
|
return line+1
|
|
endif
|
|
return 0
|
|
endfunction "}}}
|
|
|
|
" vim:set et sw=2 cc=80:
|