Initial commit: nvim-minimal

A small, fast, portable Neovim config built on bare lazy.nvim (no LazyVim,
no LSPs, no Mason). Vendored `based` colorscheme (GPLv3, self-authored,
derived from vim-vividchalk) so the config loads on any machine with just
nvim + git — the listed treesitter parsers ship prebuilt, so no compiler
is needed for the configured languages.

Plugins: snacks.nvim (picker/explorer/buffers), nvim-treesitter (pinned to
master for the declarative ensure_installed/highlight/indent API), blink.cmp
(buffer+path completion, prebuilt binary), lualine, gitsigns, mini.align/
comment/surround.

Personal keymaps ported: jj/jk/kj/чя escape, ж -> :, Russian langmap, arrow
disables, bracket-return expansions, gc/sa-sd-sr/gz-gZ.
This commit is contained in:
mk 2026-07-28 03:23:29 +03:00
commit 97a90cc1e5
16 changed files with 575 additions and 0 deletions

8
.gitignore vendored Normal file
View File

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

22
LICENSE Normal file
View File

@ -0,0 +1,22 @@
nvim-minimal — a small, portable Neovim configuration.
Copyright (C) 2025 mk
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
---
colors/based.vim is vendored from the `based.vim` project (also by the author,
GPLv3). It is derived from `vim-vividchalk` by Tim Pope, which is
permissively-licensed; the GPLv3 terms above apply to the combined work.
The original GPLv3 header in colors/based.vim is preserved verbatim.

78
README.md Normal file
View File

@ -0,0 +1,78 @@
# nvim-minimal
A small, fast, portable Neovim config. No LSPs, no heavy plugins — just the
editing essentials and a familiar UI. Clone it on any machine with Neovim + git
and you're editing in seconds.
## Requirements
- **Neovim** ≥ 0.10
- **git** (lazy.nvim bootstraps itself and clones plugins on first launch)
- a **Nerd Font** installed in your *terminal* for icons in snacks/lualine
(optional; config works without it, icons just render as `?`)
- a **C compiler + make** (`base-devel` on Arch) — *optional*. The nvim-treesitter
languages listed below ship **prebuilt** parsers in the plugin repo, so the
configured languages work without any compilation. You only need a compiler if
you later add parsers that aren't prebuilt (or force `:TSInstall` to recompile).
> On first launch nvim pauses to clone plugins (network, one-time); no compilation
> is needed for the bundled languages.
## Install
```sh
git clone <this-repo> ~/.config/nvim
nvim # lazy.nvim bootstraps and installs plugins; parsers are prebuilt
```
`lazy-lock.json` is committed, so every clone installs identical plugin
versions. To bump, run `:Lazy sync` and commit the updated lockfile.
## What's in it
- **lazy.nvim** — plugin manager (bootstrap, no LazyVim)
- **snacks.nvim** — file picker, explorer, buffer picker
- **nvim-treesitter** — highlighting, indentation, treesitter folds
- **blink.cmp** — completion (buffer words + file paths; Super-Tab keymap)
- **lualine** — statusline
- **gitsigns** — git gutter signs
- **mini.align / mini.comment / mini.surround**`gz`·`gZ`, `gc`, `sa/sd/sr`
- **`based` colorscheme** — vendored at `colors/based.vim` (self-authored,
GPLv3, derived from vim-vividchalk). Transparent against a see-through
terminal by default.
## Key bindings
| Key | Action |
|---|---|
| `gb` | buffer picker |
| `<leader>F` | find files (hidden, ignoring `node_modules`/`.git`) |
| `<leader>t` | file explorer |
| `jj` / `jk` / `kj` / `чя` | escape from insert mode |
| `ж` | enter command-line (`:`) — Russian-layout fix |
| `gc` | toggle comment (mini.comment) |
| `sa` / `sd` / `sr` | add / delete / replace surround (mini.surround) |
| `gz` / `gZ` | align / align-with-preview (mini.align) |
| `gf` | go to file under cursor (built-in; `path` + `suffixesadd`) |
| `<Tab>` / `<S-Tab>` | next / prev completion item (blink) |
| `<Cr>` | accept completion |
| `<C-space>` | show completion + docs |
| `<C-b>` / `<C-f>` | scroll docs up / down |
Arrow keys, `<Esc>`, `<C-c>`, and middle-click are deliberately disabled to
force home-row habits.
## Notes / limitations
- **No LSP.** `gd`/`gr`/hover/etc. rely on built-ins; there is no language
server. That's the point.
- **blink.cmp prebuilt binary** ships for linux/mac x86_64 & arm64 release tags.
On other architectures you'd need a Rust toolchain to build `libblink`
(out of scope here).
- Filename completion is provided by blink's `path` source; native
`<C-x><C-f>` is not configured (blink's `<C-f>` scrolls docs).
## License
GPLv3. `colors/based.vim` keeps its original GPLv3 header; it is derived from
`vim-vividchalk` by Tim Pope (permissively licensed), so GPLv3 is compatible.

103
colors/based.vim Normal file
View File

@ -0,0 +1,103 @@
" Vim color scheme
" Name: based.vim
" Author: mk <dont@me.pls>
" Version: 1.0
" Based? Based on what? Based on vim-medicchalk by @ParamagicDev, which is based on vim-vividchalk by @tpope, which is based on the Vibrank Ink theme for TextMate.
" Licensed under GPLv3.
" "GUI"-only theme. Make sure that your vim environment supports 24-bit color.
set termguicolors
set cursorline
if has("gui_running") && &background !=# 'dark'
set background=dark
endif
highlight clear
if exists("syntax_on")
syntax reset
endif
let g:colors_name="based"
highlight StatusLine guifg=White guibg=#080808 gui=bold
highlight StatusLineNC guifg=#eeeeee guibg=#1c1c1c gui=none
" Status line columns.
highlight SLC0 guifg=#00AF06 guibg=#000000 gui=NONE
highlight SLC1 guifg=#00AF06 guibg=#0A0A0A gui=NONE
highlight SLCodestats guifg=#FFFFFF guibg=#0202FF gui=NONE
highlight SLCoc guifg=#ccaa00 guibg=#000000 gui=NONE
highlight SLTitle guifg=#CCCCFF guibg=#000000
highlight SLTicker guifg=#00ff06 guibg=#000000 gui=reverse,bold
"
highlight ColorColumn guibg=#0A0A0A
highlight SignColumn guibg=#000000
highlight Comment guifg=#aa00dd
highlight ActiveBuffer guifg=#ff0000
highlight link javascriptRegexpString Regexp
highlight link diffAdded String
highlight link diffRemoved Statement
highlight link diffLine PreProc
highlight link diffSubname Comment
highlight Ignore guifg=#000000
highlight WildMenu guifg=#000000 guibg=#ffff00 gui=bold
highlight Cursor guifg=#000000 guibg=#ffffff
highlight CursorColumn guibg=#000000
highlight CursorLine guibg=#050505
highlight NonText guifg=#404040
highlight SpecialKey guifg=#404040
highlight Directory none
highlight link Directory Identifier
highlight ErrorMsg guibg=#dd0000
highlight Search guifg=NONE guibg=#232323 gui=none
highlight IncSearch guifg=#FFFFFF guibg=#000000
highlight MoreMsg guifg=#00AA00
highlight LineNr guifg=#DDEEFF guibg=#060606
highlight Question none
highlight link Question MoreMsg
highlight Title guifg=Magenta
highlight VisualNOS gui=none guibg=#444444
highlight Visual guibg=#555577
highlight MatchParen guibg=#1100AA
highlight WarningMsg guifg=#cc0000
highlight Error guibg=#AA0000
highlight Todo guifg=#32c5ff
highlight IconNameDevicon guifg=White
highlight Folded guibg=#110077 guifg=#aaddee
highlight FoldColumn none
highlight link FoldColumn Folded
highlight DiffAdd guibg=DarkBlue
highlight DiffChange guibg=DarkMagenta
highlight DiffDelete gui=bold guifg=Blue guibg=DarkCyan
highlight DiffText cterm=bold gui=bold guibg=Red
highlight Pmenu guifg=White guibg=#000099 gui=bold
highlight PmenuSel guifg=White guibg=#000000 guifg=#00FF00 gui=bold
highlight PmenuSbar guibg=Grey ctermbg=Grey
highlight PmenuThumb guibg=White ctermbg=White
highlight TabLine gui=underline guifg=#bbbbbb guibg=#333333
highlight TabLineSel guifg=White guibg=Black ctermfg=White ctermbg=Black
highlight TabLineFill gui=underline guifg=#bbbbbb guibg=#808080
highlight Type gui=none
highlight Statement gui=none
highlight Identifier cterm=none
highlight Statement guifg=#ffff66
highlight Type guifg=#FFFFCC
highlight Constant guifg=#339999
highlight String guifg=#66FF00
highlight Identifier guifg=#FFCC00
highlight PreProc guifg=#88FFFF
highlight Special guifg=#11CF01
highlight Regexp guifg=#44B4CC

22
init.lua Normal file
View File

@ -0,0 +1,22 @@
-- nvim-minimal: lightweight portable Neovim config.
-- Options first: several (termguicolors, etc.) must be set before lazy.nvim
-- starts so the plugin-install colorscheme renders correctly.
require("config.options")
-- Bootstrap + setup lazy.nvim (loads everything under lua/plugins/).
require("config.lazy")
-- Personal keymaps and autocmds. Plugin-bound keys (gb, <leader>F, <leader>t)
-- live in their plugin specs under lua/plugins/; these are the plugin-agnostic
-- ones (escape bigrams, Russian-layout fixes, arrow-key disables, etc.).
require("config.keymaps")
require("config.autocmds")
-- Colorscheme + transparency.
-- `based` is vendored at colors/based.vim (self-authored, GPLv3).
-- It never sets Normal's bg, so the terminal shows through; we still
-- force Normal/NormalFloat to none so plugin float windows stay transparent.
vim.cmd.colorscheme("based")
vim.api.nvim_set_hl(0, "Normal", { bg = "none" })
vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" })

12
lazy-lock.json Normal file
View File

@ -0,0 +1,12 @@
{
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
"gitsigns.nvim": { "branch": "main", "commit": "31d6fb2d618bca1482b9f274751ead5f03461408" },
"lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
"lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" },
"mini.align": { "branch": "main", "commit": "77d7446b9f2452193f13ced9fb73a8b3aa4a4f4d" },
"mini.comment": { "branch": "main", "commit": "27a29d6b949b9497f80a0a03421e89fed71d8c37" },
"mini.surround": { "branch": "main", "commit": "8d5d0c5aa92449368ac251e85451d79d8f69d296" },
"nvim-treesitter": { "branch": "master", "commit": "cf12346a3414fa1b06af75c79faebe7f76df080a" },
"nvim-web-devicons": { "branch": "master", "commit": "2ae6958df7ced50baac5035cec0c15799eedfbf7" },
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" }
}

1
lua/config/autocmds.lua Normal file
View File

@ -0,0 +1 @@
-- Autocmds. Currently empty; add vim.api.nvim_create_autocmd groups here as needed.

52
lua/config/keymaps.lua Normal file
View File

@ -0,0 +1,52 @@
-- Personal keymaps (plugin-agnostic). Plugin-bound keys live in their specs.
local function map(mode, lhs, rhs, opts)
local options = { noremap = true, silent = true }
if opts then
options = vim.tbl_extend('force', options, opts)
end
vim.keymap.set(mode, lhs, rhs, options)
end
local function no(lhs, rhs) map('n', lhs, rhs, { silent = false }) end
local function no_s(lhs, rhs) map('n', lhs, rhs) end
local function no_r(lhs, rhs) map('n', lhs, rhs, { noremap = false, silent = false }) end
local function i(lhs, rhs) map('i', lhs, rhs, { silent = false }) end
local function i_s(lhs, rhs) map('i', lhs, rhs) end
local function v_s(lhs, rhs) map('v', lhs, rhs) end
-- disable arrow keys and middle-click (muscle memory from the old config)
no_s('<up>', '<nop>')
no_s('<down>', '<nop>')
no_s('<left>', '<nop>')
no_s('<right>', '<nop>')
no_s('<c-left>', '<nop>')
no_s('<c-right>', '<nop>')
v_s('<up>', '<nop>')
v_s('<down>', '<nop>')
v_s('<left>', '<nop>')
v_s('<right>', '<nop>')
v_s('<c-left>', '<nop>')
v_s('<c-right>', '<nop>')
-- escape from insert mode on home-row bigrams
i_s('jj', '<esc>')
i_s('jk', '<esc>')
i_s('kj', '<esc>')
i_s('чя', '<esc>')
i_s('<esc>', '<nop>')
i_s('<C-c>', '<nop>')
-- bracket-return expansions: open a line between the delimiters, indented
i('[<CR>', '[<CR>]<Esc>O<BS><Tab>')
i('{<CR>', '{<CR>}<Esc>O<BS><Tab>')
i('(<CR>', '(<CR>)<Esc>O<BS><Tab>')
vim.keymap.set({ 'n', 'i', 'v' }, '<LeftMouse>', '<nop>')
-- Russian-layout fixes: `ж` types `:`, `W`/`E`/`w'` expand in cmdline
no_r('ж', ':')
vim.cmd.cnoreabbrev({ "<expr> W", "((getcmdtype() is# ':' && getcmdline() is# 'W')?('w'):('W'))" })
vim.cmd.cnoreabbrev({ "<expr> E", "((getcmdtype() is# ':' && getcmdline() is# 'E')?('e'):('E'))" })
vim.cmd.cnoreabbrev({ "<expr> w'", "(getcmdtype() == \":\" && getcmdline() == \"w'\" ? \"w\" : \"w'\")" })

37
lua/config/lazy.lua Normal file
View File

@ -0,0 +1,37 @@
-- Bootstrap lazy.nvim on a fresh machine (needs only git + internet).
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
spec = { { import = "plugins" } },
defaults = {
lazy = false,
version = false, -- use latest git commit; lazy-lock.json pins the exact SHAs
},
install = { colorscheme = { "based" } },
checker = { enabled = true, notify = false },
performance = {
rtp = {
disabled_plugins = {
"gzip",
"tarPlugin",
"tohtml",
"tutor",
"zipPlugin",
},
},
},
})

56
lua/config/options.lua Normal file
View File

@ -0,0 +1,56 @@
-- Options are set before lazy.nvim startup.
vim.opt.termguicolors = true
vim.opt.encoding = "utf8"
vim.opt.hidden = true
vim.opt.incsearch = true
vim.opt.langmap =
"ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯ;ABCDEFGHIJKLMNOPQRSTUVWXYZ,фисвуапршолдьтщзйкыегмцчня;abcdefghijklmnopqrstuvwxyz"
vim.opt.maxmempattern = 5000
-- completion
vim.opt.wildignorecase = true
vim.opt.smartcase = true
vim.opt.wildmenu = true
vim.opt.path:append("**")
-- `gf` will try these extensions on a bare word under the cursor.
vim.opt.suffixesadd = { ".lua", ".vim", ".md", ".json", ".ts", ".tsx", ".js", ".py", ".rs" }
vim.opt.wildignore:append("**/node_modules/**")
vim.opt.completeopt = { "menu", "menuone", "preview", "noinsert" }
-- backups and recovery
vim.opt.backup = true
vim.opt.backupdir = os.getenv("HOME") .. "/.local/state/nvim/backup"
vim.opt.swapfile = true
vim.opt.undofile = true
vim.opt.updatetime = 800
-- misc
vim.opt.wrap = false
vim.opt.whichwrap:append("<,>,[,]")
vim.opt.timeoutlen = 500
vim.opt.ttimeoutlen = 50
-- indentation/tabulation
vim.opt.tabstop = 4
vim.opt.softtabstop = 4
vim.opt.expandtab = true
vim.opt.shiftwidth = 4
vim.opt.smartindent = true
vim.opt.autoindent = true
-- layout
vim.opt.signcolumn = "yes"
vim.opt.colorcolumn = { 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 80, 99 }
vim.opt.cmdheight = 1
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.scrolloff = 10
-- folds (treesitter-based; no nvim-ufo needed)
vim.opt.foldcolumn = "1"
vim.opt.foldlevel = 99
vim.opt.foldlevelstart = 99
vim.opt.foldenable = true
vim.opt.foldmethod = "expr"
vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()"

47
lua/plugins/blink.lua Normal file
View File

@ -0,0 +1,47 @@
-- saghen/blink.cmp: fast completion (Rust-backed, prebuilt binary).
-- Sources are buffer words + file paths only (no LSP). Filename completion
-- comes from the `path` source, triggered by typing `/` or `./`.
-- `version = "*"` pulls a release tag, which ships a prebuilt `libblink`
-- binary (x86_64/arm64, linux/mac) — no Rust toolchain needed on those arches.
return {
{
"saghen/blink.cmp",
event = "InsertEnter",
version = "*",
opts = {
sources = {
default = { "buffer", "path" },
},
completion = {
ghost_text = { enabled = false },
list = { selection = { preselect = false, auto_insert = false } },
},
keymap = {
preset = "super-tab",
["<C-space>"] = { "show", "show_documentation", "hide_documentation" },
["<C-e>"] = { "hide", "fallback" },
["<Tab>"] = {
"select_next",
function(cmp)
if cmp.snippet_active() then
return cmp.accept()
else
return cmp.select_and_accept()
end
end,
"snippet_forward",
"fallback",
},
["<S-Tab>"] = { "select_prev", "snippet_backward", "fallback" },
["<cr>"] = { "select_and_accept", "fallback_to_mappings" },
["<Up>"] = { "select_prev", "fallback" },
["<Down>"] = { "select_next", "fallback" },
["<C-p>"] = { "select_prev", "fallback_to_mappings" },
["<C-n>"] = { "select_next", "fallback_to_mappings" },
["<C-b>"] = { "scroll_documentation_up", "fallback" },
["<C-f>"] = { "scroll_documentation_down", "fallback" },
["<C-k>"] = { "show_signature", "hide_signature", "fallback" },
},
},
},
}

26
lua/plugins/mini.lua Normal file
View File

@ -0,0 +1,26 @@
-- echasnovski/mini.*: small, dependency-free editing utilities.
return {
{
"echasnovski/mini.align",
keys = {
{ "gz", mode = { "n", "x" } },
{ "gZ", mode = { "n", "x" } },
},
opts = {
mappings = {
start = "gz",
start_with_preview = "gZ",
},
},
},
{
"echasnovski/mini.comment",
event = "VeryLazy",
opts = {},
},
{
"echasnovski/mini.surround",
event = "VeryLazy",
opts = {},
},
}

34
lua/plugins/snacks.lua Normal file
View File

@ -0,0 +1,34 @@
-- folke/snacks.nvim: picker, explorer, buffers.
-- The familiar `gb` / `<leader>F` / `<leader>t` entry points live here as
-- lazy `keys`, so the global `Snacks` is guaranteed to exist before any call.
return {
{
"folke/snacks.nvim",
priority = 1000,
lazy = false,
keys = {
{
"gb",
function()
Snacks.picker.buffers({ hidden = false, nofile = false, sort_lastused = true, current = false })
end,
desc = "Buffers",
},
{
"<leader>F",
function()
Snacks.picker.files({ exclude = { "node_modules/", ".git/" }, hidden = true, auto_close = true })
end,
desc = "Find Files",
},
{
"<leader>t",
function()
Snacks.picker.explorer({ exclude = { "node_modules/", ".git/" }, hidden = true, auto_close = true })
end,
desc = "Explorer",
},
},
opts = {},
},
}

View File

@ -0,0 +1,42 @@
-- nvim-treesitter: highlighting, indentation, and treesitter-based folds.
-- All listed parsers ship PREBUILT in the plugin repo, so no compiler is needed
-- for the configured languages. A C toolchain (base-devel) is only required if
-- you add parsers that aren't prebuilt or force `:TSInstall` to recompile.
-- Pinned to the legacy `master` branch, which keeps the declarative
-- ensure_installed/highlight/indent API the old config used. The new `main`
-- branch dropped this API in favor of do-it-yourself autocommands.
return {
{
"nvim-treesitter/nvim-treesitter",
branch = "master",
event = "VeryLazy",
build = ":TSUpdate",
opts = {
ensure_installed = {
"bash",
"css",
"html",
"javascript",
"json",
"lua",
"markdown",
"markdown_inline",
"python",
"query",
"regex",
"rust",
"scss",
"svelte",
"tsx",
"typescript",
"vim",
"yaml",
},
highlight = { enable = true },
indent = { enable = true },
},
config = function(_, opts)
require("nvim-treesitter.configs").setup(opts)
end,
},
}

32
lua/plugins/ui.lua Normal file
View File

@ -0,0 +1,32 @@
-- UI: statusline, git gutter signs, file icons.
-- The `based` colorscheme is vendored at ../../colors/based.vim and set in
-- init.lua, so it needs no lazy spec here.
return {
{
"nvim-lualine/lualine.nvim",
event = "VeryLazy",
dependencies = { "nvim-tree/nvim-web-devicons" },
opts = {
options = {
theme = "auto",
component_separators = { left = "", right = "" },
section_separators = {},
globalstatus = true,
},
sections = {
lualine_a = { "mode" },
lualine_b = { "branch", "diff" },
lualine_c = { { "filename", path = 1 } },
lualine_x = { "encoding", "fileformat", "filetype" },
lualine_y = { "progress" },
lualine_z = { "location" },
},
},
},
{
"lewis6991/gitsigns.nvim",
event = { "BufReadPre", "BufNewFile" },
opts = {},
},
{ "nvim-tree/nvim-web-devicons", lazy = true },
}

3
stylua.toml Normal file
View File

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