Skip to content

Instantly share code, notes, and snippets.

@lucassperez
Created April 2, 2026 04:54
Show Gist options
  • Select an option

  • Save lucassperez/466e3bc893ef4cbb027da15f62b7b265 to your computer and use it in GitHub Desktop.

Select an option

Save lucassperez/466e3bc893ef4cbb027da15f62b7b265 to your computer and use it in GitHub Desktop.
Get the neovim intro from before 0.12
if vim.fn.argc() > 0 then
return
end
local vim_version = vim.version()
if vim_version.minor < 12 then
return
end
--[[
The idea is to create a floating window
with the text the same as the old intro,
and then dismiss this floating window when
we enter insert mode, load a file into the buffer,
or move the cursor to another window.
The latter avoids weird behaviour if we open a new
split. The old intro also disappeared when doing this.
]]
vim.opt.shortmess:append('I')
local function set_intro_highlights()
vim.cmd([[
highlight link IntroTitle SpecialKey
highlight link IntroText Normal
]])
end
local intro = {
win = nil,
buf = nil,
ns = nil,
text = nil,
group = nil
}
intro.ns = vim.api.nvim_create_namespace('IntroOverlayNS')
intro.group = vim.api.nvim_create_augroup('IntroOverlay', { clear = true })
intro.text = {
{ { ' NVIM ' .. vim_version.build, 'IntroTitle' } },
{ { '' } },
{ { ' Nvim is open source and freely distributable', 'IntroText' } },
{ { ' https://neovim.io/#chat', 'IntroTitle' } },
{ { '' } },
{
{ 'type :help nvim', 'IntroText' },
{ '<Enter>', 'IntroTitle' },
{ ' if you are new!', 'IntroText' },
},
{
{ 'type :checkhealth', 'IntroText' },
{ '<Enter>', 'IntroTitle' },
{ ' to optimize Nvim', 'IntroText' },
},
{
{ 'type :q', 'IntroText' },
{ '<Enter>', 'IntroTitle' },
{ ' to exit', 'IntroText' },
},
{
{ 'type :help', 'IntroText' },
{ '<Enter>', 'IntroTitle' },
{ ' for help', 'IntroText' },
},
{ { '' } },
{
{ 'type :help news', 'IntroText' },
{ '<Enter>', 'IntroTitle' },
{ (' to see changes in v%d.%d'):format(vim_version.major, vim_version.minor), 'IntroText' },
},
{ { '' } },
{ { ' Help poor children in Uganda!', 'IntroText' } },
{
{ 'type :help Kuwasha', 'IntroText' },
{ '<Enter>', 'IntroTitle' },
{ ' for information', 'IntroText' },
},
}
local function create_intro_buf()
local buf = vim.api.nvim_create_buf(false, true)
for i, text in ipairs(intro.text) do
vim.api.nvim_buf_set_lines(buf, i - 1, i - 1, false, { '' })
vim.api.nvim_buf_set_extmark(buf, intro.ns, i - 1, 0, {
virt_text = text,
virt_text_pos = 'overlay',
})
end
return buf
end
local function create_intro_win(row, col, width, height)
local win = vim.api.nvim_open_win(intro.buf, false, {
relative = 'editor',
row = row,
col = col,
width = width,
height = height,
style = 'minimal',
border = 'none',
focusable = false,
noautocmd = true,
})
-- This set the same background color for the intro
-- floating window as your normal background,
-- so the floating window appears to be transparent.
vim.wo[win].winhighlight = 'NormalFloat:Normal'
return win
end
local function hide_intro()
if intro.win and vim.api.nvim_win_is_valid(intro.win) then
vim.api.nvim_win_close(intro.win, true)
intro.win = nil
end
end
local function render_intro()
if not intro.buf or not vim.api.nvim_buf_is_valid(intro.buf) then
intro.buf = create_intro_buf()
end
-- Width is kind of a magic number, it has to be big
-- enough to it fits the longest line present in `lines`,
-- but also not too big so it closes when the terminal
-- window is not large enough.
-- Right now, the biggest line is this:
-- type :help news<Enter> to see changes in v0.12
-- I decided to hardcode it but we could calculate it by
-- iterating over the intro.text table.
local width = 49
local height = #intro.text
-- I'm subtracting one to respect the ~ in the signal column
local usable_width = vim.o.columns - 1
-- Hide the intro if terminal is too small.
-- That + 6 is also kind of magical, and without it,
-- the intro gets too squished before closing it if the
-- terminal window gets too short.
if usable_width < width or vim.o.lines < height + 6 then
hide_intro()
return
end
local row = math.floor((vim.o.lines - height) / 3)
local col = math.floor((usable_width - width) / 2) + 2
if not intro.win or not vim.api.nvim_win_is_valid(intro.win) then
intro.win = create_intro_win(row, col, width, height)
return
end
vim.api.nvim_win_set_config(intro.win, {
relative = 'editor',
row = row,
col = col,
width = width,
height = height,
})
end
local function cleanup_intro()
hide_intro()
if intro.group then
-- When opening some help pages, this augroup deletion
-- raised some error saying the augroup was already deleted...
-- But this didn't happend when opening a file or a split or by
-- typing or by opening standalone :h.
-- I don't know what causes it, but I wrapped in a pcall to
-- silently ignore it. Error handling at its finest.
pcall(vim.api.nvim_del_augroup_by_id, intro.group)
intro.group = nil
end
if intro.buf and vim.api.nvim_buf_is_valid(intro.buf) then
if intro.ns then
vim.api.nvim_buf_clear_namespace(intro.buf, intro.ns, 0, -1)
intro.ns = nil
end
vim.api.nvim_buf_delete(intro.buf, { force = true })
intro.buf = nil
end
intro.win = nil
intro.text = nil
end
vim.api.nvim_create_autocmd('VimEnter', {
once = true,
callback = function()
set_intro_highlights()
render_intro()
vim.api.nvim_create_autocmd('VimResized', {
group = intro.group,
callback = render_intro,
})
-- If you want to recolor the intro when changing colorscheme,
-- uncomment the following block of code.
-- vim.api.nvim_create_autocmd('ColorScheme', {
-- group = intro.group,
-- callback = set_intro_highlights,
-- })
vim.api.nvim_create_autocmd({
'InsertCharPre',
'BufReadPre',
'CursorMoved',
}, {
group = intro.group,
once = true,
callback = function()
-- InsertCharPre raises some error when we try to
-- close a window during that event, so I used
-- vim.schedule to avoid the so called "textlock",
-- as :h vim.schedule itself suggests.
vim.schedule(cleanup_intro)
end,
})
end,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment