1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 13:10:04 +08:00

feat(tabline): add lua tabline

This commit is contained in:
Eric Wong 2024-04-21 22:57:47 +08:00
parent d6bc345442
commit c28fda48b1
5 changed files with 667 additions and 130 deletions

View File

@ -275,6 +275,10 @@ function! SpaceVim#default#keyBindings() abort
endfunction
fu! s:tobur(num) abort
if has('nvim-0.9.5')
lua require('spacevim.plugin.tabline').jump(vim.api.nvim_eval('a:num'))
return
endif
if index(get(g:,'_spacevim_altmoveignoreft',[]), &filetype) == -1
if a:num ==# 'next'
if tabpagenr('$') > 1
@ -301,13 +305,13 @@ fu! s:tobur(num) abort
endif
endif
endif
endf
endfunction
function! SpaceVim#default#UseSimpleMode() abort
function! SpaceVim#default#UseSimpleMode() abort
endfunction
endfunction
function! SpaceVim#default#Customfoldtext() abort
function! SpaceVim#default#Customfoldtext() abort
"get first non-blank line
let fs = v:foldstart
while getline(fs) =~# '^\s*$' | let fs = nextnonblank(fs + 1)
@ -330,13 +334,13 @@ fu! s:tobur(num) abort
let foldPercentage = printf('[%.1f', (foldSize*1.0)/lineCount*100) . '%] '
let expansionString = repeat(repeatsymbol, w - strwidth(prefix.foldSizeStr.line.foldLevelStr.foldPercentage))
return prefix . line . expansionString . foldSizeStr . foldPercentage . foldLevelStr
endfunction
endfunction
function! s:switch_tabs() abort
function! s:switch_tabs() abort
let previous_tab = s:TAB.previous_tabpagenr()
if previous_tab > 0
exe 'tabnext ' . previous_tab
endif
endfunction
endfunction
" vim:set et sw=2:
" vim:set et sw=2:

View File

@ -513,6 +513,18 @@ function! SpaceVim#layers#core#tabline#get() abort
endfunction
function! SpaceVim#layers#core#tabline#config() abort
if has('nvim-0.9.5')
lua require('spacevim.plugin.tabline').enable()
set tabline=%!v:lua.require('spacevim.plugin.tabline').get()
augroup SpaceVim_tabline
autocmd!
autocmd ColorScheme * lua require('spacevim.plugin.tabline').def_colors()
augroup END
if s:enable_default_mappings
nnoremap <silent> <C-S-Left> <cmd>lua require('spacevim.plugin.tabline').move_to_previous()<CR>
nnoremap <silent> <C-S-Right> <cmd>lua require('spacevim.plugin.tabline').move_to_next()<CR>
endif
else
let [s:lsep , s:rsep] = get(s:separators, g:spacevim_statusline_separator, s:separators['arrow'])
let [s:ilsep , s:irsep] = get(s:i_separators, g:spacevim_statusline_iseparator, s:separators['arrow'])
set tabline=%!SpaceVim#layers#core#tabline#get()
@ -526,6 +538,7 @@ function! SpaceVim#layers#core#tabline#config() abort
nnoremap <silent> <C-S-Right> :call <SID>move_tabpage(1)<CR>
endif
endif
let shift_keys = {
\ '1': '!',
\ '2': '@',
@ -554,6 +567,12 @@ function! SpaceVim#layers#core#tabline#config() abort
endfunction
function! SpaceVim#layers#core#tabline#jump(id, ...) abort
call SpaceVim#logger#info(a:id)
call SpaceVim#logger#info(string(a:000))
if has('nvim-0.9.5')
lua require('spacevim.plugin.tabline').jump(vim.api.nvim_eval('a:id'))
return
endif
if len(s:shown_items) >= a:id
let item = s:shown_items[a:id - 1]
let mouse = get(a:000, 1, '')

View File

@ -188,6 +188,10 @@ function! SpaceVim#mapping#vertical_split_previous_buffer(...) abort
endfunction
function! SpaceVim#mapping#close_current_buffer(...) abort
if has('nvim-0.9.5')
lua require('spacevim.plugin.tabline').close_current_buffer()
return
endif
if index(
\ ['startify', 'defx'],
\ &filetype) !=# -1

View File

@ -1,6 +1,6 @@
local M = {}
M.group2dict = function (name)
M.group2dict = function(name)
local id = vim.fn.hlID(name)
if id == 0 then
return {
@ -29,7 +29,7 @@ M.group2dict = function (name)
return rst
end
M.hide_in_normal = function (name)
M.hide_in_normal = function(name)
local group = M.group2dict(name)
if vim.fn.empty(group) == 1 then
return
@ -44,9 +44,7 @@ M.hide_in_normal = function (name)
M.hi(group)
end
M.hi = function (info)
M.hi = function(info)
if vim.fn.empty(info) == 1 or vim.fn.get(info, 'name', '') == '' then
return
end
@ -66,7 +64,7 @@ M.hi = function (info)
end
local style = {}
for _, sty in ipairs({'bold', 'italic', 'underline', 'reverse'}) do
for _, sty in ipairs({ 'bold', 'italic', 'underline', 'reverse' }) do
if info[sty] == 1 then
table.insert(style, sty)
end
@ -78,5 +76,25 @@ M.hi = function (info)
pcall(vim.cmd, cmd)
end
function M.hi_separator(a, b)
local hi_a = M.group2dict(a)
local hi_b = M.group2dict(b)
local hi_a_b = {
name = a .. '_' .. b,
guibg = hi_b.guibg,
guifg = hi_a.guibg,
ctermbg = hi_b.ctermbg,
ctermfg = hi_a.ctermbg,
}
local hi_b_a = {
name = b .. '_' .. a,
guibg = hi_a.guibg,
guifg = hi_b.guibg,
ctermbg = hi_a.ctermbg,
ctermfg = hi_b.ctermbg,
}
M.hi(hi_a_b)
M.hi(hi_b_a)
end
return M

View File

@ -7,46 +7,538 @@
--=============================================================================
local M = {}
-- https://github.com/ryanoasis/powerline-extra-symbols
local separators = {
arrow = { '', '' },
curve = { '', '' },
slant = { '', '' },
brace = { '', '' },
fire = { '', '' },
['nil'] = { '', '' },
}
local i_separators = {
arrow = { '', '' },
curve = { '', '' },
slant = { '', '' },
bar = { '|', '|' },
['nil'] = { '', '' },
}
local isep
local right_sep
local left_sep
local function get_no_empty(a, b)
if vim.fn.empty(a) == 1 then
return b
local highlight = require('spacevim.api.vim.highlight')
local file = require('spacevim.api.file')
local messletters = require('spacevim.api.messletters')
local shown_items = {}
local right_hide_bufs = {}
local visiable_bufs = {}
local left_hide_bufs = {}
local function check_len(bufs)
local len = 0
for _, v in ipairs(bufs) do
local name = vim.fn.bufname(v)
name = vim.fn.fnamemodify(name, ':t')
len = len + #name + 6
if len > vim.o.columns - 25 then
return true
end
end
return false
end
local function reverse_table(t)
local tmp = {}
for i = 1, #t do
local key = #t + 1 - i
tmp[i] = t[key]
end
return tmp
end
local function build_item(bufnr, n)
local name = vim.fn.bufname(bufnr)
local icon = ''
local tablineat = '%' .. n .. '@SpaceVim#layers#core#tabline#jump@'
if name == '' then
name = 'No Name'
else
return a
name = vim.fn.fnamemodify(name, ':t')
icon = file.fticon(name)
end
local item_hilight
if vim.api.nvim_buf_get_option(bufnr, 'modified') then
item_hilight = '%#SpaceVim_tabline_m# '
elseif bufnr == vim.api.nvim_get_current_buf() then
item_hilight = '%#SpaceVim_tabline_a# '
else
item_hilight = '%#SpaceVim_tabline_b# '
end
return {
str = item_hilight
.. tablineat
.. messletters.bubble_num(n, 1)
.. ' '
.. name
.. ' '
.. icon
.. ' ',
bufnr = bufnr,
len = #name + 4,
pin = false,
}
end
local function build_tab_item(tabid)
local bufnr = vim.api.nvim_win_get_buf(vim.api.nvim_tabpage_get_win(tabid))
local name = vim.fn.bufname(bufnr)
local icon = ''
local nr = vim.api.nvim_tabpage_get_number(tabid)
local tablineat = '%' .. nr .. '@SpaceVim#layers#core#tabline#jump@'
if name == '' then
name = 'No Name'
else
name = vim.fn.fnamemodify(name, ':t')
icon = file.fticon(name)
end
local item_hilight
if vim.api.nvim_buf_get_option(bufnr, 'modified') then
item_hilight = '%#SpaceVim_tabline_m# '
elseif bufnr == vim.api.nvim_get_current_buf() then
item_hilight = '%#SpaceVim_tabline_a# '
else
item_hilight = '%#SpaceVim_tabline_b# '
end
return {
str = item_hilight
.. tablineat
.. messletters.bubble_num(nr, 1)
.. ' '
.. name
.. ' '
.. icon
.. ' ',
bufnr = bufnr,
len = #name + 4,
pin = false,
}
end
local function tabline_sep(a, b)
local hi_a
local hi_b
if vim.api.nvim_buf_get_option(a.bufnr, 'modified') then
hi_a = 'SpaceVim_tabline_m'
elseif a.bufnr == vim.api.nvim_get_current_buf() then
hi_a = 'SpaceVim_tabline_a'
else
hi_a = 'SpaceVim_tabline_b'
end
if not b then
hi_b = 'SpaceVim_tabline_b'
elseif vim.api.nvim_buf_get_option(b.bufnr, 'modified') then
hi_b = 'SpaceVim_tabline_m'
elseif b.bufnr == vim.api.nvim_get_current_buf() then
hi_b = 'SpaceVim_tabline_a'
else
hi_b = 'SpaceVim_tabline_b'
end
if hi_a == hi_b then
return isep
end
return '%#' .. hi_a .. '_' .. hi_b .. '#' .. right_sep
end
local function index(list, item)
local n = 0
for _, v in ipairs(list) do
if v == item then
return n
end
n = n + 1
end
return -1
end
local function get_show_items()
if vim.fn.tabpagenr('$') > 1 then
shown_items = {}
for _, i in ipairs(vim.api.nvim_list_tabpages()) do
table.insert(shown_items, build_tab_item(i))
end
return shown_items
else
shown_items = {}
left_hide_bufs = vim.tbl_filter(function(val)
return vim.api.nvim_buf_is_valid(val) and vim.api.nvim_buf_get_option(val, 'buflisted')
end, left_hide_bufs)
right_hide_bufs = vim.tbl_filter(function(val)
return vim.api.nvim_buf_is_valid(val) and vim.api.nvim_buf_get_option(val, 'buflisted')
end, right_hide_bufs)
local origin_ct = #visiable_bufs
visiable_bufs = vim.tbl_filter(function(val)
return vim.api.nvim_buf_is_valid(val) and vim.api.nvim_buf_get_option(val, 'buflisted')
end, visiable_bufs)
if #visiable_bufs ~= origin_ct then
local matchlen = false
if #right_hide_bufs > 0 and not matchlen then
while not matchlen and #right_hide_bufs > 0 do
table.insert(visiable_bufs, table.remove(right_hide_bufs))
if check_len(visiable_bufs) then
matchlen = true
table.insert(right_hide_bufs, 1, table.remove(visiable_bufs, #visiable_bufs))
end
end
end
if #left_hide_bufs > 0 and not matchlen then
while not matchlen and #left_hide_bufs > 0 do
table.insert(visiable_bufs, 1, table.remove(left_hide_bufs, #left_hide_bufs))
if check_len(visiable_bufs) then
matchlen = true
table.insert(left_hide_bufs, table.remove(visiable_bufs, 1))
end
end
end
end
local n = 1
for _, bufnr in ipairs(visiable_bufs) do
table.insert(shown_items, build_item(bufnr, n))
n = n + 1
end
return shown_items
end
end
function M.add(bufnr) end
local function move_tabpage(direction)
local ntp = vim.fn.tabpagenr('$')
local index
function M.move_to_previous()
local bufnr = vim.api.nvim_get_current_buf()
if ntp > 1 then
local ctpn = vim.fn.tabpagenr()
if direction > 0 then
index = (ctpn + direction) % ntp
if index == 0 then
index = ntp
elseif index == 1 then
index = 0
end
else
index = (ctpn + direction) % ntp
if index < 0 then
index = ntp + index
end
if index == 0 then
index = ntp
elseif index == 1 then
index = 0
else
index = index - 1
local idx = index(visiable_bufs, bufnr)
if idx > 0 then -- second item or others
visiable_bufs[idx + 1] = visiable_bufs[idx]
visiable_bufs[idx] = bufnr
elseif idx == 0 and #left_hide_bufs > 0 then
table.insert(visiable_bufs, 2, table.remove(left_hide_bufs, #left_hide_bufs))
while check_len(visiable_bufs) and #visiable_bufs > 1 do
table.insert(right_hide_bufs, 1, table.remove(visiable_bufs, #visiable_bufs))
end
end
vim.cmd('tabmove ' .. index)
vim.cmd('redrawtabline')
end
function M.move_to_next()
local bufnr = vim.api.nvim_get_current_buf()
local idx = index(visiable_bufs, bufnr)
if idx > -1 and idx < #visiable_bufs - 1 then -- second item or others
visiable_bufs[idx + 1] = visiable_bufs[idx + 2]
visiable_bufs[idx + 2] = bufnr
elseif idx == #visiable_bufs - 1 and #right_hide_bufs > 0 then
table.insert(visiable_bufs, #visiable_bufs - 1, table.remove(right_hide_bufs, 1))
while check_len(visiable_bufs) and #visiable_bufs > 1 do
table.insert(left_hide_bufs, table.remove(visiable_bufs, 1))
end
end
vim.cmd('redrawtabline')
end
function M.close_current_buffer()
local bufnr = vim.api.nvim_get_current_buf()
local idx = index(visiable_bufs, bufnr)
local f = ''
if vim.api.nvim_buf_get_option(bufnr, 'modified') then
end
if idx > 0 then
vim.cmd('b' .. visiable_bufs[idx])
vim.cmd('bd ' .. bufnr)
end
end
function M.enable()
local seps = separators[vim.g.spacevim_statusline_separator] or separators.arrow
local iseps = i_separators[vim.g.spacevim_statusline_iseparator] or i_separators.arrow
isep = iseps[1]
right_sep = seps[1]
left_sep = seps[2]
local tabline_augroup = vim.api.nvim_create_augroup('spacevim_tabline', { clear = true })
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufReadPost' }, {
callback = vim.schedule_wrap(function(event)
if
vim.api.nvim_buf_is_valid(event.buf)
and index(right_hide_bufs, event.buf) == -1
and index(visiable_bufs, event.buf) == -1
and index(left_hide_bufs, event.buf) == -1
then
table.insert(right_hide_bufs, event.buf)
end
end),
group = tabline_augroup,
})
vim.api.nvim_create_autocmd({
'BufEnter',
}, {
callback = vim.schedule_wrap(function(event)
if
vim.api.nvim_buf_is_valid(event.buf) and vim.api.nvim_buf_get_option(event.buf, 'buflisted')
then
if index(visiable_bufs, event.buf) == -1 then
if index(left_hide_bufs, event.buf) > -1 then
local all_bufs = {}
for _, v in ipairs(left_hide_bufs) do
table.insert(all_bufs, v)
end
for _, v in ipairs(visiable_bufs) do
table.insert(all_bufs, v)
end
for _, v in ipairs(right_hide_bufs) do
table.insert(all_bufs, v)
end
left_hide_bufs = {}
visiable_bufs = {}
right_hide_bufs = {}
local find_current_buf = false
local matchlen = false
for _, v in ipairs(all_bufs) do
if v == event.buf then
find_current_buf = true
end
if not find_current_buf then
table.insert(left_hide_bufs, v)
elseif find_current_buf and not matchlen then
table.insert(visiable_bufs, v)
if check_len(visiable_bufs) then
matchlen = true
if #visiable_bufs > 1 then
table.insert(right_hide_bufs, table.remove(visiable_bufs, #visiable_bufs))
end
end
else
table.insert(right_hide_bufs, v)
end
end
elseif index(right_hide_bufs, event.buf) > -1 then
local all_bufs = {}
for _, v in ipairs(left_hide_bufs) do
table.insert(all_bufs, v)
end
for _, v in ipairs(visiable_bufs) do
table.insert(all_bufs, v)
end
for _, v in ipairs(right_hide_bufs) do
table.insert(all_bufs, v)
end
left_hide_bufs = {}
visiable_bufs = {}
right_hide_bufs = {}
local find_current_buf = false
local matchlen = false
all_bufs = reverse_table(all_bufs)
for _, v in ipairs(all_bufs) do
if v == event.buf then
find_current_buf = true
end
if not find_current_buf then
table.insert(right_hide_bufs, 1, v)
elseif find_current_buf and not matchlen then
table.insert(visiable_bufs, 1, v)
if check_len(visiable_bufs) then
matchlen = true
if #visiable_bufs > 1 then
table.insert(left_hide_bufs, table.remove(visiable_bufs, 1))
end
end
else
table.insert(left_hide_bufs, 1, v)
end
end
end
end
end
end),
group = tabline_augroup,
})
vim.api.nvim_create_autocmd({
'BufWinEnter',
'BufWinLeave',
'BufWritePost',
'TabEnter',
'VimResized',
'WinEnter',
'WinLeave',
}, {
callback = vim.schedule_wrap(function(event)
if vim.api.nvim_buf_is_valid(event.buf) then
vim.cmd('redrawtabline')
end
end),
group = tabline_augroup,
})
end
function M.get()
local tablinestr = ''
shown_items = get_show_items()
local preview_item
if #left_hide_bufs > 0 and vim.fn.tabpagenr('$') == 1 then
tablinestr = '%#SpaceVim_tabline_b# << ' .. #left_hide_bufs .. ' '
end
for _, item in ipairs(shown_items) do
if preview_item then
-- 如果存在上一个buf则增加分隔符
tablinestr = tablinestr .. tabline_sep(preview_item, item)
end
tablinestr = tablinestr .. item.str
preview_item = item
end
if preview_item then
-- 如果存在上一个buf则增加分隔符
tablinestr = tablinestr .. tabline_sep(preview_item, nil)
if #right_hide_bufs > 0 and vim.fn.tabpagenr('$') == 1 then
tablinestr = tablinestr .. '%#SpaceVim_tabline_b# ' .. #right_hide_bufs .. ' >> '
end
tablinestr = tablinestr
.. '%#SpaceVim_tabline_b#%=%#SpaceVim_tabline_a_SpaceVim_tabline_b# '
.. left_sep
if vim.fn.tabpagenr('$') > 1 then
tablinestr = tablinestr .. '%#SpaceVim_tabline_a# Tabs '
else
tablinestr = tablinestr .. '%#SpaceVim_tabline_a# Buffers '
end
end
return tablinestr
end
function M.def_colors()
local name = vim.g.colors_name or 'gruvbox'
local t
if #vim.g.spacevim_custom_color_palette > 0 then
t = vim.g.spacevim_custom_color_palette
else
local ok = pcall(function()
t = vim.fn['SpaceVim#mapping#guide#theme#' .. name .. '#palette']()
end)
if not ok then
t = vim.fn['Vim#mapping#guide#theme#gruvbox#palette']()
end
end
vim.api.nvim_set_hl(0, 'SpaceVim_tabline_a', {
fg = t[1][1],
bg = t[1][2],
ctermfg = t[1][4],
ctermbg = t[1][3],
})
vim.api.nvim_set_hl(0, 'SpaceVim_tabline_b', {
fg = t[2][1],
bg = t[2][2],
ctermfg = t[2][4],
ctermbg = t[2][3],
})
vim.api.nvim_set_hl(0, 'SpaceVim_tabline_m', {
fg = t[5][1],
bg = t[5][2],
ctermfg = t[5][3],
ctermbg = t[5][4],
})
vim.api.nvim_set_hl(0, 'SpaceVim_tabline_m_i', {
fg = t[5][2],
bg = t[2][2],
ctermfg = t[5][4],
ctermbg = t[2][3],
})
highlight.hi_separator('SpaceVim_tabline_a', 'SpaceVim_tabline_b')
highlight.hi_separator('SpaceVim_tabline_m', 'SpaceVim_tabline_b')
highlight.hi_separator('SpaceVim_tabline_m', 'SpaceVim_tabline_a')
end
function M.jump(id)
if id == 'next' then
local bufnr = vim.api.nvim_get_current_buf()
local idx = index(visiable_bufs, bufnr)
if idx > -1 and idx < #visiable_bufs - 1 then
vim.cmd('b' .. visiable_bufs[idx + 2])
elseif idx > -1 and idx == #visiable_bufs - 1 then
if #right_hide_bufs > 0 then
vim.cmd('b' .. right_hide_bufs[1])
elseif #left_hide_bufs > 0 then
vim.cmd('b' .. left_hide_bufs[1])
else
vim.cmd('b' .. visiable_bufs[1])
end
end
elseif id == 'prev' then
local bufnr = vim.api.nvim_get_current_buf()
local idx = index(visiable_bufs, bufnr)
if idx > 0 then
vim.cmd('b' .. visiable_bufs[idx])
elseif idx == 0 and idx < #visiable_bufs - 1 then
if #left_hide_bufs > 0 then
vim.cmd('b' .. left_hide_bufs[#left_hide_bufs])
elseif #right_hide_bufs > 0 then
vim.cmd('b' .. right_hide_bufs[#right_hide_bufs])
else
vim.cmd('b' .. visiable_bufs[#visiable_bufs])
end
end
elseif #shown_items >= id then
if vim.fn.tabpagenr('$') > 1 then
vim.cmd('tabnext' .. id)
else
vim.api.nvim_set_current_buf(shown_items[id].bufnr)
end
end
end
return M