- declarative configuration
- flexible layouts
- multiple vertical panes
- built-in sections:
- header: show a header
- keys: show keymaps
- projects: show recent projects
- recent_files: show recent files
- session: session support
- startup: startup time (lazy.nvim)
- terminal: colored terminal output
- super fast
terminal
sections with automatic caching
The dashboard comes with a set of default sections, that
can be customized with opts.preset
or
fully replaced with opts.sections
.
The default preset comes with support for:
- pickers:
- session managers: (only works with lazy.nvim)
A section can have an action
property that will be executed as:
- a command if it starts with
:
- a keymap if it's a string not starting with
:
- a function if it's a function
-- command
{
action = ":Telescope find_files",
key = "f",
},
-- keymap
{
action = "<leader>ff",
key = "f",
},
-- function
{
action = function()
require("telescope.builtin").find_files()
end,
key = "h",
},
Every item should have a text
property with an array of snacks.dashboard.Text
objects.
If the text
property is not provided, the snacks.dashboard.Config.formats
will be used to generate the text.
In the example below, both sections are equivalent.
{
text = {
{ "ο ", hl = "SnacksDashboardIcon" },
{ "Find File", hl = "SnacksDashboardDesc", width = 50 },
{ "[f]", hl = "SnacksDashboardKey" },
},
action = ":Telescope find_files",
key = "f",
},
{
action = ":Telescope find_files",
key = "f",
desc = "Find File",
icon = "ο ",
},
---@class snacks.dashboard.Config
---@field sections snacks.dashboard.Section
---@field formats table<string, snacks.dashboard.Text|fun(item:snacks.dashboard.Item, ctx:snacks.dashboard.Format.ctx):snacks.dashboard.Text>
{
width = 60,
row = nil, -- dashboard position. nil for center
col = nil, -- dashboard position. nil for center
pane_gap = 4, -- empty columns between vertical panes
autokeys = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", -- autokey sequence
-- These settings are used by some built-in sections
preset = {
-- Defaults to a picker that supports `fzf-lua`, `telescope.nvim` and `mini.pick`
---@type fun(cmd:string, opts:table)|nil
pick = nil,
-- Used by the `keys` section to show keymaps.
-- Set your custom keymaps here.
-- When using a function, the `items` argument are the default keymaps.
---@type snacks.dashboard.Item[]
keys = {
{ icon = "ο ", key = "f", desc = "Find File", action = ":lua Snacks.dashboard.pick('files')" },
{ icon = "ο
", key = "n", desc = "New File", action = ":ene | startinsert" },
{ icon = "ο’ ", key = "g", desc = "Find Text", action = ":lua Snacks.dashboard.pick('live_grep')" },
{ icon = "ο
", key = "r", desc = "Recent Files", action = ":lua Snacks.dashboard.pick('oldfiles')" },
{ icon = "ο£ ", key = "c", desc = "Config", action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})" },
{ icon = "ξ ", key = "s", desc = "Restore Session", section = "session" },
{ icon = "σ°² ", key = "L", desc = "Lazy", action = ":Lazy", enabled = package.loaded.lazy ~= nil },
{ icon = "ο¦ ", key = "q", desc = "Quit", action = ":qa" },
},
-- Used by the `header` section
header = [[
ββββ βββββββββββ βββββββ βββ ββββββββββ ββββ
βββββ βββββββββββββββββββββββ βββββββββββ βββββ
ββββββ βββββββββ βββ ββββββ βββββββββββββββββ
ββββββββββββββββ βββ βββββββ ββββββββββββββββββ
βββ βββββββββββββββββββββββ βββββββ ββββββ βββ βββ
βββ βββββββββββββ βββββββ βββββ ββββββ βββ]],
},
-- item field formatters
formats = {
icon = function(item)
if item.file and item.icon == "file" or item.icon == "directory" then
return M.icon(item.file, item.icon)
end
return { item.icon, width = 2, hl = "icon" }
end,
footer = { "%s", align = "center" },
header = { "%s", align = "center" },
file = function(item, ctx)
local fname = vim.fn.fnamemodify(item.file, ":~")
fname = ctx.width and #fname > ctx.width and vim.fn.pathshorten(fname) or fname
local dir, file = fname:match("^(.*)/(.+)$")
return dir and { { dir .. "/", hl = "dir" }, { file, hl = "file" } } or { { fname, hl = "file" } }
end,
},
sections = {
{ section = "header" },
{ section = "keys", gap = 1, padding = 1 },
{ section = "startup" },
},
}
A more advanced example using multiple panes
{
sections = {
{ section = "header" },
{
pane = 2,
section = "terminal",
cmd = "colorscript -e square",
height = 5,
padding = 1,
},
{ section = "keys", gap = 1, padding = 1 },
{ pane = 2, icon = "ο
", title = "Recent Files", section = "recent_files", indent = 2, padding = 1 },
{ pane = 2, icon = "οΌ ", title = "Projects", section = "projects", indent = 2, padding = 1 },
{
pane = 2,
icon = "ξ₯ ",
title = "Git Status",
section = "terminal",
enabled = Snacks.git.get_root() ~= nil,
cmd = "hub status --short --branch --renames",
height = 5,
padding = 1,
ttl = 5 * 60,
indent = 3,
},
{ section = "startup" },
},
}
An example using the chafa
command to display an image
{
sections = {
{
section = "terminal",
cmd = "chafa ~/.config/wall.png --format symbols --symbols vhalf --size 60x17 --stretch; sleep .1",
height = 17,
padding = 1,
},
{
pane = 2,
{ section = "keys", gap = 1, padding = 1 },
{ section = "startup" },
},
},
}
A more compact version of the files
example
{
sections = {
{ section = "header" },
{ icon = "ο ", title = "Keymaps", section = "keys", indent = 2, padding = 1 },
{ icon = "ο
", title = "Recent Files", section = "recent_files", indent = 2, padding = 1 },
{ icon = "οΌ ", title = "Projects", section = "projects", indent = 2, padding = 1 },
{ section = "startup" },
},
}
Similar to the Emacs Doom dashboard
{
sections = {
{ section = "header" },
{ section = "keys", gap = 1, padding = 1 },
{ section = "startup" },
},
}
A simple example with a header, keys, recent files, and projects
{
sections = {
{ section = "header" },
{ section = "keys", gap = 1 },
{ icon = "ο
", title = "Recent Files", section = "recent_files", indent = 2, padding = { 2, 2 } },
{ icon = "οΌ ", title = "Projects", section = "projects", indent = 2, padding = 2 },
{ section = "startup" },
},
}
{
sections = {
{ section = "header" },
{ section = "keys", gap = 1, padding = 1 },
{ section = "startup" },
{
section = "terminal",
cmd = "pokemon-colorscripts -r --no-title; sleep .1",
random = 10,
pane = 2,
indent = 4,
height = 30,
},
},
}
Similar to the Vim Startify dashboard
{
formats = {
key = function(item)
return { { "[", hl = "special" }, { item.key, hl = "key" }, { "]", hl = "special" } }
end,
},
sections = {
{ section = "terminal", cmd = "fortune -s | cowsay", hl = "header", padding = 1, indent = 8 },
{ title = "MRU", padding = 1 },
{ section = "recent_files", limit = 8, padding = 1 },
{ title = "MRU ", file = vim.fn.fnamemodify(".", ":~"), padding = 1 },
{ section = "recent_files", cwd = true, limit = 8, padding = 1 },
{ title = "Sessions", padding = 1 },
{ section = "projects", padding = 1 },
{ title = "Bookmarks", padding = 1 },
{ section = "keys" },
},
}
The default style for the dashboard.
When opening the dashboard during startup, only the bo
and wo
options are used.
The other options are used with :lua Snacks.dashboard()
{
zindex = 10,
height = 0,
width = 0,
bo = {
bufhidden = "wipe",
buftype = "nofile",
filetype = "snacks_dashboard",
swapfile = false,
undofile = false,
},
wo = {
colorcolumn = "",
cursorcolumn = false,
cursorline = false,
list = false,
number = false,
relativenumber = false,
sidescrolloff = 0,
signcolumn = "no",
spell = false,
statuscolumn = "",
statusline = "",
winbar = "",
winhighlight = "Normal:SnacksDashboardNormal,NormalFloat:SnacksDashboardNormal",
wrap = false,
},
}
---@class snacks.dashboard.Item
---@field indent? number
---@field align? "left" | "center" | "right"
---@field gap? number the number of empty lines between child items
---@field padding? number | {[1]:number, [2]:number} bottom or {bottom, top} padding
--- The action to run when the section is selected or the key is pressed.
--- * if it's a string starting with `:`, it will be run as a command
--- * if it's a string, it will be executed as a keymap
--- * if it's a function, it will be called
---@field action? snacks.dashboard.Action
---@field enabled? boolean|fun(opts:snacks.dashboard.Opts):boolean if false, the section will be disabled
---@field section? string the name of a section to include. See `Snacks.dashboard.sections`
---@field [string] any section options
---@field key? string shortcut key
---@field autokey? boolean automatically assign a numerical key
---@field label? string
---@field desc? string
---@field file? string
---@field footer? string
---@field header? string
---@field icon? string
---@field title? string
---@field text? string|snacks.dashboard.Text[]
---@alias snacks.dashboard.Format.ctx {width?:number}
---@alias snacks.dashboard.Action string|fun(self:snacks.dashboard.Class)
---@alias snacks.dashboard.Gen fun(self:snacks.dashboard.Class):snacks.dashboard.Section?
---@alias snacks.dashboard.Section snacks.dashboard.Item|snacks.dashboard.Gen|snacks.dashboard.Section[]
---@class snacks.dashboard.Text
---@field [1] string the text
---@field hl? string the highlight group
---@field width? number the width used for alignment
---@field align? "left" | "center" | "right"
---@class snacks.dashboard.Opts: snacks.dashboard.Config
---@field buf? number the buffer to use. If not provided, a new buffer will be created
---@field win? number the window to use. If not provided, a new floating window will be created
---@type fun(opts?: snacks.dashboard.Opts): snacks.dashboard.Class
Snacks.dashboard()
Checks if the plugin is installed. Only works with lazy.nvim
---@param name string
Snacks.dashboard.have_plugin(name)
Snacks.dashboard.health()
Get an icon
---@param name string
---@param cat? string
---@return snacks.dashboard.Text
Snacks.dashboard.icon(name, cat)
---@param opts? snacks.dashboard.Opts
---@return snacks.dashboard.Class
Snacks.dashboard.open(opts)
Used by the default preset to pick something
---@param cmd? string
Snacks.dashboard.pick(cmd, opts)
---@return snacks.dashboard.Gen
Snacks.dashboard.sections.header()
---@return snacks.dashboard.Gen
Snacks.dashboard.sections.keys()
Get the most recent projects based on git roots of recent files.
The default action will change the directory to the project root,
try to restore the session and open the picker if the session is not restored.
You can customize the behavior by providing a custom action.
Use opts.dirs
to provide a list of directories to use instead of the git roots.
---@param opts? {limit?:number, dirs?:(string[]|fun():string[]), pick?:boolean, session?:boolean, action?:fun(dir)}
Snacks.dashboard.sections.projects(opts)
Get the most recent files, optionally filtered by the current working directory or a custom directory.
---@param opts? {limit?:number, cwd?:string|boolean}
---@return snacks.dashboard.Gen
Snacks.dashboard.sections.recent_files(opts)
Adds a section to restore the session if any of the supported plugins are installed.
---@param item? snacks.dashboard.Item
---@return snacks.dashboard.Item?
Snacks.dashboard.sections.session(item)
Add the startup section
---@return snacks.dashboard.Section?
Snacks.dashboard.sections.startup()
---@param opts {cmd:string|string[], ttl?:number, height?:number, width?:number, random?:number}|snacks.dashboard.Item
---@return snacks.dashboard.Gen
Snacks.dashboard.sections.terminal(opts)
Check if the dashboard should be opened
Snacks.dashboard.setup()
Update the dashboard
Snacks.dashboard.update()