spacevim/autoload/SpaceVim/plugins/tabmanager.vim
JIe 2bb7059579
Some checks failed
Detach Plugins / check (FlyGrep.vim) (push) Has been cancelled
Detach Plugins / check (GitHub.vim) (push) Has been cancelled
Detach Plugins / check (JavaUnit.vim) (push) Has been cancelled
Detach Plugins / check (SourceCounter.vim) (push) Has been cancelled
Detach Plugins / check (cpicker.nvim) (push) Has been cancelled
Detach Plugins / check (dein-ui.vim) (push) Has been cancelled
Detach Plugins / check (git.vim) (push) Has been cancelled
Detach Plugins / check (iedit.vim) (push) Has been cancelled
Detach Plugins / check (scrollbar.vim) (push) Has been cancelled
Detach Plugins / check (vim-chat) (push) Has been cancelled
Detach Plugins / check (vim-cheat) (push) Has been cancelled
Detach Plugins / check (vim-todo) (push) Has been cancelled
Detach Plugins / check (xmake.vim) (push) Has been cancelled
test / Linux (nvim, nightly) (push) Has been cancelled
test / Linux (nvim, v0.3.8) (push) Has been cancelled
test / Linux (nvim, v0.4.0) (push) Has been cancelled
test / Linux (nvim, v0.4.2) (push) Has been cancelled
test / Linux (nvim, v0.4.3) (push) Has been cancelled
test / Linux (nvim, v0.4.4) (push) Has been cancelled
test / Linux (nvim, v0.5.0) (push) Has been cancelled
test / Linux (nvim, v0.5.1) (push) Has been cancelled
test / Linux (nvim, v0.6.0) (push) Has been cancelled
test / Linux (nvim, v0.6.1) (push) Has been cancelled
test / Linux (nvim, v0.7.0) (push) Has been cancelled
test / Linux (nvim, v0.7.2) (push) Has been cancelled
test / Linux (nvim, v0.8.0) (push) Has been cancelled
test / Linux (nvim, v0.8.1) (push) Has been cancelled
test / Linux (nvim, v0.8.2) (push) Has been cancelled
test / Linux (nvim, v0.8.3) (push) Has been cancelled
test / Linux (nvim, v0.9.0) (push) Has been cancelled
test / Linux (nvim, v0.9.1) (push) Has been cancelled
test / Linux (true, vim, v7.4.052) (push) Has been cancelled
test / Linux (true, vim, v7.4.1689) (push) Has been cancelled
test / Linux (true, vim, v7.4.629) (push) Has been cancelled
test / Linux (true, vim, v8.0.0027) (push) Has been cancelled
test / Linux (true, vim, v8.0.0183) (push) Has been cancelled
test / Linux (vim, nightly) (push) Has been cancelled
test / Linux (vim, v8.0.0184) (push) Has been cancelled
test / Linux (vim, v8.0.1453) (push) Has been cancelled
test / Linux (vim, v8.1.2269) (push) Has been cancelled
test / Linux (vim, v8.2.2434) (push) Has been cancelled
test / Linux (vim, v8.2.3995) (push) Has been cancelled
test / Windows (nvim, nightly) (push) Has been cancelled
test / Windows (nvim, v0.3.8) (push) Has been cancelled
test / Windows (nvim, v0.4.2) (push) Has been cancelled
test / Windows (nvim, v0.4.3) (push) Has been cancelled
test / Windows (nvim, v0.4.4) (push) Has been cancelled
test / Windows (nvim, v0.5.0) (push) Has been cancelled
test / Windows (nvim, v0.5.1) (push) Has been cancelled
test / Windows (nvim, v0.6.0) (push) Has been cancelled
test / Windows (nvim, v0.6.1) (push) Has been cancelled
test / Windows (nvim, v0.7.0) (push) Has been cancelled
test / Windows (nvim, v0.7.2) (push) Has been cancelled
test / Windows (nvim, v0.8.0) (push) Has been cancelled
test / Windows (nvim, v0.8.1) (push) Has been cancelled
test / Windows (nvim, v0.8.2) (push) Has been cancelled
test / Windows (nvim, v0.8.3) (push) Has been cancelled
test / Windows (nvim, v0.9.0) (push) Has been cancelled
test / Windows (nvim, v0.9.1) (push) Has been cancelled
test / Windows (vim, nightly) (push) Has been cancelled
test / Windows (vim, v7.4.1185) (push) Has been cancelled
test / Windows (vim, v7.4.1689) (push) Has been cancelled
test / Windows (vim, v8.0.0027) (push) Has been cancelled
test / Windows (vim, v8.0.1453) (push) Has been cancelled
test / Windows (vim, v8.1.2269) (push) Has been cancelled
test / Windows (vim, v8.2.2434) (push) Has been cancelled
test / Windows (vim, v8.2.3995) (push) Has been cancelled
docker / docker (push) Has been cancelled
mirror / check (coding) (push) Has been cancelled
mirror / check (gitee) (push) Has been cancelled
mirror / check (gitlab) (push) Has been cancelled
init
2024-08-21 14:17:26 +08:00

369 lines
10 KiB
VimL

"=============================================================================
" tabmanager.vim --- tab manager for SpaceVim
" Copyright (c) 2016-2023 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
scriptencoding utf-8
""
" @section tab manager, plugins-tabmanager
" @parentsection plugins
" The `tabmanager` plugin provides tab manager support for SpaceVim.
"
" @subsection Key bindings
" >
" Key binding Description
" SPC t t open tab manager windows
" <
"
" In the tab manager windows, the following key bindings can be used:
" >
" Key binding Description
" ---------------------------
" q close tab manager
" o toggle tab
" r rename tabpage
" n create new named tabpage
" N create new unamed tabpage
" x delete tabpage
" yy copy tabpage
" p paste tabpage
" Ctrl-Shift-Up move tabpage backward
" Ctrl-Shift-Down move tabpage forward
" <
" APIs
let s:BUFFER = SpaceVim#api#import('vim#buffer')
let s:TABs = SpaceVim#api#import('vim#tab')
let s:bufferid = -1
let s:bufname = '__TabManager__'
" init val
let s:open_tabs = []
" Interface
function! SpaceVim#plugins#tabmanager#open() abort
if bufexists(s:bufferid)
if index(tabpagebuflist(), s:bufferid) == -1
let s:bufferid = s:BUFFER.open(
\ {
\ 'bufname' : s:bufname,
\ 'initfunc' : function('s:init_buffer'),
\ }
\ )
call s:BUFFER.resize(30)
call s:update_context()
else
let winnr = bufwinnr(bufname(s:bufferid))
exe winnr . 'wincmd w'
endif
else
let s:bufferid = s:BUFFER.open(
\ {
\ 'bufname' : s:bufname,
\ 'initfunc' : function('s:init_buffer'),
\ }
\ )
stopinsert
call s:BUFFER.resize(30)
call s:update_context()
endif
endfunction
" local functions
function! s:init_buffer() abort
setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nomodifiable nospell number norelativenumber winfixwidth
setf SpaceVimTabsManager
nnoremap <silent> <buffer> q :bd<CR>
nnoremap <silent> <buffer> <CR> <esc>:<c-u>cal <SID>jump()<CR>
nnoremap <silent> <buffer> o :call <SID>toggle()<CR>
nnoremap <silent> <buffer> r :call <SID>rename_tab()<CR>
nnoremap <silent> <buffer> n :call <SID>create_new_named_tab()<CR>
nnoremap <silent> <buffer> N :call <SID>create_new_unnamed_tab()<CR>
nnoremap <silent> <buffer> x :call <SID>delete_tab()<CR>
nnoremap <silent> <buffer> yy :call <SID>copy_tab()<CR>
nnoremap <silent> <buffer> p :call <SID>paste_tab()<CR>
nnoremap <silent> <buffer> <C-S-Up> :call <SID>move_tab_backward()<CR>
nnoremap <silent> <buffer> <C-S-Down> :call <SID>move_tab_forward()<CR>
augroup spacevim_plugin_tabman_init
autocmd!
autocmd BufEnter <buffer> call s:update_context()
augroup END
endfunction
function! s:workspace_directory(tabnr) abort
if exists(':tcd')
return getcwd(-1, str2nr(a:tabnr))
elseif exists('*win_getid')
return getcwd(win_getid(tabpagewinnr(a:tabnr)))
elseif exists(':lcd')
let bufnr = tabpagebuflist(a:tabnr)[tabpagewinnr(a:tabnr) - 1]
return getbufvar('%', 'rootDir', '')
endif
endfunction
function! s:update_context() abort
setl modifiable
silent! normal! gg"_dG
let tree = s:TABs.get_tree()
let ctx = []
for page in sort(keys(tree), s:Nsort)
if gettabvar(page, 'spacevim_tabman_expandable', 1) == -1
call add(ctx,
\ '▼ ' . (page == tabpagenr() ? '*' : ' ')
\ . 'Tab ' . page
\ . ' ' . gettabvar(page, '_spacevim_tab_name', fnamemodify(s:workspace_directory(page), ':t'))
\ )
let winid = 1
for _buf in tree[page]
if getbufvar(_buf, '&buflisted')
call add(ctx, ' ' . winid . ' ' . fnamemodify(empty(bufname(_buf))? 'No Name' : bufname(_buf), ':t'))
elseif getbufvar(_buf, '&buftype') ==# 'terminal'
call add(ctx, ' ' . winid . ' Terminal')
endif
let winid += 1
endfor
else
call add(ctx,
\ '▷ ' . (page == tabpagenr() ? '*' : ' ')
\ . 'Tab ' . page
\ . ' ' . gettabvar(page, '_spacevim_tab_name', fnamemodify(s:workspace_directory(page), ':t'))
\ )
endif
endfor
silent! call setline(1, ctx)
setl nomodifiable
endfunction
function! s:jump() abort
if v:prevcount
exe 'keepj' v:prevcount
en
let t = s:get_cursor_tabnr()
let w = s:winid()
noautocmd quit
if t == tabpagenr()
call s:TABs._jump(t, w - 1)
else
call s:TABs._jump(t, w)
endif
doautocmd WinEnter
endfunction
function! s:tabid() abort
let line = line('.')
if getline('.') =~# '^[▷▼] [ *]Tab '
let tabid = matchstr(getline(line), '\d\+')
else
let line = search('^[▷▼] [ *]Tab ','bWnc')
let tabid = matchstr(getline(line), '\d\+')
endif
return tabid
endfunction
function! s:winid() abort
let id = str2nr(split(getline('.'), ':')[0])
return id
endfunction
function! s:toggle() abort
let tabid = s:get_cursor_tabnr()
call settabvar(tabid, 'spacevim_tabman_expandable',
\ gettabvar(tabid, 'spacevim_tabman_expandable', 1) * -1)
call s:update_context()
let line = search('^[▷▼] [ *]Tab ' . tabid,'wnc')
exe line
endfunction
function! s:rename_tab() abort
let tabid = s:get_cursor_tabnr()
let line = search('^[▷▼] [ *]Tab ' . (tabid),'wc')
let tabname = input('Tab name:', '')
if !empty(tabname)
call settabvar(tabid, '_spacevim_tab_name', tabname)
set tabline=%!SpaceVim#layers#core#tabline#get()
endif
call s:update_context()
exe line
endfunction
function! s:create_new_named_tab() abort
let tabid = s:get_cursor_tabnr()
let current_tab = tabpagenr()
let tabname = input('Tab name:', '')
if !empty(tabname)
exe tabid . 'tabnew'
let t:_spacevim_tab_name = tabname
set tabline=%!SpaceVim#layers#core#tabline#get()
else
exe tabid . 'tabnew'
endif
if tabid >= current_tab
exe 'tabnext ' . current_tab
else
exe 'tabnext ' . (current_tab + 1)
endif
call s:update_context()
let line = search('^[▷▼] [ *]Tab ' . (tabid + 1),'wc')
exe line
endfunction
function! s:create_new_unnamed_tab() abort
let tabid = s:get_cursor_tabnr()
let current_tab = tabpagenr()
exe tabid . 'tabnew'
if tabid >= current_tab
exe 'tabnext ' . current_tab
else
exe 'tabnext ' . (current_tab + 1)
endif
call s:update_context()
let line = search('^[▷▼] [ *]Tab ' . (tabid + 1),'wc')
exe line
endfunction
function! s:delete_tab() abort
let line = line('.')
if getline('.') =~# '^[▷▼] [ *]Tab '
let tabid = matchstr(getline(line), '\d\+')
if tabid ==# tabpagenr()
call s:close_tab(tabid)
else
call s:close_tab(tabid)
call s:update_context()
endif
set tabline=%!SpaceVim#layers#core#tabline#get()
endif
exe line
endfunction
function! s:close_tab(nr) abort
if tabpagenr('$') == 1
echohl WarningMsg
echon 'can not close the last tab'
echohl NONE
else
exe 'tabclose' a:nr
endif
endfunction
" 1. switch to the tab under cursor
" 2. make session of current tab
" 3. switch to previous tab
let s:copy_tab_expand_status = 1
let s:copy_tab_name = ''
function! s:copy_tab() abort
let current_tab = tabpagenr()
let line = line('.')
let cursor_tab = s:get_cursor_tabnr()
let s:copy_tab_expand_status = gettabvar(cursor_tab, 'spacevim_tabman_expandable', 1)
let s:copy_tab_name = gettabvar(cursor_tab, '_spacevim_tab_name', '')
exe 'tabnext ' . cursor_tab
let save_sessionopts = &sessionoptions
let tabsession = g:spacevim_data_dir.'SpaceVim/tabmanager_session.vim'
let &sessionoptions = 'winsize'
exe 'mksession! ' . tabsession
exe 'tabnext ' . current_tab
exe line
endfunction
function! s:get_cursor_tabnr() abort
let line = line('.')
if getline('.') =~# '^[▷▼] [ *]Tab '
let tabid = matchstr(getline(line), '\d\+')
else
let line = search('^[▷▼] [ *]Tab ','bWnc')
let tabid = matchstr(getline(line), '\d\+')
endif
return tabid
endfunction
function! s:paste_tab() abort
let current_tab = tabpagenr()
let tabid = s:get_cursor_tabnr()
silent! exe tabid . 'tabnew '
silent! exe 'so '.g:spacevim_data_dir.'SpaceVim/tabmanager_session.vim'
call settabvar(tabpagenr(),
\ 'spacevim_tabman_expandable',
\ s:copy_tab_expand_status)
call settabvar(tabpagenr(), '_spacevim_tab_name', s:copy_tab_name)
if tabid >= current_tab
exe 'tabnext ' . current_tab
else
exe 'tabnext ' . (current_tab + 1)
endif
call s:update_context()
let line = search('^[▷▼] [ *]Tab ' . (tabid + 1),'wc')
exe line
endfunction
function! s:move_tab_backward() abort
let tabid = s:get_cursor_tabnr()
if tabid == 1
return
endif
let ct = tabpagenr()
exe tabid . 'tabdo tabmove -'
if ct == tabid
call s:update_context()
elseif tabid == ct + 1
exe 'tabnext' (ct + 1)
else
exe 'tabnext' ct
endif
let line = search('^[▷▼] [ *]Tab ' . (tabid - 1),'wc')
exe line
endfunction
function! s:move_tab_forward() abort
let tabid = s:get_cursor_tabnr()
if tabid == tabpagenr('$')
return
endif
let ct = tabpagenr()
exe tabid . 'tabdo tabmove +'
if ct == tabid
call s:update_context()
elseif tabid == ct - 1
exe 'tabnext' (ct - 1)
else
exe 'tabnext' ct
endif
let line = search('^[▷▼] [ *]Tab ' . (tabid + 1),'wc')
exe line
endfunction
function! s:focus_update_context() abort
let tbm = filter(range(1, winnr('$')), 'bufname(winbufnr(v:val)) == s:bufname')
if !empty(tbm)
let winnr = winnr()
exe tbm[0]. 'wincmd w'
call s:update_context()
exe winnr . 'wincmd w'
endif
endfunction
function! s:Nsort_func(a, b) abort
let l:a = type(a:a) == type('') ? str2nr(a:a) : a:a
let l:b = type(a:b) == type('') ? str2nr(a:b) : a:b
return l:a == l:b ? 0 : l:a > l:b ? 1 : -1
endfunction
" in case the 'N' sort flag is not available (compatibility for 7.4.898)
let s:Nsort = has('patch-7.4.951') ? 'N' : 's:Nsort_func'
augroup spacevim_plugin_tabman
autocmd!
autocmd TabEnter * call s:focus_update_context()
augroup END