diff options
Diffstat (limited to '.vim/plugin')
| -rw-r--r-- | .vim/plugin/_globals.lua | 3 | ||||
| -rw-r--r-- | .vim/plugin/auto.lua | 38 | ||||
| -rw-r--r-- | .vim/plugin/colorscheme.lua | 23 | ||||
| -rw-r--r-- | .vim/plugin/diagnostics.lua | 59 | ||||
| -rw-r--r-- | .vim/plugin/hardmode.lua | 10 | ||||
| -rw-r--r-- | .vim/plugin/keymaps.lua | 29 | ||||
| -rw-r--r-- | .vim/plugin/options.lua | 27 | ||||
| -rw-r--r-- | .vim/plugin/statuscolumn.lua | 11 | ||||
| -rw-r--r-- | .vim/plugin/statusline.lua | 152 | ||||
| -rw-r--r-- | .vim/plugin/syncbg.lua | 53 | ||||
| -rw-r--r-- | .vim/plugin/termopen.lua | 59 | ||||
| -rw-r--r-- | .vim/plugin/undo.lua | 10 |
12 files changed, 474 insertions, 0 deletions
diff --git a/.vim/plugin/_globals.lua b/.vim/plugin/_globals.lua new file mode 100644 index 0000000..5bf99a4 --- /dev/null +++ b/.vim/plugin/_globals.lua @@ -0,0 +1,3 @@ +_G.feedkeys = function(keys) + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(keys, true, false, true), 'n', true) +end diff --git a/.vim/plugin/auto.lua b/.vim/plugin/auto.lua new file mode 100644 index 0000000..ab4e159 --- /dev/null +++ b/.vim/plugin/auto.lua @@ -0,0 +1,38 @@ +local augroup = vim.api.nvim_create_augroup +local autocmd = vim.api.nvim_create_autocmd + +do + local group = augroup('EasyQuit', { clear = true }) + autocmd('FileType', { + pattern = { + 'help', + 'qf', + 'dap-float', + 'gitsigns-blame', + 'git', + }, + callback = function() + vim.keymap.set('n', 'q', '<cmd>close<cr>', { silent = true, buffer = 0 }) + end, + group = group, + }) + autocmd('FileType', { + pattern = { 'gitgraph' }, + callback = function() + vim.keymap.set('n', 'q', '<cmd>bdel!<cr>', { silent = true, buffer = 0 }) + end, + group = group, + }) + autocmd('FileType', { + pattern = { 'DiffviewFiles' }, + callback = function() + vim.keymap.set('n', 'q', '<cmd>tabclose<cr>', { silent = true, buffer = 0 }) + end, + group = group, + }) + autocmd('TermClose', { + pattern = { 'term://*' }, + command = [[ if !v:event.status | exe 'bdelete! '..expand('<abuf>') | endif ]], + group = group, + }) +end diff --git a/.vim/plugin/colorscheme.lua b/.vim/plugin/colorscheme.lua new file mode 100644 index 0000000..240737e --- /dev/null +++ b/.vim/plugin/colorscheme.lua @@ -0,0 +1,23 @@ +vim.opt.background = 'dark' + +-- setup color-scheme detection via desktop portal apis +vim.api.nvim_create_autocmd('UIEnter', { + once = true, + callback = function() + local job = require('plenary.job'):new({ + command = 'porta', + args = { 'settings', 'org.freedesktop.appearance', 'color-scheme' }, + enable_recording = true, + }) + local res, exitcode = job:sync() + if exitcode == 0 and #res == 1 then + if res[1] == 'prefer-light' then + vim.opt.background = 'light' + else + vim.opt.background = 'dark' + end + end + end, +}) + +vim.api.nvim_set_hl(0, 'ColorColumn', { link = 'CursorColumn', force = true }) diff --git a/.vim/plugin/diagnostics.lua b/.vim/plugin/diagnostics.lua new file mode 100644 index 0000000..70deec3 --- /dev/null +++ b/.vim/plugin/diagnostics.lua @@ -0,0 +1,59 @@ +vim.diagnostic.config({ + signs = { + text = { + [vim.diagnostic.severity.ERROR] = '✗', + [vim.diagnostic.severity.WARN] = '▷', + [vim.diagnostic.severity.INFO] = 'ℹ', + [vim.diagnostic.severity.HINT] = '🞶', + }, + linehl = { + [vim.diagnostic.severity.ERROR] = 'Search', + -- [vim.diagnostic.severity.WARN] = '', + -- [vim.diagnostic.severity.INFO] = '', + -- [vim.diagnostic.severity.HINT] = '', + }, + numhl = { + [vim.diagnostic.severity.ERROR] = 'DiagnosticSignError', + [vim.diagnostic.severity.WARN] = 'DiagnosticSignWarn', + [vim.diagnostic.severity.INFO] = 'DiagnosticSignInfo', + [vim.diagnostic.severity.HINT] = 'DiagnosticSignHint', + }, + }, + underline = { + severity = { min = vim.diagnostic.severity.HINT }, + }, + float = { + severity = { min = vim.diagnostic.severity.HINT }, + }, + virtual_text = { + severity = { min = vim.diagnostic.severity.HINT }, + }, + severity_sort = true, +}) + +local commonhl = { undercurl = true, force = true } +vim.api.nvim_set_hl(0, 'DiagnosticUnderlineError', commonhl) +vim.api.nvim_set_hl(0, 'DiagnosticUnderlineWarn', commonhl) +vim.api.nvim_set_hl(0, 'DiagnosticUnderlineInfo', commonhl) +vim.api.nvim_set_hl(0, 'DiagnosticUnderlineHint', commonhl) + +vim.keymap.set('n', '[d', function() + vim.diagnostic.goto_next() +end, { desc = 'diagnostic: next' }) +vim.keymap.set('n', ']d', function() + vim.diagnostic.goto_prev() +end, { desc = 'diagnostic: prev' }) +vim.keymap.set('n', 'DD', vim.diagnostic.open_float, { desc = 'diagnostic: current line' }) +vim.keymap.set('n', '<leader>td', function() + if not _G.diagnostic_hidden then + -- vim.diagnostic.hide(nil, 0) + vim.diagnostic.config({ virtual_text = false }) + else + -- vim.diagnostic.show(nil, 0) + vim.diagnostic.config({ virtual_text = true }) + end + _G.diagnostic_hidden = not _G.diagnostic_hidden +end, { desc = 'diagnostic: toggle' }) +vim.keymap.set('n', '<leader>tD', function() + vim.diagnostic.enable(not vim.diagnostic.is_enabled()) +end, { desc = 'diagnostic: toggle' }) diff --git a/.vim/plugin/hardmode.lua b/.vim/plugin/hardmode.lua new file mode 100644 index 0000000..f18a5ef --- /dev/null +++ b/.vim/plugin/hardmode.lua @@ -0,0 +1,10 @@ +-- hard mode means we're not using the arrow keys! + +local bail = function() + vim.cmd([[silent! echohl ErrorMsg | echo "HARD MODE: hjkl operation only" | echohl None]]) +end + +vim.keymap.set({ 'v', 'i' }, '<up>', bail) +vim.keymap.set({ 'v', 'i' }, '<down>', bail) +vim.keymap.set({ 'v', 'i' }, '<left>', bail) +vim.keymap.set({ 'v', 'i' }, '<right>', bail) diff --git a/.vim/plugin/keymaps.lua b/.vim/plugin/keymaps.lua new file mode 100644 index 0000000..c48b1d7 --- /dev/null +++ b/.vim/plugin/keymaps.lua @@ -0,0 +1,29 @@ +local set = vim.keymap.set + +set('n', 'gb', '<cmd>bnext<cr>', { desc = 'Next buffer' }) +set('n', 'gB', '<cmd>bprevious<cr>', { desc = 'Prev buffer' }) + +set('n', ';yp', function() + local payload = (vim.fn.expand('%:p') .. ':' .. vim.fn.line('.')) + vim.fn.setreg('+', payload) + vim.notify(payload) +end, { desc = 'Yank current buffer path and line number' }) +set('n', ';yP', function() + local payload = vim.fn.expand('%:p') + vim.fn.setreg('+', payload) + vim.notify(payload) +end, { desc = 'Yank current buffer path' }) +set('n', ';yn', function() + local payload = vim.fs.basename(vim.fn.expand('%:p')) + vim.fn.setreg('+', payload) + vim.notify(payload) +end, { desc = 'Yank current buffer name' }) + +set('t', '<esc>', [[ <c-\><c-n> ]], { desc = 'Terminal: Exit INSERT mode' }) + +set('v', '<', '<gv', { desc = 'indent' }) +set('v', '>', '>gv', { desc = 'outdent' }) + +set('n', '<s-esc>', '<cmd>nohlsearch<cr>', { desc = 'Clear search highlights' }) +set('n', '<tab>', '<cmd>normal! za<cr>', { desc = 'Toggle fold under cursor' }) +set('n', '<s-tab>', '<cmd>normal! zA<cr>', { desc = 'Toggle fold under cursor (recursive)' }) diff --git a/.vim/plugin/options.lua b/.vim/plugin/options.lua new file mode 100644 index 0000000..a25a646 --- /dev/null +++ b/.vim/plugin/options.lua @@ -0,0 +1,27 @@ +local opt = vim.opt + +opt.number = true +opt.cursorline = true + +-- connect system clipboard +opt.clipboard:prepend({ 'unnamedplus' }) + +-- preview supported ops in split buffer +opt.inccommand = 'split' + +-- show whitespace indicators +opt.listchars:append({ trail = '¬', tab = '> ' }) +opt.showbreak = '↪ ' + +-- show indicator and wrap text at 80 chars +opt.colorcolumn = '+1' +opt.textwidth = 79 +opt.wrap = true + +opt.conceallevel = 2 +opt.concealcursor = nil + +-- use treesitter to determine folds +opt.foldmethod = 'expr' +opt.foldexpr = 'v:lua.vim.treesitter.foldexpr()' +opt.foldlevel = 99 diff --git a/.vim/plugin/statuscolumn.lua b/.vim/plugin/statuscolumn.lua new file mode 100644 index 0000000..06e8988 --- /dev/null +++ b/.vim/plugin/statuscolumn.lua @@ -0,0 +1,11 @@ +function _G.statuscolumn() + local sc = '' + + sc = sc .. [[%l%r%s%C]] + + sc = sc .. '│' + + return sc +end + +-- vim.opt.statuscolumn = '%{%v:lua.statuscolumn()%}' diff --git a/.vim/plugin/statusline.lua b/.vim/plugin/statusline.lua new file mode 100644 index 0000000..fed6d33 --- /dev/null +++ b/.vim/plugin/statusline.lua @@ -0,0 +1,152 @@ +function _G.statusline() + local bufnr = vim.fn.bufnr() or 0 + local hi = statusline_color(vim.fn.mode()) + + local sl = hi + -- sl = sl .. statusline_append([[ ⢷]], 'StatusLineIcon', hi) + + sl = sl .. [[%-h%-w%-q%-f %-m%-r]] + + sl = sl .. statusline_append(statusline_git(bufnr, hi), 'StatusLineGit', hi) + + sl = sl .. statusline_append(statusline_grapple(bufnr, hi), 'StatusLineGrapple', hi) + + sl = sl .. [[ %= ]] -- spacer + + sl = sl .. statusline_append(statusline_lsp_diagnostics(bufnr, hi), 'StatusLineDiagnostics', hi) + + sl = sl .. statusline_append(statusline_dap(bufnr, hi), 'StatusLineDap', hi) + + -- sl = sl .. [[ %= ]] -- spacer + + sl = sl .. statusline_append(statusline_spinner(bufnr, hi), 'StatusLineJobs', hi) + + sl = sl .. [[%-l:%-v --%p%%-- %-Y]] + + return sl +end + +function _G.statusline_color(mode) + local hi = '%*' + if mode == 'i' then + -- hi = '%#StatusLineInsert#' + elseif mode == 'c' then + -- hi = '%#StatusLineCommand#' + elseif mode == 'v' or mode == 'V' or mode == '' then + hi = '%#StatusLineVisual#' + elseif mode == 'R' or mode == 'Rv' then + hi = '%#StatusLineReplace#' + end + -- return '%{g:actual_curwin==win_getid()?'.. hi ..':%#StatusLineNC#}' + return hi +end + +-- does item highlighting and conditionnal spacing +function _G.statusline_append(element, hi, default_hi, opts) + if not element or element == '' then + return '' + end + opts = opts or { append_space = true } + + if hi ~= nil then + hi = '%#' .. hi .. '#' + end + if not (default_hi == '%*') then + hi = default_hi + end + local el = hi .. element .. default_hi + if opts.append_space then + el = el .. ' ' + end + return el +end + +function _G.statusline_combine_hi(outer_name, inner_name) + local outer = vim.api.nvim_get_hl(0, { name = outer_name, create = false }) + local inner = vim.api.nvim_get_hl(0, { name = inner_name, create = false }) + -- try to find a predefined hl + local name = (outer_name .. inner_name) + if vim.api.nvim_get_hl(0, { name = name, create = false }) then + return name + end + -- generate one new one automatically + name = ('autohi_' .. outer_name .. inner_name) + vim.api.nvim_get_hl(0, { name = name, create = true }) + local hi = vim.tbl_extend('force', inner, { bg = inner.fg }, { fg = outer.bg }) + vim.api.nvim_set_hl(0, name, hi) + return name +end + +function _G.statusline_lsp_diagnostics(bufnr, default_hi) + local signs = vim.diagnostic.config().signs.text or {} + local error_num = vim.diagnostic.get(bufnr, { severity = vim.diagnostic.severity.ERROR }) + local warn_num = vim.diagnostic.get(bufnr, { severity = vim.diagnostic.severity.WARN }) + + local s = '' + if #error_num > 0 then + local errs = signs[vim.diagnostic.severity.ERROR] .. ' ' .. #error_num + s = s + .. statusline_append(errs, statusline_combine_hi('StatusLine', 'DiagnosticError'), default_hi) + end + if #warn_num > 0 then + local warns = signs[vim.diagnostic.severity.WARN] .. ' ' .. #warn_num + s = s + .. statusline_append(warns, statusline_combine_hi('StatusLine', 'DiagnosticWarn'), default_hi) + end + return vim.trim(s) +end + +function _G.statusline_git(_, hi) + if vim.b.gitsigns_status and vim.b.gitsigns_status ~= '' then + return statusline_append('[' .. vim.b.gitsigns_status .. ']', 'StatusLineGitChanges', hi) + end +end + +function _G.statusline_grapple(_, _) + local g = package.loaded.grapple + if not g then + return '' + end + return g.statusline() + -- if not g or not g.exists({ buffer = bufnr }) then + -- return '' + -- end + -- return '➥ ' .. g.key({ buffer = bufnr }) +end + +function _G.statusline_spinner(bufnr, _) + local sp = package.loaded.spinner + if not sp then + return '' + end + return sp.status(bufnr) +end + +function _G.statusline_dap(_, _) + local dap = package.loaded.dap + if not dap then + return '' + end + local s = dap.status() + if s == '' then + return s + end + return '[DAP: ' .. s .. ']' +end + +local hi = function(name, opts) + vim.api.nvim_set_hl(0, name, opts) +end + +local statusline = vim.api.nvim_get_hl(0, { name = 'StatusLine', create = false }) +hi('StatusLineDiagnosticError', { fg = 'NvimDarkRed', bg = statusline.bg, bold = true }) +hi('StatusLineDiagnosticWarn', { fg = 'NvimDarkYellow', bg = statusline.bg, bold = true }) + +vim.opt.statusline = '%{%v:lua.statusline()%}' + +-- WINBAR -- +-- vim.opt.winbar = [[%h%w%q%f %-m %-r %= %#WinBarCwd#%{%getcwd()%}%*]] -- keep it simple +-- function _G.winbar() +-- return [[%<%F %-m %-r]] +-- end +-- vim.opt.winbar = '%{%v:lua.winbar()%}' diff --git a/.vim/plugin/syncbg.lua b/.vim/plugin/syncbg.lua new file mode 100644 index 0000000..d9243f0 --- /dev/null +++ b/.vim/plugin/syncbg.lua @@ -0,0 +1,53 @@ +-- this plugin registers two autocmds that trigger when openeing and closing vim, setting the +-- background of the terminal to the color used by our colorscheme using CSI control codes. + +local state = {} + +-- get tty +local tty_handle = io.popen('tty') +if tty_handle == nil then + return +end +local tty = tty_handle:read('*a') +tty_handle:close() +if tty:find('not a tty') then + error('not a tty') +end +state.tty = tty + +-- register update hook +vim.api.nvim_create_autocmd({ 'ColorScheme', 'UIEnter', 'VimResume' }, { + callback = function() + if state.tty == nil then + return + end + + if not state.normal then + -- get colorscheme Normal highlight + local normal = vim.api.nvim_get_hl(0, { name = 'Normal', create = false }) + if normal.bg == nil then + return + end + -- cache old value for use with VimResume + state.normal = normal + end + + -- emit CSI to change terminal background to Normal.bg + os.execute( + 'printf "\\033]11;' .. string.format('#%06x', state.normal.bg) .. '\\007" > ' .. state.tty + ) + + -- set colorscheme Normal.bg to NONE, making it transparent + vim.cmd([[hi Normal ctermbg=NONE guibg=NONE]]) + end, +}) + +-- register reset hook +vim.api.nvim_create_autocmd({ 'UILeave' }, { + callback = function() + if state.tty == nil then + return + end + os.execute('printf "\\033]111\\007" > ' .. state.tty) + end, +}) diff --git a/.vim/plugin/termopen.lua b/.vim/plugin/termopen.lua new file mode 100644 index 0000000..68b9d8d --- /dev/null +++ b/.vim/plugin/termopen.lua @@ -0,0 +1,59 @@ +local function termopen(opts) + opts = opts or {} + + -- setup the buffer + local buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_set_option_value('bufhidden', 'wipe', { buf = buf }) + vim.api.nvim_set_option_value('modifiable', false, { buf = buf }) + + -- setup keymappings + vim.keymap.set('n', 'q', '<cmd>close<cr>', { buffer = buf }) + vim.keymap.set('n', '<esc>', '<cmd>close<cr>', { buffer = buf }) + + -- setup the window + local w = math.ceil(vim.o.columns * 1.0) + local h = math.ceil(vim.o.lines * 0.4) + local win = vim.api.nvim_open_win(buf, true, { + style = 'minimal', + relative = 'editor', + width = w, + height = h, + row = math.ceil(vim.o.lines - h), + col = vim.o.columns, + border = { ' ', '─', ' ', ' ', ' ', '─', ' ', ' ' }, + }) + vim.api.nvim_set_current_win(win) + + -- spawn the command + vim.fn.termopen(opts.cmd, { + on_exit = function() + if vim.api.nvim_win_is_valid(win) then + vim.api.nvim_win_close(win, true) + end + end, + }) + + -- put into insert mode + vim.cmd.startinsert() +end + +-- provide user commands +vim.api.nvim_create_user_command('Termopen', function(a) + termopen({ cmd = a.fargs }) +end, { nargs = '*' }) + +-- alias +vim.api.nvim_create_user_command('T', function(a) + termopen({ cmd = a.fargs }) +end, { nargs = '*' }) + +-- helper to spawn &makeprg +vim.api.nvim_create_user_command('Make', function(a) + local cmd = vim.split(vim.o.makeprg, ' ') + cmd = vim.tbl_map(function(p) + p, _ = string.gsub(p, [[%$%*]], a.args) + p, _ = vim.fn.expand(p) + return p + end, cmd) + termopen({ cmd = cmd }) +end, { nargs = '*' }) diff --git a/.vim/plugin/undo.lua b/.vim/plugin/undo.lua new file mode 100644 index 0000000..aed6195 --- /dev/null +++ b/.vim/plugin/undo.lua @@ -0,0 +1,10 @@ +-- persistent undo + +local undodir = vim.fn.stdpath('cache') .. '/undodir' + +if vim.fn.isdirectory(undodir) == 0 then + vim.fn.mkdir(undodir, 'p', '0700') +end + +vim.g.undodir = undodir +vim.opt.undofile = true |