pax_global_header 0000666 0000000 0000000 00000000064 15171555353 0014524 g ustar 00root root 0000000 0000000 52 comment=2efd499a38574ff0390120e7b58f55e9bccfc822
neovim-alpha-0.0~git20260417.6c6a89d/ 0000775 0000000 0000000 00000000000 15171555353 0016556 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/.editorconfig 0000664 0000000 0000000 00000000357 15171555353 0021240 0 ustar 00root root 0000000 0000000 # top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
[.lua]
charset = utf-8
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
neovim-alpha-0.0~git20260417.6c6a89d/.github/ 0000775 0000000 0000000 00000000000 15171555353 0020116 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15171555353 0022301 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/.github/ISSUE_TEMPLATE/new-issue.md 0000664 0000000 0000000 00000000452 15171555353 0024543 0 ustar 00root root 0000000 0000000 ---
name: New Issue
about: new issue template
title: ''
labels: ''
assignees: ''
---
please *read the documentation* before asking questions about configuration or creating a feature request
for bugs: provide the expected behavior and the actual behavior, and screenshots if you want to be nice
neovim-alpha-0.0~git20260417.6c6a89d/.gitignore 0000664 0000000 0000000 00000000026 15171555353 0020544 0 ustar 00root root 0000000 0000000 doc/tags
/.luarc.json
neovim-alpha-0.0~git20260417.6c6a89d/CONTRIBUTING.md 0000664 0000000 0000000 00000000534 15171555353 0021011 0 ustar 00root root 0000000 0000000 # tooling
- stylua is used to format the lua code. `stylua lua/` should be good enough.
I'm not going to deny your PR if it's not formatted, it's just there for
people who want it.
- There's also an editorconfig file, which you may need a plugin to use
which will set some appropriate settings in your editor to hack on the code.
neovim-alpha-0.0~git20260417.6c6a89d/LICENSE 0000664 0000000 0000000 00000002041 15171555353 0017560 0 ustar 00root root 0000000 0000000 Copyright 2021 Zachary Churchill
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.
neovim-alpha-0.0~git20260417.6c6a89d/README.md 0000664 0000000 0000000 00000010472 15171555353 0020041 0 ustar 00root root 0000000 0000000 # α alpha-nvim
`alpha` is a fast and fully programmable greeter for neovim.
share or snipe some custom themes @ https://github.com/goolord/alpha-nvim/discussions/16
## Quick Start
#### vim-startify theme

EXAMPLES
With [lazy.nvim](https://github.com/folke/lazy.nvim):
```lua
{
'goolord/alpha-nvim',
dependencies = { 'nvim-mini/mini.icons' },
config = function ()
require'alpha'.setup(require'alpha.themes.startify'.config)
end
};
```
With packer:
```lua
use {
'goolord/alpha-nvim',
requires = { 'nvim-mini/mini.icons' },
config = function ()
require'alpha'.setup(require'alpha.themes.startify'.config)
end
}
```
..or using paq:
```lua
require "paq" {
"goolord/alpha-nvim";
"nvim-mini/mini.icons";
}
require'alpha'.setup(require'alpha.themes.startify'.config)
```
#### dashboard-nvim theme

EXAMPLES
With [lazy.nvim](https://github.com/folke/lazy.nvim):
```lua
{
'goolord/alpha-nvim',
config = function ()
require'alpha'.setup(require'alpha.themes.dashboard'.config)
end
};
```
With packer:
```lua
use {
'goolord/alpha-nvim',
config = function ()
require'alpha'.setup(require'alpha.themes.dashboard'.config)
end
}
```
..or using paq:
```lua
require "paq" {
"goolord/alpha-nvim";
"nvim-mini/mini.icons";
}
require'alpha'.setup(require'alpha.themes.dashboard'.config)
```
#### Theta theme
EXAMPLES
With [lazy.nvim](https://github.com/folke/lazy.nvim):
```lua
{
'goolord/alpha-nvim',
dependencies = {
'nvim-mini/mini.icons',
'nvim-lua/plenary.nvim'
},
config = function ()
require'alpha'.setup(require'alpha.themes.theta'.config)
end
};
```
With packer:
```lua
use {
'goolord/alpha-nvim',
requires = {
'nvim-mini/mini.icons',
'nvim-lua/plenary.nvim'
},
config = function ()
require'alpha'.setup(require'alpha.themes.dashboard'.config)
end
}
```
..or using paq:
```lua
require "paq" {
"goolord/alpha-nvim";
"nvim-mini/mini.icons";
'nvim-lua/plenary.nvim';
}
require'alpha'.setup(require'alpha.themes.dashboard'.config)
```
if you want sessions, see
- [`Shatur/neovim-session-manager`](https://github.com/Shatur/neovim-session-manager)
- `:h :mks`
this theme makes some assumptions about your default keybindings
to customize the buttons, see `:h alpha-example`
#### File Icons
theta/startify theme support file icons, default is enabled and `mini` icon provider is used.
- [`nvim-tree/nvim-web-devicons`](https://github.com/nvim-tree/nvim-web-devicons)
- [`nvim-mini/mini.icons`](https://github.com/nvim-mini/mini.nvim/blob/main/readmes/mini-icons.md)
if you prefer `nvim-web-devicons` icon provider, use the following example with `lazy.nvim`:
```lua
{
"goolord/alpha-nvim",
-- dependencies = { 'nvim-mini/mini.icons' },
dependencies = { 'nvim-tree/nvim-web-devicons' },
config = function()
local startify = require("alpha.themes.startify")
-- available: devicons, mini, default is mini
-- if provider not loaded and enabled is true, it will try to use another provider
startify.file_icons.provider = "devicons"
require("alpha").setup(
startify.config
)
end,
},
```
## Elevator pitch
alpha is really a general purpose neovim ui library with some conveniences for writing a greeter ui.
it has a functional, data-oriented api design. themes are expressed entirely as data, which is what makes
alpha "fully programmable". alpha is also the fastest greeter I've benchmarked (which is why I daily drive it myself!).
## Profiling Results

- using [`lewis6991/impatient.nvim`](https://github.com/lewis6991/impatient.nvim)
- only config! doesn't measure drawing, some startup plugins won't measure drawing either
## Special Thanks
- https://github.com/glepnir/dashboard-nvim - inspiration, code reference
- https://github.com/mhinz/vim-startify - inspiration
neovim-alpha-0.0~git20260417.6c6a89d/debug/ 0000775 0000000 0000000 00000000000 15171555353 0017644 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/debug/DEBUG.md 0000664 0000000 0000000 00000000516 15171555353 0021016 0 ustar 00root root 0000000 0000000 run with one of these (in order of preference)
- `nvim --clean -u debug/min-alpha-dashboard.lua`
- `nvim --clean -u debug/min-alpha-startify.lua`
- `nvim --noplugin -u debug/min-alpha-dashboard.lua`
- `nvim --noplugin -u debug/min-alpha-startify.lua`
- `nvim -u debug/min-alpha-dashboard.lua`
- `nvim -u debug/min-alpha-startify.lua`
neovim-alpha-0.0~git20260417.6c6a89d/debug/min-alpha-dashboard.lua 0000664 0000000 0000000 00000000202 15171555353 0024134 0 ustar 00root root 0000000 0000000 vim.opt.rtp:append(vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:h"))
require("alpha").setup(require("alpha.themes.dashboard").opts)
neovim-alpha-0.0~git20260417.6c6a89d/debug/min-alpha-startify.lua 0000664 0000000 0000000 00000000271 15171555353 0024060 0 ustar 00root root 0000000 0000000 vim.opt.rtp:append(vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:h"))
vim.cmd([[rshada ~/.local/share/nvim/shada/main.shada]])
require("alpha").setup(require("alpha.themes.startify").opts)
neovim-alpha-0.0~git20260417.6c6a89d/doc/ 0000775 0000000 0000000 00000000000 15171555353 0017323 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/doc/alpha.txt 0000664 0000000 0000000 00000030465 15171555353 0021161 0 ustar 00root root 0000000 0000000 *alpha.txt*
*alpha*
==============================================================================
CONTENTS *alpha-contents*
INTRO .......................................... |alpha-intro|
COMMANDS ....................................... |alpha-commands|
CONFIGURATION .................................. |alpha-configuration|
AUTOCMD ........................................ |alpha-autocmd|
COLORS ......................................... |alpha-colors|
EXAMPLE ........................................ |alpha-example|
==============================================================================
INTRO *alpha-intro*
alpha is a plugin that shows a programmable greeter screen when neovim is
launched.
==============================================================================
COMMANDS *alpha-commands*
>
:Alpha
<
Open the alpha buffer.
==============================================================================
CONFIGURATION *alpha-configuration*
the following is documentation for the types alpha uses for configuration
config:
>
config = {
-- required
-- table of elements from top to bottom
-- key is arbitrary, so you can use lua's array syntax
layout = {},
-- optional
opts = {
-- number: how much space to pad on the sides of the screen
margin = 0
-- theme-specific setup,
-- ran once before the first draw
setup = function
-- when true,
-- use 'noautocmd' when setting 'alpha' buffer local options.
-- this can help performance, but it will prevent the
-- FileType autocmd from firing, which may break integration
-- with other plguins.
-- default: false (disabled)
noautocmd = bool
-- table of default keymaps
keymap = {
-- nil | string | string[]: key combinations used to press an
-- item.
press = '',
-- nil | string | string[]: key combination used to select an item to
-- press later.
press_queue = ''
}
}
}
<
button:
>
{
-- required
-- element type
type = "button",
-- the text to display
val = "string",
-- what to do when the button is pressed
-- useful functions:
-- local key = vim.api.nvim_replace_termcodes(shortcut, true, false, true)
-- vim.api.nvim_feedkeys(key, "normal", false)
on_press = function() end,
-- optional
opts = {
-- define a buffer-local keymap for this element
-- accepts the arguments for 'nvim_set_keymap' as an array
-- normally pairs with an 'on_press' function that feeds the lhs
-- keys (see alpha.dashboard.button implementation)
keymap = { {mode}, {lhs}, {rhs}, {*opts} }
position = "left" | "center" | "right",
hl = "hl_group" | {{"hl_group", 0, -1}} | {{{"hl_group", 0, -1}}}
shortcut = "string",
align_shortcut = "left" | "right",
hl_shortcut = "hl_group",
-- starting at the first character,
-- from 0 to #shortcut + #val,
-- place the cursor on this row
cursor = 0,
-- how wide to pad the button.
-- useful if position = "center"
width = 50,
-- when `shrink_margin` is true, the margin will
-- shrink when the window width is too small to display
-- the full width margin + the full element.
-- 'dashboard' has this set to true, since it has huge margins and
-- small layout elements, and 'startify' has this set to
-- false, since it has huge layout elements and a small margin
-- defaults to true
shrink_margin = true | false
}
}
<
text:
>
{
-- required
-- element type
type = "text",
-- the text to display
-- when it's an array, each element is placed
-- on a different line
val = "string" | { "array" } | function,
-- optional
opts = {
position = "left" | "center" | "right",
hl = "hl_group" | {{"hl_group", 0, -1}} | {{{"hl_group", 0, -1}}}
}
}
<
padding:
>
{
type = "padding",
val = 0 -- number
}
<
group:
>
{
-- required
type = "group"
val = {} | function -- table of elements
-- optional
opts = {
-- number of newlines inbetween each element
spacing = 1
-- this table will extend the opts table of each entry of 'val'
-- keeping the entry from 'inherit'
-- unless the val.[n].opts.priority is >= opts.priority
inherit = {}
priority = 1 -- defaults to 1, see above
-- vertically center the group within the window.
-- padding is automatically added above the group so that the
-- group appears centered. if elements already rendered above
-- the group push it past the center point, no padding is added.
position = "v_center"
}
}
<
terminal:
>
-- note: require'alpha.term' must be called
-- after require'alpha'
{
-- required
type = "terminal"
command = "string" | function -- the shell command to run
-- command size can be fixed, or calculated by mutating these
width = 0 -- number
height = 0 -- number
-- optional
opts = {
-- turns 'false' after the command is run
-- when redraw = true alpha will rerun the command
-- on the next redraw
redraw = true
-- see :h nvim_open_win {config} parameter
window_config = {}
}
}
<
A theme may supply predefined widgets like buttons, headers, etc that
you can use to customize the theme by updating its opts table
==============================================================================
COLORS *alpha-colors*
Highlighting is handled internally by the neovim api.
Most elements accept `opts.hl = "hl_group"` or an array of
`{'hl_group', start_col, end_col}`
for multiline elements, you supply a 2 dimensional array of
`{'hl_group', start_col, end_col}`
`start_col` and `end_col` is based on byte index not char index. See
alpha.utils.charhl_to_bytehl for character-wise highlighting.
You can highlight a button shortcut by supplying a highlight group to the
option `x.opt.hl_shortcut`
the builtin themes currently highlight with builtin highlight groups
like `Number` and `Keyword`
==============================================================================
AUTOCMDS *alpha-autocmds*
alpha supports the following autocmds
- `autocmd User AlphaReady`
meaning: alpha buffer has been loaded and has completed the first draw
- `autocmd User AlphaClosed`
meaning: alpha buffer was unloaded
there is an option to use *:noautocmd* when setting alpha's buffer local options
see |alpha-configuration|
==============================================================================
THEME OPTIONS *alpha-theme-options*
theta/startify:
>
mru_opts = {
-- return 'true' for paths which should not appear as entries in the MRU
-- menu. defaults to
ignore = function(path, ext)
return (string.find(path, "COMMIT_EDITMSG")) or (vim.tbl_contains(default_mru_ignore, ext))
end,
-- when 'true', selecting an item from the MRU menu will automatically
-- change your working directory to the parent directory of the entry.
-- defaults to
autocd = false
}
file_icons = {
-- enable / disable icons in the MRU menu entries
-- defaults to
enabled = true,
-- enable / disable highlighting for the icons in the MRU menu entries
-- defaults to
highlight = true,
-- available: devicons, mini, to use nvim-web-devicons or mini.icons
-- if provider not loaded and enabled is true, it will try to use another provider
provider = "mini",
}
<
theta/dashboard:
>
-- string: replaces `leader` "leader" in the button keymaps.
-- note: does not replace how it's displayed, so you'll want to
-- redfine the `dashboard.section.buttons.val` table
leader = "SPC"
==============================================================================
EXAMPLE *alpha-example*
For the default configuration, see the Quick Start guide in the README.md
>
>
use {
"goolord/alpha-nvim",
config = function ()
local alpha = require'alpha'
local dashboard = require'alpha.themes.dashboard'
dashboard.section.header.val = {
[[ __ ]],
[[ ___ ___ ___ __ __ /\_\ ___ ___ ]],
[[ / _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\ ]],
[[/\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \ ]],
[[\ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\]],
[[ \/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/]],
}
dashboard.section.buttons.val = {
dashboard.button( "e", " New file" , ":ene startinsert "),
dashboard.button( "q", " Quit NVIM" , ":qa"),
}
local handle = io.popen('fortune')
local fortune = handle:read("*a")
handle:close()
dashboard.section.footer.val = fortune
dashboard.config.opts.noautocmd = true
vim.cmd[[autocmd User AlphaReady echo 'ready']]
alpha.setup(dashboard.config)
end
}
<
Example with the startify theme:
>
use {
"goolord/alpha-nvim",
requires = { 'echasnovski/mini.icons' },
config = function ()
local alpha = require'alpha'
local startify = require'alpha.themes.startify'
startify.section.header.val = {
[[ __ ]],
[[ ___ ___ ___ __ __ /\_\ ___ ___ ]],
[[ / _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\ ]],
[[ /\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \ ]],
[[ \ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\]],
[[ \/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/]],
}
startify.section.top_buttons.val = {
startify.button( "e", " New file" , ":ene startinsert "),
}
-- disable MRU
startify.section.mru.val = { { type = "padding", val = 0 } }
-- disable MRU cwd
startify.section.mru_cwd.val = { { type = "padding", val = 0 } }
-- disable file_icons
startify.file_icons.enabled = false
-- startify.file_icons.highlight = false
-- startify.file_icons.highlight = 'Keyword'
--
startify.section.bottom_buttons.val = {
startify.button( "q", " Quit NVIM" , ":qa"),
}
startify.section.footer.val = {
{ type = "text", val = "footer" },
}
-- ignore filetypes in MRU
startify.mru_opts.ignore = function(path, ext)
return
(string.find(path, "COMMIT_EDITMSG"))
or (vim.tbl_contains(default_mru_ignore, ext))
end
alpha.setup(startify.config)
end
}
<
==============================================================================
FAQ *alpha-faq*
How to work with indentLine plugin?~
Disable the plugin while in alpha:
>
let g:indentLine_fileTypeExclude = ['alpha']
How to disable the tabline in alpha buffer?~
>
autocmd User AlphaReady set showtabline=0 | autocmd BufUnload set showtabline=2
How do I make a theme with no buttons?~
alpha needs to know where to place the cursor, falling back to {1,0}
negatively impacted performance, so if you want to use a theme with no
buttons, either create an empty button
>
{ type = "button", val = "" }
<
or arbitrarily pick an element of some other type change to
>
el.type = "button"
<
as the sole possible cursor position for your theme
==============================================================================
vim:tw=78:sw=4:ts=8:ft=help:norl:
neovim-alpha-0.0~git20260417.6c6a89d/lua/ 0000775 0000000 0000000 00000000000 15171555353 0017337 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha.lua 0000664 0000000 0000000 00000061174 15171555353 0021140 0 ustar 00root root 0000000 0000000 local alpha = {}
-- business logic
local abs = math.abs
local concat = table.concat
local if_nil = vim.F.if_nil
local list_extend = vim.list_extend
local max = math.max
local min = math.min
local str_rep = string.rep
local strdisplaywidth = vim.fn.strdisplaywidth
local cursor_ix = 1
local cursor_jumps = {}
local cursor_jumps_press = {}
local cursor_jumps_press_queue = {}
-- map of buffer -> state
local alpha_state = {}
local function head(t)
return t[next(t)]
end
local function noop() end
local function active_window(state)
local curr_win = vim.api.nvim_get_current_win()
local win
if vim.api.nvim_win_get_buf(curr_win) == state.buffer then
win = curr_win
else
win = state.windows[1]
end
return win
end
function alpha.press()
-- only press under the cursor if there's no queue
if next(cursor_jumps_press_queue) == nil then
cursor_jumps_press[cursor_ix]()
end
for queued_cursor_ix, _ in pairs(cursor_jumps_press_queue) do
cursor_jumps_press[queued_cursor_ix]()
end
end
local function draw_press(row, col, state)
vim.api.nvim_set_option_value("modifiable", true, { buf = state.buffer })
-- todo: represent this in the alpha layout, somehow
vim.api.nvim_buf_set_text(state.buffer, row - 1, col, row - 1, col + 1, { "*" })
vim.api.nvim_set_option_value("modifiable", false, { buf = state.buffer })
end
local function draw_presses(state)
for _, loc in pairs(cursor_jumps_press_queue) do
local row = loc[1]
local col = loc[2]
draw_press(row, col, state)
end
end
function alpha.queue_press(state)
if cursor_jumps_press_queue[cursor_ix] then
cursor_jumps_press_queue[cursor_ix] = nil
else
local cursor = vim.api.nvim_win_get_cursor(active_window(state))
local row = cursor[1]
local col = cursor[2]
cursor_jumps_press_queue[cursor_ix] = {row,col}
draw_press(row,col,state)
local height = state.line
vim.api.nvim_win_set_cursor(0, { min(row + 1, height), col })
end
end
local function longest_line(tbl)
local longest = 0
for _, v in pairs(tbl) do
local width = strdisplaywidth(v)
if width > longest then
longest = width
end
end
return longest
end
local function spaces(n)
return str_rep(" ", max(0, n))
end
---@param keymaps nil | string | string[]
---@return string[]
local function normalize_keymaps(keymaps)
if keymaps == nil then
return {}
end
if type(keymaps) ~= "table" then
keymaps = { keymaps }
end
return keymaps
end
function alpha.align_center(tbl, state)
-- longest line used to calculate the center.
-- which doesn't quite give a 'justfieid' look, but w.e
local longest = longest_line(tbl)
-- div 2
local left = bit.arshift(state.win_width - longest, 1)
local padding = spaces(left)
local centered = {}
for k, v in pairs(tbl) do
centered[k] = padding .. v
end
return centered, left
end
function alpha.pad_margin(tbl, state, margin, shrink)
local longest = longest_line(tbl)
local left
if shrink then
local pot_width = margin + margin + longest
if pot_width > state.win_width then
left = (state.win_width - pot_width) + margin
else
left = margin
end
else
left = margin
end
local padding = spaces(left)
local padded = {}
for k, v in pairs(tbl) do
padded[k] = padding .. v
end
return padded, left
end
function alpha.highlight(state, end_ln, hl, left, el)
local hl_type = type(hl)
local hl_tbl = {}
if hl_type == "string" then
for i = state.line, end_ln do
table.insert(hl_tbl, { state.buffer, -1, hl, i, 0, -1 })
end
end
if hl_type == "table" then
local function single_line(the_hl, line)
for _, hl_section in pairs(the_hl) do
local col_end
if hl_section[3] < 0 then
if type(el.val) == "string" then
col_end = left + #el.val + hl_section[3] + 1
else
col_end = -1
end
else
col_end = left + hl_section[3]
end
table.insert(hl_tbl, {
state.buffer,
-1,
hl_section[1],
state.line + line,
left + hl_section[2],
col_end,
})
end
end
if hl[1] and hl[1][1] and type(hl[1][1]) == "table" then
for ix, hl_line in pairs(hl) do
single_line(hl_line, ix-1)
end
else
single_line(hl, 0)
end
end
return hl_tbl
end
local layout_element = {}
function alpha.resolve(to, el, opts, state)
local val = el.val()
local new_el = setmetatable({ val = val }, { __index = el })
return to(new_el, opts, state)
end
function layout_element.text(el, conf, state)
if type(el.val) == "function" then
return alpha.resolve(layout_element.text, el, conf, state)
end
local val
if type(el.val) == "string" then
val = {}
for s in el.val:gmatch("[^\r\n]+") do
val[#val + 1] = s
end
else
val = el.val
end
local hl = {}
local padding = { left = 0 }
local margin = vim.tbl_get(conf, 'opts', 'margin')
local position = vim.tbl_get(el, 'opts', 'position')
if margin and (position ~= "center") then
local left
val, left = alpha.pad_margin(val, state, margin, if_nil(vim.tbl_get(el, 'opts', 'shrink_margin'), true))
padding.left = padding.left + left
end
if position == "center" then
local left
val, left = alpha.align_center(val, state)
padding.left = padding.left + left
end
local el_hl = vim.tbl_get(el, 'opts', 'hl')
if type(el.val) == "string" then
if el_hl then
hl = alpha.highlight(state, state.line, el_hl, padding.left, el)
end
state.line = state.line + 1
else
local end_ln = state.line + #el.val
if el_hl then
hl = alpha.highlight(state, end_ln-1, el_hl, padding.left, el)
end
state.line = end_ln
end
return val, hl
end
---@diagnostic disable-next-line: unused-local
function layout_element.padding(el, conf, state)
local lines = 0
if type(el.val) == "function" then
lines = el.val()
end
if type(el.val) == "number" then
lines = el.val
end
local val = {}
for i = 1, lines do
val[i] = ""
end
local end_ln = state.line + lines
state.line = end_ln
return val, {}
end
function layout_element.button(el, conf, state)
local val = {}
local hl = {}
local padding = {
left = 0,
center = 0,
right = 0,
}
local opts = vim.tbl_get(el, 'opts') or {}
local shortcut = opts.shortcut
local width = opts.width
if shortcut then
-- this min lets the padding resize when the window gets smaller
if width then
local max_width = min(width, state.win_width)
local shortcut_padding = max_width - (strdisplaywidth(el.val) + strdisplaywidth(shortcut))
if opts.align_shortcut == "right" then
padding.center = shortcut_padding
else
padding.right = shortcut_padding
end
end
if opts.align_shortcut == "right" then
val = { concat({ el.val, spaces(padding.center), opts.shortcut }) }
else
val = { concat({ opts.shortcut, el.val, spaces(padding.right) }) }
end
else
val = { el.val }
end
-- margin
if vim.tbl_get(conf, 'opts', 'margin') and (opts.position ~= "center") then
local left
val, left = alpha.pad_margin(val, state, conf.opts.margin, if_nil(opts.shrink_margin, true))
if opts.align_shortcut == "right" then
padding.center = padding.center + left
else
padding.left = padding.left + left
end
end
-- center
if opts.position == "center" then
local left
val, left = alpha.align_center(val, state)
if opts.align_shortcut == "right" then
padding.center = padding.center + left
end
padding.left = padding.left + left
end
local row = state.line + 1
local col = (opts.cursor or 0) + padding.left
cursor_jumps[#cursor_jumps + 1] = { row, col }
cursor_jumps_press[#cursor_jumps_press + 1] = el.on_press
if opts.hl_shortcut then
if type(opts.hl_shortcut) == "string" then
hl = { { opts.hl_shortcut, 0, #opts.shortcut + 1 } }
else
hl = opts.hl_shortcut
end
if opts.align_shortcut == "right" then
hl = alpha.highlight(state, state.line, hl, #el.val + max(0, padding.center), el)
else
hl = alpha.highlight(state, state.line, hl, padding.left, el)
end
end
if opts.hl then
local left = padding.left
if opts.align_shortcut == "left" then
left = left + #opts.shortcut
end
list_extend(hl, alpha.highlight(state, state.line, opts.hl, left, el))
end
state.line = state.line + 1
return val, hl
end
function layout_element.group(el, conf, state)
if type(el.val) == "function" then
return alpha.resolve(layout_element.group, el, conf, state)
end
if type(el.val) == "table" then
local text_tbl = {}
local hl_tbl = {}
local priority = if_nil(vim.tbl_get(el, 'opts', 'priority'), 1)
local inherit = vim.tbl_get(el, 'opts', 'inherit')
local spacing = el.opts and el.opts.spacing
local position = vim.tbl_get(el, 'opts', 'position')
local start_line = state.line
local cursor_jumps_start = #cursor_jumps
for _, v in pairs(el.val) do
if inherit then
if v.opts then
local vpriority = if_nil(vim.tbl_get(v, 'opts', 'priority'), 0)
if priority > vpriority then
v.opts = vim.tbl_extend("force", v.opts, inherit)
end
else
v.opts = inherit
end
end
local text, hl = layout_element[v.type](v, conf, state)
if text then
list_extend(text_tbl, text)
end
if hl then
list_extend(hl_tbl, hl)
end
if spacing then
local padding_el = { type = "padding", val = spacing }
local text_1, hl_1 = layout_element[padding_el.type](padding_el, conf, state)
list_extend(text_tbl, text_1)
list_extend(hl_tbl, hl_1)
end
end
if position == "v_center" then
local group_height = #text_tbl
local shift = max(0, math.floor((state.win_height - group_height) / 2) - start_line)
if shift > 0 then
local padding = {}
for i = 1, shift do
padding[i] = ""
end
list_extend(padding, text_tbl)
text_tbl = padding
for _, hl_entry in pairs(hl_tbl) do
hl_entry[4] = hl_entry[4] + shift
end
for i = cursor_jumps_start + 1, #cursor_jumps do
cursor_jumps[i][1] = cursor_jumps[i][1] + shift
end
state.line = state.line + shift
end
end
return text_tbl, hl_tbl
end
end
local function layout(conf, state)
-- this is my way of hacking pattern matching
-- you index the table by its "type"
local hl = {}
local text = {}
for _, el in pairs(conf.layout) do
local text_el, hl_el = layout_element[el.type](el, conf, state)
list_extend(text, text_el)
list_extend(hl, hl_el)
end
vim.api.nvim_buf_set_lines(state.buffer, 0, -1, false, text)
for _, hl_line in pairs(hl) do
vim.api.nvim_buf_add_highlight(hl_line[1], hl_line[2], hl_line[3], hl_line[4], max(hl_line[5], 0), hl_line[6])
end
end
local keymaps_element = {}
keymaps_element.text = noop
keymaps_element.padding = noop
---@diagnostic disable-next-line: unused-local
function keymaps_element.button(el, conf, state)
if el.opts and el.opts.keymap then
el.opts.keymap[4] = vim.tbl_extend("force", el.opts.keymap[4] or {}, { buffer = state.buffer })
vim.keymap.set(unpack(el.opts.keymap))
end
end
function keymaps_element.group(el, conf, state)
if type(el.val) == "function" then
return alpha.resolve(keymaps_element.group, el, conf, state)
end
if type(el.val) == "table" then
for _, v in pairs(el.val) do
keymaps_element[v.type](v, conf, state)
end
end
end
local function keymaps(conf, state)
for _, el in pairs(conf.layout) do
keymaps_element[el.type](el, conf, state)
end
end
-- dragons
local function closest_cursor_jump(cursor, cursors, prev_cursor)
local direction = prev_cursor[1] > cursor[1] -- true = UP, false = DOWN
-- minimum distance key from jump point
-- excluding jumps in opposite direction
local min
local cursor_row = cursor[1]
for k, v in pairs(cursors) do
local distance = v[1] - cursor_row -- new cursor distance from old cursor
if (distance <= 0) and direction then
distance = abs(distance)
local res = { distance, k }
if not min then
min = res
end
if min[1] > res[1] then
min = res
end
end
if (distance >= 0) and not direction then
local res = { distance, k }
if not min then
min = res
end
if min[1] > res[1] then
min = res
end
end
end
if not min -- top or bottom
then
if direction then
return 1, cursors[1]
else
return #cursors, cursors[#cursors]
end
else
-- returns the key (stored in a jank way so we can sort the table)
-- and the {row, col} tuple
return min[2], cursors[min[2]]
end
end
-- stylua: ignore start
local function enable_alpha(conf, state)
local eventignore = vim.opt.eventignore
if conf.opts.noautocmd then
vim.opt.eventignore = 'all'
end
local set = function(opt, val) vim.api.nvim_set_option_value(opt, val, { scope = "local" }) end
set("bufhidden", "wipe")
set("buflisted", false)
set("matchpairs", "")
set("swapfile", false)
set("buftype", "nofile")
set("filetype", "alpha")
set("synmaxcol", 0)
set("wrap", false)
set("colorcolumn", "")
set("foldlevel", 999)
set("foldcolumn", "0")
set("cursorcolumn", false)
set("cursorline", false)
set("number", false)
set("relativenumber", false)
set("list", false)
set("spell", false)
set("signcolumn", "no")
if conf.opts.noautocmd then
vim.opt.eventignore = eventignore
end
local group_id = vim.api.nvim_create_augroup('alpha_temp', { clear = true })
vim.api.nvim_create_autocmd('BufUnload', {
group = group_id,
buffer = state.buffer,
callback = alpha.close,
})
vim.api.nvim_create_autocmd('SessionLoadPost', {
group = group_id,
callback = alpha.close,
})
vim.api.nvim_create_autocmd({'WinClosed'}, {
group = group_id,
buffer = state.buffer,
callback = alpha.handle_window,
})
vim.api.nvim_create_autocmd('CursorMoved', {
group = group_id,
buffer = state.buffer,
callback = function()
alpha.move_cursor(active_window(state))
end,
})
if conf.opts then
if if_nil(conf.opts.redraw_on_resize, true) then
if vim.version().api_level >= 11 then
vim.api.nvim_create_autocmd('WinResized', {
group = group_id,
callback = function() alpha.redraw(conf, state) end,
})
else
vim.api.nvim_create_autocmd('VimResized', {
group = group_id,
pattern = '*',
callback = function() alpha.redraw(conf, state) end,
})
vim.api.nvim_create_autocmd({ 'BufLeave', 'WinEnter', 'WinNew', 'WinClosed' }, {
group = group_id,
pattern = '*',
callback = function() alpha.redraw(conf, state) end,
})
vim.api.nvim_create_autocmd('CursorMoved', {
group = group_id,
pattern = '*',
callback = function()
local width = vim.api.nvim_win_get_width(active_window(state))
if width ~= state.win_width
then alpha.redraw(conf, state)
end
end,
})
end
end
if conf.opts.setup then
conf.opts.setup()
end
end
end
-- stylua: ignore end
-- stylua: ignore start
local function should_skip_alpha()
-- don't start when opening a file
if vim.fn.argc() > 0 then return true end
-- Do not open alpha if the current buffer has any lines (something opened explicitly).
local lines = vim.api.nvim_buf_get_lines(0, 0, 2, false)
if #lines > 1 or (#lines == 1 and lines[1]:len() > 0) then return true end
-- Skip when there are other listed buffers in windows.
local curr_buf = vim.api.nvim_get_current_buf()
for _, win in pairs(vim.api.nvim_list_wins()) do
local buf = vim.api.nvim_win_get_buf(win)
if buf ~= curr_buf and vim.bo[buf].buflisted then return true end
end
-- Handle nvim -M
if not vim.o.modifiable then return true end
---@diagnostic disable-next-line: undefined-field
for _, arg in pairs(vim.v.argv) do
-- whitelisted arguments
-- always open
if arg == "--startuptime"
then return false
end
-- blacklisted arguments
-- always skip
if arg == "-b"
-- commands, typically used for scripting
or arg == "-c" or vim.startswith(arg, "+")
or arg == "-S"
then return true
end
end
-- base case: don't skip
return false
end
-- stylua: ignore end
function alpha.draw(conf, state)
-- TODO: figure out why this can happen
if #state.windows == 0 then return end
cursor_jumps = {}
cursor_jumps_press = {}
local active_win = active_window(state)
state.win_width = vim.api.nvim_win_get_width(active_win or 0)
state.win_height = vim.api.nvim_win_get_height(active_win or 0)
state.line = 0
-- this is for redraws. i guess the cursor 'moves'
-- when the screen is cleared and then redrawn
-- so we save the index before that happens
local ix = cursor_ix
vim.api.nvim_set_option_value("modifiable", true, { buf = state.buffer })
vim.api.nvim_buf_clear_namespace(state.buffer, -1, 0, -1)
layout(conf, state)
vim.api.nvim_set_option_value("modifiable", false, { buf = state.buffer })
if vim.api.nvim_get_current_win() == active_win then
if #cursor_jumps ~= 0 then
-- TODO: this is pcalled because a bunch of window events
-- like WinEnter will say 'alpha' is the current open buffer
-- and then immedietely unload it
pcall(vim.api.nvim_win_set_cursor, active_win, cursor_jumps[ix])
end
end
draw_presses(state)
end
function alpha.move_cursor(window)
if #cursor_jumps ~= 0 then
local cursor = vim.api.nvim_win_get_cursor(window)
local closest_ix, closest_pt = closest_cursor_jump(cursor, cursor_jumps, cursor_jumps[cursor_ix])
local closest_pt_vc = vim.fn.virtcol2col(window, closest_pt[1], closest_pt[2])
cursor_ix = closest_ix
pcall(vim.api.nvim_win_set_cursor, window, {closest_pt[1], closest_pt_vc})
end
end
function alpha.redraw(conf, state)
if (conf == nil) and (state == nil) then
local buffer = vim.api.nvim_get_current_buf()
local alpha_prime = vim.tbl_get(alpha_state, buffer) or head(alpha_state)
if alpha_prime == nil then return end
conf = alpha.default_config
state = alpha_prime
end
alpha.draw(conf, state)
end
function alpha.close(ev)
alpha_state[ev.buf] = nil
cursor_ix = 1
cursor_jumps = {}
vim.api.nvim_del_augroup_by_id(ev.group)
vim.api.nvim_exec_autocmds("User", { pattern = "AlphaClosed" })
end
-- @param on_vimenter: ?bool optional
-- @param fon: ?table optional
function alpha.start(on_vimenter, conf)
if on_vimenter and should_skip_alpha() then
return
end
local window = vim.api.nvim_get_current_win()
local buffer
if on_vimenter then
buffer = vim.api.nvim_get_current_buf()
else
if vim.bo.ft ~= "alpha" then
buffer = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(window, buffer)
else
---@diagnostic disable-next-line: param-type-mismatch
if not pcall(vim.cmd, 'e #') then
buffer = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_delete(buffer, {})
end
return
end
end
if not vim.o.hidden and vim.opt_local.modified:get() then
vim.api.nvim_err_writeln("Save your changes first.")
return
end
conf = conf or alpha.default_config
local state = {
line = 0,
buffer = buffer,
windows = { window },
win_width = 0,
open = false,
}
alpha_state[buffer] = state
for _, k in pairs(normalize_keymaps(conf.opts.keymap.press)) do
vim.keymap.set("n", k, function() alpha.press() end, { noremap = false, silent = true, buffer = state.buffer })
end
for _, k in pairs(normalize_keymaps(conf.opts.keymap.queue_press)) do
vim.keymap.set("n", k, function() alpha.queue_press(state) end, { noremap = false, silent = true, buffer = state.buffer })
end
enable_alpha(conf, state)
alpha.draw(conf, state)
vim.api.nvim_exec_autocmds("User", { pattern = "AlphaReady" })
keymaps(conf, state)
end
function alpha.setup(config)
if vim.fn.has('nvim-0.11') == 1 then
vim.validate("config", config, "table")
vim.validate("config.layout", config.layout, "table")
else
vim.validate({
config = { config, "table" },
layout = { config.layout, "table" },
})
end
config.opts = vim.tbl_extend(
"keep",
if_nil(config.opts, {}),
{
autostart = true,
keymap = vim.tbl_extend("keep", if_nil(vim.tbl_get(config, "opts", "keymap"), {}), {
press = "",
queue_press = "",
})
}
)
alpha.default_config = config
vim.api.nvim_create_user_command("Alpha", function(_)
alpha.start(false, config)
end, {
bang = true,
desc = 'require"alpha".start(false)',
nargs = 0,
bar = true,
})
vim.api.nvim_create_user_command("AlphaRedraw", function(_)
alpha.redraw()
end, {
bang = true,
desc = 'require"alpha".redraw()',
nargs = 0,
bar = true,
})
vim.api.nvim_create_user_command("AlphaRemap", function(_)
local buffer = vim.api.nvim_get_current_buf()
local alpha_prime = vim.tbl_get(alpha_state, buffer) or head(alpha_state)
if alpha_prime == nil then return end
local conf = alpha.default_config
local state = alpha_prime
keymaps(conf, state)
end, {
bang = true,
desc = 'manually set keymaps',
nargs = 0,
bar = true,
})
local group_id = vim.api.nvim_create_augroup("alpha_start", { clear = true })
vim.api.nvim_create_autocmd("VimEnter", {
group = group_id,
pattern = "*",
nested = true,
callback = function()
if config.opts.autostart then
alpha.start(true, config)
end
end,
})
end
alpha.layout_element = layout_element
alpha.keymaps_element = keymaps_element
function alpha.handle_window(x)
local alpha_instance = alpha_state[x.buf]
local current_win = vim.api.nvim_get_current_win()
if alpha_instance then
local wins = vim.tbl_filter(function(win)
return (vim.api.nvim_win_get_buf(win) == x.buf) and (win ~= current_win)
end
, vim.api.nvim_list_wins()
)
alpha_instance.windows = wins
end
end
return alpha
neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/ 0000775 0000000 0000000 00000000000 15171555353 0020424 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/fortune.lua 0000664 0000000 0000000 00000063705 15171555353 0022624 0 ustar 00root root 0000000 0000000 -- fortune printing (from vim-startify)
-- To add this to the footer, simply add the following lines to the config:
-- use {
-- 'goolord/alpha-nvim',
-- config = function ()
-- require'alpha.themes.dashboard'.section.footer.val = require'alpha.fortune'()
-- require'alpha'.setup(require'alpha.themes.dashboard'.opts)
-- end
-- }
local list_extend = vim.list_extend
--- @param line string
--- @param max_width number
--- @return table
local format_line = function(line, max_width)
if line == "" then
return { " " }
end
local formatted_line = {}
-- split line by spaces into list of words
local words = {}
local target = "%S+"
for word in line:gmatch(target) do
words[#words + 1] = word
end
local buf_words = {}
local buf_len = 1 -- accounts for the leading space
local n_words = #words
for i, word in ipairs(words) do
if buf_len + #word <= max_width then
buf_words[#buf_words + 1] = word
buf_len = buf_len + #word + 1
else
-- flush current buffer
if #buf_words > 0 then
table.insert(formatted_line, " " .. table.concat(buf_words, " "))
else
table.insert(formatted_line, "")
end
-- reset with the word that didn't fit
buf_words = { word }
buf_len = 1 + #word + 1
end
-- flush whatever remains at end of words
if i == n_words then
if #buf_words > 0 then
table.insert(formatted_line, " " .. table.concat(buf_words, " "))
else
table.insert(formatted_line, "")
end
end
end
-- right-justify text if the line begins with -
if line:sub(1, 1) == "-" then
for i, val in ipairs(formatted_line) do
local space = string.rep(" ", max_width - #val - 2)
formatted_line[i] = space .. val:sub(2, -1)
end
end
return formatted_line
end
--- @param fortune table
--- @param max_width number
--- @return table
local format_fortune = function(fortune, max_width)
-- Converts list of strings to one formatted string (with linebreaks)
local formatted_fortune = { " " } -- adds spacing between alpha-menu and footer
for _, line in ipairs(fortune) do
local formatted_line = format_line(line, max_width)
list_extend(formatted_fortune, formatted_line)
end
return formatted_fortune
end
local get_fortune = function(fortune_list)
-- selects an entry from fortune_list randomly
local ind = math.random(1, #fortune_list)
return fortune_list[ind]
end
-- Credit to @mhinz for compiling this list in vim-startify
local fortune_list = {
{
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.",
"",
"- Brian Kernighan",
},
{ "If you don't finish then you're just busy, not productive." },
{
"Adapting old programs to fit new machines usually means adapting new machines to behave like old ones.",
"",
"- Alan Perlis",
},
{ "Fools ignore complexity. Pragmatists suffer it. Some can avoid it. Geniuses remove it.", "", "- Alan Perlis" },
{ "It is easier to change the specification to fit the program than vice versa.", "", "- Alan Perlis" },
{ "Simplicity does not precede complexity, but follows it.", "", "- Alan Perlis" },
{ "Optimization hinders evolution.", "", "- Alan Perlis" },
{ "Recursion is the root of computation since it trades description for time.", "", "- Alan Perlis" },
{
"It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.",
"",
"- Alan Perlis",
},
{
"There is nothing quite so useless as doing with great efficiency something that should not be done at all.",
"",
"- Peter Drucker",
},
{ "If you don't fail at least 90% of the time, you're not aiming high enough.", "", "- Alan Kay" },
{
"I think a lot of new programmers like to use advanced data structures and advanced language features as a way of demonstrating their ability. I call it the lion-tamer syndrome. Such demonstrations are impressive, but unless they actually translate into real wins for the project, avoid them.",
"",
"- Glyn Williams",
},
{ "I would rather die of passion than of boredom.", "", "- Vincent Van Gogh" },
{ "If a system is to serve the creative spirit, it must be entirely comprehensible to a single individual." },
{
"The computing scientist's main challenge is not to get confused by the complexities of his own making.",
"",
"- Edsger W. Dijkstra",
},
{
"Progress in a fixed context is almost always a form of optimization. Creative acts generally don't stay in the context that they are in.",
"",
"- Alan Kay",
},
{
"The essence of XML is this: the problem it solves is not hard, and it does not solve the problem well.",
"",
"- Phil Wadler",
},
{
"A good programmer is someone who always looks both ways before crossing a one-way street.",
"",
"- Doug Linder",
},
{ 'Patterns mean "I have run out of language."', "", "- Rich Hickey" },
{
"Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.",
"",
"- John Woods",
},
{
"Unix was not designed to stop its users from doing stupid things, as that would also stop them from doing clever things.",
},
{
"Contrary to popular belief, Unix is user friendly. It just happens to be very selective about who it decides to make friends with.",
},
{ "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." },
{
"There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies.",
"",
"- C.A.R. Hoare",
},
{ "If you don't make mistakes, you're not working on hard enough problems.", "", "- Frank Wilczek" },
{ "If you don't start with a spec, every piece of code you write is a patch.", "", "- Leslie Lamport" },
{ "Caches are bugs waiting to happen.", "", "- Rob Pike" },
{
"Abstraction is not about vagueness, it is about being precise at a new semantic level.",
"",
"- Edsger W. Dijkstra",
},
{
"dd is horrible on purpose. It's a joke about OS/360 JCL. But today it's an internationally standardized joke. I guess that says it all.",
"",
"- Rob Pike",
},
{ "All loops are infinite ones for faulty RAM modules." },
{ "All idioms must be learned. Good idioms only need to be learned once.", "", "- Alan Cooper" },
{
"For a successful technology, reality must take precedence over public relations, for Nature cannot be fooled.",
"",
"- Richard Feynman",
},
{
"If programmers were electricians, parallel programmers would be bomb disposal experts. Both cut wires.",
"",
"- Bartosz Milewski",
},
{
"Computers are harder to maintain at high altitude. Thinner air means less cushion between disk heads and platters. Also more radiation.",
},
{ "Almost every programming language is overrated by its practitioners.", "", "- Larry Wall" },
{ "Fancy algorithms are slow when n is small, and n is usually small.", "", "- Rob Pike" },
{ "Methods are just functions with a special first argument.", "", "- Andrew Gerrand" },
{ "Care about your craft.", "", "Why spend your life developing software unless you care about doing it well?" },
{
"Provide options, don't make lame excuses.",
"",
"Instead of excuses, provide options. Don't say it can't be done; explain what can be done.",
},
{
"Be a catalyst for change.",
"",
"You can't force change on people. Instead, show them how the future might be and help them participate in creating it.",
},
{
"Make quality a requirements issue.",
"",
"Involve your users in determining the project's real quality requirements.",
},
{
"Critically analyze what you read and hear.",
"",
"Don't be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project.",
},
{
"DRY - Don't Repeat Yourself.",
"",
"Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.",
},
{
"Eliminate effects between unrelated things.",
"",
"Design components that are self-contained, independent, and have a single, well-defined purpose.",
},
{
"Use tracer bullets to find the target.",
"",
"Tracer bullets let you home in on your target by trying things and seeing how close they land.",
},
{ "Program close to the problem domain.", "", "Design and code in your user's language." },
{
"Iterate the schedule with the code.",
"",
"Use experience you gain as you implement to refine the project time scales.",
},
{ "Use the power of command shells.", "", "Use the shell when graphical user interfaces don't cut it." },
{
"Always use source code control.",
"",
"Source code control is a time machine for your work - you can go back.",
},
{ "Don't panic when debugging", "", "Take a deep breath and THINK! about what could be causing the bug." },
{
"Don't assume it - prove it.",
"",
"Prove your assumptions in the actual environment - with real data and boundary conditions.",
},
{ "Write code that writes code.", "", "Code generators increase your productivity and help avoid duplication." },
{
"Design With contracts.",
"",
"Use contracts to document and verify that code does no more and no less than it claims to do.",
},
{
"Use assertions to prevent the impossible.",
"",
"Assertions validate your assumptions. Use them to protect your code from an uncertain world.",
},
{
"Finish what you start.",
"",
"Where possible, the routine or object that allocates a resource should be responsible for deallocating it.",
},
{
"Configure, don't integrate.",
"",
"Implement technology choices for an application as configuration options, not through integration or engineering.",
},
{ "Analyze workflow to improve concurrency.", "", "Exploit concurrency in your user's workflow." },
{
"Always design for concurrency.",
"",
"Allow for concurrency, and you'll design cleaner interfaces with fewer assumptions.",
},
{
"Use blackboards to coordinate workflow.",
"",
"Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants.",
},
{
"Estimate the order of your algorithms.",
"",
"Get a feel for how long things are likely to take before you write code.",
},
{
"Refactor early, refactor often.",
"",
"Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem.",
},
{ "Test your software, or your users will.", "", "Test ruthlessly. Don't make your users find bugs for you." },
{
"Don't gather requirements - dig for them.",
"",
"Requirements rarely lie on the surface. They're buried deep beneath layers of assumptions, misconceptions, and politics.",
},
{
"Abstractions live longer than details.",
"",
"Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies.",
},
{
"Don't think outside the box - find the box.",
"",
'When faced with an impossible problem, identify the real constraints. Ask yourself: "Does it have to be done this way? Does it have to be done at all?"',
},
{
"Some things are better done than described.",
"",
"Don't fall into the specification spiral - at some point you need to start coding.",
},
{
"Costly tools don't produce better designs.",
"",
"Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits.",
},
{
"Don't use manual procedures.",
"",
"A shell script or batch file will execute the same instructions, in the same order, time after time.",
},
{ "Coding ain't done 'til all the Tests run.", "", "'Nuff said." },
{
"Test state coverage, not code coverage.",
"",
"Identify and test significant program states. Just testing lines of code isn't enough.",
},
{
"English is just a programming language.",
"",
"Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on.",
},
{
"Gently exceed your users' expectations.",
"",
"Come to understand your users' expectations, then deliver just that little bit more.",
},
{
"Think about your work.",
"",
"Turn off the autopilot and take control. Constantly critique and appraise your work.",
},
{ "Don't live with broken windows.", "", "Fix bad designs, wrong decisions, and poor code when you see them." },
{
"Remember the big picture.",
"",
"Don't get so engrossed in the details that you forget to check what's happening around you.",
},
{ "Invest regularly in your knowledge portfolio.", "", "Make learning a habit." },
{
"It's both what you say and the way you say it.",
"",
"There's no point in having great ideas if you don't communicate them effectively.",
},
{
"Make it easy to reuse.",
"",
"If it's easy to reuse, people will. Create an environment that supports reuse.",
},
{
"There are no final decisions.",
"",
"No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change.",
},
{
"Prototype to learn.",
"",
"Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn.",
},
{ "Estimate to avoid surprises.", "", "Estimate before you start. You'll spot potential problems up front." },
{
"Keep knowledge in plain text.",
"",
"Plain text won't become obsolete. It helps leverage your work and simplifies debugging and testing.",
},
{
"Use a single editor well.",
"",
"The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable.",
},
{
"Fix the problem, not the blame.",
"",
"It doesn't really matter whether the bug is your fault or someone else's - it is still your problem, and it still needs to be fixed.",
},
{
'"select" isn\'t broken.',
"",
"It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in the application.",
},
{
"Learn a text manipulation language.",
"",
"You spend a large part of each day working with text. Why not have the computer do some of it for you?",
},
{
"You can't write perfect software.",
"",
"Software can't be perfect. Protect your code and users from the inevitable errors.",
},
{ "Crash early.", "", "A dead program normally does a lot less damage than a crippled one." },
{
"Use exceptions for exceptional problems.",
"",
"Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things.",
},
{
"Minimize coupling between modules.",
"",
'Avoid coupling by writing "shy" code and applying the Law of Demeter.',
},
{
"Put abstractions in code, details in metadata.",
"",
"Program for the general case, and put the specifics outside the compiled code base.",
},
{
"Design using services.",
"",
"Design in terms of services-independent, concurrent objects behind well-defined, consistent interfaces.",
},
{
"Separate views from models.",
"",
"Gain flexibility at low cost by designing your application in terms of models and views.",
},
{
"Don't program by coincidence.",
"",
"Rely only on reliable things. Beware of accidental complexity, and don't confuse a happy coincidence with a purposeful plan.",
},
{
"Test your estimates.",
"",
"Mathematical analysis of algorithms doesn't tell you everything. Try timing your code in its target environment.",
},
{ "Design to test.", "", "Start thinking about testing before you write a line of code." },
{
"Don't use wizard code you don't understand.",
"",
"Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project.",
},
{
"Work with a user to think like a user.",
"",
"It's the best way to gain insight into how the system will really be used.",
},
{
"Use a project glossary.",
"",
"Create and maintain a single source of all the specific terms and vocabulary for a project.",
},
{
"Start when you're ready.",
"",
"You've been building experience all your life. Don't ignore niggling doubts.",
},
{
"Don't be a slave to formal methods.",
"",
"Don't blindly adopt any technique without putting it into the context of your development practices and capabilities.",
},
{
"Organize teams around functionality.",
"",
"Don't separate designers from coders, testers from data modelers. Build teams the way you build code.",
},
{
"Test early. Test often. Test automatically.",
"",
"Tests that run with every build are much more effective than test plans that sit on a shelf.",
},
{
"Use saboteurs to test your testing.",
"",
"Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them.",
},
{
"Find bugs once.",
"",
"Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on.",
},
{ "Sign your work.", "", "Craftsmen of an earlier age were proud to sign their work. You should be, too." },
{ "Think twice, code once." },
{ "No matter how far down the wrong road you have gone, turn back now." },
{ "Why do we never have time to do it right, but always have time to do it over?" },
{ "Weeks of programming can save you hours of planning." },
{ "To iterate is human, to recurse divine.", "", "- L. Peter Deutsch" },
{ "Computers are useless. They can only give you answers.", "", "- Pablo Picasso" },
{
"The question of whether computers can think is like the question of whether submarines can swim.",
"",
"- Edsger W. Dijkstra",
},
{
"It's ridiculous to live 100 years and only be able to remember 30 million bytes. You know, less than a compact disc. The human condition is really becoming more obsolete every minute.",
"",
"- Marvin Minsky",
},
{ "The city's central computer told you? R2D2, you know better than to trust a strange computer!", "", "- C3PO" },
{
"Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.",
"",
"- Alan Kay",
},
{
'I\'ve finally learned what "upward compatible" means. It means we get to keep all our old mistakes.',
"",
"- Dennie van Tassel",
},
{
"There are two major products that come out of Berkeley: LSD and UNIX. We don't believe this to be a coincidence.",
"",
"- Jeremy S. Anderson",
},
{
"The bulk of all patents are crap. Spending time reading them is stupid. It's up to the patent owner to do so, and to enforce them.",
"",
"- Linus Torvalds",
},
{ "Controlling complexity is the essence of computer programming.", "", "- Brian Kernighan" },
{
"Complexity kills. It sucks the life out of developers, it makes products difficult to plan, build and test, it introduces security challenges, and it causes end-user and administrator frustration.",
"",
"- Ray Ozzie",
},
{ "The function of good software is to make the complex appear to be simple.", "", "- Grady Booch" },
{
"There's an old story about the person who wished his computer were as easy to use as his telephone. That wish has come true, since I no longer know how to use my telephone.",
"",
"- Bjarne Stroustrup",
},
{ 'There are only two industries that refer to their customers as "users".', "", "- Edward Tufte" },
{
"Most of you are familiar with the virtues of a programmer. There are three, of course: laziness, impatience, and hubris.",
"",
"- Larry Wall",
},
{
"Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter.",
"",
"- Eric S. Raymond",
},
{ "Optimism is an occupational hazard of programming; feedback is the treatment.", "", "- Kent Beck" },
{ "First, solve the problem. Then, write the code.", "", "- John Johnson" },
{
"Measuring programming progress by lines of code is like measuring aircraft building progress by weight.",
"",
"- Bill Gates",
},
{
"Don't worry if it doesn't work right. If everything did, you'd be out of a job.",
"",
"- Mosher's Law of Software Engineering",
},
{ "A LISP programmer knows the value of everything, but the cost of nothing.", "", "- Alan J. Perlis" },
{ "All problems in computer science can be solved with another level of indirection.", "", "- David Wheeler" },
{
"Functions delay binding; data structures induce binding. Moral: Structure data late in the programming process.",
"",
"- Alan J. Perlis",
},
{ "Easy things should be easy and hard things should be possible.", "", "- Larry Wall" },
{ "Nothing is more permanent than a temporary solution." },
{
"If you can't explain something to a six-year-old, you really don't understand it yourself.",
"",
"- Albert Einstein",
},
{ "All programming is an exercise in caching.", "", "- Terje Mathisen" },
{ "Software is hard.", "", "- Donald Knuth" },
{ "They did not know it was impossible, so they did it!", "", "- Mark Twain" },
{
"The object-oriented model makes it easy to build up programs by accretion. What this often means, in practice, is that it provides a structured way to write spaghetti code.",
"",
"- Paul Graham",
},
{ "Question: How does a large software project get to be one year late?", "Answer: One day at a time!" },
{
"The first 90% of the code accounts for the first 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time.",
"",
"- Tom Cargill",
},
{
"In software, we rarely have meaningful requirements. Even if we do, the only measure of success that matters is whether our solution solves the customer's shifting idea of what their problem is.",
"",
"- Jeff Atwood",
},
{
"If debugging is the process of removing bugs, then programming must be the process of putting them in.",
"",
"- Edsger W. Dijkstra",
},
{ "640K ought to be enough for anybody.", "", "- Bill Gates, 1981" },
{ "To understand recursion, one must first understand recursion.", "", "- Stephen Hawking" },
{
"Developing tolerance for imperfection is the key factor in turning chronic starters into consistent finishers.",
"",
"- Jon Acuff",
},
{
"Every great developer you know got there by solving problems they were unqualified to solve until they actually did it.",
"",
"- Patrick McKenzie",
},
{
"The average user doesn't give a damn what happens, as long as (1) it works and (2) it's fast.",
"",
"- Daniel J. Bernstein",
},
{
"Walking on water and developing software from a specification are easy if both are frozen.",
"",
"- Edward V. Berard",
},
{
"Be curious. Read widely. Try new things. I think a lot of what people call intelligence boils down to curiosity.",
"",
"- Aaron Swartz",
},
{ "What one programmer can do in one month, two programmers can do in two months.", "", "- Frederick P. Brooks" },
}
--- @return table
--- @param opts number|table? optional
--- returns an array of strings
local main = function(opts)
local options = {
max_width = 54,
fortune_list = fortune_list,
}
if type(opts) == "number" then
options.max_width = opts
elseif type(opts) == "table" then
options = vim.tbl_extend("force", options, opts)
end
local fortune = get_fortune(options.fortune_list)
local formatted_fortune = format_fortune(fortune, options.max_width)
return formatted_fortune
end
return main
neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/term.lua 0000664 0000000 0000000 00000005403 15171555353 0022100 0 ustar 00root root 0000000 0000000 local alpha = require("alpha")
local M = {}
function M.open_window(el, state, line)
local parent_win = state.windows[1]
local position = M.calc_position(parent_win, el, state, line)
local win_config = vim.tbl_extend("keep", (el.opts and el.opts.window_config) or {}, {
relative = "editor",
row = position.row,
col = position.col,
width = el.width,
height = el.height,
style = "minimal",
focusable = false,
noautocmd = true,
zindex = 1,
})
local bufnr = vim.api.nvim_create_buf(false, true)
local winid = vim.api.nvim_open_win(bufnr, true, win_config)
vim.api.nvim_win_set_option(winid, "winhl", "Normal:Normal")
return { bufnr, winid }
end
function M.run_command(cmd, el, state, line)
el.parent_id = state.windows[1]
if cmd == nil then
return
end
if type(cmd) == 'function' then
cmd = cmd()
end
vim.loop.new_async(vim.schedule_wrap(function()
local wininfo = M.open_window(el, state, line)
el.wininfo = wininfo
vim.api.nvim_create_autocmd("User", {
pattern = "AlphaClosed",
callback = function()
if vim.api.nvim_buf_is_valid(wininfo[1]) then
vim.api.nvim_buf_delete(wininfo[1], { force = true })
end
end,
})
vim.api.nvim_command("terminal " .. cmd)
vim.api.nvim_command("wincmd j")
vim.api.nvim_buf_set_option(wininfo[1], "buflisted", false)
vim.api.nvim_command('let b:term_title ="alpha_terminal" ')
end)):send()
end
function M.calc_position(parent_id, el, state, line)
local parent_win_width = state.win_width
local position = vim.api.nvim_win_get_position(parent_id)
local res = {}
res.row = math.floor(position[1] + line)
res.col = math.floor(((parent_win_width - el.width) / 2) + position[2])
return res
end
function M.reposition(el, state, line)
local parent_id = el.parent_id
if parent_id == nil then
return
end
local new_position = M.calc_position(parent_id, el, state, line)
local term_id = el.wininfo[2]
local win_config = vim.api.nvim_win_get_config(term_id)
win_config.row = new_position.row
win_config.col = new_position.col
vim.api.nvim_win_set_config(term_id, win_config)
end
function alpha.layout_element.terminal(el, conf, state)
local line = state.line
if el.opts and (el.opts.redraw == nil or el.opts.redraw) then
el.opts.redraw = false
M.run_command(el.command, el, state, line)
else
M.reposition(el, state, line)
end
return alpha.layout_element.padding({ type = "padding", val = el.height }, conf, state)
end
function alpha.keymaps_element.terminal(_, _, _)
end
return M
neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/themes/ 0000775 0000000 0000000 00000000000 15171555353 0021711 5 ustar 00root root 0000000 0000000 neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/themes/dashboard.lua 0000664 0000000 0000000 00000005316 15171555353 0024350 0 ustar 00root root 0000000 0000000 local if_nil = vim.F.if_nil
local default_terminal = {
type = "terminal",
command = nil,
width = 69,
height = 8,
opts = {
redraw = true,
window_config = {},
},
}
local default_header = {
type = "text",
val = {
[[ __]],
[[ ___ ___ ___ __ __ /\_\ ___ ___]],
[[ / _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\]],
[[ /\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \]],
[[ \ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\]],
[[ \/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/]],
},
opts = {
position = "center",
hl = "Type",
-- wrap = "overflow";
},
}
local footer = {
type = "text",
val = "",
opts = {
position = "center",
hl = "Number",
},
}
local leader = "SPC"
--- @param sc string
--- @param txt string
--- @param keybind string? optional
--- @param keybind_opts table? optional
local function button(sc, txt, keybind, keybind_opts)
local sc_ = sc:gsub("%s", ""):gsub(leader, "")
local opts = {
position = "center",
shortcut = sc,
cursor = 3,
width = 50,
align_shortcut = "right",
hl_shortcut = "Keyword",
}
if keybind then
keybind_opts = if_nil(keybind_opts, { noremap = true, silent = true, nowait = true })
opts.keymap = { "n", sc_, keybind, keybind_opts }
end
local function on_press()
local key = vim.api.nvim_replace_termcodes(keybind or sc_ .. "", true, false, true)
vim.api.nvim_feedkeys(key, "t", false)
end
return {
type = "button",
val = txt,
on_press = on_press,
opts = opts,
}
end
local buttons = {
type = "group",
val = {
button("e", " New file", "ene "),
button("SPC f f", " Find file"),
button("SPC f h", " Recently opened files"),
button("SPC f r", " Frecency/MRU"),
button("SPC f g", " Find word"),
button("SPC f m", " Jump to bookmarks"),
button("SPC s l", " Open last session"),
},
opts = {
spacing = 1,
},
}
local section = {
terminal = default_terminal,
header = default_header,
buttons = buttons,
footer = footer,
}
local config = {
layout = {
{ type = "padding", val = 2 },
section.header,
{ type = "padding", val = 2 },
section.buttons,
section.footer,
},
opts = {
margin = 5,
},
}
return {
button = button,
section = section,
config = config,
-- theme config
leader = leader,
-- deprecated
opts = config,
}
neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/themes/startify.lua 0000664 0000000 0000000 00000023026 15171555353 0024264 0 ustar 00root root 0000000 0000000 local utils = require("alpha.utils")
--- Mutable theme table; closures read fields here so user config (e.g. mru_sections) applies.
local startify = {}
local if_nil = vim.F.if_nil
local fnamemodify = vim.fn.fnamemodify
local default_header = {
type = "text",
val = {
[[ __]],
[[ ___ ___ ___ __ __ /\_\ ___ ___]],
[[ / _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\]],
[[ /\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \]],
[[ \ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\]],
[[ \/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/]],
},
opts = {
hl = "Type",
shrink_margin = false,
-- wrap = "overflow";
},
}
local leader = "SPC"
local git_info = { is_git = false, branch = nil }
local _git_cwd = nil
local function update_git_info()
local cwd = vim.fn.getcwd()
if cwd == _git_cwd then return end
_git_cwd = cwd
local git_root = utils.git_worktree_root(cwd)
if not git_root then
git_info = { is_git = false, branch = nil }
return
end
local branch = vim.fn.systemlist({ "git", "-C", cwd, "branch", "--show-current" })[1]
git_info = {
is_git = true,
branch = (branch and branch ~= "") and branch or nil,
}
end
--- @param sc string
--- @param txt string
--- @param keybind string? optional
--- @param keybind_opts table? optional
local function button(sc, txt, keybind, keybind_opts)
local sc_ = sc:gsub("%s", ""):gsub(leader, "")
local opts = {
position = "left",
shortcut = "[" .. sc .. "] ",
cursor = 1,
-- width = 50,
align_shortcut = "left",
hl_shortcut = { { "Operator", 0, 1 }, { "Number", 1, #sc + 1 }, { "Operator", #sc + 1, #sc + 2 } },
shrink_margin = false,
}
if keybind then
keybind_opts = if_nil(keybind_opts, { noremap = true, silent = true, nowait = true })
opts.keymap = { "n", sc_, keybind, keybind_opts }
end
local function on_press()
local key = vim.api.nvim_replace_termcodes(keybind .. "", true, false, true)
vim.api.nvim_feedkeys(key, "t", false)
end
return {
type = "button",
val = txt,
on_press = on_press,
opts = opts,
}
end
local file_icons = {
enabled = true,
highlight = true,
-- available: devicons, mini, to use nvim-web-devicons or mini.icons
-- if provider not loaded and enabled is true, it will try to use another provider
provider = "mini",
}
local function icon(fn)
return utils.get_icon(file_icons, fn)
end
local function file_button(fn, sc, short_fn, autocd)
short_fn = if_nil(short_fn, fn)
local ico_txt
local fb_hl = {}
if file_icons.enabled then
local ico, hl = icon(fn)
local hl_option_type = type(file_icons.highlight)
if hl_option_type == "boolean" then
if hl and file_icons.highlight then
table.insert(fb_hl, { hl, 0, #ico })
end
end
if hl_option_type == "string" then
table.insert(fb_hl, { file_icons.highlight, 0, #ico })
end
ico_txt = ico .. " "
else
ico_txt = ""
end
local cd_cmd = (autocd and " | cd %:p:h" or "")
local file_button_el = button(sc, ico_txt .. short_fn, "e " .. vim.fn.fnameescape(fn) .. cd_cmd .. " ")
local fn_start = short_fn:match(".*[/\\]")
if fn_start ~= nil then
table.insert(fb_hl, { "Comment", #ico_txt, #fn_start + #ico_txt })
end
file_button_el.opts.hl = fb_hl
return file_button_el
end
local default_mru_ignore = { "gitcommit" }
local mru_opts = {
ignore = function(path, ext)
return (string.find(path, "COMMIT_EDITMSG")) or (vim.tbl_contains(default_mru_ignore, ext))
end,
autocd = false
}
local function mru_git(start, cwd, items_number, opts)
opts = opts or mru_opts
items_number = if_nil(items_number, 10)
local found = utils.get_git_files(cwd, items_number, opts.ignore)
local tbl = {}
for i, fn in ipairs(found) do
local short_fn
if cwd then
short_fn = fnamemodify(fn, ":.")
else
short_fn = fnamemodify(fn, ":~")
end
local file_button_el = file_button(fn, tostring(i + start - 1), short_fn, opts.autocd)
tbl[i] = file_button_el
end
return {
type = "group",
val = tbl,
opts = {},
}
end
local function mru(start, cwd, items_number, opts)
opts = opts or mru_opts
items_number = if_nil(items_number, 10)
local found = utils.get_mru(cwd, items_number, opts.ignore)
local tbl = {}
for i, fn in ipairs(found) do
local short_fn
if cwd then
short_fn = fnamemodify(fn, ":.")
else
short_fn = fnamemodify(fn, ":~")
end
local file_button_el = file_button(fn, tostring(i + start - 1), short_fn, opts.autocd)
tbl[i] = file_button_el
end
return {
type = "group",
val = tbl,
opts = {},
}
end
local function make_git_title_el(opts)
local cwd_short = fnamemodify(vim.fn.getcwd(), ":~")
local branch = git_info.branch
if branch then
local head = "MRU " .. cwd_short .. " "
return {
type = "text",
val = head .. branch,
opts = vim.tbl_extend("force", {
hl = {
{ "SpecialComment", 0, #head },
{ "Label", #head, #head + #branch },
},
shrink_margin = false,
}, opts or {}),
}
else
return {
type = "text",
val = "MRU " .. cwd_short,
opts = vim.tbl_extend("force", { hl = "SpecialComment", shrink_margin = false }, opts or {}),
}
end
end
local section = {
header = default_header,
top_buttons = {
type = "group",
val = {
button("e", "New file", "ene "),
},
},
-- note about MRU: currently this is a function,
-- since that means we can get a fresh mru
-- whenever there is a DirChanged. this is *really*
-- inefficient on redraws, since mru does a lot of I/O.
-- should probably be cached, or maybe figure out a way
-- to make it a reference to something mutable
-- and only mutate that thing on DirChanged
mru = {
type = "group",
val = {
{ type = "padding", val = 1 },
{ type = "text", val = "MRU", opts = { hl = "SpecialComment" } },
{ type = "padding", val = 1 },
{
type = "group",
val = function()
return { mru(10) }
end,
},
},
},
mru_cwd = {
type = "group",
val = function()
local cwd = vim.fn.getcwd()
return {
{ type = "padding", val = 1 },
{ type = "text", val = "MRU " .. fnamemodify(cwd, ":~"), opts = { hl = "SpecialComment", shrink_margin = false } },
{ type = "padding", val = 1 },
{
type = "group",
val = function() return { mru(0, cwd) } end,
opts = { shrink_margin = false },
},
}
end,
},
mru_git = {
type = "group",
val = function()
update_git_info()
return {
{ type = "padding", val = 1 },
make_git_title_el(),
{ type = "padding", val = 1 },
{
type = "group",
val = function()
return { mru_git(0, vim.fn.getcwd()) }
end,
opts = { shrink_margin = false },
},
}
end,
},
bottom_buttons = {
type = "group",
val = {
button("q", "Quit", "q "),
},
},
footer = {
type = "group",
val = {},
},
}
startify.mru_sections = { "mru_cwd", "mru" }
local config = {
layout = {
{ type = "padding", val = 1 },
section.header,
{ type = "padding", val = 2 },
section.top_buttons,
{
type = "group",
val = function()
local result = {}
for _, name in ipairs(startify.mru_sections) do
if section[name] then
table.insert(result, section[name])
end
end
return result
end,
},
{ type = "padding", val = 1 },
section.bottom_buttons,
section.footer,
},
opts = {
margin = 3,
redraw_on_resize = false,
setup = function()
vim.api.nvim_create_autocmd('DirChanged', {
pattern = '*',
group = "alpha_temp",
callback = function()
utils.mru_cache = {}
utils.git_toplevel_cache = {}
_git_cwd = nil
require('alpha').redraw()
vim.cmd('AlphaRemap')
end,
})
end,
},
}
startify.icon = icon
startify.button = button
startify.file_button = file_button
startify.mru = mru
startify.mru_git = mru_git
startify.mru_opts = mru_opts
startify.section = section
startify.config = config
startify.file_icons = file_icons
startify.nvim_web_devicons = file_icons
startify.leader = leader
startify.opts = config
return startify
neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/themes/theta.lua 0000664 0000000 0000000 00000017274 15171555353 0023534 0 ustar 00root root 0000000 0000000 local utils = require("alpha.utils")
local dashboard = require("alpha.themes.dashboard")
local if_nil = vim.F.if_nil
local file_icons = {
enabled = true,
highlight = true,
-- available: devicons, mini, to use nvim-web-devicons or mini.icons
-- if provider not loaded and enabled is true, it will try to use another provider
provider = "mini",
}
local function icon(fn)
return utils.get_icon(file_icons, fn)
end
local function file_button(fn, sc, short_fn, autocd)
short_fn = short_fn or fn
local ico_txt
local fb_hl = {}
if file_icons.enabled then
local ico, hl = icon(fn)
local hl_option_type = type(file_icons.highlight)
if hl_option_type == "boolean" then
if hl and file_icons.highlight then
table.insert(fb_hl, { hl, 0, #ico })
end
end
if hl_option_type == "string" then
table.insert(fb_hl, { file_icons.highlight, 0, #ico })
end
ico_txt = ico .. " "
else
ico_txt = ""
end
local cd_cmd = (autocd and " | cd %:p:h" or "")
local file_button_el =
dashboard.button(sc, ico_txt .. short_fn, "e " .. vim.fn.fnameescape(fn) .. cd_cmd .. " ")
local fn_start = short_fn:match(".*[/\\]")
if fn_start ~= nil then
table.insert(fb_hl, { "Comment", #ico_txt - 2, #fn_start + #ico_txt })
end
file_button_el.opts.cursor = vim.fn.strdisplaywidth(ico_txt)
file_button_el.opts.hl = fb_hl
return file_button_el
end
local default_mru_ignore = { "gitcommit" }
local mru_opts = {
ignore = function(path, ext)
return (string.find(path, "COMMIT_EDITMSG")) or (vim.tbl_contains(default_mru_ignore, ext))
end,
autocd = false,
}
local git_info = { is_git = false, branch = nil }
local _git_cwd = nil
local function update_git_info()
local cwd = vim.fn.getcwd()
if cwd == _git_cwd then return end
_git_cwd = cwd
local git_root = utils.git_worktree_root(cwd)
if not git_root then
git_info = { is_git = false, branch = nil }
return
end
local branch = vim.fn.systemlist({ "git", "-C", cwd, "branch", "--show-current" })[1]
git_info = {
is_git = true,
branch = (branch and branch ~= "") and branch or nil,
}
end
-- Module-level plenary cache; only marked tried on success so lazy-loaded
-- plenary is picked up on the next redraw after it becomes available.
local _plenary_path, _plenary_tried
local function _mru_impl(fetch_fn, start, cwd, items_number, opts)
opts = opts or mru_opts
items_number = if_nil(items_number, 10)
local found = fetch_fn(cwd, items_number, opts.ignore)
local target_width = 35
local tbl = {}
for i, fn in ipairs(found) do
local short_fn
if cwd then
short_fn = vim.fn.fnamemodify(fn, ":.")
else
short_fn = vim.fn.fnamemodify(fn, ":~")
end
if #short_fn > target_width then
if not _plenary_tried then
local ok
ok, _plenary_path = pcall(require, "plenary.path")
if ok then _plenary_tried = true else _plenary_path = nil end
end
if _plenary_path then
short_fn = _plenary_path.new(short_fn):shorten(1, { -2, -1 })
if #short_fn > target_width then
short_fn = _plenary_path.new(short_fn):shorten(1, { -1 })
end
end
end
local shortcut = tostring(i + start - 1)
tbl[i] = file_button(fn, shortcut, short_fn, opts.autocd)
end
return { type = "group", val = tbl, opts = {} }
end
--- @param start number
--- @param cwd string? optional
--- @param items_number number? optional number of items to generate, default = 10
local function mru(start, cwd, items_number, opts)
return _mru_impl(utils.get_mru, start, cwd, items_number, opts)
end
--- @param start number
--- @param cwd string? optional
--- @param items_number number? optional number of items to generate, default = 10
local function mru_git(start, cwd, items_number, opts)
return _mru_impl(utils.get_git_files, start, cwd, items_number, opts)
end
local header = {
type = "text",
val = {
[[ __]],
[[ ___ ___ ___ __ __ /\_\ ___ ___]],
[[ / _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\]],
[[ /\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \]],
[[ \ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\]],
[[ \/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/]],
},
opts = {
position = "center",
hl = "Type",
-- wrap = "overflow";
},
}
local section_mru = {
type = "group",
val = {
{
type = "text",
val = "Recent files",
opts = {
hl = "SpecialComment",
shrink_margin = false,
position = "center",
},
},
{ type = "padding", val = 1 },
{
type = "group",
val = function()
return { mru(0, vim.fn.getcwd()) }
end,
opts = { shrink_margin = false },
},
},
}
local section_mru_git = {
type = "group",
val = function()
update_git_info()
return {
{
type = "text",
val = function()
local branch = git_info.branch
if branch then
return "MRU " .. branch
else
return "MRU"
end
end,
opts = {
hl = "SpecialComment",
shrink_margin = false,
position = "center",
},
},
{ type = "padding", val = 1 },
{
type = "group",
val = function()
return { mru_git(0, vim.fn.getcwd()) }
end,
opts = { shrink_margin = false },
},
}
end,
}
local buttons = {
type = "group",
val = {
{ type = "text", val = "Quick links", opts = { hl = "SpecialComment", position = "center" } },
{ type = "padding", val = 1 },
dashboard.button("e", " New file", "ene"),
dashboard.button("SPC f f", " Find file"),
dashboard.button("SPC f g", " Live grep"),
dashboard.button("c", " Configuration", "exe 'cd' stdpath ('config')"),
dashboard.button("u", " Update plugins", "Lazy sync"),
dashboard.button("q", " Quit", "qa"),
},
position = "center",
}
local config = {
layout = {
{ type = "padding", val = 2 },
header,
{ type = "padding", val = 2 },
section_mru,
{ type = "padding", val = 2 },
buttons,
},
opts = {
margin = 5,
setup = function()
vim.api.nvim_create_autocmd('DirChanged', {
pattern = '*',
group = "alpha_temp",
callback = function()
utils.mru_cache = {}
utils.git_toplevel_cache = {}
_git_cwd = nil
require('alpha').redraw()
vim.cmd('AlphaRemap')
end,
})
end,
},
}
return {
header = header,
buttons = buttons,
mru = mru,
mru_git = mru_git,
section_mru = section_mru,
section_mru_git = section_mru_git,
config = config,
-- theme specific config
mru_opts = mru_opts,
leader = dashboard.leader,
file_icons = file_icons,
-- deprecated
nvim_web_devicons = file_icons,
}
neovim-alpha-0.0~git20260417.6c6a89d/lua/alpha/utils.lua 0000664 0000000 0000000 00000021110 15171555353 0022262 0 ustar 00root root 0000000 0000000 local M = {}
M.mru_cache = {}
--- cwd -> git toplevel path, or false if not a repo (negative cache).
M.git_toplevel_cache = {}
local uv = vim.uv or vim.loop
--- @param work_dir string
--- @param git_args string[]
--- @return string[]|nil lines, or nil on git failure
local function git_cmd_lines(work_dir, git_args)
local cmd = vim.list_extend({ "git", "-C", work_dir }, git_args)
local out = vim.fn.systemlist(cmd)
if vim.v.shell_error ~= 0 then
return nil
end
return out
end
--- Same ordering as `{ ... } | sort | uniq`: sorted unique non-empty lines.
--- @param lines string[]
--- @return string[]
local function sorted_unique_lines(lines)
if #lines == 0 then
return lines
end
local sorted = vim.list_extend({}, lines)
table.sort(sorted)
local out = {}
local prev
for _, p in ipairs(sorted) do
if p ~= "" and p ~= prev then
prev = p
out[#out + 1] = p
end
end
return out
end
--- Resolve the git worktree root for cwd, using a small cache (cleared with MRU cache on DirChanged).
--- @param work_dir string?
--- @return string|nil
function M.git_worktree_root(work_dir)
work_dir = work_dir or vim.fn.getcwd()
local cached = M.git_toplevel_cache[work_dir]
if cached == false then
return nil
end
if cached ~= nil then
return cached
end
local top_out = git_cmd_lines(work_dir, { "rev-parse", "--show-toplevel" })
if not top_out or not top_out[1] then
M.git_toplevel_cache[work_dir] = false
return nil
end
M.git_toplevel_cache[work_dir] = top_out[1]
return top_out[1]
end
local READABLE_CACHE_MAX = 500
local _readable_cache = {}
local _readable_cache_size = 0
--- Reset the readable cache and its size counter atomically.
--- Always use this instead of assigning to the table directly.
function M.clear_readable_cache()
_readable_cache = {}
_readable_cache_size = 0
end
--- @param path string
--- @return boolean
function M.filereadable(path)
if _readable_cache[path] ~= nil then
return _readable_cache[path]
end
if _readable_cache_size >= READABLE_CACHE_MAX then
M.clear_readable_cache()
end
local readable = uv.fs_stat(path) ~= nil
_readable_cache[path] = readable
_readable_cache_size = _readable_cache_size + 1
return readable
end
--- @param cwd string? working directory, defaults to cwd
--- @param items_number number max number of items to return
--- @param ignore_cb function? optional ignore callback(path, ext) -> bool
--- @return string[]
function M.get_git_files(cwd, items_number, ignore_cb)
local work_dir = cwd or vim.fn.getcwd()
local key = "git_" .. work_dir
if M.mru_cache[key] and #M.mru_cache[key] >= items_number then
return M.mru_cache[key]
end
local git_root = M.git_worktree_root(work_dir)
if not git_root then
return {}
end
local diff_out = git_cmd_lines(work_dir, { "diff", "--name-only" }) or {}
local cached_out = git_cmd_lines(work_dir, { "diff", "--cached", "--name-only" }) or {}
local found = {}
local prev_unique_count = -1
local n_commits = math.max(50, items_number * 25)
local n_max = 2048
while #found < items_number and n_commits <= n_max do
local log_out = git_cmd_lines(work_dir, {
"log",
"--pretty=format:",
"--name-only",
"-n",
tostring(n_commits),
}) or {}
local combined = {}
vim.list_extend(combined, diff_out)
vim.list_extend(combined, cached_out)
vim.list_extend(combined, log_out)
local sorted_paths = sorted_unique_lines(combined)
if #sorted_paths == prev_unique_count then
break
end
prev_unique_count = #sorted_paths
found = {}
for _, rel_path in ipairs(sorted_paths) do
local abs_path = git_root .. "/" .. rel_path
local ignore = ignore_cb and ignore_cb(abs_path, M.get_extension(abs_path))
if not ignore and M.filereadable(abs_path) then
table.insert(found, abs_path)
if #found >= items_number then
break
end
end
end
if #found >= items_number then
break
end
n_commits = n_commits * 2
end
M.mru_cache[key] = found
return found
end
--- @param cwd string?
--- @param items_number number
--- @param ignore_cb function?
--- @return string[]
function M.get_mru(cwd, items_number, ignore_cb)
local key = cwd or "global"
if M.mru_cache[key] and #M.mru_cache[key] >= items_number then
return M.mru_cache[key]
end
local all_oldfiles = vim.v.oldfiles
local found = {}
local max_check = math.min(#all_oldfiles, 200)
for i = 1, max_check do
local v = all_oldfiles[i]
local cwd_cond = not cwd or vim.startswith(v, cwd)
local ignore = (ignore_cb and ignore_cb(v, M.get_extension(v))) or false
if cwd_cond and not ignore then
if M.filereadable(v) then
table.insert(found, v)
if #found >= items_number then
break
end
end
end
end
M.mru_cache[key] = found
return found
end
--- @param fn string file name or path
--- @return string
function M.get_extension(fn)
local basename = vim.fs.basename(fn)
local match = basename:match("^.+(%..+)$")
local ext = ""
if match ~= nil then
ext = match:sub(2)
end
return ext
end
local _devicons, _devicons_tried
local function devicons_get_icon(fn, ext)
if not _devicons_tried then
local ok
ok, _devicons = pcall(require, "nvim-web-devicons")
if ok then _devicons_tried = true else _devicons = nil end
end
if not _devicons then return nil, nil end
return _devicons.get_icon(fn, ext, { default = true })
end
local _mini_icons, _mini_tried
local function mini_get_icon(fn, ext)
if not _mini_tried then
local ok
ok, _mini_icons = pcall(require, "mini.icons")
if ok then _mini_tried = true else _mini_icons = nil end
end
if not _mini_icons then return nil, nil end
if ext ~= "" then
local icon, hl, _ = _mini_icons.get("extension", ext)
return icon, hl
else
local icon, hl, _ = _mini_icons.get("file", fn)
return icon, hl
end
end
--- @param provider string devicons or mini
--- @param fn string file name or path
--- @return string, string
function M.get_file_icon(provider, fn)
local ext = M.get_extension(fn)
if provider == "devicons" then
local ico, hl = devicons_get_icon(fn, ext)
-- if devicons is not installed, fallback to mini icons
if ico == nil then ico, hl = mini_get_icon(fn, ext) end
return ico or "", hl or ""
end
if provider == "mini" then
local ico, hl = mini_get_icon(fn, ext)
-- if mini icons is not installed, fallback to devicons
if ico == nil then ico, hl = devicons_get_icon(fn, ext) end
return ico or "", hl or ""
end
return "", ""
end
--- Validate the provider, fetch the icon, and mutate file_icons.enabled on failure.
--- @param file_icons table theme-local file_icons config table (provider, enabled fields)
--- @param fn string file name or path
--- @return string, string icon and highlight group
function M.get_icon(file_icons, fn)
if file_icons.provider ~= "devicons" and file_icons.provider ~= "mini" then
vim.notify(
"Alpha: Invalid file icons provider: " .. file_icons.provider .. ", disable file icons",
vim.log.levels.WARN
)
file_icons.enabled = false
return "", ""
end
local ico, hl = M.get_file_icon(file_icons.provider, fn)
if ico == "" then
file_icons.enabled = false
vim.notify("Alpha: Mini icons or devicons get icon failed, disable file icons", vim.log.levels.WARN)
end
return ico, hl
end
--- @param hl (string | number)[][][] highlight
--- @param text string[] text lines corresponding to the highlights
--- @param utf16? boolean default: false
--- @return (string | number)[][][]
function M.charhl_to_bytehl(hl, text, utf16)
utf16 = utf16 or false
local new_hl = {}
for row, line_hl in ipairs(hl) do
new_hl[row] = {}
for i, item in ipairs(line_hl) do
local group = item[1]
local start_col = vim.fn.byteidx(text[row], item[2], utf16)
local end_col = vim.fn.byteidx(text[row], item[3], utf16)
new_hl[row][i] = { group, start_col, end_col }
end
end
return new_hl
end
return M
neovim-alpha-0.0~git20260417.6c6a89d/stylua.toml 0000664 0000000 0000000 00000000216 15171555353 0020773 0 ustar 00root root 0000000 0000000 column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 4
quote_style = "AutoPreferDouble"
no_call_parentheses = false