1

Refresh generated nvim config

This commit is contained in:
2024-06-05 13:03:21 +02:00
parent c9bb45dfc4
commit bbcc7f34a3
31 changed files with 3002 additions and 0 deletions

View File

@ -0,0 +1,2 @@
github: glepnir
custom: ['https://www.paypal.me/bobbyhub']

View File

@ -0,0 +1,24 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,38 @@
name: ci
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Stylua
uses: JohnnyMorganz/stylua-action@v1.1.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --check .
docs:
runs-on: ubuntu-latest
name: pandoc to vimdoc
steps:
- uses: actions/checkout@v3
- name: panvimdoc
uses: kdheepak/panvimdoc@main
with:
vimdoc: dashboard
version: Nvim 0.8.0
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: 'chore(doc): auto generate docs'
commit_user_name: "github-actions[bot]"
commit_user_email: "github-actions[bot]@users.noreply.github.com"
commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"

View File

@ -0,0 +1,6 @@
column_width = 100
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferSingle"
call_parentheses = "Always"

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 StephenHuan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,250 @@
<h1 align="center">
Fancy and Blazing Fast start screen plugin of neovim
</h1>
| <center>Hyper</center> | <center>Doom</center> |
| --- | --- |
| <center><img src="https://user-images.githubusercontent.com/41671631/215015845-b13343c4-427e-45d6-9f92-267ab909eff1.png" width=80% height=80%/></center>|<center> <img src="https://user-images.githubusercontent.com/41671631/214518543-d7d6afbf-f405-4a6f-a505-568c5a101e92.png" width=80% height=80%/> </center>|
# Feature
- Low memory usage. dashboard does not store the all user configs in memory like header etc these string will take some memory. now it will be clean after you open a file. you can still use dashboard command to open a new one , then dashboard will read the config from cache.
- Blazing fast
# Install
- Lazy.nvim
```lua
{
'nvimdev/dashboard-nvim',
event = 'VimEnter',
config = function()
require('dashboard').setup {
-- config
}
end,
dependencies = { {'nvim-tree/nvim-web-devicons'}}
}
```
- Packer
```lua
use {
'nvimdev/dashboard-nvim',
event = 'VimEnter',
config = function()
require('dashboard').setup {
-- config
}
end,
requires = {'nvim-tree/nvim-web-devicons'}
}
```
# Configuration
## Options
```lua
theme = 'hyper' -- theme is doom and hyper default is hyper
disable_move -- default is false disable move keymap for hyper
shortcut_type -- shorcut type 'letter' or 'number'
change_to_vcs_root -- default is false,for open file in hyper mru. it will change to the root of vcs
config = {}, -- config used for theme
hide = {
statusline -- hide statusline default is true
tabline -- hide the tabline
winbar -- hide winbar
},
preview = {
command -- preview command
file_path -- preview file path
file_height -- preview file height
file_width -- preview file width
},
```
## Theme config
the `config` field is used for theme. general field
```lua
config = {
header -- type is table def
week_header = {
enable --boolean use a week header
concat --concat string after time string line
append --table append after time string line
},
disable_move -- boolean default is false disable move key
}
```
### Hyper
when use `hyper` theme the available options in `config` is
```lua
config = {
shortcut = {
-- action can be a function type
{ desc = string, group = 'highlight group', key = 'shortcut key', action = 'action when you press key' },
},
packages = { enable = true }, -- show how many plugins neovim loaded
-- limit how many projects list, action when you press key or enter it will run this action.
-- action can be a functino type, e.g.
-- action = func(path) vim.cmd('Telescope find_files cwd=' .. path) end
project = { enable = true, limit = 8, icon = 'your icon', label = '', action = 'Telescope find_files cwd=' },
mru = { limit = 10, icon = 'your icon', label = '', cwd_only = false },
footer = {}, -- footer
}
```
### Doom
when use `doom` theme the available options in `config` is
```lua
config = {
center = {
{
icon = '',
icon_hl = 'group',
desc = 'description',
desc_hl = 'group',
key = 'shortcut key in dashboard buffer not keymap !!',
key_hl = 'group',
key_format = ' [%s]', -- `%s` will be substituted with value of `key`
action = '',
},
},
footer = {},
}
```
notice if you don't link config every highlight group. you can ignore this key.
dashboard will use default highlight group like `DashboardKey/Icon/Desc` instead
### Commands
- `Dashboard` open dashboard
- `DbProjectDelete count` delete project in cache works for hyper theme. count is number
- `DashboardUpdateFooter` updates the content of the Footer
### Highlight
all highlight groups
```
-- General
DashboardHeader DashboardFooter
-- Hyper theme
DashboardProjectTitle DashboardProjectTitleIcon DashboardProjectIcon
DashboardMruTitle DashboardMruIcon DashboardFiles DashboardShortCutIcon
-- Doome theme
DashboardDesc DashboardKey DashboardIcon DashboardShortCut
```
### Example config
example config of screenshot
<details>
<summary> Hyper </summary>
```lua
db.setup({
theme = 'hyper',
config = {
week_header = {
enable = true,
},
shortcut = {
{ desc = '󰊳 Update', group = '@property', action = 'Lazy update', key = 'u' },
{
icon = ' ',
icon_hl = '@variable',
desc = 'Files',
group = 'Label',
action = 'Telescope find_files',
key = 'f',
},
{
desc = ' Apps',
group = 'DiagnosticHint',
action = 'Telescope app',
key = 'a',
},
{
desc = ' dotfiles',
group = 'Number',
action = 'Telescope dotfiles',
key = 'd',
},
},
},
})
```
</details>
<details>
<summary> Doom </summary>
```lua
db.setup({
theme = 'doom',
config = {
header = {}, --your header
center = {
{
icon = ' ',
icon_hl = 'Title',
desc = 'Find File ',
desc_hl = 'String',
key = 'b',
keymap = 'SPC f f',
key_hl = 'Number',
key_format = ' %s', -- remove default surrounding `[]`
action = 'lua print(2)'
},
{
icon = ' ',
desc = 'Find Dotfiles',
key = 'f',
keymap = 'SPC f d',
key_format = ' %s', -- remove default surrounding `[]`
action = 'lua print(3)'
},
},
footer = {} --your footer
}
})
```
</details
### Changed
- Removed Session as a start screen plugin speed is first.if you want use session you can take a
look at [glepnir/dbsession.nvim](https://github.com/glepnir/dbsession.nvim)
- Removed Ueberzug script, as the Ueberzug author has deleted the repository.
### TODO
- I will write a plugin to implement some popular terminal evaluators image protocol then I think
can make it work with dashboard
# Backers
[@RakerZh](https://github.com/RakerZh)
# Donate
If you'd like to support my work financially, buy me a drink through Github Sponsor or [![](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white)](https://paypal.me/bobbyhub)
# LICENSE
MIT

View File

@ -0,0 +1,289 @@
*dashboard.txt* For Nvim 0.8.0 Last change: 2024 May 17
==============================================================================
Table of Contents *dashboard-table-of-contents*
1. Feature |dashboard-feature|
2. Install |dashboard-install|
3. Configuration |dashboard-configuration|
- Options |dashboard-configuration-options|
- Theme config |dashboard-configuration-theme-config|
4. Backers |dashboard-backers|
5. Donate |dashboard-donate|
6. LICENSE |dashboard-license|
7. Links |dashboard-links|
Fancy and Blazing Fast start screen plugin of neovim ----------------------------------- -----------------------------------
----------------------------------- -----------------------------------
==============================================================================
1. Feature *dashboard-feature*
- Low memory usage. dashboard does not store the all user configs in memory like header etc these string will take some memory. now it will be clean after you open a file. you can still use dashboard command to open a new one , then dashboard will read the config from cache.
- Blazing fast
==============================================================================
2. Install *dashboard-install*
- Lazy.nvim
>lua
{
'nvimdev/dashboard-nvim',
event = 'VimEnter',
config = function()
require('dashboard').setup {
-- config
}
end,
dependencies = { {'nvim-tree/nvim-web-devicons'}}
}
<
- Packer
>lua
use {
'nvimdev/dashboard-nvim',
event = 'VimEnter',
config = function()
require('dashboard').setup {
-- config
}
end,
requires = {'nvim-tree/nvim-web-devicons'}
}
<
==============================================================================
3. Configuration *dashboard-configuration*
OPTIONS *dashboard-configuration-options*
>lua
theme = 'hyper' -- theme is doom and hyper default is hyper
disable_move -- default is false disable move keymap for hyper
shortcut_type -- shorcut type 'letter' or 'number'
change_to_vcs_root -- default is false,for open file in hyper mru. it will change to the root of vcs
config = {}, -- config used for theme
hide = {
statusline -- hide statusline default is true
tabline -- hide the tabline
winbar -- hide winbar
},
preview = {
command -- preview command
file_path -- preview file path
file_height -- preview file height
file_width -- preview file width
},
<
THEME CONFIG *dashboard-configuration-theme-config*
the `config` field is used for theme. general field
>lua
config = {
header -- type is table def
week_header = {
enable --boolean use a week header
concat --concat string after time string line
append --table append after time string line
},
disable_move -- boolean default is false disable move key
}
<
HYPER ~
when use `hyper` theme the available options in `config` is
>lua
config = {
shortcut = {
-- action can be a function type
{ desc = string, group = 'highlight group', key = 'shortcut key', action = 'action when you press key' },
},
packages = { enable = true }, -- show how many plugins neovim loaded
-- limit how many projects list, action when you press key or enter it will run this action.
-- action can be a functino type, e.g.
-- action = func(path) vim.cmd('Telescope find_files cwd=' .. path) end
project = { enable = true, limit = 8, icon = 'your icon', label = '', action = 'Telescope find_files cwd=' },
mru = { limit = 10, icon = 'your icon', label = '', cwd_only = false },
footer = {}, -- footer
}
<
DOOM ~
when use `doom` theme the available options in `config` is
>lua
config = {
center = {
{
icon = '',
icon_hl = 'group',
desc = 'description',
desc_hl = 'group',
key = 'shortcut key in dashboard buffer not keymap !!',
key_hl = 'group',
key_format = ' [%s]', -- `%s` will be substituted with value of `key`
action = '',
},
},
footer = {},
}
<
notice if you dont link config every highlight group. you can ignore this
key. dashboard will use default highlight group like `DashboardKey/Icon/Desc`
instead
COMMANDS ~
- `Dashboard` open dashboard
- `DbProjectDelete count` delete project in cache works for hyper theme. count is number
- `DashboardUpdateFooter` updates the content of the Footer
HIGHLIGHT ~
all highlight groups
>
-- General
DashboardHeader DashboardFooter
-- Hyper theme
DashboardProjectTitle DashboardProjectTitleIcon DashboardProjectIcon
DashboardMruTitle DashboardMruIcon DashboardFiles DashboardShortCutIcon
-- Doome theme
DashboardDesc DashboardKey DashboardIcon DashboardShortCut
<
EXAMPLE CONFIG ~
example config of screenshot
Hyper ~
>lua
db.setup({
theme = 'hyper',
config = {
week_header = {
enable = true,
},
shortcut = {
{ desc = '󰊳 Update', group = '@property', action = 'Lazy update', key = 'u' },
{
icon = ' ',
icon_hl = '@variable',
desc = 'Files',
group = 'Label',
action = 'Telescope find_files',
key = 'f',
},
{
desc = ' Apps',
group = 'DiagnosticHint',
action = 'Telescope app',
key = 'a',
},
{
desc = ' dotfiles',
group = 'Number',
action = 'Telescope dotfiles',
key = 'd',
},
},
},
})
<
Doom ~
>lua
db.setup({
theme = 'doom',
config = {
header = {}, --your header
center = {
{
icon = ' ',
icon_hl = 'Title',
desc = 'Find File ',
desc_hl = 'String',
key = 'b',
keymap = 'SPC f f',
key_hl = 'Number',
key_format = ' %s', -- remove default surrounding `[]`
action = 'lua print(2)'
},
{
icon = ' ',
desc = 'Find Dotfiles',
key = 'f',
keymap = 'SPC f d',
key_format = ' %s', -- remove default surrounding `[]`
action = 'lua print(3)'
},
},
footer = {} --your footer
}
})
<
</details
CHANGED ~
- Removed Session as a start screen plugin speed is first.if you want use session you can take a
look at glepnir/dbsession.nvim <https://github.com/glepnir/dbsession.nvim>
- Removed Ueberzug script, as the Ueberzug author has deleted the repository.
TODO ~
- I will write a plugin to implement some popular terminal evaluators image protocol then I think
can make it work with dashboard
==============================================================================
4. Backers *dashboard-backers*
@RakerZh <https://github.com/RakerZh>
==============================================================================
5. Donate *dashboard-donate*
If youd like to support my work financially, buy me a drink through Github
Sponsor or <https://paypal.me/bobbyhub>
==============================================================================
6. LICENSE *dashboard-license*
MIT
==============================================================================
7. Links *dashboard-links*
1. *@RakerZh*:
2. **: https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -0,0 +1,11 @@
dashboard-backers dashboard.txt /*dashboard-backers*
dashboard-configuration dashboard.txt /*dashboard-configuration*
dashboard-configuration-options dashboard.txt /*dashboard-configuration-options*
dashboard-configuration-theme-config dashboard.txt /*dashboard-configuration-theme-config*
dashboard-donate dashboard.txt /*dashboard-donate*
dashboard-feature dashboard.txt /*dashboard-feature*
dashboard-install dashboard.txt /*dashboard-install*
dashboard-license dashboard.txt /*dashboard-license*
dashboard-links dashboard.txt /*dashboard-links*
dashboard-table-of-contents dashboard.txt /*dashboard-table-of-contents*
dashboard.txt dashboard.txt /*dashboard.txt*

View File

@ -0,0 +1,59 @@
local api, lsp, uv = vim.api, vim.lsp, vim.loop
local au = {}
local get_lsp_clients = vim.fn.has('nvim-0.10') == 1 and vim.lsp.get_clients
or lsp.get_active_clients
function au.register_lsp_root(path)
api.nvim_create_autocmd('VimLeavePre', {
callback = function()
local projects = {}
for _, client in pairs(get_lsp_clients() or {}) do
local root_dir = client.config.root_dir
if root_dir and not vim.tbl_contains(projects, root_dir) then
table.insert(projects, root_dir)
end
for _, folder in pairs(client.workspace_folders or {}) do
if not vim.tbl_contains(projects, folder.name) then
table.insert(projects, folder.name)
end
end
end
if #projects == 0 then
return
end
-- callback hell holy shit but simply than write a async await lib
-- also I don't link to add a thirdpart plugin. this is just a small code
uv.fs_open(path, 'r+', 384, function(err, fd)
assert(not err, err)
uv.fs_fstat(fd, function(err, stat)
assert(not err, err)
uv.fs_read(fd, stat.size, 0, function(err, data)
assert(not err, err)
local before = assert(loadstring(data))
local plist = before()
if plist and #plist > 10 then
plist = vim.list_slice(plist, 10)
end
plist = vim.tbl_filter(function(k)
return not vim.tbl_contains(projects, k)
end, plist or {})
plist = vim.list_extend(plist, projects)
local dump = 'return ' .. vim.inspect(plist)
uv.fs_write(fd, dump, 0, function(err, _)
assert(not err, err)
uv.fs_ftruncate(fd, #dump, function(err, _)
assert(not err, err)
uv.fs_close(fd)
end)
end)
end)
end)
end)
end,
})
end
return au

View File

@ -0,0 +1,278 @@
local api, fn = vim.api, vim.fn
local utils = require('dashboard.utils')
local ctx = {}
local db = {}
db.__index = db
db.__newindex = function(t, k, v)
rawset(t, k, v)
end
local function clean_ctx()
for k, _ in pairs(ctx) do
ctx[k] = nil
end
end
local function cache_dir()
local dir = utils.path_join(vim.fn.stdpath('cache'), 'dashboard')
if fn.isdirectory(dir) == 0 then
fn.mkdir(dir, 'p')
end
return dir
end
local function cache_path()
local dir = cache_dir()
return utils.path_join(dir, 'cache')
end
local function conf_cache_path()
return utils.path_join(cache_dir(), 'conf')
end
local function default_options()
return {
theme = 'hyper',
disable_move = false,
shortcut_type = 'letter',
buffer_name = 'Dashboard',
change_to_vcs_root = false,
config = {
week_header = {
enable = false,
concat = nil,
append = nil,
},
},
hide = {
statusline = true,
tabline = true,
},
preview = {
command = '',
file_path = nil,
file_height = 0,
file_width = 0,
},
}
end
local function buf_local()
local opts = {
['bufhidden'] = 'wipe',
['colorcolumn'] = '',
['foldcolumn'] = '0',
['matchpairs'] = '',
['buflisted'] = false,
['cursorcolumn'] = false,
['cursorline'] = false,
['list'] = false,
['number'] = false,
['relativenumber'] = false,
['spell'] = false,
['swapfile'] = false,
['readonly'] = false,
['filetype'] = 'dashboard',
['wrap'] = false,
['signcolumn'] = 'no',
['winbar'] = '',
}
for opt, val in pairs(opts) do
vim.opt_local[opt] = val
end
if fn.has('nvim-0.9') == 1 then
vim.opt_local.stc = ''
end
end
function db:new_file()
vim.cmd('enew')
if self.user_laststatus_value then
vim.opt_local.laststatus = self.user_laststatus_value
self.user_laststatus_value = nil
end
if self.user_tabline_value then
vim.opt_local.showtabline = self.user_showtabline_value
self.user_showtabline_value = nil
end
end
-- cache the user options value restore after leave the dahsboard buffer
-- or use DashboardNewFile command
function db:cache_ui_options(opts)
if opts.hide.statusline then
---@diagnostic disable-next-line: param-type-mismatch
self.user_laststatus_value = vim.opt.laststatus:get()
vim.opt.laststatus = 0
end
if opts.hide.tabline then
---@diagnostic disable-next-line: param-type-mismatch
self.user_tabline_value = vim.opt.showtabline:get()
vim.opt.showtabline = 0
end
end
function db:restore_options()
if self.user_cursor_line then
vim.opt.cursorline = self.user_cursor_line
self.user_cursor_line = nil
end
if self.user_laststatus_value then
vim.opt.laststatus = tonumber(self.user_laststatus_value)
self.user_laststatus_value = nil
end
if self.user_tabline_value then
vim.opt.showtabline = tonumber(self.user_tabline_value)
self.user_tabline_value = nil
end
end
function db:cache_opts()
if not self.opts then
return
end
local uv = vim.loop
local path = conf_cache_path()
if self.opts.config.shortcut then
for _, item in pairs(self.opts.config.shortcut) do
if type(item.action) == 'function' then
---@diagnostic disable-next-line: param-type-mismatch
local dump = assert(string.dump(item.action))
item.action = dump
end
end
end
if self.opts.config.project and type(self.opts.config.project.action) == 'function' then
---@diagnostic disable-next-line: param-type-mismatch
local dump = assert(string.dump(self.opts.config.project.action))
self.opts.config.project.action = dump
end
if self.opts.config.center then
for _, item in pairs(self.opts.config.center) do
if type(item.action) == 'function' then
---@diagnostic disable-next-line: param-type-mismatch
local dump = assert(string.dump(item.action))
item.action = dump
end
end
end
if self.opts.config.footer and type(self.opts.config.footer) == 'function' then
---@diagnostic disable-next-line: param-type-mismatch
local dump = assert(string.dump(self.opts.config.footer))
self.opts.config.footer = dump
end
local dump = vim.json.encode(self.opts)
uv.fs_open(path, 'w+', tonumber('664', 8), function(err, fd)
assert(not err, err)
---@diagnostic disable-next-line: redefined-local
uv.fs_write(fd, dump, 0, function(err, _)
assert(not err, err)
uv.fs_close(fd)
end)
end)
end
function db:get_opts(callback)
utils.async_read(
conf_cache_path(),
vim.schedule_wrap(function(data)
if not data or #data == 0 then
return
end
local obj = vim.json.decode(data)
if obj then
callback(obj)
end
end)
)
end
function db:load_theme(opts)
local config = vim.tbl_extend('force', opts.config, {
path = cache_path(),
bufnr = self.bufnr,
winid = self.winid,
confirm_key = opts.confirm_key or nil,
shortcut_type = opts.shortcut_type,
change_to_vcs_root = opts.change_to_vcs_root,
})
if #opts.preview.command > 0 then
config = vim.tbl_extend('force', config, opts.preview)
end
require('dashboard.theme.' .. opts.theme)(config)
self:cache_ui_options(opts)
api.nvim_create_autocmd('VimResized', {
buffer = self.bufnr,
callback = function()
require('dashboard.theme.' .. opts.theme)(config)
vim.bo[self.bufnr].modifiable = false
end,
})
api.nvim_create_autocmd('BufEnter', {
callback = function(opt)
local bufs = api.nvim_list_bufs()
bufs = vim.tbl_filter(function(k)
return vim.bo[k].filetype == 'dashboard'
end, bufs)
if #bufs == 0 then
self:cache_opts()
self:restore_options()
clean_ctx()
pcall(api.nvim_del_autocmd, opt.id)
end
end,
desc = '[Dashboard] clean dashboard data reduce memory',
})
end
-- create dashboard instance
function db:instance()
local mode = api.nvim_get_mode().mode
if mode == 'i' or not vim.bo.modifiable then
return
end
if not vim.o.hidden and vim.bo.modified then
--save before open
vim.cmd.write()
return
end
if not utils.buf_is_empty(0) then
self.bufnr = api.nvim_create_buf(false, true)
else
self.bufnr = api.nvim_get_current_buf()
end
self.winid = api.nvim_get_current_win()
api.nvim_win_set_buf(self.winid, self.bufnr)
self.user_cursor_line = vim.opt.cursorline:get()
buf_local()
if self.opts then
self:load_theme(self.opts)
else
self:get_opts(function(obj)
self:load_theme(obj)
end)
end
end
function db.setup(opts)
opts = opts or {}
ctx.opts = vim.tbl_deep_extend('force', default_options(), opts)
end
return setmetatable(ctx, db)

View File

@ -0,0 +1,138 @@
local api = vim.api
local db = require('dashboard')
local view = {}
function view:open_window(opt)
local row = math.floor(opt.height / 5)
local col = math.floor((vim.o.columns - opt.width) / 2)
local opts = {
relative = 'editor',
row = row,
col = col,
width = opt.width,
height = opt.height,
style = 'minimal',
noautocmd = true,
}
self.bufnr = api.nvim_create_buf(false, true)
api.nvim_buf_set_option(self.bufnr, 'filetype', 'dashboardpreview')
self.winid = api.nvim_open_win(self.bufnr, false, opts)
if vim.fn.has('nvim-0.8') == 1 then
local normal = api.nvim_get_hl_by_name('Normal', true)
pcall(api.nvim_set_hl, 0, 'DashboardPreview', normal)
else
api.nvim_set_hl(0, 'DashboardPreview', { bg = 'none' })
end
api.nvim_win_set_option(self.winid, 'winhl', 'Normal:DashboardPreview')
return { self.bufnr, self.winid }
end
function view:close_preview_window()
if self.bufnr and api.nvim_buf_is_loaded(self.bufnr) then
api.nvim_buf_delete(self.bufnr, { force = true })
self.bufnr = nil
end
if self.winid and api.nvim_win_is_valid(self.winid) then
api.nvim_win_close(self.winid, true)
self.winid = nil
end
end
function view:preview_events()
local group =
api.nvim_create_augroup('DashboardClosePreview' .. self.preview_bufnr, { clear = true })
--refresh the preview window col position.
local function refresh_preview_wincol()
if not self.preview_winid or not api.nvim_win_is_valid(self.preview_winid) then
return
end
local winconfig = api.nvim_win_get_config(self.preview_winid)
local cur_width = api.nvim_win_get_width(self.main_winid)
if cur_width ~= self.win_width then
local wins = api.nvim_list_wins()
if #wins == 2 then
local scol = bit.rshift(vim.o.columns, 1) - bit.rshift(winconfig.width, 1)
winconfig.col[false] = scol
api.nvim_win_set_config(self.preview_winid, winconfig)
self.win_width = cur_width
return
end
if #wins == 3 then
local new_win = vim.tbl_filter(function(k)
return k ~= self.main_winid and k ~= self.preview_winid
end, wins)[1]
winconfig.col[false] = winconfig.col[false] + api.nvim_win_get_width(new_win)
api.nvim_win_set_config(self.preview_winid, winconfig)
self.win_width = cur_width
end
end
end
local function winresized()
api.nvim_create_autocmd('WinResized', {
group = group,
callback = function()
refresh_preview_wincol()
end,
desc = ' Dashboard preview window resized for nvim 0.9',
})
end
api.nvim_create_autocmd('VimResized', {
group = group,
callback = function()
refresh_preview_wincol()
end,
})
if vim.fn.has('nvim-0.9') == 1 then
winresized()
else
---@deprecated when 0.9 version release remove
api.nvim_create_autocmd('BufEnter', {
group = group,
callback = function()
refresh_preview_wincol()
end,
desc = 'dashboard preview window resize for neovim 0.8+ version',
})
end
end
function view:open_preview(opt)
self.preview_bufnr, self.preview_winid = unpack(view:open_window(opt))
api.nvim_buf_call(self.preview_bufnr, function()
vim.fn.termopen(opt.cmd, {
on_exit = function() end,
})
end)
self.main_winid = api.nvim_get_current_win()
self.win_width = api.nvim_win_get_width(self.main_winid)
api.nvim_create_autocmd('BufWipeout', {
buffer = db.bufnr,
callback = function()
if self.winid and api.nvim_win_is_valid(self.preview_winid) then
api.nvim_win_close(self.preview_winid, true)
self.preview_winid = nil
self.preview_bufnr = nil
self.main_winid = nil
self.win_width = nil
end
end,
once = true,
desc = 'make preview have same lifetime with dashboard buffer',
})
self:preview_events()
end
return view

View File

@ -0,0 +1,225 @@
local api, keymap = vim.api, vim.keymap
local utils = require('dashboard.utils')
local function generate_center(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
local count = item.keymap and #item.keymap or 0
local line = (item.icon or '') .. item.desc
if item.key then
line = line .. (' '):rep(#item.key + 4)
count = count + #item.key + 3
local desc = 'Dashboard-action: ' .. item.desc:gsub('^%s+', '')
keymap.set('n', item.key, function()
if type(item.action) == 'string' then
local dump = loadstring(item.action)
if not dump then
vim.cmd(item.action)
else
dump()
end
elseif type(item.action) == 'function' then
item.action()
end
end, { buffer = config.bufnr, nowait = true, silent = true, desc = desc })
end
if item.keymap then
line = line .. (' '):rep(#item.keymap)
end
table.insert(lines, line)
table.insert(lines, '')
table.insert(counts, count)
table.insert(counts, 0)
end
lines = utils.element_align(lines)
lines = utils.center_align(lines)
for i, count in ipairs(counts) do
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
local ns = api.nvim_create_namespace('DashboardDoom')
local seed = 0
local pos_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
local _, scol = lines[i]:find('%s+')
local ecol = scol + (config.center[idx].icon and #config.center[idx].icon or 0)
if config.center[idx].icon then
api.nvim_buf_add_highlight(
config.bufnr,
0,
config.center[idx].icon_hl or 'DashboardIcon',
first_line + i - 1,
0,
ecol
)
end
api.nvim_buf_add_highlight(
config.bufnr,
0,
config.center[idx].desc_hl or 'DashboardDesc',
first_line + i - 1,
ecol,
-1
)
if config.center[idx].key then
local virt_tbl = {}
if config.center[idx].keymap then
table.insert(virt_tbl, { config.center[idx].keymap, 'DashboardShortCut' })
end
table.insert(virt_tbl, {
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, {
virt_text_pos = 'eol',
virt_text = virt_tbl,
})
end
end
end
local line = api.nvim_buf_get_lines(config.bufnr, first_line, first_line + 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 })
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
api.nvim_create_autocmd('CursorMoved', {
buffer = config.bufnr,
callback = function()
local buf = api.nvim_win_get_buf(0)
if vim.api.nvim_buf_get_option(buf, 'filetype') ~= '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
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 numbers of bytes not
-- the number of characters.
local curline_str = api.nvim_buf_get_lines(config.bufnr, curline - 1, curline, false)[1]
local delta = col_width - api.nvim_strwidth(curline_str:sub(1, col + 1))
api.nvim_win_set_cursor(config.winid, { curline, col + delta })
end,
})
end, 0)
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]
if index and config.center[index].action then
if type(config.center[index].action) == 'string' then
local dump = loadstring(config.center[index].action)
if not dump then
vim.cmd(config.center[index].action)
else
dump()
end
elseif type(config.center[index].action) == 'function' then
config.center[index].action()
else
print('Error with action, check your config')
end
end
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 package_manager_stats = utils.get_package_manager_stats()
local footer = {}
if package_manager_stats.name == 'lazy' then
footer = {
'',
'',
'Startuptime: ' .. package_manager_stats.time .. ' ms',
'Plugins: '
.. package_manager_stats.loaded
.. ' loaded / '
.. package_manager_stats.count
.. ' installed',
}
else
footer = {
'',
'neovim loaded ' .. package_manager_stats.count .. ' plugins',
}
end
if config.footer then
if type(config.footer) == 'function' then
footer = config.footer()
elseif type(config.footer) == 'string' then
local dump = loadstring(config.footer)
if dump then
footer = dump()
end
elseif type(config.footer) == 'table' then
footer = config.footer
end
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)
end
utils.add_update_footer_command(config.bufnr, footer)
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
vim.schedule(function()
api.nvim_exec_autocmds('User', {
pattern = 'DashboardLoaded',
modeline = false,
})
end)
end
return setmetatable({}, {
__call = function(_, t)
return theme_instance(t)
end,
})

View File

@ -0,0 +1,135 @@
local api = vim.api
local utils = require('dashboard.utils')
local function week_ascii_text()
return {
['Monday'] = {
'',
'███╗ ███╗ ██████╗ ███╗ ██╗██████╗ █████╗ ██╗ ██╗',
'████╗ ████║██╔═══██╗████╗ ██║██╔══██╗██╔══██╗╚██╗ ██╔╝',
'██╔████╔██║██║ ██║██╔██╗ ██║██║ ██║███████║ ╚████╔╝ ',
'██║╚██╔╝██║██║ ██║██║╚██╗██║██║ ██║██╔══██║ ╚██╔╝ ',
'██║ ╚═╝ ██║╚██████╔╝██║ ╚████║██████╔╝██║ ██║ ██║ ',
'╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ',
'',
},
['Tuesday'] = {
'',
'████████╗██╗ ██╗███████╗███████╗██████╗ █████╗ ██╗ ██╗',
'╚══██╔══╝██║ ██║██╔════╝██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝',
' ██║ ██║ ██║█████╗ ███████╗██║ ██║███████║ ╚████╔╝ ',
' ██║ ██║ ██║██╔══╝ ╚════██║██║ ██║██╔══██║ ╚██╔╝ ',
' ██║ ╚██████╔╝███████╗███████║██████╔╝██║ ██║ ██║ ',
' ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ',
'',
},
['Wednesday'] = {
'',
'██╗ ██╗███████╗██████╗ ███╗ ██╗███████╗███████╗██████╗ █████╗ ██╗ ██╗',
'██║ ██║██╔════╝██╔══██╗████╗ ██║██╔════╝██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝',
'██║ █╗ ██║█████╗ ██║ ██║██╔██╗ ██║█████╗ ███████╗██║ ██║███████║ ╚████╔╝ ',
'██║███╗██║██╔══╝ ██║ ██║██║╚██╗██║██╔══╝ ╚════██║██║ ██║██╔══██║ ╚██╔╝ ',
'╚███╔███╔╝███████╗██████╔╝██║ ╚████║███████╗███████║██████╔╝██║ ██║ ██║ ',
' ╚══╝╚══╝ ╚══════╝╚═════╝ ╚═╝ ╚═══╝╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ',
'',
},
['Thursday'] = {
'',
'████████╗██╗ ██╗██╗ ██╗██████╗ ███████╗██████╗ █████╗ ██╗ ██╗',
'╚══██╔══╝██║ ██║██║ ██║██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝',
' ██║ ███████║██║ ██║██████╔╝███████╗██║ ██║███████║ ╚████╔╝ ',
' ██║ ██╔══██║██║ ██║██╔══██╗╚════██║██║ ██║██╔══██║ ╚██╔╝ ',
' ██║ ██║ ██║╚██████╔╝██║ ██║███████║██████╔╝██║ ██║ ██║ ',
' ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ',
'',
},
['Friday'] = {
'',
'███████╗██████╗ ██╗██████╗ █████╗ ██╗ ██╗',
'██╔════╝██╔══██╗██║██╔══██╗██╔══██╗╚██╗ ██╔╝',
'█████╗ ██████╔╝██║██║ ██║███████║ ╚████╔╝ ',
'██╔══╝ ██╔══██╗██║██║ ██║██╔══██║ ╚██╔╝ ',
'██║ ██║ ██║██║██████╔╝██║ ██║ ██║ ',
'╚═╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ',
'',
},
['Saturday'] = {
'',
'███████╗ █████╗ ████████╗██╗ ██╗██████╗ ██████╗ █████╗ ██╗ ██╗',
'██╔════╝██╔══██╗╚══██╔══╝██║ ██║██╔══██╗██╔══██╗██╔══██╗╚██╗ ██╔╝',
'███████╗███████║ ██║ ██║ ██║██████╔╝██║ ██║███████║ ╚████╔╝ ',
'╚════██║██╔══██║ ██║ ██║ ██║██╔══██╗██║ ██║██╔══██║ ╚██╔╝ ',
'███████║██║ ██║ ██║ ╚██████╔╝██║ ██║██████╔╝██║ ██║ ██║ ',
'╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ',
'',
},
['Sunday'] = {
'',
'███████╗██╗ ██╗███╗ ██╗██████╗ █████╗ ██╗ ██╗',
'██╔════╝██║ ██║████╗ ██║██╔══██╗██╔══██╗╚██╗ ██╔╝',
'███████╗██║ ██║██╔██╗ ██║██║ ██║███████║ ╚████╔╝ ',
'╚════██║██║ ██║██║╚██╗██║██║ ██║██╔══██║ ╚██╔╝ ',
'███████║╚██████╔╝██║ ╚████║██████╔╝██║ ██║ ██║ ',
'╚══════╝ ╚═════╝ ╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ',
'',
},
}
end
local function default_header()
return {
'',
' ██████╗ █████╗ ███████╗██╗ ██╗██████╗ ██████╗ █████╗ ██████╗ ██████╗ ',
' ██╔══██╗██╔══██╗██╔════╝██║ ██║██╔══██╗██╔═══██╗██╔══██╗██╔══██╗██╔══██╗ ',
' ██║ ██║███████║███████╗███████║██████╔╝██║ ██║███████║██████╔╝██║ ██║ ',
' ██║ ██║██╔══██║╚════██║██╔══██║██╔══██╗██║ ██║██╔══██║██╔══██╗██║ ██║ ',
' ██████╔╝██║ ██║███████║██║ ██║██████╔╝╚██████╔╝██║ ██║██║ ██║██████╔╝ ',
' ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ',
'',
}
end
local function week_header(concat, append)
local week = week_ascii_text()
local daysoftheweek =
{ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' }
local day = daysoftheweek[os.date('*t').wday]
local tbl = week[day]
table.insert(tbl, os.date('%Y-%m-%d %H:%M:%S ') .. (concat or ''))
if append then
vim.list_extend(tbl, append)
end
table.insert(tbl, '')
return tbl
end
local function generate_header(config)
if not vim.bo[config.bufnr].modifiable then
vim.bo[config.bufnr].modifiable = true
end
if not config.command then
local header = config.week_header
and config.week_header.enable
and week_header(config.week_header.concat, config.week_header.append)
or (config.header or default_header())
api.nvim_buf_set_lines(config.bufnr, 0, -1, false, utils.center_align(header))
for i, _ in ipairs(header) do
vim.api.nvim_buf_add_highlight(config.bufnr, 0, 'DashboardHeader', i - 1, 0, -1)
end
return
end
local empty_table = utils.generate_empty_table(config.file_height + 4)
api.nvim_buf_set_lines(config.bufnr, 0, -1, false, utils.center_align(empty_table))
local preview = require('dashboard.preview')
preview:open_preview({
width = config.file_width,
height = config.file_height,
cmd = config.command .. ' ' .. config.file_path,
})
end
return {
generate_header = generate_header,
}

View File

@ -0,0 +1,533 @@
local api, keymap, uv = vim.api, vim.keymap, vim.loop
local utils = require('dashboard.utils')
local ns = api.nvim_create_namespace('dashboard')
local function gen_shortcut(config)
local shortcut = config.shortcut
or {
{ desc = '[ Github]', group = 'DashboardShortCut' },
{ desc = '[ glepnir]', group = 'DashboardShortCut' },
{ desc = '[ 0.2.3]', group = 'DashboardShortCut' },
}
if vim.tbl_isempty(shortcut) then
shortcut = {}
end
local lines = ''
for _, item in pairs(shortcut) do
local str = item.icon and item.icon .. item.desc or item.desc
if item.key then
str = str .. '[' .. item.key .. ']'
end
lines = lines .. ' ' .. str
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 }))
local line = api.nvim_buf_get_lines(config.bufnr, first_line, -1, false)[1]
local start = line:find('[^%s]') - 1
for _, item in pairs(shortcut) do
local _end = start + (item.icon and #(item.icon .. item.desc) or #item.desc)
if item.key then
_end = _end + api.nvim_strwidth(item.key) + 2
keymap.set('n', item.key, function()
if type(item.action) == 'string' then
local dump = loadstring(item.action)
if not dump then
vim.cmd(item.action)
else
dump()
end
elseif type(item.action) == 'function' then
item.action()
end
end, { buffer = config.bufnr, nowait = true, silent = true })
end
api.nvim_buf_add_highlight(
config.bufnr,
0,
item.group or 'DashboardShortCut',
first_line,
start,
_end
)
if item.icon then
api.nvim_buf_add_highlight(
config.bufnr,
0,
item.icon_hl or 'DashboardShortCutIcon',
first_line,
start,
start + #item.icon
)
end
start = _end + 2
end
end
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 lines = {}
if package_manager_stats.name == 'lazy' then
lines = {
'',
'Startuptime: ' .. package_manager_stats.time .. ' ms',
'Plugins: '
.. package_manager_stats.loaded
.. ' loaded / '
.. package_manager_stats.count
.. ' installed',
}
else
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
end
local function reverse(tbl)
for i = 1, math.floor(#tbl / 2) do
tbl[i], tbl[#tbl - i + 1] = tbl[#tbl - i + 1], tbl[i]
end
end
local function project_list(config, callback)
config.project = vim.tbl_extend('force', {
limit = 8,
enable = true,
icon = '󰏓 ',
icon_hl = 'DashboardRecentProjectIcon',
action = 'Telescope find_files cwd=',
label = ' Recent Projects:',
}, config.project or {})
local function read_project(data)
local res = {}
data = string.gsub(data, '%z', '')
local dump = assert(loadstring(data))
local list = dump()
if list then
list = vim.list_slice(list, #list - config.project.limit)
end
for _, dir in ipairs(list or {}) do
dir = dir:gsub(vim.env.HOME, '~')
table.insert(res, (' '):rep(3) .. '' .. dir)
end
if #res == 0 then
table.insert(res, (' '):rep(3) .. ' empty project')
else
reverse(res)
end
table.insert(res, 1, config.project.icon .. config.project.label)
table.insert(res, 1, '')
table.insert(res, '')
return res
end
utils.async_read(
config.path,
vim.schedule_wrap(function(data)
local res = {}
if config.project.enable then
res = read_project(data)
end
callback(res)
end)
)
end
local function mru_list(config)
config.mru = vim.tbl_extend('force', {
icon = '',
limit = 10,
icon_hl = 'DashboardMruIcon',
label = ' Most Recent Files:',
cwd_only = false,
}, config.mru or {})
local list = {
config.mru.icon .. config.mru.label,
}
local groups = {}
local mlist = utils.get_mru_list()
if config.mru.cwd_only then
local cwd = uv.cwd()
mlist = vim.tbl_filter(function(file)
local file_dir = vim.fn.fnamemodify(file, ':p:h')
if file_dir and cwd then
return file_dir:find(cwd, 1, true) == 1
end
end, mlist)
end
for _, file in pairs(vim.list_slice(mlist, 1, config.mru.limit)) do
local filename = vim.fn.fnamemodify(file, ':t')
local icon, group = utils.get_icon(filename)
icon = icon or ''
if config.mru.cwd_only then
file = vim.fn.fnamemodify(file, ':.')
elseif not utils.is_win then
file = vim.fn.fnamemodify(file, ':~')
end
file = icon .. ' ' .. file
table.insert(groups, { #icon, group })
table.insert(list, (' '):rep(3) .. file)
end
if #list == 1 then
table.insert(list, (' '):rep(3) .. ' empty files')
end
return list, groups
end
local function shuffle_table(table)
for i = #table, 2, -1 do
local j = math.random(i)
table[i], table[j] = table[j], table[i]
end
end
local function letter_hotkey(config)
-- Reserve j, k keys to move up and down.
local list = { 106, 107 }
for _, item in pairs(config.shortcut or {}) do
if item.key then
table.insert(list, item.key:byte())
end
end
math.randomseed(os.time())
-- Create key table, fill it with unused characters.
local unused_keys = {}
-- a - z
for key = 97, 122 do
if not vim.tbl_contains(list, key) then
table.insert(unused_keys, key)
end
end
shuffle_table(unused_keys)
local unused_uppercase_keys = {}
-- A - Z
for key = 65, 90 do
if not vim.tbl_contains(list, key) then
table.insert(unused_uppercase_keys, key)
end
end
shuffle_table(unused_uppercase_keys)
-- Push shuffled uppercase keys after the lowercase ones
for _, key in pairs(unused_uppercase_keys) do
table.insert(unused_keys, key)
end
local fallback_hotkey = 0
return function()
if #unused_keys ~= 0 then
-- Pop an unused key to use it as a hotkey.
local key = table.remove(unused_keys, 1)
return string.char(key)
else
-- All keys are already used. Fallback to the number generation.
fallback_hotkey = fallback_hotkey + 1
return fallback_hotkey
end
end
end
local function number_hotkey()
local start = 0
return function()
start = start + 1
return start
end
end
local function gen_hotkey(config)
if config.shortcut_type == 'number' then
return number_hotkey()
end
return letter_hotkey(config)
end
local function map_key(config, key, content)
keymap.set('n', key, function()
local text = content or api.nvim_get_current_line()
local scol = utils.is_win and text:find('%w') or text:find('%p')
local path = nil
if scol ~= nil then -- scol == nil if pressing enter in empty space
if text:sub(scol, scol + 1) ~= '~/' then -- is relative path
scol = math.min(text:find('%w'), text:find('%p'))
end
text = text:sub(scol)
path = text:sub(1, text:find('%w(%s+)$'))
path = vim.fs.normalize(path)
end
if path == nil then
vim.cmd('enew')
elseif vim.fn.isdirectory(path) == 1 then
vim.cmd('lcd ' .. path)
if type(config.project.action) == 'function' then
config.project.action(path)
elseif type(config.project.action) == 'string' then
local dump = loadstring(config.project.action)
if not dump then
vim.cmd(config.project.action .. path)
else
dump(path)
end
end
else
vim.cmd('edit ' .. vim.fn.fnameescape(path))
local root = utils.get_vcs_root()
if not config.change_to_vcs_root then
return
end
if #root > 0 then
vim.cmd('lcd ' .. vim.fn.fnamemodify(root[#root], ':h'))
else
vim.cmd('lcd ' .. vim.fn.fnamemodify(path, ':h'))
end
end
end, { buffer = config.bufnr, silent = true, nowait = true })
end
local function gen_center(plist, config)
local mlist, mgroups = mru_list(config)
local plist_len = #plist
if plist_len == 0 then
plist[#plist + 1] = ''
plist_len = 1
end
---@diagnostic disable-next-line: param-type-mismatch
vim.list_extend(plist, mlist)
local max_len = utils.get_max_len(plist)
if max_len <= 40 then
local fill = (' '):rep(math.floor(vim.o.columns / 4))
for i, v in pairs(plist) do
plist[i] = v .. fill
end
end
plist = utils.element_align(plist)
plist = utils.center_align(plist)
local first_line = api.nvim_buf_line_count(config.bufnr)
api.nvim_buf_set_lines(config.bufnr, first_line, -1, false, plist)
local start_col = plist[plist_len + 2]:find('[^%s]') - 1
local _, scol = plist[2]:find('%S')
local hotkey = gen_hotkey(config)
api.nvim_buf_add_highlight(config.bufnr, 0, 'DashboardProjectTitle', first_line + 1, 0, -1)
api.nvim_buf_add_highlight(
config.bufnr,
0,
'DashboardProjectTitleIcon',
first_line + 1,
0,
scol + #config.project.icon
)
for i = 3, plist_len do
api.nvim_buf_add_highlight(
config.bufnr,
0,
'DashboardProjectIcon',
first_line + i - 1,
0,
start_col + 3
)
api.nvim_buf_add_highlight(
config.bufnr,
0,
'DashboardFiles',
first_line + i - 1,
start_col + 3,
-1
)
local text = api.nvim_buf_get_lines(config.bufnr, first_line + i - 1, first_line + i, false)[1]
if text and text:find('%w') and not text:find('empty') then
local key = tostring(hotkey())
api.nvim_buf_set_extmark(config.bufnr, ns, first_line + i - 1, 0, {
virt_text = { { key, 'DashboardShortCut' } },
virt_text_pos = 'eol',
})
map_key(config, key, text)
end
end
-- initialize the cursor pos
api.nvim_win_set_cursor(config.winid, { first_line + 3, start_col + 4 })
api.nvim_buf_add_highlight(config.bufnr, 0, 'DashboardMruTitle', first_line + plist_len, 0, -1)
api.nvim_buf_add_highlight(
config.bufnr,
0,
'DashboardMruIcon',
first_line + plist_len,
0,
scol + #config.mru.icon
)
for i, data in pairs(mgroups) do
local len, group = unpack(data)
api.nvim_buf_add_highlight(
config.bufnr,
0,
group,
first_line + i + plist_len,
start_col,
start_col + len
)
api.nvim_buf_add_highlight(
config.bufnr,
0,
'DashboardFiles',
first_line + i + plist_len,
start_col + len,
-1
)
local text = api.nvim_buf_get_lines(
config.bufnr,
first_line + i + plist_len,
first_line + i + plist_len + 1,
false
)[1]
if text and text:find('%w') then
local key = tostring(hotkey())
api.nvim_buf_set_extmark(config.bufnr, ns, first_line + i + plist_len, 0, {
virt_text = { { key, 'DashboardShortCut' } },
virt_text_pos = 'eol',
})
map_key(config, key, text)
end
end
end
local function gen_footer(config)
local footer = {
'',
' 🚀 Sharp tools make good work.',
}
if type(config.footer) == 'string' then
local dump = loadstring(config.footer)
if dump then
footer = dump()
end
elseif type(config.footer) == 'function' then
footer = config.footer()
elseif type(config.footer) == 'table' then
footer = 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(footer))
---@diagnostic disable-next-line: param-type-mismatch
for i, _ in pairs(footer) do
api.nvim_buf_add_highlight(config.bufnr, 0, 'DashboardFooter', first_line + i - 1, 0, -1)
end
utils.add_update_footer_command(config.bufnr, footer)
end
local function project_delete()
api.nvim_create_user_command('DbProjectDelete', function(args)
local path = utils.path_join(vim.fn.stdpath('cache'), 'dashboard', 'cache')
utils.async_read(
path,
vim.schedule_wrap(function(data)
local dump = assert(loadstring(data))
local list = dump()
local count = tonumber(args.args)
if vim.tbl_count(list) < count then
return
end
list = vim.list_slice(list, count + 1)
local str = string.dump(assert(loadstring('return ' .. vim.inspect(list))))
local handle = io.open(path, 'w+')
if not handle then
return
end
handle:write(str)
handle:close()
end)
)
end, {
nargs = '+',
})
end
local function theme_instance(config)
project_list(config, function(plist)
if not api.nvim_buf_is_valid(config.bufnr) then
return
end
if config.disable_move then
utils.disable_move_key(config.bufnr)
end
require('dashboard.theme.header').generate_header(config)
if not config.shortcut or not vim.tbl_isempty(config.shortcut) then
gen_shortcut(config)
end
load_packages(config)
gen_center(plist, config)
gen_footer(config)
map_key(config, config.confirm_key or '<CR>')
require('dashboard.events').register_lsp_root(config.path)
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)
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',
modeline = false,
})
end)
project_delete()
end)
end
return setmetatable({}, {
__call = function(_, t)
theme_instance(t)
end,
})

View File

@ -0,0 +1,198 @@
local uv = vim.loop
local utils = {}
utils.is_win = uv.os_uname().version:match('Windows')
function utils.path_join(...)
local path_sep = utils.is_win and '\\' or '/'
return table.concat({ ... }, path_sep)
end
function utils.element_align(tbl)
local lens = {}
vim.tbl_map(function(k)
table.insert(lens, vim.api.nvim_strwidth(k))
end, tbl)
table.sort(lens)
local max = lens[#lens]
local res = {}
for _, item in pairs(tbl) do
local len = vim.api.nvim_strwidth(item)
local times = math.floor((max - len) / vim.api.nvim_strwidth(' '))
item = item .. (' '):rep(times)
table.insert(res, item)
end
return res
end
function utils.get_max_len(contents)
vim.validate({
contents = { contents, 't' },
})
local cells = {}
for _, v in pairs(contents) do
table.insert(cells, vim.api.nvim_strwidth(v))
end
table.sort(cells)
return cells[#cells]
end
-- draw the graphics into the screen center
function utils.center_align(tbl)
vim.validate({
tbl = { tbl, 'table' },
})
local function fill_sizes(lines)
local fills = {}
for _, line in pairs(lines) do
table.insert(fills, math.floor((vim.o.columns - vim.api.nvim_strwidth(line)) / 2))
end
return fills
end
local centered_lines = {}
local fills = fill_sizes(tbl)
for i = 1, #tbl do
local fill_line = (' '):rep(fills[i]) .. tbl[i]
table.insert(centered_lines, fill_line)
end
return centered_lines
end
function utils.get_icon(filename)
local ok, devicons = pcall(require, 'nvim-web-devicons')
if not ok then
vim.notify('[dashboard.nvim] not found nvim-web-devicons')
return nil
end
return devicons.get_icon(filename, nil, { default = true })
end
function utils.read_project_cache(path)
local fd = assert(uv.fs_open(path, 'r', tonumber('644', 8)))
local stat = uv.fs_fstat(fd)
local chunk = uv.fs_read(fd, stat.size, 0)
local dump = assert(loadstring(chunk))
return dump()
end
function utils.async_read(path, callback)
uv.fs_open(path, 'a+', 438, function(err, fd)
assert(not err, err)
uv.fs_fstat(fd, function(err, stat)
assert(not err, err)
uv.fs_read(fd, stat.size, 0, function(err, data)
assert(not err, err)
uv.fs_close(fd, function(err)
assert(not err, err)
callback(data)
end)
end)
end)
end)
end
function utils.disable_move_key(bufnr)
local keys = { 'w', 'f', 'b', 'h', 'j', 'k', 'l', '<Up>', '<Down>', '<Left>', '<Right>' }
vim.tbl_map(function(k)
vim.keymap.set('n', k, '<Nop>', { buffer = bufnr })
end, keys)
end
--- return the most recently files list
function utils.get_mru_list()
local mru = {}
for _, file in pairs(vim.v.oldfiles or {}) do
if file and vim.fn.filereadable(file) == 1 then
table.insert(mru, file)
end
end
return mru
end
function utils.get_package_manager_stats()
local package_manager_stats = { name = '', count = 0, loaded = 0, time = 0 }
---@diagnostic disable-next-line: undefined-global
if packer_plugins then
package_manager_stats.name = 'packer'
---@diagnostic disable-next-line: undefined-global
package_manager_stats.count = #vim.tbl_keys(packer_plugins)
end
local status, lazy = pcall(require, 'lazy')
if status then
package_manager_stats.name = 'lazy'
package_manager_stats.loaded = lazy.stats().loaded
package_manager_stats.count = lazy.stats().count
package_manager_stats.time = lazy.stats().startuptime
end
return package_manager_stats
end
--- generate an empty table by length
function utils.generate_empty_table(length)
local empty_tbl = {}
if length == 0 then
return empty_tbl
end
for _ = 1, length do
table.insert(empty_tbl, '')
end
return empty_tbl
end
function utils.generate_truncateline(cells)
local char = ''
return char:rep(math.floor(cells / vim.api.nvim_strwidth(char)))
end
function utils.get_vcs_root(buf)
buf = buf or 0
local path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(buf), ':p:h')
local patterns = { '.git', '.hg', '.bzr', '.svn' }
for _, pattern in pairs(patterns) do
local root = vim.fs.find(pattern, { path = path, upward = true, stop = vim.env.HOME })
if root then
return root
end
end
end
local index = 0
function utils.gen_bufname(prefix)
index = index + 1
return prefix .. '-' .. index
end
function utils.buf_is_empty(bufnr)
bufnr = bufnr or 0
return vim.api.nvim_buf_line_count(0) == 1
and vim.api.nvim_buf_get_lines(0, 0, -1, false)[1] == ''
end
local last_footer_size = nil
function utils.add_update_footer_command(bufnr, footer)
vim.api.nvim_create_user_command('DashboardUpdateFooter', function(args)
if last_footer_size == nil then
last_footer_size = #footer
end
local first_line = vim.api.nvim_buf_line_count(bufnr)
vim.bo[bufnr].modifiable = true
vim.api.nvim_buf_set_lines(
bufnr,
first_line - last_footer_size,
-1,
false,
utils.center_align(args.fargs)
)
vim.bo[bufnr].modifiable = false
vim.bo[bufnr].modified = false
last_footer_size = #args.fargs -- For future calculation of size
end, { nargs = '*' })
end
return utils

View File

@ -0,0 +1,27 @@
-- version 0.2.3
local g = vim.api.nvim_create_augroup('dashboard', { clear = true })
vim.api.nvim_create_autocmd('StdinReadPre', {
group = g,
callback = function()
vim.g.read_from_stdin = 1
end,
})
vim.api.nvim_create_autocmd('UIEnter', {
group = g,
callback = function()
if
vim.fn.argc() == 0
and vim.api.nvim_buf_get_name(0) == ''
and vim.g.read_from_stdin == nil
then
require('dashboard'):instance()
end
end,
})
vim.api.nvim_create_user_command('Dashboard', function()
require('dashboard'):instance()
end, {})

View File

@ -0,0 +1,89 @@
name: Bug Report
description: File a bug/issue
title: "bug: "
labels: [bug]
body:
- type: markdown
attributes:
value: |
**Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/persistence.nvim) and search [existing issues](https://github.com/folke/persistence.nvim/issues). Usage questions such as ***"How do I...?"*** belong in [Discussions](https://github.com/folke/persistence.nvim/discussions) and will be closed.
- type: checkboxes
attributes:
label: Did you check docs and existing issues?
description: Make sure you checked all of the below before submitting an issue
options:
- label: I have read all the persistence.nvim docs
required: true
- label: I have searched the existing issues of persistence.nvim
required: true
- label: I have searched the existing issues of plugins related to this issue
required: true
- type: input
attributes:
label: "Neovim version (nvim -v)"
placeholder: "0.8.0 commit db1b0ee3b30f"
validations:
required: true
- type: input
attributes:
label: "Operating system/version"
placeholder: "MacOS 11.5"
validations:
required: true
- type: textarea
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is. Please include any related errors you see in Neovim.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1.
2.
3.
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Repro
description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
value: |
-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")
-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)
-- install plugins
local plugins = {
"folke/tokyonight.nvim",
"folke/persistence.nvim",
-- add any other plugins here
}
require("lazy").setup(plugins, {
root = root .. "/plugins",
})
vim.cmd.colorscheme("tokyonight")
-- add anything else here
render: Lua
validations:
required: false

View File

@ -0,0 +1,36 @@
name: Feature Request
description: Suggest a new feature
title: "feature: "
labels: [enhancement]
body:
- type: checkboxes
attributes:
label: Did you check the docs?
description: Make sure you read all the docs before submitting a feature request
options:
- label: I have read all the persistence.nvim docs
required: true
- type: textarea
validations:
required: true
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
- type: textarea
validations:
required: true
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
- type: textarea
validations:
required: true
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
- type: textarea
validations:
required: false
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,72 @@
name: CI
on:
push:
pull_request:
jobs:
tests:
strategy:
matrix:
# os: [ubuntu-latest, windows-latest]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Install Neovim
shell: bash
run: |
mkdir -p /tmp/nvim
wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim.appimage -O /tmp/nvim/nvim.appimage
cd /tmp/nvim
chmod a+x ./nvim.appimage
./nvim.appimage --appimage-extract
echo "/tmp/nvim/squashfs-root/usr/bin/" >> $GITHUB_PATH
- name: Run Tests
run: |
nvim --version
[ ! -d tests ] && exit 0
nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua', sequential = true}"
docs:
runs-on: ubuntu-latest
needs: tests
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v3
- name: panvimdoc
uses: kdheepak/panvimdoc@main
with:
vimdoc: persistence.nvim
version: "Neovim >= 0.8.0"
demojify: true
treesitter: true
- name: Push changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "chore(build): auto-generate vimdoc"
commit_user_name: "github-actions[bot]"
commit_user_email: "github-actions[bot]@users.noreply.github.com"
commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
release:
name: release
if: ${{ github.ref == 'refs/heads/main' }}
needs:
- docs
- tests
runs-on: ubuntu-latest
steps:
- uses: google-github-actions/release-please-action@v3
id: release
with:
release-type: simple
package-name: persistence.nvim
- uses: actions/checkout@v3
- name: tag stable versions
if: ${{ steps.release.outputs.release_created }}
run: |
git config user.name github-actions[bot]
git config user.email github-actions[bot]@users.noreply.github.com
git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git"
git tag -d stable || true
git push origin :stable || true
git tag -a stable -m "Last Stable Release"
git push origin stable

View File

@ -0,0 +1,8 @@
tt.*
.tests
doc/tags
debug
.repro
foo.*
*.log
data

View File

@ -0,0 +1,61 @@
# Changelog
## [2.0.0](https://github.com/folke/persistence.nvim/compare/v1.2.1...v2.0.0) (2023-10-15)
### ⚠ BREAKING CHANGES
* **start:** session name is now based on the cwd when the session starts and not when the session ends. Fixes #1688
### Bug Fixes
* **start:** session name is now based on the cwd when the session starts and not when the session ends. Fixes [#1688](https://github.com/folke/persistence.nvim/issues/1688) ([0361df7](https://github.com/folke/persistence.nvim/commit/0361df7775f5b4ed51a6d7fe159438573b7f07a6))
## [1.2.1](https://github.com/folke/persistence.nvim/compare/v1.2.0...v1.2.1) (2023-10-13)
### Bug Fixes
* dont save the session when only `gitcommit` buffers are present. Fixes [#14](https://github.com/folke/persistence.nvim/issues/14) ([8f7cbcc](https://github.com/folke/persistence.nvim/commit/8f7cbccfb506fe6cb35db9ad966137c363b049c5))
## [1.2.0](https://github.com/folke/persistence.nvim/compare/v1.1.0...v1.2.0) (2023-10-13)
### Features
* don't save the session when no files are open (save_empty = false) ([e9afeaf](https://github.com/folke/persistence.nvim/commit/e9afeaf3a7bb645ca73980cd13048c48c292500c))
## [1.1.0](https://github.com/folke/persistence.nvim/compare/v1.0.1...v1.1.0) (2023-02-28)
### Features
* **persistence:** `pre_save` option to call before saving ([#22](https://github.com/folke/persistence.nvim/issues/22)) ([f4bb0c5](https://github.com/folke/persistence.nvim/commit/f4bb0c5641a0e6c9ac3675ddd794ca78099d8510))
## [1.0.1](https://github.com/folke/persistence.nvim/compare/v1.0.0...v1.0.1) (2023-01-06)
### Bug Fixes
* dont throw error when session was already stopped ([70c281e](https://github.com/folke/persistence.nvim/commit/70c281e54e34630d8bef9b1cf9f7a0ac3edd6a1c))
## 1.0.0 (2023-01-04)
### ⚠ BREAKING CHANGES
* save sessions in state instead of config
### Features
* added config options ([a39f3f1](https://github.com/folke/persistence.nvim/commit/a39f3f10c836709f9b6e009b20a1f028851c50e0))
* inital version ([8b32094](https://github.com/folke/persistence.nvim/commit/8b32094309ee986066c219d2b4d88a4045fbcb8c))
* save sessions in state instead of config ([c304745](https://github.com/folke/persistence.nvim/commit/c30474509666187181add6122e775f9978478c81))
### Bug Fixes
* dont show errors when loading a session ([ad7fcd4](https://github.com/folke/persistence.nvim/commit/ad7fcd4fed0cecb9ae3c6cbc4a61801ef4e2466d))
* properly escape session file names on Windows ([#7](https://github.com/folke/persistence.nvim/issues/7)) ([83af96b](https://github.com/folke/persistence.nvim/commit/83af96b1f205dddab066c96b029ceeee192b48d4))
* renamed session to persistence in autocmds ([38203a1](https://github.com/folke/persistence.nvim/commit/38203a17a97d49bfcc938f171ecfa44f52dda08e))
* vim.fn.has('win32') returns 0 or 1, not a boolean ([#8](https://github.com/folke/persistence.nvim/issues/8)) ([77cf5a6](https://github.com/folke/persistence.nvim/commit/77cf5a6ee162013b97237ff25450080401849f85))

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,61 @@
# 💾 Persistence
**Persistence** is a simple lua plugin for automated session management.
## ✨ Features
- automatically saves the active session under `~/.local/state/nvim/sessions` on exit
- simple API to restore the current or last session
## ⚡️ Requirements
- Neovim >= 0.7.2
## 📦 Installation
Install the plugin with your preferred package manager:
### [lazy.nvim](https://github.com/folke/lazy.nvim)
```lua
-- Lua
{
"folke/persistence.nvim",
event = "BufReadPre", -- this will only start session saving when an actual file was opened
opts = {
-- add any custom options here
}
}
```
## ⚙️ Configuration
Persistence comes with the following defaults:
```lua
{
dir = vim.fn.expand(vim.fn.stdpath("state") .. "/sessions/"), -- directory where session files are saved
options = { "buffers", "curdir", "tabpages", "winsize" }, -- sessionoptions used for saving
pre_save = nil, -- a function to call before saving the session
post_save = nil, -- a function to call after saving the session
save_empty = false, -- don't save if there are no open file buffers
pre_load = nil, -- a function to call before loading the session
post_load = nil, -- a function to call after loading the session
}
```
## 🚀 Usage
**Persistence** works well with plugins like `startify` or `dashboard`. It will never restore a session automatically,
but you can of course write an autocmd that does exactly that if you want.
```lua
-- restore the session for the current directory
vim.api.nvim_set_keymap("n", "<leader>qs", [[<cmd>lua require("persistence").load()<cr>]], {})
-- restore the last session
vim.api.nvim_set_keymap("n", "<leader>ql", [[<cmd>lua require("persistence").load({ last = true })<cr>]], {})
-- stop Persistence => session won't be saved on exit
vim.api.nvim_set_keymap("n", "<leader>qd", [[<cmd>lua require("persistence").stop()<cr>]], {})
```

View File

@ -0,0 +1,85 @@
*persistence.nvim.txt* For Neovim >= 0.8.0 Last change: 2024 May 16
==============================================================================
Table of Contents *persistence.nvim-table-of-contents*
1. Persistence |persistence.nvim-persistence|
- Features |persistence.nvim-persistence-features|
- Requirements |persistence.nvim-persistence-requirements|
- Installation |persistence.nvim-persistence-installation|
- Configuration |persistence.nvim-persistence-configuration|
- Usage |persistence.nvim-persistence-usage|
==============================================================================
1. Persistence *persistence.nvim-persistence*
**Persistence** is a simple lua plugin for automated session management.
FEATURES *persistence.nvim-persistence-features*
- automatically saves the active session under `~/.local/state/nvim/sessions` on exit
- simple API to restore the current or last session
REQUIREMENTS *persistence.nvim-persistence-requirements*
- Neovim >= 0.7.2
INSTALLATION *persistence.nvim-persistence-installation*
Install the plugin with your preferred package manager:
LAZY.NVIM ~
>lua
-- Lua
{
"folke/persistence.nvim",
event = "BufReadPre", -- this will only start session saving when an actual file was opened
opts = {
-- add any custom options here
}
}
<
CONFIGURATION *persistence.nvim-persistence-configuration*
Persistence comes with the following defaults:
>lua
{
dir = vim.fn.expand(vim.fn.stdpath("state") .. "/sessions/"), -- directory where session files are saved
options = { "buffers", "curdir", "tabpages", "winsize" }, -- sessionoptions used for saving
pre_save = nil, -- a function to call before saving the session
post_save = nil, -- a function to call after saving the session
save_empty = false, -- don't save if there are no open file buffers
pre_load = nil, -- a function to call before loading the session
post_load = nil, -- a function to call after loading the session
}
<
USAGE *persistence.nvim-persistence-usage*
**Persistence** works well with plugins like `startify` or `dashboard`. It will
never restore a session automatically, but you can of course write an autocmd
that does exactly that if you want.
>lua
-- restore the session for the current directory
vim.api.nvim_set_keymap("n", "<leader>qs", [[<cmd>lua require("persistence").load()<cr>]], {})
-- restore the last session
vim.api.nvim_set_keymap("n", "<leader>ql", [[<cmd>lua require("persistence").load({ last = true })<cr>]], {})
-- stop Persistence => session won't be saved on exit
vim.api.nvim_set_keymap("n", "<leader>qd", [[<cmd>lua require("persistence").stop()<cr>]], {})
<
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -0,0 +1,8 @@
persistence.nvim-persistence persistence.nvim.txt /*persistence.nvim-persistence*
persistence.nvim-persistence-configuration persistence.nvim.txt /*persistence.nvim-persistence-configuration*
persistence.nvim-persistence-features persistence.nvim.txt /*persistence.nvim-persistence-features*
persistence.nvim-persistence-installation persistence.nvim.txt /*persistence.nvim-persistence-installation*
persistence.nvim-persistence-requirements persistence.nvim.txt /*persistence.nvim-persistence-requirements*
persistence.nvim-persistence-usage persistence.nvim.txt /*persistence.nvim-persistence-usage*
persistence.nvim-table-of-contents persistence.nvim.txt /*persistence.nvim-table-of-contents*
persistence.nvim.txt persistence.nvim.txt /*persistence.nvim.txt*

View File

@ -0,0 +1,22 @@
local M = {}
---@class PersistenceOptions
---@field pre_save? fun()
---@field post_save? fun()
---@field pre_load? fun()
---@field post_load? fun()
local defaults = {
dir = vim.fn.expand(vim.fn.stdpath("state") .. "/sessions/"), -- directory where session files are saved
options = { "buffers", "curdir", "tabpages", "winsize", "skiprtp" }, -- sessionoptions used for saving
save_empty = false, -- don't save if there are no open file buffers
}
---@type PersistenceOptions
M.options = {}
function M.setup(opts)
M.options = vim.tbl_deep_extend("force", {}, defaults, opts or {})
vim.fn.mkdir(M.options.dir, "p")
end
return M

View File

@ -0,0 +1,99 @@
local Config = require("persistence.config")
local M = {}
---@type string?
M.current = nil
local e = vim.fn.fnameescape
function M.get_current()
local pattern = "/"
if vim.fn.has("win32") == 1 then
pattern = "[\\:]"
end
local name = vim.fn.getcwd():gsub(pattern, "%%")
return Config.options.dir .. name .. ".vim"
end
function M.get_last()
local sessions = M.list()
table.sort(sessions, function(a, b)
return vim.loop.fs_stat(a).mtime.sec > vim.loop.fs_stat(b).mtime.sec
end)
return sessions[1]
end
function M.setup(opts)
Config.setup(opts)
M.start()
end
function M.start()
M.current = M.get_current()
vim.api.nvim_create_autocmd("VimLeavePre", {
group = vim.api.nvim_create_augroup("persistence", { clear = true }),
callback = function()
if Config.options.pre_save then
Config.options.pre_save()
end
if not Config.options.save_empty then
local bufs = vim.tbl_filter(function(b)
if vim.bo[b].buftype ~= "" then
return false
end
if vim.bo[b].filetype == "gitcommit" then
return false
end
if vim.bo[b].filetype == "gitrebase" then
return false
end
return vim.api.nvim_buf_get_name(b) ~= ""
end, vim.api.nvim_list_bufs())
if #bufs == 0 then
return
end
end
M.save()
if type(Config.options.post_save) == "function" then
Config.options.post_save()
end
end,
})
end
function M.stop()
M.current = nil
pcall(vim.api.nvim_del_augroup_by_name, "persistence")
end
function M.save()
local tmp = vim.o.sessionoptions
vim.o.sessionoptions = table.concat(Config.options.options, ",")
vim.cmd("mks! " .. e(M.current or M.get_current()))
vim.o.sessionoptions = tmp
end
function M.load(opt)
opt = opt or {}
local sfile = opt.last and M.get_last() or M.get_current()
if sfile and vim.fn.filereadable(sfile) ~= 0 then
if type(Config.options.pre_load) == "function" then
Config.options.pre_load()
end
vim.cmd("silent! source " .. e(sfile))
if type(Config.options.post_load) == "function" then
Config.options.post_load()
end
end
end
function M.list()
return vim.fn.glob(Config.options.dir .. "*.vim", true, true)
end
return M

View File

@ -0,0 +1 @@
std="lua51+vim"

View File

@ -0,0 +1,3 @@
indent_type = "Spaces"
indent_width = 2
column_width = 120

View File

@ -0,0 +1,2 @@
[vim]
any = true