From 18a37da86840c9e111172f5f24ceebe227ca56ed Mon Sep 17 00:00:00 2001 From: Mike Vink Date: Sat, 29 Oct 2022 16:26:38 +0200 Subject: add neovim lua files --- home.nix | 44 +++--- neovim/README.md | 2 + neovim/autoload/buffers.vim | 98 ++++++++++++ neovim/autoload/reloadpackage.vim | 3 + neovim/init.lua | 293 ++++++++++++++++++++++++++++++++++ neovim/lua/vimrc.lua | 211 +++++++++++++++++++++++++ neovim/lua/vimrc/ansible.lua | 195 +++++++++++++++++++++++ neovim/lua/vimrc/azure.lua | 39 +++++ neovim/lua/vimrc/buffers.lua | 35 +++++ neovim/lua/vimrc/dap.lua | 266 +++++++++++++++++++++++++++++++ neovim/lua/vimrc/helm.lua | 129 +++++++++++++++ neovim/lua/vimrc/lsp.lua | 322 ++++++++++++++++++++++++++++++++++++++ neovim/lua/vimrc/snippets.lua | 133 ++++++++++++++++ neovim/lua/vimrc/term.lua | 91 +++++++++++ neovim/lua/vimrc/terragrunt.lua | 141 +++++++++++++++++ neovim/lua/vimrc/utils.lua | 70 +++++++++ 16 files changed, 2051 insertions(+), 21 deletions(-) create mode 100644 neovim/README.md create mode 100644 neovim/autoload/buffers.vim create mode 100644 neovim/autoload/reloadpackage.vim create mode 100644 neovim/init.lua create mode 100644 neovim/lua/vimrc.lua create mode 100644 neovim/lua/vimrc/ansible.lua create mode 100644 neovim/lua/vimrc/azure.lua create mode 100644 neovim/lua/vimrc/buffers.lua create mode 100644 neovim/lua/vimrc/dap.lua create mode 100644 neovim/lua/vimrc/helm.lua create mode 100644 neovim/lua/vimrc/lsp.lua create mode 100644 neovim/lua/vimrc/snippets.lua create mode 100644 neovim/lua/vimrc/term.lua create mode 100644 neovim/lua/vimrc/terragrunt.lua create mode 100644 neovim/lua/vimrc/utils.lua diff --git a/home.nix b/home.nix index 9513602..f7905f7 100644 --- a/home.nix +++ b/home.nix @@ -66,40 +66,42 @@ programs.neovim = { enable = true; - package = unstable.neovim-unwrapped; + package = pkgs.neovim-unwrapped; viAlias = true; vimAlias = true; extraConfig = " - luafile ~/.config/nvim/user.lua + luafile neovim/init.lua "; plugins = with pkgs.vimPlugins; let - fetchPluginFromGit = name: ref: pkgs.vimUtils.buildVimPluginFrom2Nix { + fetchPluginFromGit = name: rev: pkgs.vimUtils.buildVimPluginFrom2Nix { name = name; src = builtins.fetchGit { url = "https://github.com/${name}"; submodules = true; - inherit ref; + inherit rev; }; }; in [ - (fetchPluginFromGit "LnL7/vim-nix" "HEAD") - (fetchPluginFromGit "tpope/vim-fugitive" "HEAD") - (fetchPluginFromGit "sainnhe/gruvbox-material" "HEAD") - (fetchPluginFromGit "nvim-treesitter/nvim-treesitter" "HEAD") - (fetchPluginFromGit "mvinkio/tnychain" "HEAD") - (fetchPluginFromGit "L3MON4D3/LuaSnip" "HEAD") - (fetchPluginFromGit "Furkanzmc/firvish.nvim" "HEAD") - (fetchPluginFromGit "folke/trouble.nvim" "HEAD") - (fetchPluginFromGit "klen/nvim-test" "HEAD") - (fetchPluginFromGit "neovim/nvim-lspconfig" "HEAD") - (fetchPluginFromGit "mfussenegger/nvim-dap" "HEAD") - (fetchPluginFromGit "rcarriga/nvim-dap-ui" "HEAD") - (fetchPluginFromGit "tjdevries/nlua.nvim" "HEAD") - (fetchPluginFromGit "jose-elias-alvarez/null-ls.nvim" "HEAD") - (fetchPluginFromGit "nvim-lua/plenary.nvim" "HEAD") - (fetchPluginFromGit "ray-x/lsp_signature.nvim" "HEAD") - (fetchPluginFromGit "justinmk/vim-dirvish" "HEAD") + vim-nix + vim-dirvish + nvim-dap + nvim-dap-ui + vim-fugitive + gruvbox-material + luasnip + nvim-lspconfig + trouble-nvim + nlua-nvim + null-ls-nvim + plenary-nvim + + (nvim-treesitter.withPlugins (_: pkgs.tree-sitter.allGrammars)) + + (fetchPluginFromGit "klen/nvim-test" "32f162c27045fc712664b9ddbd33d3c550cb2bfc") + (fetchPluginFromGit "mvinkio/tnychain" "cef72f688e67f40616db8ecf9d7c63e505c2dd23") + (fetchPluginFromGit "Furkanzmc/firvish.nvim" "127f9146175d6bbaff6a8b761081cfd2279f8351") + (fetchPluginFromGit "ray-x/lsp_signature.nvim" "137bfaa7c112cb058f8e999a8fb49363fae3a697") ]; }; } diff --git a/neovim/README.md b/neovim/README.md new file mode 100644 index 0000000..3a441bd --- /dev/null +++ b/neovim/README.md @@ -0,0 +1,2 @@ +# mike_neovim +installs my neovim config on mac or linux diff --git a/neovim/autoload/buffers.vim b/neovim/autoload/buffers.vim new file mode 100644 index 0000000..3fc7818 --- /dev/null +++ b/neovim/autoload/buffers.vim @@ -0,0 +1,98 @@ +" all taken from: https://github.com/Furkanzmc/dotfiles/tree/master/vim/autoload/buffers.vim +" Buffer related code from https://stackoverflow.com/a/4867969 +function! s:get_buflist() + return filter(range(1, bufnr('$')), 'buflisted(v:val)') +endfunction + +function! s:matching_buffers(pattern) + return filter(s:get_buflist(), 'bufname(v:val) =~ a:pattern') +endfunction + +function! s:cmd_line(mode, str) + call feedkeys(a:mode . a:str) +endfunction + +function! buffers#wipe_matching(pattern, bang) + if a:pattern == "*" + let l:matchList = s:get_buflist() + else + let l:matchList = s:matching_buffers(a:pattern) + endif + + let l:count = len(l:matchList) + if l:count < 1 + echohl WarningMsg + echo '[vimrc] No buffers found matching pattern "' . a:pattern . '"' + echohl Normal + return + endif + + if l:count == 1 + let l:suffix = '' + else + let l:suffix = 's' + endif + + if a:bang == "!" + exec 'bw! ' . join(l:matchList, ' ') + else + exec 'bw ' . join(l:matchList, ' ') + endif + + echohl IncSearch + echo '[vimrc] Wiped ' . l:count . ' buffer' . l:suffix . '.' + echohl Normal +endfunction + +function! buffers#wipe_nonexisting_files() + let l:matchList = filter(s:get_buflist(), + \ '!file_readable(bufname(v:val)) && !has_key(getbufinfo(v:val)[0].variables, "terminal_job_id") && getbufvar(v:val, "&buftype") != "nofile" && getbufvar(v:val, "&filetype") != "qf"') + + let l:count = len(l:matchList) + if l:count < 1 + return + endif + + if l:count == 1 + let l:suffix = '' + else + let l:suffix = 's' + endif + + exec 'bw! ' . join(l:matchList, ' ') + + echohl IncSearch + echo '[vimrc] Wiped ' . l:count . ' buffer' . l:suffix . '.' + echohl Normal +endfunction + +" Code taken from here: https://stackoverflow.com/a/6271254 +function! buffers#get_visual_selection() + let [l:line_start, l:column_start] = getpos("'<")[1:2] + let [l:line_end, l:column_end] = getpos("'>")[1:2] + let l:lines = getline(l:line_start, l:line_end) + if len(l:lines) == 0 + return l:lines + endif + + let l:lines[-1] = l:lines[-1][: l:column_end - (&selection == 'inclusive' ? 1 : 2)] + let l:lines[0] = l:lines[0][l:column_start - 1:] + return l:lines +endfunction + +function! buffers#visual_selection(direction, extra_filter) range + let l:saved_reg = @" + execute "normal! vgvy" + + let l:pattern = escape(@", "\\/.*'$^~[]") + let l:pattern = substitute(l:pattern, "\n$", "", "") + + if a:direction == 'search' + call s:cmd_line('/', l:pattern) + elseif a:direction == 'replace' + call s:cmd_line(':', "%s" . '/'. l:pattern . '/') + endif + + let @/ = l:pattern + let @" = l:saved_reg +endfunction diff --git a/neovim/autoload/reloadpackage.vim b/neovim/autoload/reloadpackage.vim new file mode 100644 index 0000000..f8a76a2 --- /dev/null +++ b/neovim/autoload/reloadpackage.vim @@ -0,0 +1,3 @@ +function reloadpackage#complete(arg_lead, cmd_line, cursor_pos) + return luaeval("require('vimrc').reload_package_complete('" . a:arg_lead . "', '" . a:cmd_line . "', '" . a:cursor_pos . "')") +endfunction diff --git a/neovim/init.lua b/neovim/init.lua new file mode 100644 index 0000000..542348c --- /dev/null +++ b/neovim/init.lua @@ -0,0 +1,293 @@ +-- general options {{{ +vim.opt.clipboard = {} +vim.api.nvim_set_keymap( + "n", + "s", + "Ysurround", + {silent=true,noremap=true} +) + +-- don't load standard plugins + +vim.g.loaded_2html_plugin = false +vim.g.loaded_fzf = false +vim.g.loaded_man = false +vim.g.loaded_gzip = false +vim.g.loaded_health = false +vim.g.loaded_matchit = false +vim.g.loaded_matchparen = false +vim.g.loaded_netrwPlugin = false +vim.g.loaded_rplugin = false +vim.g.loaded_shada = false +vim.g.loaded_spellfile = false +vim.g.loaded_tarPlugin = false +vim.g.loaded_tohtml = false +vim.g.loaded_tutor = false +vim.g.loaded_zipPlugin = false + +vim.cmd [[filetype plugin on]] +vim.cmd [[filetype indent on]] +vim.cmd [[colorscheme gruvbox-material]] +vim.cmd [[highlight WinSeparator guibg=None]] +vim.opt.laststatus = 3 +vim.opt.winbar = "%=%m %f" + + +vim.g.dirvish_mode = ':sort | sort ,^.*[^/]$, r' + +vim.opt.foldopen = "block,hor,jump,mark,percent,quickfix,search,tag" +vim.opt.complete = ".,w,k,kspell,b" +vim.opt.completeopt = "menuone,noselect" + + +vim.opt.secure = true +vim.opt.exrc = true + +-- relativenumbers and absolute number +vim.opt.relativenumber = true +vim.opt.number = true + +-- don't show previous search pattern +vim.opt.hlsearch = false + +-- don't free buffer memory when abandoned +vim.opt.hidden = true + +-- 1 tab == 4 spaces +vim.opt.tabstop = 4 +vim.opt.softtabstop = 4 +vim.opt.shiftwidth = 4 + +-- use spaces instead of tabs +vim.opt.expandtab = true + +vim.opt.smartindent = true +vim.opt.autoindent = true + +-- show special characters as listed +vim.opt.list = true +vim.opt.listchars = { tab = ' ', eol = "﬋" } +vim.opt.showbreak = '﬋' + +-- make pasting better but makes insert mappings stop working... +-- vim.opt.paste = true + +-- magic vim patterns +vim.opt.magic = true + +-- make splitting consistent +vim.opt.splitbelow = true + +vim.opt.wrap = false +vim.opt.swapfile = false +vim.opt.backup = false +vim.opt.undodir = os.getenv('HOME') .. "/.local/share/nvim/undo" +vim.opt.undofile = true +vim.opt.incsearch = true +vim.opt.termguicolors = true +vim.opt.scrolloff = 8 +vim.opt.smd = false +vim.opt.signcolumn = "yes" +vim.opt.inccommand = "split" +vim.opt.wmw = 10 +vim.opt.isfname:append("@-@") +vim.opt.diffopt:append("vertical") +vim.opt.shortmess:append("c") +vim.opt.shell = "/bin/zsh" +-- }}} + +-- load global and utility functions + +vim.g.mapleader = " " +vim.g.maplocalleader = " " +local vimrc = require('vimrc') +-- save session file in cwd +vimrc.cwd_save_session() + +-- tree-sitter {{{ +require('vimrc').setup_treesitter() +-- }}} + +-- {{{ git +vim.cmd([[command! -bang Gap :G commit -am 'fixmeuplater' | G push]]) +-- }}} + +-- completion {{{ +vim.api.nvim_set_keymap('n', ']p', ':tabn', { silent = true, noremap = true}) +vim.api.nvim_set_keymap('n', '[p', ':tabp', { silent = true, noremap = true}) + +require'tnychain'.setup( + { + complete_key = '', + repeat_chain = '' + } +) + +-- require'vimrc.snippets'.setup() + +-- }}} + +-- buffers {{{ +vim.opt.switchbuf = "useopen,usetab" +vim.opt.stal = 2 + +vim.api.nvim_set_keymap( + "n", + ";", + "", + { silent = true, noremap = true } +) + +-- taken from: https://github.com/Furkanzmc/dotfiles/blob/master/vim/init.lua +-- searching and replacing in buffers +vim.api.nvim_set_keymap( + "v", + "s", + ":call buffers#visual_selection('search', '')", + { silent = true, noremap = true } +) +vim.api.nvim_set_keymap( + "v", + "r", + ":call buffers#visual_selection('replace', '')", + { silent = true, noremap = true } +) +vim.cmd([[command -nargs=1 -complete=file E execute('silent! !mkdir -p "$(dirname "")"') e ]]) +-- wiping buffers and wiping nofile-buffers +vim.cmd([[command! -nargs=1 -bang Bdeletes :call buffers#wipe_matching('', )]]) +vim.cmd([[command! Bdnonexisting :call buffers#wipe_nonexisting_files()]]) + +vim.cmd([[command! CleanTrailingWhiteSpace :lua require"vimrc.buffers".clean_trailing_spaces()]]) + +vim.cmd([[augroup vimrc_plugin_buffers]]) +vim.cmd([[au!]]) +vim.cmd( + [[autocmd BufWritePre *.md,*.hcl,*.tf,*.py,*.cpp,*.qml,*.js,*.txt,*.json,*.html,*.lua,*.yaml,*.yml,*.bash,*.sh,*.go :lua require"vimrc.buffers".clean_trailing_spaces()]] +) +vim.cmd( + [[autocmd BufReadPost * lua require"vimrc.buffers".setup_white_space_highlight(vim.fn.bufnr())]] +) +vim.cmd( + [[autocmd BufReadPre *.tf,*.hcl packadd vim-terraform]] +) +vim.cmd([[augroup END]]) + +-- }}} + +-- quickfix {{{ +vim.api.nvim_set_keymap( + "n", + "o", + ":copen", + { silent = true, noremap = true } +) +vim.api.nvim_set_keymap( + "n", + "z", + ":cclose", + { silent = true, noremap = true } +) + +vim.api.nvim_set_keymap( + "n", + "lo", + ":lopen", + { silent = true, noremap = true } +) +vim.api.nvim_set_keymap( + "n", + "lz", + ":lclose", + { silent = true, noremap = true } +) +vim.api.nvim_set_keymap("n", "]q", ":cnext", { silent = true, noremap = true }) +vim.api.nvim_set_keymap("n", "[q", ":cprevious", { silent = true, noremap = true }) +vim.api.nvim_set_keymap("n", "]Q", ":cfirst", { silent = true, noremap = true }) +vim.api.nvim_set_keymap("n", "[Q", ":clast", { silent = true, noremap = true }) +vim.api.nvim_set_keymap("n", "]l", ":lnext", { silent = true, noremap = true }) +vim.api.nvim_set_keymap("n", "[l", ":lprevious", { silent = true, noremap = true }) +vim.api.nvim_set_keymap("n", "]L", ":lfirst", { silent = true, noremap = true }) +vim.api.nvim_set_keymap("n", "[L", ":llast", { silent = true, noremap = true }) +-- }}} + +-- firvish {{{ +require'firvish'.setup() +vim.g.firvish_use_default_mappings=1 +require'vimrc'.setup_jq_function() +require'vimrc'.setup_build_function() +-- }}} + +-- {{{ trouble +require"trouble".setup { } +-- }}} + +-- {{{ tests +require"nvim-test".setup{} +vim.api.nvim_set_keymap( + "n", + "t", + "TestFile", + {silent = true, noremap = true} +) +-- }}} + +-- lsp {{{ +vim.cmd [[augroup vimrc_nvim_lsp_setup]] +vim.cmd [[au!]] +vim.cmd [[au VimEnter * lua require'vimrc.lsp'.setup()]] +vim.cmd [[augroup END]] +-- }}} + +-- dap {{{ +vim.cmd [[augroup vimrc_nvim_dap_setup]] +vim.cmd [[au!]] +vim.cmd [[au VimEnter * lua require('vimrc.dap').setup_dap()]] +vim.cmd [[augroup END]] +-- }}} + +-- terminal {{{ +-- open close terminal +vim.cmd [[command! Term :lua require('vimrc.term').toggle()]] +-- run current file +vim.cmd [[command! Run :lua require('vimrc.term').run()]] +-- send selection +vim.cmd [[command! -range Send :lua require('vimrc.term').sendSelection()]] +vim.api.nvim_set_keymap( + "t", + "", + "", + { silent = true, noremap = true } +) +-- }}} + +-- statusline {{{ +-- require('el').setup {} +-- TODO: move to colortemplates +vim.cmd [[hi! link Winbar StatusLine]] +-- }}} + +-- init autocommand {{{ +vim.cmd([[augroup vimrc_init]]) +vim.cmd([[autocmd!]]) +vim.cmd( + [[autocmd BufReadPre,FileReadPre *.rest :if !exists("g:vimrc_rest_nvim_loaded") | packadd vim-rest-console | let g:vimrc_rest_nvim_loaded = v:true | endif | :e]] +) +vim.cmd( + [[autocmd TextYankPost * silent! lua vim.highlight.on_yank{on_visual=false, higroup="IncSearch", timeout=100}]] +) +vim.cmd( + [[ autocmd TextYankPost * if v:event.operator is 'y' && v:event.regname is '' | execute 'OSCYankReg "' | endif ]] +) +vim.cmd( + [[autocmd VimEnter * if filereadable(".exrc.lua") | call execute("luafile .exrc.lua") | endif]] +) +vim.cmd( + [[autocmd VimEnter * if filereadable(".env") | echo execute("Dotenv") | call execute("Dotenv .env") | endif]] +) +-- temp fix for screen redrawing issues +-- cmd( +-- [[autocmd BufEnter * mod]] +-- ) +vim.cmd([[augroup END]]) +-- }}} +-- vim: fdm=marker diff --git a/neovim/lua/vimrc.lua b/neovim/lua/vimrc.lua new file mode 100644 index 0000000..fc40e80 --- /dev/null +++ b/neovim/lua/vimrc.lua @@ -0,0 +1,211 @@ +-- vim: fdm=marker +local log_warning = require 'vimrc.utils'.log_warning +local M = {} + +M.cwd_save_session = function() + vim.cmd([[ +augroup vimrc_save_session + au! + au VimLeave * mksession! ]] .. os.getenv("PWD") .. [[/Session.vim +augroup end + ]]) +end + +function M.setup_treesitter() + if vim.o.loadplugins == false then + return + end + + assert(vim.fn.exists(":TSInstall") == 0, "TreeSitter is already configured.") + + -- vim.cmd([[packadd nvim-treesitter]]) + require 'nvim-treesitter.configs'.setup { + highlight = { + enable = true, + -- Setting this to true will run `:h syntax` and tree-sitter at the same time. + -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation). + -- Using this option may slow down your editor, and you may see some duplicate highlights. + -- Instead of true it can also be a list of languages + }, + } +end + +function M.setup_rest_nvim() + require("rest-nvim").setup({ + result_split_horizontal = true, + skip_ssl_verification = false, + highlight = { enabled = true, timeout = 150 }, + jump_to_request = false, + }) + + local map = vim.api.nvim_set_keymap + map( + "n", + "tt", + "RestNvim", + { silent = true } + ) + map( + "n", + "tp", + "RestNvimPreview", + { silent = true } + ) +end + +local jq_functions = {} +function M.setup_jq_function() + jq_functions.filter_jq = function(path, first, last) + P(path) + local buf = vim.api.nvim_get_current_buf() + first, last = tonumber(first), tonumber(last) + first = first - 1 + local json_string = table.concat(vim.api.nvim_buf_get_lines(buf, first, last, true)) + local tmp = os.tmpname() + local f = io.open(tmp, "w") + if f then + f:write(json_string) + f:close() + else + return false + end + local cmd = { + "/bin/sh", + "-c", + [[cat ]] .. tmp .. [[ | jq ']] .. path .. [[']] + } + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "json", + title = "jq", + listed = true, + output_qf = false, + is_background_job = false, + }) + end + _G.jq_functions = jq_functions + vim.cmd [[command! -nargs=* -range FJq :lua _G.jq_functions.filter_jq('', "", "")]] +end + +local build_functions = {} +function M.setup_build_function() + build_functions.rebuild = function() + local cmd = { "rebuild" } + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "job-output", + title = "rebuild", + listed = true, + output_qf = true, + is_background_job = true, + }) + end + _G.build_functions = build_functions + vim.cmd [[command! Rebuild :lua _G.build_functions.rebuild()]] + + build_functions.azure_yaml = function(file) + local cwd = os.getenv('PWD') + local auth = os.getenv('AZURE_DEVOPS_AUTH') + local ado_org = os.getenv('AZURE_DEVOPS_ORG') + local ado_proj = os.getenv('AZURE_DEVOPS_PROJECT') + local pipeline = os.getenv('AZURE_YAML_DEFINITION_ID') + local branch = os.getenv('AZURE_YAML_BRANCH') + + local url = [[https://dev.azure.com/]] .. ado_org .. [[/]] .. ado_proj .. [[/_apis/pipelines/]] .. pipeline .. [[/preview?api-version=7.1-preview.1]] + local auth_header = [[Authorization: Basic ]] .. auth + local yaml_file = cwd .. "/" .. file + + local shell_script = string.format( +[[yaml_string=" +$(cat ${PWD}/${AZURE_YAML_DEBUG_SNIPPET}) +$(cat %s) +" +yaml_string="$(echo "$yaml_string" | yq '... style="single"' - | sed -re /\s*\#.*$/d)" +curl -s -X POST '%s' -H 'Content-Type: application/json' -H '%s' --data-binary @- << THEEND | jq '.finalYaml // .' | yq '... style="double"' - +{ + "previewRun":true, + "templateParameters": {}, + "resources": { + "repositories": { + "self": { + "refName": "refs/heads/%s" + } + } + }, + "yamlOverride":"$yaml_string" +} +THEEND]], + yaml_file, url, auth_header, branch, branch + ) + local cmd = { + "/bin/bash", "-c", shell_script + } + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "yaml", + title = "azureyaml", + use_last_buffer = false, + listed = true, + output_qf = true, + is_background_job = false, + cwd = cwd + }) + end + vim.cmd [[command! -nargs=1 -complete=file AzureYaml :lua _G.build_functions.azure_yaml("")]] +end + +-- {{{ global lua debugging +_G.P = function(arg) + print(vim.inspect(arg)) +end + +M.reload_package_complete = function(_, _, _) + -- arg_lead, cmd_line, cursor_pos + -- TODO: implement completion based on loaded packages + return 'hi' +end + +M.reload_package = function(name) + P([[name=]] .. name) + if package.loaded[name] == nil then + log_warning("Package not loaded.", "[vimrc]") + return + end + package.loaded[name] = nil + return require(name) +end + +vim.cmd( + [[command! -complete=custom,reloadpackage#complete -nargs=1 LuaReload :lua require('vimrc').reload_package()]] +) + +M.activate_reload_on_write = function(name) + vim.cmd([[augroup package_reload_]] .. name) + vim.cmd([[au!]]) + vim.cmd([[au BufWritePost ]] + .. string.format([[:lua require('vimrc').reload_package('%s')]], name)) + vim.cmd([[augroup END]]) +end + +vim.cmd( + [[command! -complete=custom,reloadpackage#complete -nargs=1 ActivateReload :lua require('vimrc').activate_reload_on_write()]] +) + +-- }}} +-- {{{ syntax tools +M.print_synstack_at = function(line, col) + local syn = vim.fn.synstack(line, col) + for _, id in pairs(syn) do + P(vim.fn.synIDattr(id, 'name')) + end +end + +vim.cmd( + string.format("command! SyntaxInspect :lua require('vimrc').print_synstack_at(%s, %s)", + vim.fn.line("."), + vim.fn.col(".") + ) +) +-- }}} + +return M diff --git a/neovim/lua/vimrc/ansible.lua b/neovim/lua/vimrc/ansible.lua new file mode 100644 index 0000000..4dfeee9 --- /dev/null +++ b/neovim/lua/vimrc/ansible.lua @@ -0,0 +1,195 @@ +local vim = vim +local cmd = vim.cmd +local fn = vim.fn + +local M = {} +function M.setup(opts) + P(opts) + local home = os.getenv('HOME') + local user = os.getenv('USER') + assert(opts.cwd, "cwd is required. ") + assert(opts.inventory, "inventory is required. ") + -- This needs to be built on the machine you use it due to requiring the user to be present in the /etc/passwd table. + local functions = {} + local secrets_exist = fn.filereadable(fn.expand(opts.vault_file)) == 1 + local vars_files = "" + if secrets_exist then + vars_files = vars_files .. [[ + vars_files: + - ]] .. opts.vault_file .. "\n" + end + functions.ansible_dump = function(output_qf) + local cmd = { + "docker", + "run", + "--interactive", + "--rm", + "--network=host", + "--user=" .. user, + "-e", + "HOME=" .. home, + "--volume=" .. home .. ":" .. home, + "--workdir=" .. opts.cwd, + "mvinkio/ansible", + "/bin/bash", + "-c", +[[cat < dev-plabook.yaml +--- +- name: dump all + hosts: all +]] +.. +vars_files +.. +[[ + tasks: + - name: Print vars + debug: + var: vars + - name: Print environment + debug: + var: environment + - name: Print group_names + debug: + var: group_names + - name: Print groups + debug: + var: groups + - name: Print hostvars +/ debug: + var: hostvars +EOF]] .. +"\n ansible-playbook -vvv -i " .. opts.inventory .. " dev-plabook.yaml " + } + P(cmd) + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "dump", + listed = true, + output_qf = false, + is_background_job = false, + }) + end + + functions.ansible_run = function (playbook, debug) + P(playbook) + P(debug) + local set_debug = "" + if debug then + set_debug = "ANSIBLE_ENABLE_TASK_DEBUGGER=True" + end + local run_cmd = set_debug .. + [[ ansible-playbook ]] .. + [[-v ]] .. + [[-i ]] .. opts.inventory .. [[ ]] .. + playbook + local job_cmd = { + "docker", + "run", + "--interactive", + "--rm", + "--network=host", + "--user=" .. user, + "-e", "HOME=" .. home, + "-e", "USER=" .. user, + "--volume=" .. home .. ":" .. home, + "--workdir=" .. opts.cwd, + "mvinkio/ansible", + "/bin/bash", + "-c", + run_cmd + } + local interactive_cmd = { + "docker", + "run", + "--interactive", + "--tty", + "--rm", + "--network=host", + "--user=" .. user, + "-e", + "HOME=" .. home, + "-e", + "USER=" .. user, + "--volume=" .. home .. ":" .. home, + "--workdir=" .. opts.cwd, + "mvinkio/ansible", + "/bin/bash", + "-c" + } + if not debug then + P(job_cmd) + require('firvish.job_control').start_job({ + cmd = job_cmd, + filetype = "log", + title = "ansiblejob", + listed = true, + output_qf = false, + is_background_job = false, + }) + else + local term_cmd = [[sp | term /bin/bash -c ']] .. table.concat(interactive_cmd, ' ') .. [[ "]] .. run_cmd .. [["']] + P(term_cmd) + vim.cmd(term_cmd) + end + end + + functions.install_requirements = function (bang) + local cmd = { + "docker", + "run", + "--interactive", + "--rm", + "--network=host", + "--user=" .. user, + "-e", "HOME=" .. home, + "--volume=" .. home .. ":" .. home, + "--workdir=" .. opts.cwd, + "mvinkio/ansible", + "/bin/bash", + "-c", + "ansible-galaxy install -r " .. opts.ansible_galaxy_requirements + } + P(cmd) + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "ansiblejob", + listed = true, + output_qf = false, + is_background_job = false, + }) + end + + functions.ansible_session = function (bang) + local interactive_cmd = { + "docker", + "run", + "--interactive", + "--tty", + "--rm", + "--network=host", + "--user=" .. user, + "-e", + "USER=" .. user, + "-e", + "HOME=" .. home, + "--volume=" .. home .. ":" .. home, + "--workdir=" .. opts.cwd, + "mvinkio/ansible", + "/bin/bash" + } + local term_cmd = [[sp | term ]] .. table.concat(interactive_cmd, ' ') + P(term_cmd) + vim.cmd(term_cmd) + end + + _G.ansible_functions = functions + cmd [[command! -bang AnsibleBug :lua _G.ansible_functions.ansible_dump("" ~= "!")]] + cmd [[command! -complete=file -nargs=1 -bang AnsiblePlaybook :lua _G.ansible_functions.ansible_run("", "" == "!")]] + cmd [[command! -bang AnsibleGalaxyRequirements :lua _G.ansible_functions.install_requirements("" ~= "!")]] + cmd [[command! -bang AnsibleSession :lua _G.ansible_functions.ansible_session("" ~= "!")]] + +end +return M diff --git a/neovim/lua/vimrc/azure.lua b/neovim/lua/vimrc/azure.lua new file mode 100644 index 0000000..9b6b245 --- /dev/null +++ b/neovim/lua/vimrc/azure.lua @@ -0,0 +1,39 @@ +local M = {} + +function M.setup(opts) + -- assert(opts.org_url, "org url is required. ") + -- assert(opts.pipeline_id, "pipeline id is required. ") + -- assert(opts.api_version, "api version is required. ") + -- assert(opts.basic_auth_token, "basic auth token is required. ") + + -- local functions = {} + -- functions.pipeline_bug = function(output_qf) + -- local cmd = { + -- "/bin/sh", + -- "-c", + -- [[curl -sSL --compressed -X POST -H ]] .. + -- [['Authorization: Basic ]] .. opts.basic_auth_token .. [[' ]] .. + -- [[-H 'Content-Type: application/json' ]] .. + -- [[--data-raw "{ \"previewRun\": true }" ]] .. + -- opts.org_url .. "/_apis/pipelines/" .. opts.pipeline_id .. "/preview?api-version=" .. opts.api_version .. + -- " | jq .finalYaml | xargs -0 printf %b | sed -e 's@^\"@@' -e 's@\"$@@'" + -- } + -- P(cmd) + -- require('firvish.job_control').start_job({ + -- cmd = cmd, + -- filetype = "log", + -- title = "pipeline", + -- listed = true, + -- output_qf = output_qf, + -- is_background_job = false, + -- cwd = opts.chart_dir, + -- }) + -- end + + -- _G.azure_functions = functions + + -- cmd [[command! -bang PipelineBug :lua _G.azure_functions.pipeline_bug("" ~= "!")]] + +end + +return M diff --git a/neovim/lua/vimrc/buffers.lua b/neovim/lua/vimrc/buffers.lua new file mode 100644 index 0000000..f185b6f --- /dev/null +++ b/neovim/lua/vimrc/buffers.lua @@ -0,0 +1,35 @@ +local M = {} + +function M.clean_trailing_spaces() + + local save_cursor = vim.fn.getpos(".") + local old_query = vim.fn.getreg("/") + vim.cmd [[%s/\s\+$//e]] + + vim.fn.setpos(".", save_cursor) + vim.fn.setreg("/", old_query) +end + +function M.setup_white_space_highlight(bufnr) + if vim.b.vimrc_trailing_white_space_highlight_enabled then + return + end + + -- if options.get_option_value("trailingwhitespacehighlight", bufnr) == false then + -- return + -- end + + vim.cmd([[highlight link TrailingWhiteSpace Error]]) + vim.cmd([[highlight NonText ctermfg=7 guifg=gray]]) + + vim.cmd("augroup vimrc_trailing_white_space_highlight_buffer_" .. bufnr) + vim.cmd([[autocmd! * ]]) + vim.cmd([[autocmd BufReadPost match TrailingWhiteSpace /\s\+$/]]) + vim.cmd([[autocmd InsertEnter match TrailingWhiteSpace /\s\+\%#\@ match TrailingWhiteSpace /\s\+$/]]) + vim.cmd([[augroup END]]) + + vim.b.vimrc_trailing_white_space_highlight_enabled = true +end + +return M diff --git a/neovim/lua/vimrc/dap.lua b/neovim/lua/vimrc/dap.lua new file mode 100644 index 0000000..313e043 --- /dev/null +++ b/neovim/lua/vimrc/dap.lua @@ -0,0 +1,266 @@ +local vim = vim +local cmd = vim.cmd +local api = vim.api +local M = {} + +local function register_debug_adapters(cwd) + local dap = require 'dap' + local python_args = { + "run", + "--rm", + "--volume=/var/run/docker.sock:/var/run/docker.sock", + "--interactive", + "--env-file=" .. cwd .. "/.env", + "--volume", cwd .. ":" .. cwd, + "--network=host", + "mvinkio/python", + "python", "-m", "debugpy.adapter" + } + dap.adapters.python = { + type = 'executable', + command = "docker", + args = python_args, + } + + dap.adapters.go = function(callback, _) + -- _ config + local stdout = vim.loop.new_pipe(false) + local stderr = vim.loop.new_pipe(false) + local handle + local pid_or_err + local port = 38697 + + -- "docker", + -- "run", + -- "--rm", + -- "--interactive", + -- "-e=GOPROXY=https://proxy.golang.org", + -- "-e=GOOS=linux", + -- "-e=GOARCH=amd64", + -- "-e=GOPATH=" .. new_root_dir .. "/go", + -- "-e=GOCACHE=" .. new_root_dir .. "/.cache/go-build", + -- "--workdir=" .. new_root_dir, + -- "--volume=" .. new_root_dir .. ":" .. new_root_dir, + -- "--network=bridge", + -- "mvinkio/go", + -- "gopls" + local opts = { + stdio = { nil, stdout }, + args = { "run", + "-i", "--rm", + "--security-opt=seccomp:unconfined", + "--volume=/var/run/docker.sock:/var/run/docker.sock", + "--env-file=" .. cwd .. "/.env", + "-e=GOPROXY=https://proxy.golang.org", + "-e=GOOS=linux", + "-e=GOARCH=amd64", + "-e=GOPATH=" .. cwd .. "/go", + "-e=GOCACHE=" .. cwd .. "/.cache/go-build", + "-v", cwd .. ":" .. cwd, -- TODO: use os.getenv here + "-w", cwd, -- TODO: use find root here + "--network", "host", + "mvinkio/go", + "dlv", "dap", "-l", "127.0.0.1:" .. port, + "--only-same-user=false", + "--log", + }, + detached = false + } + handle, pid_or_err = vim.loop.spawn("docker", opts, function(code) + stdout:close() + stderr:close() + handle:close() + if code ~= 0 then + print('dlv exited with code', code) + end + end) + assert(handle, 'Error running dlv: ' .. tostring(pid_or_err)) + stdout:read_start(function(err, chunk) + assert(not err, err) + if chunk then + P(chunk) + vim.schedule(function() + require('dap.repl').append(chunk) + end) + end + end) + stderr:read_start(function(err, chunk) + assert(not err, err) + if chunk then + P(chunk) + end + end) + -- Wait for delve to start + vim.defer_fn( + function() + callback({ type = "server", host = "127.0.0.1", port = port }) + end, + 2000) + end + +end + +local function set_configurations() + local dap = require 'dap' + dap.configurations.python = { + { + -- The first three options are required by nvim-dap + type = 'python'; -- the type here established the link to the adapter definition: `dap.adapters.python` + request = 'launch'; + name = "Launch file"; + + -- Options below are for debugpy, see https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings for supported options + + program = "${file}"; -- This configuration will launch the current file if used. + -- TODO: use container for python interpreter + -- pythonPath = function() + -- -- debugpy supports launching an application with a different interpreter then the one used to launch debugpy itself. + -- -- The code below looks for a `venv` or `.venv` folder in the current directly and uses the python within. + -- -- You could adapt this - to for example use the `VIRTUAL_ENV` environment variable. + -- local cwd = vim.fn.getcwd() + -- if vim.fn.executable(cwd .. '/venv/bin/python') == 1 then + -- return cwd .. '/venv/bin/python' + -- elseif vim.fn.executable(cwd .. '/.venv/bin/python') == 1 then + -- return cwd .. '/.venv/bin/python' + -- else + -- return '/usr/bin/python' + -- end + -- end; + }, + } + + -- docker run --rm -i -v /home/mike:/home/mike --network=host -w /home/mike/projects/example/hello mvinkio/godap dap -l 127.0.0.1:38697 --log --log-output="dap" --only-same-user=false + + dap.configurations.go = { + { + type = "go", + name = "Debug", + request = "launch", + program = "${file}" + }, + { + type = "go", + name = "Debug test", -- configuration for debugging test files + request = "launch", + mode = "test", + program = vim.fn.fnamemodify(vim.fn.expand('%'),':p:h') + }, + -- works with go.mod packages and sub packages + { + type = "go", + name = "Debug test (go.mod)", + request = "launch", + mode = "test", + program = "./${relativeFileDirname}" + } + } + local set_go_keymaps = function() + vim.keymap.set( + "n", + "df", + [[lua require'vimrc.dap'.continue(require'dap'.configurations.go[1])]], + { noremap = true } + ) + vim.keymap.set( + "n", + "df", + [[lua require'vimrc.dap'.continue(require'dap'.configurations.go[1])]], + { noremap = true } + ) + end + local augroup = api.nvim_create_augroup("vimrc_go_dap_config", { clear = true }) + api.nvim_create_autocmd("FileType", { pattern = "go", callback = set_go_keymaps, group = augroup }) + +end + +local function set_keymaps() + local map = vim.api.nvim_set_keymap + -- taken from: https://github.com/Furkanzmc/dotfiles/blob/master/vim/lua/vimrc/dap.lua + -- version: 9561e7c700e0ffe74cf9fd61a0e4543ae14938c6 + map("n", "dc", ":lua require'vimrc.dap'.continue()", { silent = true, noremap = true }) + map("n", "dt", ":lua require'dap'.close()", { silent = true, noremap = true }) + map("n", "ds", ":lua require'dap'.step_into()", { silent = true, noremap = true }) + + map("n", "dk", ":lua require('dapui').eval()", { silent = true, noremap = true }) + map("v", "dk", ":lua require('dapui').eval()", { silent = true, noremap = true }) + map("n", "do", ":lua require'dap'.step_out()", { silent = true, noremap = true }) + + map("n", "dn", ":lua require'dap'.step_over()", { silent = true, noremap = true }) + map("n", "du", ":lua require'dap'.up()", { silent = true, noremap = true }) + map("n", "dd", ":lua require'dap'.down()", { silent = true, noremap = true }) + + map( + "n", + "db", + ":lua require'dap'.toggle_breakpoint()", + { silent = true, noremap = true } + ) + map( + "n", + "dbc", + ":lua require'dap'.set_breakpoint(vim.fn.input('Breakpoint condition: '))", + { silent = true, noremap = true } + ) + map( + "n", + "dbl", + ":lua require'dap'.set_breakpoint(nil, nil, vim.fn.input('Log point message: '))", + { silent = true, noremap = true } + ) + + map("n", "dui", ":lua require'dapui'.toggle()", { silent = true, noremap = true }) + map("n", "dr", ":lua require'dap'.run_to_cursor()", { silent = true, noremap = true }) + map( + "n", + "dl", + ":lua require'dap'.list_breakpoints(true)", + { silent = true, noremap = true } + ) + -- map( + -- "n", + -- "dp", + -- ":lua require'dap.ui.variables'.scopes()", + -- { silent = true, noremap = true } + -- ) +end + +local function set_commands() + cmd([[command! DapUIOpen :lua require'dapui'.open()]]) + cmd([[command! DapUIClose :lua require'dapui'.close()]]) +end + +function M.continue(config) + local dap = require 'dap' + register_debug_adapters(vim.fn.getcwd()) + set_configurations() + if config then + dap.run(config) + else + dap.continue() + end +end + +function M.setup_dap() + if vim.o.loadplugins == false then + return + end + + cmd([[packadd nvim-dap]]) + cmd([[packadd nvim-dap-ui]]) + + local vim_startup_dir = vim.fn.getcwd() + register_debug_adapters(vim_startup_dir) + set_configurations() + + cmd [[augroup vimrc_dap]] + cmd [[au!]] + cmd [[au FileType dap-repl lua require('dap.ext.autocompl').attach()]] + cmd [[augroup END]] + + -- Commands and keymaps + require('dapui').setup() + set_keymaps() + set_commands() +end + +return M diff --git a/neovim/lua/vimrc/helm.lua b/neovim/lua/vimrc/helm.lua new file mode 100644 index 0000000..5597759 --- /dev/null +++ b/neovim/lua/vimrc/helm.lua @@ -0,0 +1,129 @@ +local vim = vim +local cmd = vim.cmd +local fn = vim.fn + +local M = {} +function M.setup(opts) + assert(opts.release_name, "release name is required. ") + assert(opts.chart_dir, "chartdir is required. ") + assert(opts.docker_dir, "docker_dir is required. ") + assert(opts.docker_tag, "docker_tag is required. ") + + local values_files = opts.values_files or {} + local values_sets = opts.values_sets or {} + local cluster = opts.cluster or "so" + + local dependency_update = "" + if opts.dependency_update then + dependency_update = "--dependency-update" + end + + table.insert(values_sets, "envshort=" .. cluster) + table.insert(values_sets, "cluster=" .. cluster) + table.insert(values_sets, "clusterHost=" .. cluster .. ".stater.com") + + local functions = {} + functions.helm_upgrade = function(output_qf) + local cmd = { + "helm", + "upgrade", + "--install", + "--values", + string.join(values_files, ","), + opts.release_name, + "." + } + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "upgrade", + listed = true, + output_qf = output_qf, + is_background_job = true, + cwd = opts.chart_dir, + }) + end + + functions.helm_delete = function(output_qf) + require('firvish.job_control').start_job({ + cmd = { + "helm", + "delete", + opts.release_name, + }, + filetype = "log", + title = "delete", + listed = true, + output_qf = output_qf, + is_background_job = true, + cwd = opts.chart_dir, + }) + end + + functions.helm_build = function(output_qf) + local cmd = { + "/bin/sh", + "-c", + string.format( + [[if docker build -t %s %s && ]] .. + [[docker push %s ; then ]] .. + [[helm delete %s ; ]] .. + [[helm upgrade --install %s --values %s --set %s %s . ; fi]], + opts.docker_tag, + opts.docker_dir, + opts.docker_tag, + opts.release_name, + dependency_update, + string.join(values_files, ","), + string.join(values_sets, ","), + opts.release_name + ) + } + P(cmd) + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "delete", + listed = true, + output_qf = output_qf, + is_background_job = true, + cwd = opts.chart_dir, + }) + end + + functions.helm_debug = function(update_remote) + local cmd = { + "helm", + "template", + "--debug", + "--values", + string.join(values_files, ","), + "--set", + string.join(values_sets, ","), + opts.release_name, + "." + } + P(cmd) + if update_remote then + table.insert(cmd, 3, "--dependency-update") + end + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "delete", + listed = true, + output_qf = false, + is_background_job = false, + cwd = opts.chart_dir, + }) + end + + _G.helm_functions = functions + cmd [[command! -bang HelmPut :lua _G.helm_functions.helm_upgrade("" ~= "!")]] + cmd [[command! -bang HelmDelete :lua _G.helm_functions.helm_delete("" ~= "!")]] + + cmd [[command! -bang HelmBuild :lua _G.helm_functions.helm_build("" ~= "!")]] + cmd [[command! -bang HelmBug :lua _G.helm_functions.helm_debug("" ~= "!")]] + +end +return M diff --git a/neovim/lua/vimrc/lsp.lua b/neovim/lua/vimrc/lsp.lua new file mode 100644 index 0000000..94a2cc2 --- /dev/null +++ b/neovim/lua/vimrc/lsp.lua @@ -0,0 +1,322 @@ +local utils = require 'vimrc.utils' +local M = {} + +-- TODO: parameterise +-- TODO: extend stuff later + +M.client_log = {} + +-- local functions {{{ +local function on_publish_diagnostics(_, result, ctx, config) + vim.lsp.diagnostic.on_publish_diagnostics(_, result, ctx, config) + vim.diagnostic.setloclist({ + open = false + }) +end + +local function setup_handlers(client, _) + client.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(on_publish_diagnostics, { + virtual_text = false, + underline = true, + update_in_insert = false, + severity_sort = true + }) +end + +local function setup_server_capabilities_maps(client, bufnr) + local map = vim.api.nvim_buf_set_keymap + local opts = { silent = true, noremap = true } + local capabilities = client.server_capabilities + + if capabilities.completion ~= false then + vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc") + end + + if capabilities.hover ~= false then + vim.api.nvim_buf_set_option(bufnr, "keywordprg", ":LspHover") + end + + if capabilities.rename == true then + map(bufnr, "n", "gr", "lua vim.lsp.buf.rename()", opts) + end + + if capabilities.signature_help == true then + map(bufnr, "n", "gs", "lua vim.lsp.buf.signature_help()", opts) + end + + if capabilities.goto_definition ~= false then + map(bufnr, "n", "gd", "lua vim.lsp.buf.definition()", opts) + end + + if capabilities.declaration == true then + map(bufnr, "n", "gD", "lua vim.lsp.buf.declaration()", opts) + end + + if capabilities.implementation == true then + map(bufnr, "n", "gi", "lua vim.lsp.buf.implementation()", opts) + end + + if capabilities.find_references ~= false then + map(bufnr, "n", "gg", "lua vim.lsp.buf.references()", opts) + end + + map(bufnr, "n", "ge", "lua require'vimrc.lsp'.line_diagnostic()", opts) + + if capabilities.document_symbol ~= false then + map(bufnr, "n", "gds", "lua vim.lsp.buf.document_symbol()", opts) + end + + if capabilities.workspace_symbol ~= true then + map(bufnr, "n", "gw", "lua vim.lsp.buf.workspace_symbol()", opts) + end + + if capabilities.code_action ~= false then + map(bufnr, "n", "ga", "lua vim.lsp.buf.code_action()", opts) + end + + if capabilities.documentFormattingProvider == true then + vim.api.nvim_buf_set_option(bufnr, "formatexpr", "v:lua.vim.lsp.format()") + map(bufnr, "n", "gq", "lua vim.lsp.buf.format({ async = true })", opts) + end + + if capabilities.document_range_formatting == true then + map(bufnr, "v", "gq", "lua vim.lsp.buf.range_formatting()", opts) + end + + if capabilities.hover ~= false then + vim.api.nvim_command("command! -buffer -nargs=1 LspHover lua vim.lsp.buf.hover()") + end +end + +-- }}} + +-- diagnostics {{{ +function M.line_diagnostic() + local line = vim.fn.line('.') - 1 + local diags = vim.diagnostic.get(0, { + lnum = line + }) + for _, diag in ipairs(diags) do + utils.log_warning(diag.message, diag.source) + end +end + +-- }}} + +-- setup {{{ +function M.setup() + + local buffer_setup = function(client) + table.insert(M.client_log, client) + local bufnr = vim.api.nvim_get_current_buf() + + setup_server_capabilities_maps(client, bufnr) + setup_handlers(client, bufnr) + require("lsp_signature").on_attach({ + bind = true, + floating_window = false, + toggle_key = "", + extra_trigger_chars = { "{", "}" }, + hint_prefix = "@ ", + check_pumvisible = false + }, bufnr) + end + + local buffer_setup_no_format = function(client) + client.server_capabilities.document_formatting = false + buffer_setup(client) + end + + -- lspconfig {{{ + local lspconfig = require 'lspconfig' + -- check if docker is executable first? + local runtime_path = vim.split(package.path, ';') + table.insert(runtime_path, "lua/?.lua") + table.insert(runtime_path, "lua/?/init.lua") + + -- always load lua lsp + require('nlua.lsp.nvim').setup(require('lspconfig'), { + cmd = { "/lsp/bin/lua-language-server", "-E", "/lsp/main.lua" }, + on_attach = buffer_setup_no_format, + + -- Include globals you want to tell the LSP are real :) + globals = { + -- Colorbuddy + "Color", "c", "Group", "g", "s", + } + }) + + -- lspconfig.sumneko_lua.setup { + -- filetypes = { "lua" }, + -- on_attach = buffer_setup_no_format, + -- settings = { + -- Lua = { + -- completion = { + -- keywordSnippet = "Disable", + -- showWord = "Disable", + -- }, + -- diagnostics = { + -- enable = true, + -- globals = vim.list_extend({ + -- -- Neovim + -- "vim", + -- -- Busted + -- "describe", "it", "before_each", "after_each", "teardown", "pending", "clear" + -- }, {}) + -- }, + -- runtime = { + -- version = "LuaJIT", + -- }, + -- workspace = { + -- vim.list_extend(get_lua_runtime(), {}), + -- maxPreload = 10000, + -- preloadFileSize = 10000, + -- }, + -- } + -- } + -- } + + -- out = vim.fn.system('docker images -q mvinkio/azure-pipelines-lsp') + -- if string.len(out) ~= 0 then + -- lspconfig.yamlls.setup { + -- before_init = function(params) + -- params.processId = vim.NIL + -- end, + -- on_new_config = function(new_config, new_root_dir) + -- new_config.cmd = { + -- "node", + -- new_root_dir, + -- home .. "/projects/devops-pipelines/node_modules/azure-pipelines-language-server/out/server.js", + -- "--stdio" + -- } + -- end, + -- filetypes = { "yaml" }, + -- root_dir = lspconfig.util.root_pattern(".git", vim.fn.getcwd()), + -- on_attach = buffer_setup_no_format, + -- settings = { + -- yaml = { + -- format = { + -- enable = true + -- }, + -- schemas = { + -- [home .. "/projects/devops-pipelines/schema"] = "/*" + -- }, + -- validate = true + -- } + -- } + -- } + -- else + -- utils.log_warning("No image mvinkio/azure-pipelines-lsp.", "vimrc/lsp", true) + -- end + + local out = vim.fn.system('docker images -q mvinkio/python') + if string.len(out) ~= 0 then + lspconfig.pyright.setup { + cmd = { + "docker", + "run", + "--rm", + "--env-file=" .. vim.fn.getcwd() .. "/.env", + "--interactive", + "--workdir=" .. vim.fn.getcwd(), + "--volume=" .. vim.fn.getcwd() .. ":" .. vim.fn.getcwd(), + "mvinkio/python", + "pyright-langserver", "--stdio" + }, + on_new_config = function(new_config, new_root_dir) + new_config.cmd = { + "docker", + "run", + "--rm", + "--env-file=" .. new_root_dir .. "/.env", + "--interactive", + "--workdir=" .. new_root_dir, + "--volume=" .. new_root_dir .. ":" .. new_root_dir, + "mvinkio/python", + "pyright-langserver", "--stdio" + } + end, + filetypes = { "python" }, + root_dir = lspconfig.util.root_pattern(".git", vim.fn.getcwd()), + on_attach = buffer_setup_no_format, + } + else + utils.log_warning("No image mvinkio/python.", "vimrc/lsp", true) + end + + out = vim.fn.system('docker images -q mvinkio/go') + if string.len(out) ~= 0 then + lspconfig.gopls.setup { + before_init = function(params) + params.processId = vim.NIL + end, + on_new_config = function(new_config, new_root_dir) + new_config.cmd = { + "docker", + "run", + "--rm", + "--interactive", + "-e=GOPROXY=https://proxy.golang.org", + "-e=GOOS=linux", + "-e=GOARCH=amd64", + "-e=GOPATH=" .. new_root_dir .. "/go", + "-e=GOCACHE=" .. new_root_dir .. "/.cache/go-build", + "--workdir=" .. new_root_dir, + "--volume=" .. new_root_dir .. ":" .. new_root_dir, + "--network=bridge", + "mvinkio/go", + "gopls" + } + end, + -- cmd = { "docker", "run", "--rm", "-i", "-v", home .. ":" .. home, "mvinkio/gopls" }, + filetypes = { "go", "gomod", "gotmpl" }, + on_attach = buffer_setup_no_format, + } + else + utils.log_warning("No image mvinkio/go.", "vimrc/lsp", true) + end + + -- out = vim.fn.system('docker images -q mvinkio/sveltels') + -- if string.len(out) ~= 0 then + -- lspconfig.svelte.setup { + -- before_init = function(params) + -- params.processId = vim.NIL + -- end, + -- cmd = { + -- "docker", + -- "run", + -- "--rm", + -- "--interactive", + -- "--volume=" .. home .. ":" .. home, + -- "--network=none", + -- "mvinkio/sveltels" + -- }, + -- on_attach = buffer_setup, + -- } + -- else + -- utils.log_warning("No image mvinkio/sveltels.", "vimrc/lsp", true) + -- end + + -- }}} + + local null_ls = require("null-ls") + local my_black = null_ls.builtins.formatting.black.with({ + filetypes = { "python" }, + command = "black", + args = { "$FILENAME" } + }) + null_ls.setup({ + debug = vim.fn.expand("$VIMRC_NULL_LS_DEBUG") == "1", + update_on_insert = false, + on_attach = buffer_setup, + sources = { + my_black, + null_ls.builtins.completion.luasnip + } + }) +end + +-- }}} + +return M +-- vim: fdm=marker diff --git a/neovim/lua/vimrc/snippets.lua b/neovim/lua/vimrc/snippets.lua new file mode 100644 index 0000000..e4d60d7 --- /dev/null +++ b/neovim/lua/vimrc/snippets.lua @@ -0,0 +1,133 @@ +local ls = require "luasnip" +local s = ls.snippet +local sn = ls.snippet_node +local isn = ls.indent_snippet_node +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node +local c = ls.choice_node +local d = ls.dynamic_node +local r = ls.restore_node +local events = require("luasnip.util.events") +local ai = require("luasnip.nodes.absolute_indexer") +local fmt = require("luasnip.extras.fmt").fmt +local m = require("luasnip.extras").m +local lambda = require("luasnip.extras").l +local postfix = require("luasnip.extras.postfix").postfix + +local map = vim.api.nvim_set_keymap + +local M = {} + +local go_snippets = function() + ls.add_snippets("go", { + + s(";r", fmt([[ + <>, err := <> + if err != nil { + <> + } + ]], { + i(1,"ret"), i(2,"fun"), i(3, "return err") + }, { + delimiters = "<>" + })), + + s(";e", fmt([[ + if <>, <> := <>; <> { + <> + } + ]], { + i(1,"v"),i(2,"err"),i(3,"fun"), i(4, "err != nil"), i(5,"return err") + }, { + delimiters = "<>" + })), + + s(";fr", fmt([[ + for <>, <> := range <> { + <> + } + ]], { + i(1,"_"),i(2,"_"), i(3,"iterable"), i(4,"body") + }, { + delimiters = "<>" + })), + + s(";sj", fmt([[ + <> <> `json:"<>"` + ]], { + i(1,"field"),i(2,"type"), d(3, function(args) + for i, line in pairs(args[1]) do + args[1][i] = line:gsub("(%u)", function(ch) return '_' .. ch:lower() end):gsub("^_", '') + end + return sn(nil, {i(1,args[1])}) + end, + {1}) + }, { + delimiters = "<>" + })), + + s(";test", fmt([[ +func Test<>(t *testing.T) { + for i, c := range []struct { + expected <> + }{ + } { + t.Run(fmt.Sprintf("%d %s", i, c.expected), func(t *testing.T) { + <> + }) + } +} + ]], { + i(1,"test"),i(2,"type"), i(3,"body") + }, { + delimiters = "<>" + })), + + + + }) +end + + +function M.setup() + go_snippets() + ls.config.setup({ + load_ft_func = + -- Also load both lua and json when a markdown-file is opened, + -- javascript for html. + -- Other filetypes just load themselves. + require("luasnip.extras.filetype_functions").extend_load_ft({ + markdown = { "lua", "json" }, + html = { "javascript" } + }) + }) + -- press to expand or jump in a snippet. These can also be mapped separately + -- via luasnip-expand-snippet and luasnip-jump-next. + vim.keymap.set( + "i", + "", + [[luasnip#expand_or_jumpable() ? 'luasnip-expand-or-jump' : '']], + { silent = true, noremap = true, expr = true } + ) + vim.keymap.set( + { "i", "s" }, + "", + [[lua require'luasnip'.jump(-1)]], + { silent = true, noremap = true } + ) + vim.keymap.set( + "s", + "", + [[lua require'luasnip'.jump(1)]], + { silent = true, noremap = true } + ) + vim.keymap.set( + { "i", "s" }, + "", + [[luasnip#choice_active() ? 'luasnip-next-choice' : '']], + { silent = true, noremap = true, expr = true } + ) +end + +return M diff --git a/neovim/lua/vimrc/term.lua b/neovim/lua/vimrc/term.lua new file mode 100644 index 0000000..409ff72 --- /dev/null +++ b/neovim/lua/vimrc/term.lua @@ -0,0 +1,91 @@ +local api = vim.api +local cmd = vim.cmd + +local M = {} +local jobid = nil +local winid = nil + + +local function bo(option, value) + api.nvim_buf_set_option(0, option, value) +end + +local function launch_term(cmd, opts) + opts = opts or {} + vim.cmd("belowright new") + winid = vim.fn.win_getid() + api.nvim_win_set_var(0, 'REPL', 1) + bo('buftype', 'nofile') + bo('bufhidden', 'wipe') + bo('buflisted', false) + bo('swapfile', false) + opts = vim.tbl_extend('error', opts, { + on_exit = function() + jobid = nil + end + }) + jobid = vim.fn.termopen(cmd, opts) +end + +local function close_term() + if not jobid then return end + vim.fn.jobstop(jobid) + if api.nvim_win_is_valid(winid) then + api.nvim_win_close(winid, true) + end + winid = nil +end + +function M.toggle() + if jobid then + close_term() + else + launch_term(vim.fn.environ()['SHELL'] or 'sh') + end +end + + +function M.run() + local filepath = api.nvim_buf_get_name(0) + close_term() + launch_term(filepath) +end + + +function M.sendLine(line) + if not jobid then return end + vim.fn.chansend(jobid, line .. '\n') +end + +function M.sendSelection() + if not jobid then return end + local start_row, start_col = unpack(api.nvim_buf_get_mark(0, '<')) + local end_row, end_col = unpack(api.nvim_buf_get_mark(0, '>')) + local mode = vim.fn.visualmode() + local offset + if mode == '' then -- in block mode all following lines are indented + offset = start_col + elseif mode == 'V' then + end_row = end_row + 1 + offset = 0 + else + offset = 0 + end + local lines = api.nvim_buf_get_lines(0, start_row - 1, end_row, false) + for idx, line in pairs(lines) do + local l + if idx == 1 and idx == #lines then + l = line:sub(start_col + 1, end_col + 1) + elseif idx == 1 then + l = line:sub(start_col + 1) + elseif idx == #lines then + l = line:sub(offset + 1, end_col > #line and #line or end_col + 1) + elseif offset > 0 then + l = line:sub(offset + 1) + else + l = line + end + vim.fn.chansend(jobid, l .. '\n') + end +end +return M diff --git a/neovim/lua/vimrc/terragrunt.lua b/neovim/lua/vimrc/terragrunt.lua new file mode 100644 index 0000000..84ac867 --- /dev/null +++ b/neovim/lua/vimrc/terragrunt.lua @@ -0,0 +1,141 @@ +local vim = vim +local cmd = vim.cmd +local fn = vim.fn + +local M = {} +function M.setup(opts) + local env_file = opts.env_file or '' + local home = os.getenv('HOME') + local user = os.getenv('USER') + local cwd = opts.cwd or home + P(cwd) + + local functions = {} + + functions.clean = function() + require('firvish.job_control').start_job({ + cmd = { + "docker", + "run", + "--interactive", + "--rm", + "--env-file", + env_file, + "--volume", + cwd .. ":" .. cwd, + "--workdir", + cwd, + "alpine/terragrunt", + "/bin/sh", + "-c", + [[find ]] .. cwd .. [[ -type d -name .terragrunt-cache -prune -exec rm -rf {} \; &&]] + .. [[find ]] .. cwd .. [[ -type f -name .terraform.lock.hcl -prune -exec rm -rf {} \;]] + }, + filetype = "log", + title = "clean", + listed = true, + output_qf = false, + is_background_job = true + }) + end + + functions.plan = function(terragrunt_path, dirty) + if not dirty then + functions.clean() + end + P(terragrunt_path) + local cmd = { + "docker", + "run", + "--interactive", + "--rm", + "--env-file", + env_file, + "--volume", + cwd .. ":" .. cwd, + "--workdir", + cwd .. "/" .. terragrunt_path, + "alpine/terragrunt", + "terragrunt", + "plan" + } + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "plan", + listed = true, + output_qf = true, + is_background_job = false + }) + end + + functions.apply = function(terragrunt_path, dirty) + if not dirty then + functions.clean() + end + local cmd = { + "docker", + "run", + "--interactive", + "--rm", + "--env-file", + env_file, + "--volume", + cwd .. ":" .. cwd, + "--workdir", + cwd .. "/" .. terragrunt_path, + "alpine/terragrunt", + "terragrunt", + "apply", + "--terragrunt-non-interactive", + "--auto-approve" + } + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "plan", + listed = true, + output_qf = true, + is_background_job = false + }) + end + + functions.destroy = function(terragrunt_path, dirty) + if not dirty then + functions.clean() + end + local cmd = { + "docker", + "run", + "--interactive", + "--rm", + "--env-file", + env_file, + "--volume", + cwd .. ":" .. cwd, + "--workdir", + cwd .. "/" .. terragrunt_path, + "alpine/terragrunt", + "terragrunt", + "destroy", + "--terragrunt-non-interactive", + "--auto-approve" + } + require('firvish.job_control').start_job({ + cmd = cmd, + filetype = "log", + title = "plan", + listed = true, + output_qf = true, + is_background_job = false + }) + end + + _G.terragrunt_functions = functions + cmd [[command! -nargs=1 -complete=dir -bang TGplan :lua _G.terragrunt_functions.plan("", "" ~= "!")]] + cmd [[command! -nargs=1 -complete=dir -bang TGapply :lua _G.terragrunt_functions.apply("", "" ~= "!")]] + cmd [[command! -nargs=1 -complete=dir -bang TGdestroy :lua _G.terragrunt_functions.destroy("", "" ~= "!")]] + cmd [[command! TGclean :lua _G.terragrunt_functions.clean()]] + +end +return M diff --git a/neovim/lua/vimrc/utils.lua b/neovim/lua/vimrc/utils.lua new file mode 100644 index 0000000..386efd2 --- /dev/null +++ b/neovim/lua/vimrc/utils.lua @@ -0,0 +1,70 @@ +local vim = vim +local cmd = vim.cmd +local M = {} + +-- paths {{{ +-- }}} +-- +-- logging {{{ +function M.log_error(msg, source, persist) + if source then + msg = "[" .. source .. "] " .. msg + end + cmd [[echohl ErrorMsg]] + if persist then + cmd("echomsg '" .. msg .. "'") + else + cmd("echo '" .. msg .. "'") + end + cmd [[echohl Normal]] +end + +function M.log_warning(msg, source, persist) + if source then + msg = "[" .. source .. "]" .. msg + end + msg = string.gsub(msg, "'", '"') + cmd [[echohl WarningMsg]] + if persist then + cmd("echomsg '" .. msg .. "'") + else + cmd("echo '" .. msg .. "'") + end + cmd [[echohl Normal]] +end +-- }}} + +-- tables {{{ +function table.filter() + print"hi" +end + +function table.keys(tbl) + local k = {} + for key, val in pairs(tbl) do + table.insert(k, key) + end + return k +end + +-- }}} + +-- string {{{ +function string.join(str, join_token) + local j = "" + local join = join_token or "" + if #str == 1 then + return str[1] + end + for i, token in ipairs(str) do + if i > 1 then + j = j .. join .. token + else + j = j .. token + end + end + return j +end +-- }}} +return M +-- vim: fdm=marker -- cgit v1.2.3