1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 11:20:06 +08:00

perf(guide): improve key binding guide

This commit is contained in:
Eric Wong 2024-06-01 22:51:47 +08:00
parent d6a34e3aff
commit 24712351a1
2 changed files with 161 additions and 112 deletions

View File

@ -7,125 +7,144 @@
--=============================================================================
local M = {}
local system = require('spacevim.api').import('system')
function M.eval(l)
if vim.api ~= nil then
return vim.api.nvim_eval(l)
if vim.api ~= nil then
return vim.api.nvim_eval(l)
else
return vim.eval(l)
end
end
function M.islist(val)
if vim.islist then
return vim.islist(val)
---@diagnostic disable-next-line
elseif vim.tbl_islist then
---@diagnostic disable-next-line
return vim.tbl_islist(val)
else
if type(val) ~= 'table' then
return false
else
return vim.eval(l)
for k, _ in pairs(val) do
if type(k) ~= 'number' then
return false
end
end
return true
end
end
end
if vim.command ~= nil then
function M.cmd(command)
return vim.command(command)
end
function M.cmd(command)
return vim.command(command)
end
else
function M.cmd(command)
return vim.api.nvim_command(command)
end
function M.cmd(command)
return vim.api.nvim_command(command)
end
end
-- there is no want to call viml function in old vim and neovim
local function build_argv(...)
local str = ''
for index, value in ipairs(...) do
if str ~= '' then
str = str .. ','
end
if type(value) == 'string' then
str = str .. '"' .. value .. '"'
elseif type(value) == 'number' then
str = str .. value
end
local str = ''
for _, value in ipairs(...) do
if str ~= '' then
str = str .. ','
end
return str
if type(value) == 'string' then
str = str .. '"' .. value .. '"'
elseif type(value) == 'number' then
str = str .. value
end
end
return str
end
function M.call(funcname, ...)
if vim.call ~= nil then
return vim.call(funcname, ...)
if vim.call ~= nil then
return vim.call(funcname, ...)
else
if vim.api ~= nil then
return vim.api.nvim_call_function(funcname, { ... })
else
if vim.api ~= nil then
return vim.api.nvim_call_function(funcname, {...})
else
-- call not call vim script function in lua
vim.command('let g:lua_rst = ' .. funcname .. '(' .. build_argv({...}) .. ')')
return M.eval('g:lua_rst')
end
-- call not call vim script function in lua
vim.command('let g:lua_rst = ' .. funcname .. '(' .. build_argv({ ... }) .. ')')
return M.eval('g:lua_rst')
end
end
end
-- this is for Vim and old neovim
M.fn = setmetatable({}, {
__index = function(t, key)
local _fn
if vim.api ~= nil and vim.api[key] ~= nil then
_fn = function()
error(string.format("Tried to call API function with vim.fn: use vim.api.%s instead", key))
end
else
_fn = function(...)
return M.call(key, ...)
end
end
t[key] = _fn
return _fn
__index = function(t, key)
local _fn
if vim.api ~= nil and vim.api[key] ~= nil then
_fn = function()
error(string.format('Tried to call API function with vim.fn: use vim.api.%s instead', key))
end
else
_fn = function(...)
return M.call(key, ...)
end
end
t[key] = _fn
return _fn
end,
})
-- This is for vim and old neovim to use vim.o
M.vim_options = setmetatable({}, {
__index = function(t, key)
local _fn
if vim.api ~= nil then
-- for neovim
return vim.api.nvim_get_option(key)
else
-- for vim
_fn = M.eval('&' .. key)
end
t[key] = _fn
return _fn
__index = function(t, key)
local _fn
if vim.api ~= nil then
-- for neovim
return vim.api.nvim_get_option(key)
else
-- for vim
_fn = M.eval('&' .. key)
end
t[key] = _fn
return _fn
end,
})
function M.echo(msg)
if vim.api ~= nil then
vim.api.nvim_echo({{msg}}, false, {})
else
vim.command('echo ' .. build_argv({msg}))
end
if vim.api ~= nil then
vim.api.nvim_echo({ { msg } }, false, {})
else
vim.command('echo ' .. build_argv({ msg }))
end
end
local has_cache = {}
function M.has(feature)
if has_cache[feature] ~= nil then
return has_cache[feature]
else
return M.eval('float2nr(has("' .. feature .. '"))')
end
if has_cache[feature] ~= nil then
return has_cache[feature]
else
return M.eval('float2nr(has("' .. feature .. '"))')
end
end
if M.has('patch-7.4.279') then
function M.globpath(dir, expr)
return M.fn.globpath(dir, expr, 1, 1)
end
function M.globpath(dir, expr)
return M.fn.globpath(dir, expr, 1, 1)
end
else
function M.globpath(dir, expr)
return M.fn.split(fn.globpath(dir, expr), "\n")
end
function M.globpath(dir, expr)
return M.fn.split(vim.fn.globpath(dir, expr), '\n')
end
end
function M.execute(cmd, silent)
return M.fn.execute(cmd, silent)
return M.fn.execute(cmd, silent)
end
function M.win_screenpos(nr)
return vim.fn.win_screenpos(nr)
return vim.fn.win_screenpos(nr)
end
return M

View File

@ -15,6 +15,7 @@ local cmp = require('spacevim.api').import('vim.compatible')
local buffer = require('spacevim.api').import('vim.buffer')
local VIM = require('spacevim.api').import('vim')
local SL = require('spacevim.api').import('vim.statusline')
local hl = require('spacevim.api.vim.highlight')
-- all local values should be listed here:
@ -164,27 +165,27 @@ local function add_map_to_dict(map, level, dict)
local nlevel = level + 1
if not dict[curkey] then
dict[curkey] = { name = vim.g.leaderGuide_default_group_name }
elseif vim.tbl_islist(dict[curkey]) and vim.g.leaderGuide_flatten == 1 then
elseif cmp.islist(dict[curkey]) and vim.g.leaderGuide_flatten == 1 then
local cmd = escape_mappings(map)
curkey = table.concat(map.lhs, '', level)
nlevel = level
if not dict[curkey] then
dict[curkey] = { cmd, map.display }
end
elseif vim.tbl_islist(dict[curkey]) and vim.g.leaderGuide_flatten == 0 then
elseif cmp.islist(dict[curkey]) and vim.g.leaderGuide_flatten == 0 then
curkey = curkey .. 'm'
if not dict[curkey] then
dict[curkey] = { name = vim.g.leaderGuide_default_group_name }
end
end
if not vim.tbl_islist(dict[curkey]) then
if not cmp.islist(dict[curkey]) then
add_map_to_dict(map, nlevel, dict[curkey])
end
else
local cmd = escape_mappings(map)
if not dict[map.lhs[level]] then
dict[map.lhs[level]] = { cmd, map.display }
elseif not vim.tbl_islist(dict[map.lhs[level]]) and vim.g.leaderGuide_flatten == 1 then
elseif not cmp.islist(dict[map.lhs[level]]) and vim.g.leaderGuide_flatten == 1 then
local childmap = flattenmap(dict[map.lhs[level]], map.lhs[level])
for it, _ in pairs(childmap) do
dict[it] = childmap[it]
@ -282,22 +283,44 @@ local function start_parser(key, dict)
end
end
---@param v string key board string
---@return string # displayed string of each item
local function get_displaystring(v)
local desc = ''
if lmap[v].name then
desc = lmap[v].name
else
desc = lmap[v][2] or ''
end
local offset = string.rep(' ', 8 - #v)
local displaystring
if vim.g.spacevim_leader_guide_theme == 'whichkey' then
displaystring = offset .. v .. ' -> ' .. desc
else
displaystring = offset .. '[' .. v .. '] ' .. desc
end
return displaystring
end
local function calc_layout()
local ret = {}
local smap = {}
local smap = vim.fn.filter(vim.fn.copy(lmap), 'v:key !=# "name"')
ret.n_items = vim.fn.len(smap)
local length = {}
for k, v in pairs(smap) do
if v.name then
table.insert(length, vim.fn.strdisplaywidth('[' .. k .. ']' .. v.name))
else
table.insert(length, vim.fn.strdisplaywidth('[' .. k .. ']' .. v[2]))
for k, v in pairs(lmap) do
if v ~= 'name' then
smap[k] = v
end
end
local maxlength = vim.fn.max(length) + vim.g.leaderGuide_hspace
ret.n_items = vim.fn.len(smap)
local length = {}
log.debug('smap is:' .. vim.inspect(smap))
for k, _ in pairs(smap) do
table.insert(length, vim.fn.strdisplaywidth(get_displaystring(k)))
end
local maxlength = vim.fn.max(length) + vim.g.leaderGuide_hspace
log.debug('maxlength is:' .. maxlength)
if vim.g.leaderGuide_vertical == 1 then
ret.n_rows = vim.fn.winheight(0) - 2
ret.n_cols = math.floor(ret.n_items / ret.n_rows)
@ -319,6 +342,7 @@ local function calc_layout()
end
ret.win_dim = ret.n_rows
end
log.debug('layout is:' .. vim.inspect(ret))
return ret
end
@ -396,19 +420,7 @@ local function create_string(layout)
table.sort(smap, compare_key)
for _, k in ipairs(smap) do
local desc = ''
if lmap[k].name then
desc = lmap[k].name
else
desc = lmap[k][2] or ''
end
local offset = string.rep(' ', 8 - #k)
local displaystring
if vim.g.spacevim_leader_guide_theme == 'whichkey' then
displaystring = offset .. k .. ' -> ' .. desc
else
displaystring = offset .. '[' .. k .. '] ' .. desc
end
local displaystring = get_displaystring(k)
crow = rows[row] or {}
if #crow == 0 then
@ -416,10 +428,10 @@ local function create_string(layout)
end
-- if the displaystring is too long
if #displaystring > l.col_width then
table.insert(crow, string.sub(displaystring, 1, l.col_width -5) .. '... ')
table.insert(crow, string.sub(displaystring, 1, l.col_width - 5) .. '... ')
else
table.insert(crow, displaystring)
table.insert(crow, vim.fn['repeat'](' ', l.col_width - vim.fn.strdisplaywidth(displaystring)))
table.insert(crow, string.rep(' ', l.col_width - vim.fn.strdisplaywidth(displaystring)))
end
if vim.g.leaderGuide_sort_horizontal == 0 then
if row > n_rows then
@ -455,8 +467,16 @@ local function create_string(layout)
return r
end
local cursor_highlight_info
local function highlight_cursor()
vim.cmd('hi! def link SpaceVimGuideCursor Cursor')
cursor_highlight_info = hl.group2dict('Cursor')
local hlinfo = {
name = 'SpaceVimGuideCursor',
guibg = cursor_highlight_info.guibg,
ctermbg = cursor_highlight_info.ctermbg,
}
hl.hi(hlinfo)
hl.hide_in_normal('Cursor')
if vis == 'gv' then
local _begin = vim.fn.getpos("'<")
local _end = vim.fn.getpos("'>")
@ -480,6 +500,7 @@ local function highlight_cursor()
end
local function remove_cursor_highlight()
hl.hi(cursor_highlight_info)
pcall(vim.fn.matchdelete, cursor_hilight_id)
end
@ -505,14 +526,23 @@ local function updateStatusline()
end
local keys = prefix_key_inp
local separators = {
arrow = '',
curve = '',
slant = '',
brace = '',
fire = '',
['nil'] = '',
}
local sep = separators[vim.g.spacevim_statusline_separator] or separators.arrow
SL.open_float({
{ 'Guide: ', 'LeaderGuiderPrompt' },
{ '', 'LeaderGuiderSep1' },
{ sep .. ' ', 'LeaderGuiderSep1' },
{
vim.fn['SpaceVim#mapping#leader#getName'](prefix_key) .. table.concat(keys, '') .. gname,
'LeaderGuiderName',
},
{ '', 'LeaderGuiderSep2' },
{ sep .. ' ', 'LeaderGuiderSep2' },
{ guide_help_msg(false), 'LeaderGuiderFill' },
{ string.rep(' ', 999), 'LeaderGuiderFill' },
})
@ -563,11 +593,12 @@ local function winopen()
winfixwidth = true,
winfixheight = true,
})
updateStatusline()
return winid, bufnr
end
local function start_buffer()
winid, bufnr = winopen()
if not vim.api.nvim_win_is_valid(winid) or not vim.api.nvim_buf_is_valid(bufnr) then
winid, bufnr = winopen()
end
local layout = calc_layout()
local text = create_string(layout)
if vim.g.leaderGuide_max_size then
@ -583,12 +614,13 @@ local function start_buffer()
col = 0,
})
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, text)
updateStatusline()
cmp.fn.setbufvar(bufnr, '&modifiable', 0)
vim.cmd('redraw!')
vim.cmd('redraw')
wait_for_input()
end
@ -603,11 +635,11 @@ local function winclose()
end
local function handle_input(input)
winclose()
if not vim.tbl_islist(input) then
if not cmp.islist(input) then
lmap = input
start_buffer()
else
winclose()
prefix_key_inp = {}
cmp.fn.feedkeys(vis .. reg .. count, 'ti')
@ -628,7 +660,6 @@ local function page_down()
end
local function page_undo()
winclose()
if #prefix_key_inp then
table.remove(prefix_key_inp)
end
@ -639,7 +670,6 @@ local function page_undo()
end
local function page_up()
-- vim.api.nvim_feedkeys(Key.t('<C-c>'), 'n', false)
vim.api.nvim_feedkeys(Key.t('<C-u>'), 'x', false)
vim.cmd('redraw!')