Skip to content

Commit

Permalink
feat(doom): Add vertical center (#476)
Browse files Browse the repository at this point in the history
* refactor(doom): Add load_packages function. Rename elements

* refactor(doom): Split center_entry_list into its own function.

* feat(doom)!: Center the dashboard on the vertical (`vertical_center`)

To disable this add `vertical_center = false` in the doom `configs`

* fix(doom): Fix center generation without a config

* feat(doom): Change `vertical_center` to be opt-in
  • Loading branch information
polirritmico authored Jan 19, 2025
1 parent 2f641b0 commit 63e83ad
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 44 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ config = {
},
},
footer = {},
vertical_center = false, -- Center the Dashboard on the vertical (from top to bottom)
}
```

Expand All @@ -145,7 +146,7 @@ DashboardHeader DashboardFooter
-- Hyper theme
DashboardProjectTitle DashboardProjectTitleIcon DashboardProjectIcon
DashboardMruTitle DashboardMruIcon DashboardFiles DashboardShortCutIcon
-- Doome theme
-- Doom theme
DashboardDesc DashboardKey DashboardIcon DashboardShortCut
```

Expand Down
144 changes: 101 additions & 43 deletions lua/dashboard/theme/doom.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
local api, keymap = vim.api, vim.keymap
local utils = require('dashboard.utils')

local function generate_center(config)
local vert_offset

local function gen_center_icons_and_descriptions(config)
local lines = {}
local center = config.center
or {
{ desc = 'Please config your own center section', key = 'p' },
}

local counts = {}
for _, item in pairs(center) do
Expand Down Expand Up @@ -47,21 +46,19 @@ local function generate_center(config)
lines[i] = lines[i]:sub(1, #lines[i] - count)
end

local first_line = api.nvim_buf_line_count(config.bufnr)
api.nvim_buf_set_lines(config.bufnr, first_line, -1, false, lines)

if not config.center then
return
end
api.nvim_buf_set_lines(config.bufnr, vert_offset, -1, false, lines)
return lines
end

local function gen_center_highlights_and_keys(config, lines)
local ns = api.nvim_create_namespace('DashboardDoom')
local seed = 0
local pos_map = {}
local position_map = {}
for i = 1, #lines do
if lines[i]:find('%w') then
local idx = i == 1 and i or i - seed
seed = seed + 1
pos_map[i] = idx
position_map[i] = idx
local _, scol = lines[i]:find('%s+')
local ecol = scol + (config.center[idx].icon and #config.center[idx].icon or 0)

Expand All @@ -70,7 +67,7 @@ local function generate_center(config)
config.bufnr,
0,
config.center[idx].icon_hl or 'DashboardIcon',
first_line + i - 1,
vert_offset + i - 1,
0,
ecol
)
Expand All @@ -80,7 +77,7 @@ local function generate_center(config)
config.bufnr,
0,
config.center[idx].desc_hl or 'DashboardDesc',
first_line + i - 1,
vert_offset + i - 1,
ecol,
-1
)
Expand All @@ -94,45 +91,61 @@ local function generate_center(config)
string.format(config.center[idx].key_format or ' [%s]', config.center[idx].key),
config.center[idx].key_hl or 'DashboardKey',
})
api.nvim_buf_set_extmark(config.bufnr, ns, first_line + i - 1, 0, {
api.nvim_buf_set_extmark(config.bufnr, ns, vert_offset + i - 1, 0, {
virt_text_pos = 'eol',
virt_text = virt_tbl,
})
end
end
end
return position_map
end

local line = api.nvim_buf_get_lines(config.bufnr, first_line, first_line + 1, false)[1]
local function gen_center_base(config)
if not config.center then
local msg = utils.center_align({ 'Please config your own center section', '' })
api.nvim_buf_set_lines(config.bufnr, vert_offset, -1, false, msg)
return {}
end

local lines = gen_center_icons_and_descriptions(config)
return lines
end

local function move_cursor_behaviour(config, bottom_linenr)
local line = api.nvim_buf_get_lines(config.bufnr, vert_offset, vert_offset + 1, false)[1]
local col = line:find('%w')
local col_width = api.nvim_strwidth(line:sub(1, col))
col = col and col - 1 or 9999
api.nvim_win_set_cursor(config.winid, { first_line + 1, col })
api.nvim_win_set_cursor(config.winid, { vert_offset + 1, col })

local bottom = api.nvim_buf_line_count(config.bufnr)
vim.defer_fn(function()
local before = 0
if api.nvim_get_current_buf() ~= config.bufnr then
return
end

local dashboard_group = api.nvim_create_augroup('DashboardDoomCursor', { clear = true })
api.nvim_create_autocmd('CursorMoved', {
buffer = config.bufnr,
group = dashboard_group,
callback = function()
local buf = api.nvim_win_get_buf(0)
if vim.api.nvim_get_option_value('filetype', { buf = buf }) ~= 'dashboard' then
return
end

local curline = api.nvim_win_get_cursor(0)[1]
if curline < first_line + 1 then
curline = bottom - 1
elseif curline > bottom - 1 then
curline = first_line + 1
if curline < vert_offset + 1 then
curline = bottom_linenr - 1
elseif curline > bottom_linenr - 1 then
curline = vert_offset + 1
elseif not api.nvim_get_current_line():find('%w') then
curline = curline + (before > curline and -1 or 1)
end
before = curline

-- FIX: #422: In Lua the length of a string is the number of bytes not
-- NOTE: #422: In Lua the length of a string is the number of bytes not
-- the number of characters.
local curline_str = api.nvim_buf_get_lines(config.bufnr, curline - 1, curline, false)[1]
local strwidth = api.nvim_strwidth(curline_str:sub(1, col + 1))
Expand All @@ -144,10 +157,12 @@ local function generate_center(config)
end,
})
end, 0)
end

local function confirm_key(config, position_map)
keymap.set('n', config.confirm_key or '<CR>', function()
local curline = api.nvim_win_get_cursor(0)[1]
local index = pos_map[curline - first_line]
local index = position_map[curline - vert_offset]
if index and config.center[index].action then
if type(config.center[index].action) == 'string' then
local dump = loadstring(config.center[index].action)
Expand All @@ -165,13 +180,18 @@ local function generate_center(config)
end, { buffer = config.bufnr, nowait = true, silent = true })
end

local function generate_footer(config)
local first_line = api.nvim_buf_line_count(config.bufnr)
local function load_packages(config)
local packages = config.packages or {
enable = true,
}
if not packages.enable then
return
end

local package_manager_stats = utils.get_package_manager_stats()
local footer = {}
local lines = {}
if package_manager_stats.name == 'lazy' then
footer = {
'',
lines = {
'',
'Startuptime: ' .. package_manager_stats.time .. ' ms',
'Plugins: '
Expand All @@ -181,39 +201,77 @@ local function generate_footer(config)
.. ' installed',
}
else
footer = {
lines = {
'',
'neovim loaded ' .. package_manager_stats.count .. ' plugins',
}
end

local first_line = api.nvim_buf_line_count(config.bufnr)
api.nvim_buf_set_lines(config.bufnr, first_line, -1, false, utils.center_align(lines))

for i, _ in pairs(lines) do
api.nvim_buf_add_highlight(config.bufnr, 0, 'Comment', first_line + i - 1, 0, -1)
end

return lines
end

local function gen_footer(config)
local lines = {} ---@type table?
if config.footer then
if type(config.footer) == 'function' then
footer = config.footer()
lines = config.footer()
elseif type(config.footer) == 'string' then
local dump = loadstring(config.footer)
if dump then
footer = dump()
lines = dump()
end
elseif type(config.footer) == 'table' then
footer = config.footer
lines = config.footer
end
local first_line = api.nvim_buf_line_count(config.bufnr)
api.nvim_buf_set_lines(config.bufnr, first_line, -1, false, utils.center_align(lines))
for i = 1, #lines do
api.nvim_buf_add_highlight(config.bufnr, 0, 'DashboardFooter', first_line + i - 1, 0, -1)
end
else
lines = load_packages(config)
end
api.nvim_buf_set_lines(config.bufnr, first_line, -1, false, utils.center_align(footer))
for i = 1, #footer do
api.nvim_buf_add_highlight(config.bufnr, 0, 'DashboardFooter', first_line + i - 1, 0, -1)
utils.add_update_footer_command(config.bufnr, lines)
return #lines
end

local function vertical_center(config)
if config.vertical_center ~= true then
return
end

utils.add_update_footer_command(config.bufnr, footer)
local size = math.floor(vim.o.lines / 2)
- math.ceil(api.nvim_buf_line_count(config.bufnr) / 2)
- 2
local fill = utils.generate_empty_table(size)
api.nvim_buf_set_lines(config.bufnr, 0, 0, false, fill)

vert_offset = vert_offset + (size < 0 and 0 or size)
end

---@private
local function theme_instance(config)
require('dashboard.theme.header').generate_header(config)
generate_center(config)
generate_footer(config)
api.nvim_set_option_value('modifiable', false, { buf = config.bufnr })
api.nvim_set_option_value('modified', false, { buf = config.bufnr })
--defer until next event loop
vert_offset = api.nvim_buf_line_count(config.bufnr)

local lines = gen_center_base(config)
local footer_size = gen_footer(config)
vertical_center(config)
local actions_position_map = gen_center_highlights_and_keys(config, lines)

local last_entry_pos = api.nvim_buf_line_count(config.bufnr) - footer_size
move_cursor_behaviour(config, last_entry_pos)
confirm_key(config, actions_position_map)

vim.bo[config.bufnr].modifiable = false
vim.bo[config.bufnr].modified = false
-- defer until next event loop
vim.schedule(function()
api.nvim_exec_autocmds('User', {
pattern = 'DashboardLoaded',
Expand Down

0 comments on commit 63e83ad

Please sign in to comment.