Astro Vim¤
[2022-03-20 18:58]
This weekend I tested Astro Vim, which is a pretty well tuned (and good looking) LSP configuration bundle for nvim.
I like
-
the idea of having
-
LSP
- treesitter
- telescope
- floatterm
- (...)
...out of the box - and out of the way from my local conf - also to throw it also on servers with colleagues and point them to an "official" repo with docs. Those are not easy to get right with so many variants.
- the full lua approach (but I'll have to have vim lang stuff, see below)
- Also, while mine became a bit laggy on big files, this one is still pretty fast, with all the LSP goodies.
Here my notes about the conversion:
Cleaning Up¤
-
Backup and Remove:
-
$HOME/.config/nvim
$HOME/.cache/nvim
$HOME/.local/share/nvim
Install¤
git clone https://github.com/kabinspace/AstroVim ~/.config/nvim
nvim +PackerSync # nice
then e.g.
:LspInstall pyright
:TSInstall python # treesitter
Note
All user config is in .config/nvim/lua/user
, from init.lua
there.
Conventional Folders: ftplugin and spell: Symlinked¤
Put my old ones into lua/user/<ftplugin|spell>
and symlinked 2 directories up. Worked.
Own Lua and Own Vimscript¤
Besides a few declarative config possibilities, for own plugins, in init.lua there is a lua polish function, loaded at the end.
There you hook in your stuff like this:
require('user.mymodule')
-- and vimscript like this:
vim.cmd('source $HOME/.config/nvim/lua/user/polish.vim')
and in vimscript then back to lua in user folder like this: nmap ,g viW"ay:lua require('user.utils').smart_open([[<C-R>a]])<CR>
Colors¤
The declarative approach with colorscheme via lua failed, loading it in my .vim file at the end.
Spell¤
It did not ask me to download german at set spelllang=de
, so:
mkdir .config/nvim/spell && cd $_` && wget 'http://ftp.vim.org/pub/vim/runtime/spell/de.utf-8.spl'
Telescope¤
- AstroVim Config: https://github.com/kabinspace/AstroVim/issues/141
- Generic Telescope Tuning: https://github-wiki-see.page/m/nvim-telescope/telescope.nvim/wiki/Configuration-Recipes
LSP¤
Pretty straight forward, via their null_ls LSP "hub", where nvim is the direct server for all languages and calls the actual programs behind the scenes.
That way one can pick from a huge list of features and just
install the binaries if required (command
), done.
LSP log as always in $HOME/.cache/nvim/
, file null_ls.log
.
axblack¤
null_ls
calls black with their --stdin-filename
parameter. Had to add that to axblack so that
single quote formatting works, as a no op (not in use anyway for stdin/stdout based formatting).
Edit: Found only later, that one can specify CLI args....
Special Plugins¤
Completion¤
I use "uga-rosa/cmp-dictionary", with 10k words.
Caution
For async the loading order is important (after cmp) - then the mpack import works.
Edit: Nope. After a packer sync it failed again, same error (mpack.so missing - loads too eaerly again)
Debugging¤
- lsp:
~ ❯ tail -f .cache/nvim/null-ls.log
(setlsp.debug = true
) - tables:
lua U.dump(vim.lsp)
Gotchas¤
-
When trying cmp or lsp, always try on files which exist at vi start. Do NOT create new files, it will not work.
-
The async flag at cmp_dictionary was behaving totally different after PackerSync calls, failed with mpack not found, allthough working before... Had to switch it off.
Config Dumps¤
My init.lua
$ cat /home/gk/.config/nvim.personal/init.lua
-- https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#super-tab-like-mapping
--
local cmp_setup = function()
local _, cmp = pcall(require, "cmp")
local _, luasnip = pcall(require, "luasnip")
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
local lines = vim.api.nvim_buf_get_lines
return col ~= 0 and lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
return {
mapping = {
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { "i", "s" }),
},
}
end
local config = {
-- Set colorscheme
-- colorscheme = "default_theme",
colorscheme = "kanagawa",
-- Default theme configuration
default_theme = {
diagnostics_style = "none",
-- Modify the color table
colors = { fg = "#abb2bf" },
-- Modify the highlight groups
highlights = function(highlights)
local C = require("default_theme.colors")
highlights.Normal = { fg = C.fg, bg = C.bg }
return highlights
end,
},
-- Disable default plugins
enabled = {
bufferline = true,
nvim_tree = true,
lualine = true,
lspsaga = true,
gitsigns = true,
colorizer = true,
toggle_term = true,
comment = true,
symbols_outline = true,
indent_blankline = true,
dashboard = true,
which_key = true,
neoscroll = true,
ts_rainbow = true,
ts_autotag = true,
},
plugins = {
cmp = cmp_setup(),
init = {
"ThePrimeagen/refactoring.nvim",
"arcticicestudio/nord-vim",
"godlygeek/tabular",
"iamcco/markdown-preview.nvim",
"kdheepak/lazygit.nvim",
"matsuuu/pinkmare",
"rebelot/kanagawa.nvim",
"tpope/vim-repeat",
"tpope/vim-surround",
"voldikss/vim-floaterm",
"rafamadriz/friendly-snippets",
{
"uga-rosa/cmp-dictionary",
after = "nvim-cmp",
config = function()
local cmp = require("cmp")
local config = cmp.get_config()
table.insert(config.sources, { name = "dictionary", keyword_length = 2 })
cmp.setup(config)
end,
require("cmp_dictionary").setup({
dic = {
["markdown"] = { "/home/gk/.config/nvim.personal/10k.txt" },
--["markdown"] = { "/usr/share/dict/words" },
-- ["lua"] = "path/to/lua.dic",
-- ["javascript,typescript"] = { "path/to/js.dic", "path/to/js2.dic" },
-- filename = {
-- ["xmake.lua"] = { "path/to/xmake.dic", "path/to/lua.dic" },
-- },
-- filepath = {
-- ["%.tmux.*%.conf"] = "path/to/tmux.dic",
-- },
},
-- The following are default values, so you don't need to write them if you don't want to change them
-- exact = 2,
-- first_case_insensitive = false,
-- document = false,
-- document_command = "wn %s -over",
async = false,
-- capacity = 5,
-- debug = false,
})
},
-- { "andweeb/presence.nvim" },
-- {
-- "ray-x/lsp_signature.nvim",
-- event = "BufRead",
-- config = function()
-- require("lsp_signature").setup()
-- end,
-- },
},
-- All other entries override the setup() call for default plugins
treesitter = { ensure_installed = { "lua" } },
packer = {
compile_path = vim.fn.stdpath("config") .. "/lua/packer_compiled.lua",
},
},
-- Add paths for including more VS Code style snippets in luasnip
luasnip = {
vscode_snippet_paths = {},
},
-- Modify which-key registration
["which-key"] = {
-- Add bindings to the normal mode <leader> mappings
-- register_n_leader = {["N"] = {"<cmd>tabnew<cr>", "New Buffer"}}
},
-- Extend LSP configuration
lsp = {
-- add to the server on_attach function
-- on_attach = function(client, bufnr)
-- end,
-- override the lsp installer server-registration function
-- server_registration = function(server, opts)
-- server:setup(opts)
-- end
-- Add overrides for LSP server settings, the keys are the name of the server
["server-settings"] = {
-- example for addings schemas to yamlls
-- yamlls = {
-- settings = {
-- yaml = {
-- schemas = {
-- ["http://json.schemastore.org/github-workflow"] = ".github/workflows/*.{yml,yaml}",
-- ["http://json.schemastore.org/github-action"] = ".github/action.{yml,yaml}",
-- ["http://json.schemastore.org/ansible-stable-2.9"] = "roles/tasks/*.{yml,yaml}",
-- },
-- },
-- },
-- },
},
},
-- Diagnostics configuration (for vim.diagnostics.config({}))
diagnostics = { virtual_text = true, underline = true },
-- null-ls configuration
["null-ls"] = function()
-- Formatting and linting
-- https://github.com/jose-elias-alvarez/null-ls.nvim
local status_ok, null_ls = pcall(require, "null-ls")
if not status_ok then
return
end
-- Check supported formatters
-- https://github.com/jose-elias-alvarez/null-ls.nvim/tree/main/lua/null-ls/builtins/formatting
-- Check supported linters
-- https://github.com/jose-elias-alvarez/null-ls.nvim/tree/main/lua/null-ls/builtins/diagnostics
local b = null_ls.builtins
local txt = { filetypes = { "markdown", "text" } }
null_ls.setup({
debug = true,
sources = {
-- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md
b.code_actions.refactoring,
b.code_actions.shellcheck,
b.completion.luasnip,
b.completion.spell.with(txt),
b.diagnostics.misspell.with(txt),
b.diagnostics.shellcheck,
b.diagnostics.write_good,
b.formatting.black.with({ extra_args = { "--fast" } }),
b.formatting.prettier.with({ filetypes = { "html", "json", "yaml" } }),
b.formatting.shfmt,
b.formatting.stylua,
b.hover.dictionary.with(txt), -- shift-k is hover
},
-- NOTE: You can remove this on attach function to disable format on save
on_attach = function(client)
if client.resolved_capabilities.document_formatting then
vim.cmd("autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting()")
end
end,
})
end,
polish = function()
local opts = { noremap = true, silent = true }
local map = vim.api.nvim_set_keymap
-- Set options
local set = vim.opt
require("luasnip.loaders.from_snipmate").lazy_load()
-- cmp.formatting.fields = {"kind"}
U = require("user.utils") -- allows :lua U.dump(vim.lsp)
require("luasnip.loaders.from_vscode").lazy_load()
set.shiftwidth = 4 -- Number of space inserted for indentation
set.tabstop = 4 -- Number of spaces in a tab
set.foldmethod = "indent"
set.foldlevel = 99 -- open all
set.relativenumber = true
--set.dict = "/usr/share/dict/words" -- much more
set.dict = "~/.config/nvim.personal/10k.txt"
-- map("n", "<C-s>", ":w!<CR>", opts)
vim.api.nvim_set_keymap(
"v",
"<leader>rr",
"<Esc><cmd>lua require('telescope').extensions.refactoring.refactors()<CR>",
{ noremap = true }
)
map("n", ",4", ":ToggleTerm size=100 <CR>", opts)
map("n", ",D", ":lua vim.diagnostic.config({virtual_text = false})<CR>", opts)
-- all viml:
vim.cmd("source $HOME/.config/nvim.personal/polish.vim")
-- do this only here so that require mpack works for async:
end,
}
return config
My polish.vim
$ cat /home/gk/.config/nvim.personal/polish.vim
" this is simply ctrl-i:
"nnoremap <Tab> za
nnoremap <C-i> za
"cnoremap <silent> x<CR> :call ConfirmQuit(1)<CR>
" "Yank constent with D and C:
nnoremap Y y$
nnoremap ,l :LazyGit<CR>
nnoremap ,q :q!<CR>
nnoremap ,Q :Q!<cr>
nnoremap ,d :wq!<CR>
nnoremap ,w :w<cr>
nnoremap ,1 :source ~/.config/nvim/init.lua<CR>
nnoremap ,2 :edit ~/.config/nvim/lua/user/init.lua<CR>
nnoremap ,c :close<CR> " close just a split or a tab
nmap ,f za "folds
nnoremap <silent> ,3 :FloatermNew! --autoclose=2 --wintype=vsplit cd %:p:h<CR>
"" Line join better, position cursor at join point:
" (J is 5 lines jumps)
nnoremap gj $mx<cmd>join<CR>0$[`dmx
" Universal python scriptable file or browser opener over word:
"nmap ,g viW"ay:lua require('utils').smart_open([[<C-R>a]])<CR><CR>
nmap ,g viW"ay:lua require('user.utils').smart_open([[<C-R>a]])<CR>
vmap ,g :lua require('user.utils').smart_open([[visualsel]])<CR><CR>
" tabularize:
nmap ga :Tabularize/
xmap ga :Tabularize/
nmap tt vip:s:,,:\|:ge<CR>vip:Tabularize/\|<CR>
" markdown table
nnoremap ,ta vip:s/$/\|/ge<CR>vip:s:,,:\|:ge<CR>vip:s:^:\|:ge<CR>vip:s:\|\|:\|:ge<CR>vip:Tabularize/\|<CR>
nnoremap S :%s//gI<Left><Left><Left>
" move between splits with alt-jk
nnoremap <M-j> <C-W><C-W>
nnoremap <M-k> <C-W><C-W>
inoremap <M-j> <ESC><C-W><C-W>
inoremap <M-k> <ESC><C-W><C-W>
nnoremap <C-L> <C-W><C-J>
nnoremap <C-H> <C-W><C-K>
" we often have old stuff at end of files:
nnoremap G G?begin_archive<CR>
nmap <silent> <Leader><Leader> <Leader>ff
nnoremap <silent> <Leader>j :Telescope buffers<cr>
nnoremap <silent> <Leader>g :Telescope live_grep<cr>
" go to the position I was when last editing the file
au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal g'\"" | endif
"colorscheme pinkmare"colorscheme kanagawa
"" AutoSave
nmap ,s :AutoSave<CR>
function! s:autosave(enable)
augroup autosave
autocmd!
" at $IDE we call this at ANY BufEnter, with enable=2
if a:enable == 2
if $IDE != 'true'
return
endif
endif
if a:enable
autocmd TextChanged,InsertLeave <buffer>
\ if empty(&buftype) && !empty(bufname(''))
\| silent! update
\| endif
endif
augroup END
endfunction
command! -bang AutoSave call s:autosave(<bang>1)
autocmd BufEnter *.* :call s:autosave(2) " $IDE -> always
"" Yank hilite
augroup highlight_yank
autocmd!
au TextYankPost * silent! lua vim.highlight.on_yank({higroup="IncSearch", timeout=400})
augroup END
"" Packer
augroup packer_conf
autocmd!
autocmd BufWritePost plugins.lua source <afile> | PackerSync
augroup end