diff --git a/Makefile b/Makefile index 71ba305..9599bec 100644 --- a/Makefile +++ b/Makefile @@ -297,7 +297,7 @@ install_asdf: check_os .PHONY: install_vim install_vim: check_os link_vim @echo "Installing vim packages..." - @echo "\n\n\n" | vim +PlugInstall +qall + @echo "y\n\n\n" | nvim +PackerCompile +PackerInstall +qall .PHONY: oh_my_zsh oh_my_zsh: check_os diff --git a/symlinks/config/nvim/README.md b/symlinks/config/nvim/README.md index 9348240..5cd2597 100644 --- a/symlinks/config/nvim/README.md +++ b/symlinks/config/nvim/README.md @@ -1,3 +1,16 @@ -## NeoVim config +## My vim configuration -Current NeoVim configuration only reads .vim config, since both are currently shared. Complete migration to NeoVim and lua based config is planned. +Currently configuration is shared between Vim and NeoVim, although I use NeoVim. Migration will happen when NeoVim 0.5.0 is released and `init.lua` is supported. + +Configuration is separated into directories: + - `plugin` for logical collection of functionalities into a simple plugin + - `colors` my colorscheme + - `compiler` for compiler plugins + - `ftdetect` for autocommands for detecting file types + - `undodir` is just a placeholder for configured undo directory + - `spell` for spelling dictionary + - `after` with same directory structure for loading after plugins - allows easy overrides, most `ftplugins` are here + +Besides this, directory contains other files: + - `plugins.vim` all used plugins + - `vimrc` global basic configuration diff --git a/symlinks/config/nvim/after/ftplugin/README.md b/symlinks/config/nvim/after/ftplugin/README.md new file mode 100644 index 0000000..06623ab --- /dev/null +++ b/symlinks/config/nvim/after/ftplugin/README.md @@ -0,0 +1,3 @@ +## Filetype plugins + +All filetype plugins should be located in this /after dir to ensure no defaults or other plugins override these settings. diff --git a/symlinks/config/nvim/after/ftplugin/elixir.vim b/symlinks/config/nvim/after/ftplugin/elixir.vim new file mode 100644 index 0000000..a1c91f6 --- /dev/null +++ b/symlinks/config/nvim/after/ftplugin/elixir.vim @@ -0,0 +1,5 @@ +setlocal ts=2 sts=2 sw=2 expandtab autoindent +let b:undo_ftplugin .= '|setlocal ts< sts< sw< expandtab< autoindent<' + +compiler elixir +let b:undo_ftplugin .= '|compiler<' diff --git a/symlinks/config/nvim/after/ftplugin/gitcommit.vim b/symlinks/config/nvim/after/ftplugin/gitcommit.vim new file mode 100644 index 0000000..19915a8 --- /dev/null +++ b/symlinks/config/nvim/after/ftplugin/gitcommit.vim @@ -0,0 +1,4 @@ +set textwidth=72 +set spell +set cc=+1 +let b:undo_ftplugin .= '|setlocal textwidth< spell< cc<' diff --git a/symlinks/config/nvim/after/ftplugin/javascript.vim b/symlinks/config/nvim/after/ftplugin/javascript.vim new file mode 100644 index 0000000..fa15b9a --- /dev/null +++ b/symlinks/config/nvim/after/ftplugin/javascript.vim @@ -0,0 +1,2 @@ +setlocal ts=2 sts=2 sw=2 expandtab autoindent +let b:undo_ftplugin .= '|setlocal ts< sts< sw< expandtab< autoindent<' diff --git a/symlinks/config/nvim/after/ftplugin/python.vim b/symlinks/config/nvim/after/ftplugin/python.vim new file mode 100644 index 0000000..3e80fcc --- /dev/null +++ b/symlinks/config/nvim/after/ftplugin/python.vim @@ -0,0 +1,7 @@ +" ----------------------------------------------------------------------------- +" - Python file plugin - +" ----------------------------------------------------------------------------- + +" Without this, weird issues occurred with asdf + direnv + python virtualenv +setlocal shell=/bin/sh +let b:undo_ftplugin .= "|setlocal shell<" diff --git a/symlinks/config/nvim/after/ftplugin/text.vim b/symlinks/config/nvim/after/ftplugin/text.vim new file mode 100644 index 0000000..1693a33 --- /dev/null +++ b/symlinks/config/nvim/after/ftplugin/text.vim @@ -0,0 +1,3 @@ +setlocal textwidth=78 +set spell +let b:undo_ftplugin .= '|setlocal textwidth< spell<' diff --git a/symlinks/config/nvim/after/plugin/README.md b/symlinks/config/nvim/after/plugin/README.md new file mode 100644 index 0000000..0cb9a1e --- /dev/null +++ b/symlinks/config/nvim/after/plugin/README.md @@ -0,0 +1,5 @@ +## Plugin overrides + +This directory should mostly be used to configure specific plugins, by running after them. +In some cases it may be required to run some code before plugin, in which case /plugin dir can be used. +Other than this, custom plugins should be located in /plugin dir, unless plugin explicitly overrides some other plugin, in which case, it would probably be better to either disable other plugin or just override it with that plugin specific file. diff --git a/symlinks/config/nvim/after/plugin/fzf.vim b/symlinks/config/nvim/after/plugin/fzf.vim new file mode 100644 index 0000000..bcb659b --- /dev/null +++ b/symlinks/config/nvim/after/plugin/fzf.vim @@ -0,0 +1,3 @@ +" Map FZF to CtrlP +nnoremap :Files +nnoremap :Rg diff --git a/symlinks/config/nvim/after/plugin/grepper.vim b/symlinks/config/nvim/after/plugin/grepper.vim new file mode 100644 index 0000000..73912ec --- /dev/null +++ b/symlinks/config/nvim/after/plugin/grepper.vim @@ -0,0 +1,13 @@ +" ----------------------------------------------------------------------------- +" - vim-grepper configuration - +" ----------------------------------------------------------------------------- + +let g:grepper = {} +let g:grepper.tools = ['rg', 'git', 'grep'] + +" Search for the current word (similar to *) +nnoremap * :Grepper -cword -noprompt + +" Search for the current selection +nmap gs (GrepperOperator) +xmap gs (GrepperOperator) diff --git a/symlinks/config/nvim/after/plugin/python_host.vim b/symlinks/config/nvim/after/plugin/python_host.vim new file mode 100644 index 0000000..ba22ba7 --- /dev/null +++ b/symlinks/config/nvim/after/plugin/python_host.vim @@ -0,0 +1,6 @@ +" ----------------------------------------------------------------------------- +" - Neovim python host - +" Explicit declaration of python host program to "prevent suprises" +" ----------------------------------------------------------------------------- +let g:python_host_prog = $HOME.'/.asdf/shims/python2' +let g:python3_host_prog = $HOME.'/.asdf/shims/python3' diff --git a/symlinks/config/nvim/after/plugin/supertab.vim b/symlinks/config/nvim/after/plugin/supertab.vim new file mode 100644 index 0000000..5227319 --- /dev/null +++ b/symlinks/config/nvim/after/plugin/supertab.vim @@ -0,0 +1,2 @@ +" More natural auto complete +let g:SuperTabDefaultCompletionType = "" diff --git a/symlinks/config/nvim/after/plugin/testing.vim b/symlinks/config/nvim/after/plugin/testing.vim new file mode 100644 index 0000000..f843c32 --- /dev/null +++ b/symlinks/config/nvim/after/plugin/testing.vim @@ -0,0 +1,13 @@ +" ----------------------------------------------------------------------------- +" - Vim-test and general testing config - +" ----------------------------------------------------------------------------- + +" make test commands execute using dispatch.vim +let test#strategy = "dispatch" + +" Map test running commands +nmap tn :TestNearest +nmap tf :TestFile +nmap ts :TestSuite +nmap tl :TestLast +nmap tg :TestVisit diff --git a/symlinks/config/nvim/compiler/README.md b/symlinks/config/nvim/compiler/README.md new file mode 100644 index 0000000..979c157 --- /dev/null +++ b/symlinks/config/nvim/compiler/README.md @@ -0,0 +1,3 @@ +## Compiler settings + +Used just to set up makeprg and compile errors parsing diff --git a/symlinks/config/nvim/compiler/elixir.vim b/symlinks/config/nvim/compiler/elixir.vim new file mode 100644 index 0000000..c48ed76 --- /dev/null +++ b/symlinks/config/nvim/compiler/elixir.vim @@ -0,0 +1,19 @@ +" Vim compiler file +" Compiler: Elixir Script Compiler + +if exists('current_compiler') + finish +endif +let current_compiler = "elixir" + +let s:save_cpo = &cpo +set cpo&vim + +if exists(':CompilerSet') != 2 + command -nargs=* CompilerSet setlocal +endif + +CompilerSet makeprg=elixir\ % + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/symlinks/config/nvim/compiler/gradle.vim b/symlinks/config/nvim/compiler/gradle.vim new file mode 100644 index 0000000..f84ca68 --- /dev/null +++ b/symlinks/config/nvim/compiler/gradle.vim @@ -0,0 +1,30 @@ +" Vim Compiler File +" Compiler: gradle + +if exists("current_compiler") + finish +endif +let current_compiler = "gradle" + +let s:save_cpo = &cpo +set cpo&vim + +if exists(":CompilerSet") != 2 + command -nargs=* CompilerSet setlocal +endif + +CompilerSet makeprg=gradle + +CompilerSet errorformat= + \%E[ant:scalac]\ %f:%l:\ error:\ %m, + \%W[ant:scalac]\ %f:%l:\ warning:\ %m, + \%E%.%#:compile%\\w%#Java%f:%l:\ error:\ %m,%-Z%p^,%-C%.%#, + \%W%.%#:compile%\\w%#Java%f:%l:\ warning:\ %m,%-Z%p^,%-C%.%#, + \%E%f:%l:\ error:\ %m,%-Z%p^,%-C%.%#, + \%W%f:%l:\ warning:\ %m,%-Z%p^,%-C%.%#, + \%E%f:\ %\\d%\\+:\ %m\ @\ line\ %l\\,\ column\ %c.,%-C%.%#,%Z%p^, + \%E%>%f:\ %\\d%\\+:\ %m,%C\ @\ line\ %l\\,\ column\ %c.,%-C%.%#,%Z%p^, + \%-G%.%# + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/symlinks/config/nvim/compiler/gradlew.vim b/symlinks/config/nvim/compiler/gradlew.vim new file mode 100644 index 0000000..7fbbace --- /dev/null +++ b/symlinks/config/nvim/compiler/gradlew.vim @@ -0,0 +1,30 @@ +" Vim Compiler File +" Compiler: gradlew + +if exists("current_compiler") + finish +endif +let current_compiler = "gradlew" + +let s:save_cpo = &cpo +set cpo&vim + +if exists(":CompilerSet") != 2 + command -nargs=* CompilerSet setlocal +endif + +CompilerSet makeprg=./gradlew + +CompilerSet errorformat= + \%E[ant:scalac]\ %f:%l:\ error:\ %m, + \%W[ant:scalac]\ %f:%l:\ warning:\ %m, + \%E%.%#:compile%\\w%#Java%f:%l:\ error:\ %m,%-Z%p^,%-C%.%#, + \%W%.%#:compile%\\w%#Java%f:%l:\ warning:\ %m,%-Z%p^,%-C%.%#, + \%E%f:%l:\ error:\ %m,%-Z%p^,%-C%.%#, + \%W%f:%l:\ warning:\ %m,%-Z%p^,%-C%.%#, + \%E%f:\ %\\d%\\+:\ %m\ @\ line\ %l\\,\ column\ %c.,%-C%.%#,%Z%p^, + \%E%>%f:\ %\\d%\\+:\ %m,%C\ @\ line\ %l\\,\ column\ %c.,%-C%.%#,%Z%p^, + \%-G%.%# + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/symlinks/config/nvim/ftdetect/gradle.vim b/symlinks/config/nvim/ftdetect/gradle.vim new file mode 100644 index 0000000..20533b9 --- /dev/null +++ b/symlinks/config/nvim/ftdetect/gradle.vim @@ -0,0 +1,2 @@ +" gradle syntax highlighting +au BufNewFile,BufRead *.gradle set filetype=groovy diff --git a/symlinks/config/nvim/init.lua b/symlinks/config/nvim/init.lua new file mode 100644 index 0000000..880c33e --- /dev/null +++ b/symlinks/config/nvim/init.lua @@ -0,0 +1,44 @@ +if require('personal.first_load')() then + return +end + +vim.api.nvim_exec('let $OVIMHOME = $HOME."/.vim"', false) +vim.api.nvim_exec('let $VIMHOME = $HOME."/.config/nvim"', false) +vim.api.nvim_exec('let $NVIMHOME = $HOME."/.local/share/nvim"', false) +vim.api.nvim_exec('let $VIMPLUGINS = expand($VIMHOME."/lua/personal/plugins.lua")', false) + +-- Leader config to +vim.g.mapleader = ' ' + +-- Globals taken from TJ config +-- Helpful for configuration +-- Might be removed in future version of NeoVim +require('personal.globals') + +require('personal.plugins') + +require('personal.options') + +require('lsp') + +-- Colorscheme +vim.cmd('syntax on') +require('personal.colors') + +vim.api.nvim_set_keymap('n', 'Q', 'gq', {}) +vim.api.nvim_set_keymap('i', '', 'u', {noremap = true}) + +vim.cmd('command! Wq :wq') +vim.cmd('command! W :w') + +vim.api.nvim_set_keymap('n', 'c', ':ccl lcl', {noremap = true}) + +-- Allow recursive searches +vim.cmd('set path+=**') + +-- Save whenever switching windows or leaving vim. This is useful when running +-- the tests inside vim without having to save all files first. +vim.cmd('autocmd FocusLost,WinLeave * :silent! wa') + +-- automatically rebalance windows on vim resize +vim.cmd('autocmd VimResized * :wincmd =') diff --git a/symlinks/config/nvim/init.vim b/symlinks/config/nvim/init.vim deleted file mode 100644 index dbf8872..0000000 --- a/symlinks/config/nvim/init.vim +++ /dev/null @@ -1,3 +0,0 @@ -set runtimepath^=~/.vim runtimepath+=~/.vim/after -let &packpath = &runtimepath -source ~/.vim/vimrc diff --git a/symlinks/config/nvim/lua/lsp/completion.lua b/symlinks/config/nvim/lua/lsp/completion.lua new file mode 100644 index 0000000..784391f --- /dev/null +++ b/symlinks/config/nvim/lua/lsp/completion.lua @@ -0,0 +1,12 @@ +------------------------------------------------------------------------------- +-- - LSP completion config - +------------------------------------------------------------------------------- +-- Use and to navigate through popup menu + +-- Set completeopt to have a better completion experience +vim.o.completeopt = "menuone,noinsert,noselect" +-- Avoid showing message extra message when using completion +vim.cmd('set shortmess+=c') +vim.cmd('let g:completion_enable_snippet = "UltiSnips"') +vim.cmd('let g:completion_confirm_key = "\\"') +vim.cmd("autocmd BufEnter * lua require'completion'.on_attach()") diff --git a/symlinks/config/nvim/lua/lsp/diagnostic.lua b/symlinks/config/nvim/lua/lsp/diagnostic.lua new file mode 100644 index 0000000..862bd40 --- /dev/null +++ b/symlinks/config/nvim/lua/lsp/diagnostic.lua @@ -0,0 +1,16 @@ +------------------------------------------------------------------------------- +-- - LSP diagnostics config - +------------------------------------------------------------------------------- + +require("nvim-ale-diagnostic") + +vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( + vim.lsp.diagnostic.on_publish_diagnostics, { + underline = false, + virtual_text = false, + signs = true, + update_in_insert = false, + } +) + +vim.g.diagnostic_enable_virtual_text = 1 diff --git a/symlinks/config/nvim/lua/lsp/init.lua b/symlinks/config/nvim/lua/lsp/init.lua new file mode 100644 index 0000000..a2a838c --- /dev/null +++ b/symlinks/config/nvim/lua/lsp/init.lua @@ -0,0 +1,8 @@ +------------------------------------------------------------------------------- +-- - LSP configuration - +------------------------------------------------------------------------------- + +require("lsp.diagnostic") +require("lsp.servers") +require("lsp.completion") +require("lsp.maps") diff --git a/symlinks/config/nvim/lua/lsp/maps.lua b/symlinks/config/nvim/lua/lsp/maps.lua new file mode 100644 index 0000000..983bbe6 --- /dev/null +++ b/symlinks/config/nvim/lua/lsp/maps.lua @@ -0,0 +1,20 @@ +------------------------------------------------------------------------------- +-- - LSP related keymaps - +------------------------------------------------------------------------------- +default_opts = {noremap = true, silent = true} + +-- Lsp keymaps +vim.api.nvim_set_keymap('n', 'gd', 'lua vim.lsp.buf.definition()', default_opts) +vim.api.nvim_set_keymap('n', 'gD', 'lua vim.lsp.buf.declaration()', default_opts) +vim.api.nvim_set_keymap('n', 'gr', 'lua vim.lsp.buf.references()', default_opts) +vim.api.nvim_set_keymap('n', 'rn', 'lua vim.lsp.buf.rename()', default_opts) +vim.api.nvim_set_keymap('n', '', 'lua vim.lsp.buf.signature_help()', default_opts) +vim.api.nvim_set_keymap('n', 'K', 'lua vim.lsp.buf.hover()', default_opts) +vim.api.nvim_set_keymap('n', '', 'lua vim.lsp.buf.code_action()', default_opts) +vim.api.nvim_set_keymap('n', 'ac', 'lua vim.lsp.buf.code_action()', default_opts) +vim.api.nvim_set_keymap('n', 'a', 'lua vim.lsp.buf.code_action_range()', default_opts) + +completion_opts = {silent = true} + +-- Completion keymaps +vim.api.nvim_set_keymap('i', '', '(completion_trigger)', completion_opts) diff --git a/symlinks/config/nvim/lua/lsp/servers.lua b/symlinks/config/nvim/lua/lsp/servers.lua new file mode 100644 index 0000000..5bec69e --- /dev/null +++ b/symlinks/config/nvim/lua/lsp/servers.lua @@ -0,0 +1,26 @@ +------------------------------------------------------------------------------- +-- - LSP servers configuration - +------------------------------------------------------------------------------- + +local lspconfig = require("lspconfig") + +local on_attach = function(client, bufnr) + require'completion'.on_attach() +end +-- Lsp language servers +lspconfig.bashls.setup {on_attach = on_attach} +lspconfig.clangd.setup {on_attach = on_attach} +lspconfig.dartls.setup {on_attach = on_attach} +lspconfig.jsonls.setup {on_attach = on_attach} +lspconfig.pyright.setup {on_attach = on_attach} +lspconfig.rust_analyzer.setup {on_attach = on_attach} +lspconfig.vimls.setup {on_attach = on_attach} + +-- Lua bultin lsp +-- require('nlua.lsp.nvim').setup(lspconfig, { +-- on_attach = on_attach, + +-- -- Include globals you want to tell the LSP are real :) +-- globals = { +-- } +-- }) diff --git a/symlinks/config/nvim/lua/personal/colors.lua b/symlinks/config/nvim/lua/personal/colors.lua new file mode 100644 index 0000000..20220ae --- /dev/null +++ b/symlinks/config/nvim/lua/personal/colors.lua @@ -0,0 +1 @@ +vim.api.nvim_exec('colorscheme gruvbox-material', false) diff --git a/symlinks/config/nvim/lua/personal/first_load.lua b/symlinks/config/nvim/lua/personal/first_load.lua new file mode 100644 index 0000000..2c11bc5 --- /dev/null +++ b/symlinks/config/nvim/lua/personal/first_load.lua @@ -0,0 +1,35 @@ +-- Adopted from https://github.com/tjdevries/config_manager/blob/master/xdg_config/nvim/lua/tj/first_load.lua +local download_packer = function() + if vim.fn.input("Download Packer? (y for yes)") ~= "y" then + return + end + + local directory = string.format( + '%s/site/pack/packer/start/', + vim.fn.stdpath('data') + ) + + vim.fn.mkdir(directory, 'p') + + local out = vim.fn.system(string.format( + 'git clone %s %s', + 'https://github.com/wbthomason/packer.nvim', + directory .. '/packer.nvim' + )) + + print(out) + print("Downloading packer.nvim...") + vim.api.nvim_command('PackerCompile') + vim.api.nvim_command('PackerInstall') + print("( You'll need to restart now )") +end + +return function() + if not pcall(require, 'packer') then + download_packer() + + return true + end + + return false +end diff --git a/symlinks/config/nvim/lua/personal/globals/init.lua b/symlinks/config/nvim/lua/personal/globals/init.lua new file mode 100644 index 0000000..1f1b956 --- /dev/null +++ b/symlinks/config/nvim/lua/personal/globals/init.lua @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------- +-- - Adopted from TJ config (https://github.com/tjdevries/config_manager/blob/master/xdg_config/nvim/lua/tj/globals/init.lua) - +------------------------------------------------------------------------------- +P = function(v) + print(vim.inspect(v)) + return v +end + +if pcall(require, 'plenary') then + RELOAD = require('plenary.reload').reload_module + + R = function(name) + RELOAD(name) + return require(name) + end +end + +-- `vim.opt` +require('personal.globals.opt') diff --git a/symlinks/config/nvim/lua/personal/globals/opt.lua b/symlinks/config/nvim/lua/personal/globals/opt.lua new file mode 100644 index 0000000..d55ac10 --- /dev/null +++ b/symlinks/config/nvim/lua/personal/globals/opt.lua @@ -0,0 +1,263 @@ +--[[ To use a more declarative syntax, you could do something like this: + +local function set_opts(opts_table) + for k, v in pairs(opts_table) do + vim.opt[k] = v + end +end + +set_opts { + mouse = 'n', + fillchars = { eob = "~" }, +} + +--]] + +--[[ Global option names + +For those wondering how to get the values at the top level, + you could use Lua's `setfenv` function to set the environment + equal to the vim.opt dict + +cc @mccanch + +setfenv(function() + mouse = 'n' +end, vim.opt)() + +--]] + +local if_nil = function(a, b) + if a == nil then + return b + end + return a +end + +local singular_values = { + ['boolean'] = true, + ['number'] = true, + ['nil'] = true, +} + +local set_key_value = function(t, key_value_str) + assert(string.find(key_value_str, ":"), "Must have a :" .. tostring(key_value_str)) + + local key, value = unpack(vim.split(key_value_str, ":")) + key = vim.trim(key) + value = vim.trim(value) + + t[key] = value +end + +local convert_vimoption_to_lua = function(option, val) + -- Short circuit if we've already converted! + if type(val) == 'table' then + return val + end + + if singular_values[type(val)] then + return val + end + + if type(val) == "string" then + -- TODO: Bad hax I think + if string.find(val, ":") then + local result = {} + local items = vim.split(val, ",") + for _, item in ipairs(items) do + set_key_value(result, item) + end + + return result + else + return vim.split(val, ",") + end + end +end + +-- local concat_keys = function(t, sep) +-- return table.concat(vim.tbl_keys(t), sep) +-- end + +local concat_key_values = function(t, sep, divider) + local final = {} + for k, v in pairs(t) do + table.insert(final, string.format('%s%s%s', k, divider, v)) + end + + table.sort(final) + return table.concat(final, sep) +end + +local remove_duplicate_values = function(t) + local result = {} + for _, v in ipairs(t) do + result[v] = true + end + + return vim.tbl_keys(result) +end + +local remove_value = function(t, val) + if vim.tbl_islist(t) then + local remove_index = nil + for i, v in ipairs(t) do + if v == val then + remove_index = i + end + end + + if remove_index then + table.remove(t, remove_index) + end + else + t[val] = nil + end + + return t +end + +local add_value = function(current, new) + if singular_values[type(current)] then + error( + "This is not possible to do. Please do something different: " + .. tostring(current) + .. " // " + .. tostring(new) + ) + end + + if type(new) == 'string' then + if vim.tbl_islist(current) then + table.insert(current, new) + else + set_key_value(current, new) + end + + return current + elseif type(new) == 'table' then + if vim.tbl_islist(current) then + assert(vim.tbl_islist(new)) + vim.list_extend(current, new) + else + assert(not vim.tbl_islist(new), vim.inspect(new) .. vim.inspect(current)) + current = vim.tbl_extend("force", current, new) + end + + return current + else + error("Unknown type") + end +end + +local convert_lua_to_vimoption = function(t) + if vim.tbl_islist(t) then + t = remove_duplicate_values(t) + + table.sort(t) + return table.concat(t, ',') + else + return concat_key_values(t, ',', ':') + end +end + +local clean_value = function(v) + if singular_values[type(v)] then + return v + end + + local result = v:gsub('^,', '') + + return result +end + +local opt_mt + +opt_mt = { + __index = function(t, k) + if k == '_value' then + return rawget(t, k) + end + + return setmetatable({ _option = k, }, opt_mt) + end, + + __newindex = function(t, k, v) + if k == '_value' then + return rawset(t, k, v) + end + + if type(v) == 'table' then + local new_value + if getmetatable(v) ~= opt_mt then + new_value = v + else + assert(v._value, "Must have a value to set this") + new_value = v._value + end + + vim.o[k] = convert_lua_to_vimoption(new_value) + return + end + + if v == nil then + v = '' + end + + -- TODO: Figure out why nvim_set_option doesn't override values the same way. + -- @bfredl said he will fix this for me, so I can just use nvim_set_option + if type(v) == 'boolean' then + vim.o[k] = clean_value(v) + if v then + vim.cmd(string.format("set %s", k)) + else + vim.cmd(string.format("set no%s", k)) + end + else + vim.cmd(string.format("set %s=%s", k, clean_value(v))) + end + end, + + __add = function(left, right) + --[[ + set.wildignore = set.wildignore + 'hello' + set.wildignore = set.wildignore + { '*.o', '*~', } + --]] + + assert(left._option, "must have an option key") + if left._option == 'foldcolumn' then + error("not implemented for foldcolumn.. use a string") + end + + local existing = if_nil(left._value, vim.o[left._option]) + local current = convert_vimoption_to_lua(left._option, existing) + if not current then + left._value = convert_vimoption_to_lua(right) + end + + left._value = add_value(current, right) + return left + end, + + __sub = function(left, right) + assert(left._option, "must have an option key") + + local existing = if_nil(left._value, vim.o[left._option]) + local current = convert_vimoption_to_lua(left._option, existing) + if not current then + return left + end + + left._value = remove_value(current, right) + return left + end +} + +vim.opt = setmetatable({}, opt_mt) + +return { + convert_vimoption_to_lua = convert_vimoption_to_lua, + opt = vim.opt, + opt_mt = opt_mt +} diff --git a/symlinks/config/nvim/lua/personal/options.lua b/symlinks/config/nvim/lua/personal/options.lua new file mode 100644 index 0000000..1d752dc --- /dev/null +++ b/symlinks/config/nvim/lua/personal/options.lua @@ -0,0 +1,33 @@ +local opt = vim.opt + +opt.wildignore = '__pycache__' +opt.wildignore = opt.wildignore + { '*.o' , '*~', '*.pyc', '*pycache*' } + +-- Indentation config +opt.tabstop = 2 +opt.tabstop = 2 +opt.shiftwidth = 2 +opt.autoindent = true + +-- Line numbers +opt.number = true +opt.relativenumber = true + +-- Misc +opt.backspace = 'indent,eol,start' -- Allow backspacing over everything in insert mode +opt.ttimeoutlen = 50 +opt.backup = false -- do not keep a backup file, use versions instead +opt.history = 50 -- Keep 50 lines of command line history +opt.ruler = true -- Show the cursor position all the time +opt.laststatus = 2 -- Always display the status line +opt.swapfile = false -- Disable swapfile +opt.undofile = true -- Enable undofile (auto supported in NeoVim) +opt.showcmd = true -- Display incomplete commands +opt.incsearch = true -- Do incremental searching +opt.autoread = true -- Reload files changed outside +opt.hidden = true -- Allow leaving unsaved buffers +opt.inccommand = 'nosplit' -- Enable live preview of text replacement +opt.hlsearch = true +opt.mouse = 'a' + +opt.encoding = "utf-8" diff --git a/symlinks/config/nvim/lua/personal/plugins.lua b/symlinks/config/nvim/lua/personal/plugins.lua new file mode 100644 index 0000000..0039a79 --- /dev/null +++ b/symlinks/config/nvim/lua/personal/plugins.lua @@ -0,0 +1,75 @@ +return require('packer').startup { + function(use) + use 'wbthomason/packer.nvim' + + -- General plugins + use 'tpope/vim-sensible' + use 'tpope/vim-endwise' + use 'tpope/vim-surround' + use 'tpope/vim-fugitive' + use 'tpope/vim-vinegar' + use 'tpope/vim-obsession' + use 'tpope/vim-dadbod' + use 'airblade/vim-gitgutter' + use 'godlygeek/tabular' + use { 'Shougo/vimproc.vim', run = 'make' } + use 'vim-scripts/utl.vim' + use { 'mbbill/undotree', cmd = 'UndotreeToggle' } + use { 'junegunn/fzf', run = function() vim.fn['fzf#install']() end } + use 'junegunn/fzf.vim' + use 'mhinz/vim-grepper' + use 'direnv/direnv.vim' + use 'tpope/vim-speeddating' + use 'sainnhe/gruvbox-material' + + -- Tools + use 'tpope/vim-dispatch' + use 'radenling/vim-dispatch-neovim' + use 'vim-test/vim-test' + use 'dense-analysis/ale' + use 'tpope/vim-projectionist' + use 'ervandew/supertab' + + -- Vim improvements + use 'wellle/targets.vim' + use 'tpope/vim-unimpaired' + use 'tpope/vim-repeat' + use 'tpope/vim-commentary' + use 'tpope/vim-sleuth' + + -- Snippets + if vim.g.loaded_python3_provider ~= 0 + then + use 'SirVer/ultisnips' + use 'honza/vim-snippets' + end + + -- Language support + use 'sheerun/vim-polyglot' + use 'c-brenn/phoenix.vim' + use 'tpope/vim-rails' + use 'tpope/vim-salve' + use 'tpope/vim-fireplace' + use 'vimwiki/vimwiki' + use 'ledger/vim-ledger' + + -- Treesitter + use { 'nvim-treesitter/nvim-treesitter', run = ':TSUpdate' } + + -- LSP + -- use 'tjdevries/nlua.nvim' + use 'neovim/nvim-lspconfig' + use 'alexaandru/nvim-lspupdate' + use 'nvim-lua/completion-nvim' + use 'nvim-treesitter/completion-treesitter' + use 'nvim-lua/lsp_extensions.nvim' + + -- Extras + use 'nathunsmitty/nvim-ale-diagnostic' + + -- Lua support + use 'tjdevries/astronauta.nvim' + use 'nvim-lua/popup.nvim' + use 'nvim-lua/plenary.nvim' + end +} diff --git a/symlinks/config/nvim/lua/plugin/README.md b/symlinks/config/nvim/lua/plugin/README.md new file mode 100644 index 0000000..a8a2fc1 --- /dev/null +++ b/symlinks/config/nvim/lua/plugin/README.md @@ -0,0 +1,4 @@ +## Plugins + +This directory should be mostly used to group custom functionalities together into a "plugin". +In some cases this can be used to set up plugin settings, if it is required to be run before plugin (othwerise use /after/plugin). diff --git a/symlinks/config/nvim/lua/plugin/treesitter.lua b/symlinks/config/nvim/lua/plugin/treesitter.lua new file mode 100644 index 0000000..eceeed7 --- /dev/null +++ b/symlinks/config/nvim/lua/plugin/treesitter.lua @@ -0,0 +1,6 @@ +require'nvim-treesitter.configs'.setup { + ensure_installed = "maintained", -- one of "all", "maintained" (parsers with maintainers), or a list of languages + highlight = { + enable = true, -- false will disable the whole extension + }, +} diff --git a/symlinks/config/nvim/plugin/.gitignore b/symlinks/config/nvim/plugin/.gitignore new file mode 100644 index 0000000..22cd314 --- /dev/null +++ b/symlinks/config/nvim/plugin/.gitignore @@ -0,0 +1 @@ +packer_compiled.vim diff --git a/symlinks/config/nvim/plugin/README.md b/symlinks/config/nvim/plugin/README.md new file mode 100644 index 0000000..a8a2fc1 --- /dev/null +++ b/symlinks/config/nvim/plugin/README.md @@ -0,0 +1,4 @@ +## Plugins + +This directory should be mostly used to group custom functionalities together into a "plugin". +In some cases this can be used to set up plugin settings, if it is required to be run before plugin (othwerise use /after/plugin). diff --git a/symlinks/config/nvim/plugin/ale.vim b/symlinks/config/nvim/plugin/ale.vim new file mode 100644 index 0000000..5a2f363 --- /dev/null +++ b/symlinks/config/nvim/plugin/ale.vim @@ -0,0 +1,24 @@ +" ----------------------------------------------------------------------------- +" - ALE Plugin configuration - +" ----------------------------------------------------------------------------- + +" ALE Options +let g:ale_disable_lsp = 1 " Disable LSP, we have other stuff for that +let g:ale_fix_on_save = 1 " Default + +" ALE Linters configuration +let g:ale_linters = {} +let g:ale_linters.python = ['flake8'] +let g:ale_linters.kotlin = ['ktlint'] + +" ALE Fixers configuration +let g:ale_fixers = {} +let g:ale_fixers['*'] = ['remove_trailing_lines', 'trim_whitespace'] +let g:ale_fixers.python = ['autopep8', 'isort'] +let g:ale_fixers.dart = ['dartfmt'] + +" Warnings navigation +nmap [W (ale_first) +nmap [w (ale_previous) +nmap ]w (ale_next) +nmap ]W (ale_last) diff --git a/symlinks/config/nvim/plugin/coc.vim b/symlinks/config/nvim/plugin/coc.vim new file mode 100644 index 0000000..7a4c9ac --- /dev/null +++ b/symlinks/config/nvim/plugin/coc.vim @@ -0,0 +1,79 @@ +" Must have extensions! + +lua <", "lua vim.lsp.buf.definition()", default_opts) +vim.api.nvim_set_keymap("n", "gD", "lua vim.lsp.buf.declaration()", default_opts) +vim.api.nvim_set_keymap("n", "gr", "lua vim.lsp.buf.references()", default_opts) +vim.api.nvim_set_keymap("n", "rn", "lua vim.lsp.buf.rename()", default_opts) +vim.api.nvim_set_keymap("n", "", "lua vim.lsp.buf.signature_help()", default_opts) +vim.api.nvim_set_keymap("n", "K", "lua vim.lsp.buf.hover()", default_opts) +vim.api.nvim_set_keymap("n", "", "lua vim.lsp.buf.code_action()", default_opts) +vim.api.nvim_set_keymap("n", "ac", "lua vim.lsp.buf.code_action()", default_opts) +vim.api.nvim_set_keymap("n", "a", "lua vim.lsp.buf.code_action_range()", default_opts) + +lspconfig.bashls.setup {on_attach = on_attach} +lspconfig.clangd.setup {on_attach = on_attach} +lspconfig.dartls.setup {on_attach = on_attach} +lspconfig.jsonls.setup {on_attach = on_attach} +lspconfig.pyright.setup {on_attach = on_attach} +lspconfig.rust_analyzer.setup {on_attach = on_attach} +lspconfig.vimls.setup {on_attach = on_attach} + +require'compe'.setup { + enabled = true; + autocomplete = true; + debug = false; + min_length = 1; + preselect = 'enable'; + throttle_time = 80; + source_timeout = 200; + incomplete_delay = 400; + max_abbr_width = 100; + max_kind_width = 100; + max_menu_width = 100; + documentation = true; + + source = { + path = true; + buffer = true; + calc = true; + vsnip = true; + nvim_lsp = true; + nvim_lua = true; + spell = true; + tags = true; + snippets_nvim = true; + treesitter = true; + }; +} + +require("nvim-ale-diagnostic") + +vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with( + vim.lsp.diagnostic.on_publish_diagnostics, { + underline = false, + virtual_text = false, + signs = true, + update_in_insert = false, + } +) + +EOF + +inoremap compe#complete() +inoremap compe#confirm('') +inoremap compe#close('') +inoremap compe#scroll({ 'delta': +4 }) +inoremap compe#scroll({ 'delta': -4 }) + +" Set completeopt to have a better completion experience +set completeopt=menuone,noselect diff --git a/symlinks/config/nvim/plugin/fugitive.vim b/symlinks/config/nvim/plugin/fugitive.vim new file mode 100644 index 0000000..0d71aa3 --- /dev/null +++ b/symlinks/config/nvim/plugin/fugitive.vim @@ -0,0 +1,84 @@ +" ----------------------------------------------------------------------------- +" - Fugitive.vim setup and extra mappings - +" ----------------------------------------------------------------------------- + +" Shorcut to push directly to current branch on origin +" Similar to `ggpush` in fish config +function! s:PushOrigin() + execute 'Git push origin ' . FugitiveHead() +endfunction + +" Shorcut to pull directly from current branch on origin +" Similar to `ggpull` in fish config +function! s:PullOrigin() + execute 'Git pull origin ' . FugitiveHead() +endfunction + +" Generates url for creating PR for current branch +" Tested only with github.com +" Works regardless of ssh or https for origin config +" Hardcoded to use 'origin' remote +function! s:GetPrUrl(...) + let origin_url = fugitive#RemoteUrl('origin') + let l:origin_url = substitute(l:origin_url, '\.git$', '', '') + let l:origin_url = substitute(l:origin_url, ':', '/', '') + let l:origin_url = substitute(l:origin_url, 'git@', 'https://', '') + + " Remove prefix if it is available, for some of common git services + let common_services = ['github.com', 'bitbucket.org', 'gitlab.com'] + for service in l:common_services + if (l:origin_url =~ l:service) + " Common mechanism for managing multiple SSH keys + let l:origin_url = substitute(l:origin_url, '://.*' . l:service, '://' . l:service, '') + endif + endfor + + " This part probably only works on github + if a:0 == 0 + let pr_url = l:origin_url . '/compare/' . FugitiveHead() . '?expand=1' + else + let pr_url = l:origin_url . '/compare/' . a:1 . '...' . FugitiveHead() . '?expand=1' + endif + return l:pr_url +endfunction + +" Prints current branches PR url (not saved to :messages) +" Makes it easy to use terminal for opening url on click +function! s:PrintPrUrl(...) + echo call('s:GetPrUrl', a:000) +endfunction + +" Copies current branches PR url to system clipboard +function! s:CopyPrUrl(...) + let @+ = call('s:GetPrUrl', a:000) +endfunction + +" Opens current banches PR url in default browser +" Utilizes netrw browse, meaning it should behave same as netrw +function! s:OpenNewPr(...) + call netrw#BrowseX(call('s:GetPrUrl', a:000), 0) +endfunction + +" Creates new branch and checks out to it +" Similar to `gcb` in fish config +function! s:CreateBranch(branch) + execute 'Git checkout -b ' . a:branch +endfunction + +" Switches to branch +function! s:CheckoutBranch(branch) + execute 'Git checkout ' . a:branch +endfunction + +command! -nargs=0 Ggpush :call s:PushOrigin() +command! -nargs=0 Ggpull :call s:PullOrigin() +command! -nargs=? Gpropen :call s:OpenNewPr() +command! -nargs=? Gpr Gpropen +command! -nargs=? Gprprint :call s:PrintPrUrl() +command! -nargs=? Gprcopy :call s:CopyPrUrl() +command! -nargs=1 Gcbranch :call s:CreateBranch() +command! -nargs=0 Gcmaster :call s:CheckoutBranch('main') +command! -nargs=0 Gcm Gcmaster +command! -nargs=0 Gcdev :call s:CheckoutBranch('develop') +command! -nargs=1 Gcheckout :call s:CheckoutBranch() +command! -nargs=1 Gc Gcheckout diff --git a/symlinks/config/nvim/plugin/ledger.vim b/symlinks/config/nvim/plugin/ledger.vim new file mode 100644 index 0000000..8f924ca --- /dev/null +++ b/symlinks/config/nvim/plugin/ledger.vim @@ -0,0 +1,5 @@ +" ----------------------------------------------------------------------------- +" - Ledger-cli vim support config - +" ----------------------------------------------------------------------------- +let g:ledger_extra_options = '--pedantic --explicit --check-payees' +let g:ledger_decimal_sep = ',' diff --git a/symlinks/config/nvim/plugin/netrw.vim b/symlinks/config/nvim/plugin/netrw.vim new file mode 100644 index 0000000..67d8f3e --- /dev/null +++ b/symlinks/config/nvim/plugin/netrw.vim @@ -0,0 +1,5 @@ +" ----------------------------------------------------------------------------- +" - Netrw config - +" ----------------------------------------------------------------------------- + + let g:netrw_keepdir = 0 diff --git a/symlinks/config/nvim/plugin/ruby_host.vim b/symlinks/config/nvim/plugin/ruby_host.vim new file mode 100644 index 0000000..2e99f40 --- /dev/null +++ b/symlinks/config/nvim/plugin/ruby_host.vim @@ -0,0 +1,4 @@ +" ----------------------------------------------------------------------------- +" - Neovim ruby host - +" ----------------------------------------------------------------------------- +let g:ruby_host_prog = '~/.asdf/shims/ruby' diff --git a/symlinks/config/nvim/plugin/scratch_buffer.vim b/symlinks/config/nvim/plugin/scratch_buffer.vim new file mode 100644 index 0000000..049587b --- /dev/null +++ b/symlinks/config/nvim/plugin/scratch_buffer.vim @@ -0,0 +1,19 @@ +" ----------------------------------------------------------------------------- +" - Scratch buffer - +" Creates a basic scratch buffer +" Adopted from https://github.com/hagsteel/vimconf/blob/master/vimrc +" ----------------------------------------------------------------------------- + +functio CreateScratchBuffer(vertical) + if a:vertical == 1 + :vnew + else + :new + endif + :setlocal buftype=nofile + :setlocal bufhidden=hide + :setlocal noswapfile + :set ft=scratch +endfunction +:command! Scratch call CreateScratchBuffer(1) +:command! Scratchh call CreateScratchBuffer(0) diff --git a/symlinks/config/nvim/plugin/statusline.vim b/symlinks/config/nvim/plugin/statusline.vim new file mode 100644 index 0000000..f3f5406 --- /dev/null +++ b/symlinks/config/nvim/plugin/statusline.vim @@ -0,0 +1,180 @@ +" ----------------------------------------------------------------------------- +" - Statusline setup - +" ----------------------------------------------------------------------------- + +function s:UpdateColors() + let ctermbg = synIDattr(synIDtrans(hlID('StatusLine')), 'bg', 'cterm') + let guibg = synIDattr(synIDtrans(hlID('StatusLine')), 'bg', 'gui') + let idguifg1 = synIDattr(synIDtrans(hlID('Function')), 'fg', 'gui') + let idctermfg1 = synIDattr(synIDtrans(hlID('Function')), 'fg', 'cterm') + " Green in gruvbox + exec 'hi User1 guifg=' . l:idguifg1 . + \' guibg=' . l:guibg . + \' cterm=bold gui=bold' + if l:idctermfg1 + exec 'hi User1 ctermfg=' . l:idctermfg1 + endif + let idguifg2 = synIDattr(synIDtrans(hlID('ErrorMsg')), 'fg', 'gui') + let idctermfg2 = synIDattr(synIDtrans(hlID('ErrorMsg')), 'fg', 'cterm') + " Red in gruvbox + exec 'hi User2 guifg=' . l:idguifg2 . + \' guibg=' . l:guibg . + \' cterm=bold gui=bold' + if l:idctermfg2 + exec 'hi User2 ctermfg=' . l:idctermfg2 + endif + let idguifg3 = synIDattr(synIDtrans(hlID('WarningMsg')), 'fg', 'gui') + let idctermfg3 = synIDattr(synIDtrans(hlID('WarningMsg')), 'fg', 'cterm') + " Yellow in gruvbox + exec 'hi User3 guifg=' . l:idguifg3 . + \' guibg=' . l:guibg . + \' cterm=bold gui=bold' + if l:idctermfg3 + exec 'hi User3 ctermfg=' . l:idctermfg3 + endif + let idguifg4 = synIDattr(synIDtrans(hlID('Identifier')), 'fg', 'gui') + let idctermfg4 = synIDattr(synIDtrans(hlID('Identifier')), 'fg', 'cterm') + " Blue in gruvbox + exec 'hi User4 guifg=' . l:idguifg4 + \' guibg=' . l:guibg . + \' cterm=bold gui=bold' + if l:idctermfg4 + exec 'hi User4 ctermfg=' . l:idctermfg4 + endif + let idguifg5 = synIDattr(synIDtrans(hlID('Number')), 'fg', 'gui') + let idctermfg5 = synIDattr(synIDtrans(hlID('Number')), 'fg', 'cterm') + " Blue in gruvbox + exec 'hi User5 guifg=' . l:idguifg5 . + \' guibg=' . l:guibg . + \' cterm=bold gui=bold' + if l:idctermfg5 + exec 'hi User5 ctermfg=' . l:idctermfg5 + endif + + if l:ctermbg + exec 'hi User1 ctermbg=' . l:ctermbg + exec 'hi User2 ctermbg=' . l:ctermbg + exec 'hi User3 ctermbg=' . l:ctermbg + exec 'hi User4 ctermbg=' . l:ctermbg + exec 'hi User5 ctermbg=' . l:ctermbg + endif +endfunction + +augroup statuslineconf + autocmd! + autocmd ColorScheme * call s:UpdateColors() +augroup END + +call s:UpdateColors() + + +" Checks file type to add a pretty glyph if available +function s:GetFileType() + if &filetype ==# "rust" + return "%2*%*" + elseif &filetype ==# "c" + return "%4*%*" + elseif &filetype ==# "python" + return "%3*%*" + elseif &filetype ==# "javascript" + return "" + elseif &filetype ==# "typescript" + return "%4*%*" + elseif &filetype ==# "vim" + return "%1*%*" + elseif &filetype ==# "clojure" + return "" + elseif &filetype ==# "html" + return "" + elseif &filetype ==# "haskell" + return "" + elseif &filetype ==# "markdown" + return "" + elseif &filetype ==# "org" + return "" + elseif &filetype ==# "scss" + return "" + elseif &filetype ==# "scala" + return "" + elseif &filetype ==# "elixir" + return "%5*%*" + elseif &filetype ==# "kotlin" + return "%2*洞%*" + elseif &filetype ==# "yml" + return "" + elseif &filetype ==# "toml" + return "" + elseif &filetype ==# "json" + return "" + else + return "%y" +endfunction + +" Check current mode to add colorized mode +function s:GetMode() + if mode() == "n" + return "N" + elseif mode() == "i" + return "%3*I%*" + elseif mode() == "v" + return "%1*V%*" + elseif mode() == "V" + return "%1*V.%*" + elseif mode() == "\" + return "%1*VB%*" + elseif mode() == "c" + return "%4*C%*" + else + return "[mode: " . mode() . "]" +endfunction + +" Add basic [paste] if paste mode is enabled +function! s:PasteForStatusline() + let paste_status = &paste + if paste_status == 1 + return " [paste] " + else + return "" + endif +endfunction + +function! s:LinterStatus() abort + let l:counts = ale#statusline#Count(bufnr('')) + + let l:all_errors = l:counts.error + l:counts.style_error + let l:all_non_errors = l:counts.total - l:all_errors + + return l:counts.total == 0 ? '%1*OK%*' : printf( + \ '%%3*%dW%%* %%2*%dE%%*', + \ all_non_errors, + \ all_errors + \) +endfunction + +function GetStatusLine() + let l:status_line_left = " " . s:GetMode() . " " + if exists('g:loaded_fugitive') + let l:fugitive_head = FugitiveHead() + if strlen(l:fugitive_head) + let l:status_line_left .= "%4* " . l:fugitive_head . "%*" + endif + endif + let l:status_line_left .= " %f" " Filename + let l:status_line_left .= " %1*%M%*" " Modified + let l:status_line_left .= " %2*%r%*" " Read only + let l:status_line_left .= s:PasteForStatusline() + if exists('g:did_coc_loaded') + let l:coc_status = coc#status() + if strlen(l:coc_status) + let l:status_line_left .= "%2*" . l:coc_status . "%*" + endif + endif + let l:status_line_right = "%= " " Align right statusline + if exists('g:loaded_ale') + let l:status_line_right .= s:LinterStatus() " ALE status + endif + let l:status_line_right .= " %2c:%3l/%3L (%3p%%) " " col, line, tot. lines + let l:status_line_right .= s:GetFileType() . " " " File type + return l:status_line_left . l:status_line_right +endfunction +set statusline=%!GetStatusLine() diff --git a/symlinks/config/nvim/plugin/tabline.vim b/symlinks/config/nvim/plugin/tabline.vim new file mode 100644 index 0000000..ccd1776 --- /dev/null +++ b/symlinks/config/nvim/plugin/tabline.vim @@ -0,0 +1,35 @@ +" ----------------------------------------------------------------------------- +" - Tabline setup - +" ----------------------------------------------------------------------------- +function! GuiTabLabel() + let label = '' + let bufnrlist = tabpagebuflist(v:lnum) + " Add '+' if one of the buffers in the tab page is modified + for bufnr in bufnrlist + if getbufvar(bufnr, "&modified") + let label = '+' + break + endif + endfor + " Append the tab number + let label .= v:lnum.': ' + " Append the buffer name + let name = bufname(bufnrlist[tabpagewinnr(v:lnum) - 1]) + if name == '' + " give a name to no-name documents + if &buftype=='quickfix' + let name = '[Quickfix List]' + else + let name = '[No Name]' + endif + else + " get only the file name + let name = fnamemodify(name,":t") + endif + let label .= name + " Append the number of windows in the tab page + let wincount = tabpagewinnr(v:lnum, '$') + return label . ' [' . wincount . ']' +endfunction + +set guitablabel=%{GuiTabLabel()} diff --git a/symlinks/config/nvim/plugin/tex.vim b/symlinks/config/nvim/plugin/tex.vim new file mode 100644 index 0000000..32584b4 --- /dev/null +++ b/symlinks/config/nvim/plugin/tex.vim @@ -0,0 +1,7 @@ +" ----------------------------------------------------------------------------- +" - Tex plugin configuration - +" Must be run before plugin, therefore it can't be located in after dir +" ----------------------------------------------------------------------------- + +" Set default .tex file flavor to latex +let g:tex_flavor = 'latex' diff --git a/symlinks/config/nvim/plugin/ultisnips.vim b/symlinks/config/nvim/plugin/ultisnips.vim new file mode 100644 index 0000000..13c1a1f --- /dev/null +++ b/symlinks/config/nvim/plugin/ultisnips.vim @@ -0,0 +1,6 @@ +" ----------------------------------------------------------------------------- +" - UltiSnips configuration - +" ----------------------------------------------------------------------------- + +" Force ultisnips to use vim directory (for supporting both NeoVim and Vim) +let g:UltiSnipsSnippetDirectories=[$OVIMHOME."/UltiSnips"] diff --git a/symlinks/config/nvim/plugin/undoconf.vim b/symlinks/config/nvim/plugin/undoconf.vim new file mode 100644 index 0000000..4a3833e --- /dev/null +++ b/symlinks/config/nvim/plugin/undoconf.vim @@ -0,0 +1,10 @@ +" ----------------------------------------------------------------------------- +" - Undo configuration - +" ----------------------------------------------------------------------------- +set undofile + +" Disable persistent undofile for temporary files! +augroup undoconf + autocmd! + autocmd BufWritePre /tmp/* setlocal noundofile +augroup END diff --git a/symlinks/config/nvim/plugin/vimwiki.vim b/symlinks/config/nvim/plugin/vimwiki.vim new file mode 100644 index 0000000..6ebff58 --- /dev/null +++ b/symlinks/config/nvim/plugin/vimwiki.vim @@ -0,0 +1,25 @@ +" Must be set up before vimwiki plugin is initialized, can't be in after +let personal_wiki = {} +let personal_wiki.path = '~/vimwiki/' +let personal_wiki.ext = '.md' +let personal_wiki.index = 'Home' +let personal_wiki.syntax = 'markdown' +let personal_wiki.auto_diary_index = 1 +let personal_wiki.auto_generate_links = 1 +let personal_wiki.auto_toc = 1 + +let work_wiki = {} +let work_wiki.path = '~/vimwiki_work/' +let work_wiki.syntax = 'markdown' +let work_wiki.ext = '.md' +let work_wiki.auto_diary_index = 1 +let work_wiki.auto_generate_links = 1 +let work_wiki.auto_toc = 1 + +let g:vimwiki_list = [personal_wiki, work_wiki] + +" Disable vimwiki filetype on all markdown files +let g:vimwiki_global_ext = 0 + +" Prettier checkboxes +let g:vimwiki_listsyms = '✗○◐●✓' diff --git a/symlinks/config/nvim/plugin/vimwiki_reviews.vim b/symlinks/config/nvim/plugin/vimwiki_reviews.vim new file mode 100644 index 0000000..6322e30 --- /dev/null +++ b/symlinks/config/nvim/plugin/vimwiki_reviews.vim @@ -0,0 +1,133 @@ +" ----------------------------------------------------------------------------- +" - Vimwiki extensions for working with weekly/monthly/yearly reviews - +" +" DEPENDS ON VIMWIKI PLUGIN +" ----------------------------------------------------------------------------- + +" Gets path to reviews dir of provided vimwiki (by index) +function! s:GetReviewsDir(...) + if a:0 == 0 + let l:vimwiki = g:vimwiki_list[0] + else + let l:vimwiki = g:vimwiki_list[str2nr(a:1) - 1] + endif + + return l:vimwiki.path . 'reviews/' +endfunction + +" Finds review template path for provided review type +function! s:GetReviewTemplatePath(vimwiki_reviews_path, review_type) + return a:vimwiki_reviews_path . 'template-' . a:review_type . '.md' +endfunction + +" Edits weekly review template +function! s:OpenReviewWeeklyTemplate(...) + let reviews_dir = call('s:GetReviewsDir', a:000) + execute 'edit ' . s:GetReviewTemplatePath(l:reviews_dir, 'week') +endfunction + +" Edits monthly review template +function! s:OpenReviewMonthlyTemplate(...) + let reviews_dir = call('s:GetReviewsDir', a:000) + execute 'edit ' . s:GetReviewTemplatePath(l:reviews_dir, 'month') +endfunction + +" Edits yearly review template +function! s:OpenReviewYearlyTemplate(...) + let reviews_dir = call('s:GetReviewsDir', a:000) + execute 'edit ' . s:GetReviewTemplatePath(l:reviews_dir, 'year') +endfunction + +" Reads template for provided review type into current buffer +" Uses overrides in form of files in reviews directory +" Looks for file named template-{review_type}.md: +" - template-week.md +" - template-month.md +" - template-year.md +" Templates can use variables using %variable% syntax +" Currently supported variables are: +" - %date% (Puts different date based on review type) +function! s:ReadReviewTemplateIntoBuffer(vimwiki_reviews_path, review_type) + let template_path = s:GetReviewTemplatePath(a:vimwiki_reviews_path, a:review_type) + if filereadable(glob(l:template_path)) + execute 'read ' . l:template_path + else + if a:review_type == 'week' + call setline(1, '# %date% Weekly Review') + elseif a:review_type == 'month' + call setline(1, '# %date% Monthly Review') + elseif a:review_type == 'year' + call setline(1, '# %date% Yearly Review') + endif + endif +endfunction + +" Open current week weekly review file +" Created buffer is dated to Sunday of current week +" Opens current week because Sunday is good time to do this review +function! s:VimwikiWeeklyReview(...) + let reviews_dir = call('s:GetReviewsDir', a:000) + let days_to_sunday = 7 - str2nr(strftime('%u')) + let week_date = strftime('%Y-%m-%d', localtime() + l:days_to_sunday * 24 * 60 * 60) + let file_name = l:reviews_dir . l:week_date . '-week.md' + let exists = filereadable(glob(l:file_name)) + execute 'edit ' . l:file_name + if exists == v:false + call s:ReadReviewTemplateIntoBuffer(l:reviews_dir, 'week') + execute '%substitute/%date%/' . l:week_date + endif +endfunction + + +" Open past month monthly review file +" Created buffer is dated to previous month +" Previous month is calculated in an erroneous way +" 28 days are subtracted from current time to get previous month +function! s:VimwikiMonthlyReview(...) + let reviews_dir = call('s:GetReviewsDir', a:000) + let month_time = localtime() - 28 * 24 * 60 * 60 + let month_date = strftime('%Y-%m', l:month_time) + let file_name = l:reviews_dir . l:month_date .'-month.md' + let exists = filereadable(glob(l:file_name)) + execute 'edit ' . l:file_name + if exists == v:false + call s:ReadReviewTemplateIntoBuffer(l:reviews_dir, 'month') + execute '%substitute/%date%/' . strftime('%Y %B', l:month_time) + endif +endfunction + +" Open past year yearly review file +" Created buffer is dated to previous year +function! s:VimwikiYearlyReview(...) + let reviews_dir = call('s:GetReviewsDir', a:000) + let year_date = (str2nr(strftime('%Y')) - 1) + let file_name = l:reviews_dir . l:year_date .'-year.md' + let exists = filereadable(glob(l:file_name)) + execute 'edit ' . l:file_name + if exists == v:false + call s:ReadReviewTemplateIntoBuffer(l:reviews_dir, 'year') + execute '%substitute/%date%/' . l:year_date + endif +endfunction + +" Open reviews index file +function! s:VimwikiReviewIndex(...) + let reviews_dir = call('s:GetReviewsDir', a:000) + execute 'edit ' . l:reviews_dir . 'reviews.md' +endfunction + +command! -nargs=? VimwikiWeeklyReview :call s:VimwikiWeeklyReview() +command! -nargs=? VimwikiWeeklyTemplate :call s:OpenReviewWeeklyTemplate() +command! -nargs=? VimwikiMonthlyReview :call s:VimwikiMonthlyReview() +command! -nargs=? VimwikiMonthlyTemplate :call s:OpenReviewMonthlyTemplate() +command! -nargs=? VimwikiYearlyReview :call s:VimwikiYearlyReview() +command! -nargs=? VimwikiYearlyTemplate :call s:OpenReviewYearlyTemplate() +command! -nargs=? VimwikiReviewIndex :call s:VimwikiReviewIndex() + +nnoremap wrw :VimwikiWeeklyReview +nnoremap wrtw :VimwikiWeeklyTemplate +nnoremap wrm :VimwikiMonthlyReview +nnoremap wrtm :VimwikiMonthlyTemplate +nnoremap wry :VimwikiYearlyReview +nnoremap wrty :VimwikiYearlyTemplate +nnoremap wri :VimwikiReviewIndex diff --git a/symlinks/config/nvim/plugin/vsnip.vim b/symlinks/config/nvim/plugin/vsnip.vim new file mode 100644 index 0000000..9b58695 --- /dev/null +++ b/symlinks/config/nvim/plugin/vsnip.vim @@ -0,0 +1,22 @@ +" NOTE: You can use other key to expand snippet. + +" Expand +imap vsnip#expandable() ? '(vsnip-expand)' : '' +smap vsnip#expandable() ? '(vsnip-expand)' : '' + +" Expand or jump +imap vsnip#available(1) ? '(vsnip-expand-or-jump)' : '' +smap vsnip#available(1) ? '(vsnip-expand-or-jump)' : '' + +" Jump forward or backward +imap vsnip#jumpable(1) ? '(vsnip-jump-next)' : '' +smap vsnip#jumpable(1) ? '(vsnip-jump-next)' : '' +imap vsnip#jumpable(-1) ? '(vsnip-jump-prev)' : '' +smap vsnip#jumpable(-1) ? '(vsnip-jump-prev)' : '' + +" Select or cut text to use as $TM_SELECTED_TEXT in the next snippet. +" See https://github.com/hrsh7th/vim-vsnip/pull/50 +nmap s (vsnip-select-text) +xmap s (vsnip-select-text) +nmap S (vsnip-cut-text) +xmap S (vsnip-cut-text) diff --git a/symlinks/config/nvim/spell/en.utf-8.add b/symlinks/config/nvim/spell/en.utf-8.add new file mode 100644 index 0000000..8ed1446 --- /dev/null +++ b/symlinks/config/nvim/spell/en.utf-8.add @@ -0,0 +1 @@ +Polymorphism diff --git a/symlinks/config/nvim/spell/en.utf-8.add.spl b/symlinks/config/nvim/spell/en.utf-8.add.spl new file mode 100644 index 0000000..735e29c Binary files /dev/null and b/symlinks/config/nvim/spell/en.utf-8.add.spl differ diff --git a/symlinks/config/nvim/spell/en.utf-8.spl b/symlinks/config/nvim/spell/en.utf-8.spl new file mode 100644 index 0000000..83b9b8f Binary files /dev/null and b/symlinks/config/nvim/spell/en.utf-8.spl differ diff --git a/symlinks/config/nvim/spell/en.utf-8.sug b/symlinks/config/nvim/spell/en.utf-8.sug new file mode 100644 index 0000000..bbdf36a Binary files /dev/null and b/symlinks/config/nvim/spell/en.utf-8.sug differ diff --git a/symlinks/config/nvim/undodir/.gitignore b/symlinks/config/nvim/undodir/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/symlinks/config/nvim/undodir/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/symlinks/tool-versions b/symlinks/tool-versions index 78066f3..9f875ad 100644 --- a/symlinks/tool-versions +++ b/symlinks/tool-versions @@ -8,4 +8,5 @@ poetry 1.1.4 python 3.9.1 2.7.18 ruby 3.0.0 rust 1.49.0 -neovim 0.4.4 +neovim nightly +vim 8.2.2544 diff --git a/symlinks/vim/README.md b/symlinks/vim/README.md index 5cd2597..8e29b74 100644 --- a/symlinks/vim/README.md +++ b/symlinks/vim/README.md @@ -1,6 +1,4 @@ -## My vim configuration - -Currently configuration is shared between Vim and NeoVim, although I use NeoVim. Migration will happen when NeoVim 0.5.0 is released and `init.lua` is supported. +## My NeoVim configuration Configuration is separated into directories: - `plugin` for logical collection of functionalities into a simple plugin diff --git a/symlinks/vim/UltiSnips/lua.snippets b/symlinks/vim/UltiSnips/lua.snippets new file mode 100644 index 0000000..3e368db --- /dev/null +++ b/symlinks/vim/UltiSnips/lua.snippets @@ -0,0 +1,5 @@ +snippet cmt +------------------------------------------------------------------------------- +-- - $1 - +-------------------------------------------------------------------------------$0 +endsnippet diff --git a/symlinks/vim/plugin/statusline.vim b/symlinks/vim/plugin/statusline.vim index f487039..699d0b0 100644 --- a/symlinks/vim/plugin/statusline.vim +++ b/symlinks/vim/plugin/statusline.vim @@ -3,38 +3,48 @@ " ----------------------------------------------------------------------------- function s:UpdateColors() - let ctermbg = synIDattr(synIDtrans(hlID('StatusLine')), 'bg', 'cterm') - let guibg = synIDattr(synIDtrans(hlID('StatusLine')), 'bg', 'gui') + let ctermbg = synIDattr(synIDtrans(hlID('StatusLine')), 'fg', 'cterm') + let guibg = synIDattr(synIDtrans(hlID('StatusLine')), 'fg', 'gui') let idguifg1 = synIDattr(synIDtrans(hlID('Function')), 'fg', 'gui') let idctermfg1 = synIDattr(synIDtrans(hlID('Function')), 'fg', 'cterm') " Green in gruvbox exec 'hi User1 guifg=' . l:idguifg1 . \' ctermfg=' . l:idctermfg1 . - \' cterm=bold,reverse gui=bold,reverse' + \' guibg=' . l:guibg . + \' ctermbg=' . l:ctermbg . + \' cterm=bold gui=bold' let idguifg2 = synIDattr(synIDtrans(hlID('WarningMsg')), 'fg', 'gui') let idctermfg2 = synIDattr(synIDtrans(hlID('WarningMsg')), 'fg', 'cterm') " Red in gruvbox exec 'hi User2 guifg=' . l:idguifg2 . \' ctermfg=' . l:idctermfg2 . - \' cterm=bold,reverse gui=bold,reverse' + \' guibg=' . l:guibg . + \' ctermbg=' . l:ctermbg . + \' cterm=bold gui=bold' let idguifg3 = synIDattr(synIDtrans(hlID('MoreMsg')), 'fg', 'gui') let idctermfg3 = synIDattr(synIDtrans(hlID('MoreMsg')), 'fg', 'cterm') " Yellow in gruvbox exec 'hi User3 guifg=' . l:idguifg3 . \' ctermfg=' . l:idctermfg3 . - \' cterm=bold,reverse gui=bold,reverse' + \' guibg=' . l:guibg . + \' ctermbg=' . l:ctermbg . + \' cterm=bold gui=bold' let idguifg4 = synIDattr(synIDtrans(hlID('Identifier')), 'fg', 'gui') let idctermfg4 = synIDattr(synIDtrans(hlID('Identifier')), 'fg', 'cterm') " Blue in gruvbox exec 'hi User4 guifg=' . l:idguifg4 . \' ctermfg=' . l:idctermfg4 . - \' cterm=bold,reverse gui=bold,reverse' + \' guibg=' . l:guibg . + \' ctermbg=' . l:ctermbg . + \' cterm=bold gui=bold' let idguifg5 = synIDattr(synIDtrans(hlID('Number')), 'fg', 'gui') let idctermfg5 = synIDattr(synIDtrans(hlID('Number')), 'fg', 'cterm') " Blue in gruvbox exec 'hi User5 guifg=' . l:idguifg5 . \' ctermfg=' . l:idctermfg5 . - \' cterm=bold,reverse gui=bold,reverse' + \' guibg=' . l:guibg . + \' ctermbg=' . l:ctermbg . + \' cterm=bold gui=bold' endfunction augroup statuslineconf @@ -48,41 +58,41 @@ call s:UpdateColors() " Checks file type to add a pretty glyph if available function s:GetFileType() if &filetype ==# "rust" - return "%2*  %*" + return "%2*%*" elseif &filetype ==# "c" - return "%4*  %*" + return "%4*%*" elseif &filetype ==# "python" - return "%3*  %*" + return "%3*%*" elseif &filetype ==# "javascript" - return "  " + return "" elseif &filetype ==# "typescript" - return "%4*  %*" + return "%4*%*" elseif &filetype ==# "vim" - return "%1*  %*" + return "%1*%*" elseif &filetype ==# "clojure" - return "  " + return "" elseif &filetype ==# "html" - return "  " + return "" elseif &filetype ==# "haskell" - return "  " + return "" elseif &filetype ==# "markdown" - return "  " + return "" elseif &filetype ==# "org" - return "  " + return "" elseif &filetype ==# "scss" - return "  " + return "" elseif &filetype ==# "scala" - return "  " + return "" elseif &filetype ==# "elixir" - return "%5*  %*" + return "%5*%*" elseif &filetype ==# "kotlin" - return "%2* 洞 %*" + return "%2*洞%*" elseif &filetype ==# "yml" - return "  " + return "" elseif &filetype ==# "toml" - return "  " + return "" elseif &filetype ==# "json" - return "  " + return "" else return "%y" endfunction @@ -90,17 +100,17 @@ endfunction " Check current mode to add colorized mode function s:GetMode() if mode() == "n" - return " N " + return "N" elseif mode() == "i" - return "%3* I %*" + return "%3*I%*" elseif mode() == "v" - return "%1* V %*" + return "%1*V%*" elseif mode() == "V" - return "%1* V. %*" + return "%1*V.%*" elseif mode() == "\" - return "%1* VB %*" + return "%1*VB%*" elseif mode() == "c" - return "%4* C %*" + return "%4*C%*" else return "[mode: " . mode() . "]" endfunction @@ -122,18 +132,18 @@ function! s:LinterStatus() abort let l:all_non_errors = l:counts.total - l:all_errors return l:counts.total == 0 ? '%1* OK %*' : printf( - \ '%%3* %dW %%* %%2* %dE %%*', + \ '%%3*%dW%%* %%2*%dE%%*', \ all_non_errors, \ all_errors \) endfunction function GetStatusLine() - let l:status_line_left = s:GetMode() + let l:status_line_left = " " . s:GetMode() . " " if exists('g:loaded_fugitive') let l:fugitive_head = FugitiveHead() if strlen(l:fugitive_head) - let l:status_line_left .= "%4*  " . l:fugitive_head . " %*" + let l:status_line_left .= "%4* " . l:fugitive_head . "%*" endif endif let l:status_line_left .= " %f" " Filename @@ -143,7 +153,7 @@ function GetStatusLine() if exists('g:did_coc_loaded') let l:coc_status = coc#status() if strlen(l:coc_status) - let l:status_line_left .= "%2* " . l:coc_status . " %*" + let l:status_line_left .= "%2*" . l:coc_status . "%*" endif endif let l:status_line_right = "%= " " Align right statusline diff --git a/symlinks/vim/vimrc b/symlinks/vim/vimrc index 7b45837..00d22e1 100644 --- a/symlinks/vim/vimrc +++ b/symlinks/vim/vimrc @@ -68,7 +68,6 @@ set showcmd " display incomplete commands set incsearch " do incremental searching set autoread " Reload files changed outside vim set hidden " Allow leaving unsaved buffers -set inccommand=nosplit " Enable live preview of text replacement " Trigger autoread when changing buffers or coming back to vim in terminal. if !has('win32') && !has('win64') @@ -128,5 +127,3 @@ if &term =~ '256color' " render properly when inside 256-color tmux and GNU screen. set t_ut= endif - -highlight Comment cterm=italic