summary refs log tree commit diff
path: root/.vim/plugin
diff options
context:
space:
mode:
authorRobert Günzler <r@gnzler.io>2024-11-25 13:30:37 +0100
committerRobert Günzler <r@gnzler.io>2024-11-25 13:58:25 +0100
commit23de12baba9fbfc4ca24581b37c374aa5345cc25 (patch)
treee4b3c421bad572eb85a1089eaad44dc3059ab6e6 /.vim/plugin
parent18e3848110da0a59843058927ea04b496f5db2a5 (diff)
update nvim config
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to '.vim/plugin')
-rw-r--r--.vim/plugin/_globals.lua3
-rw-r--r--.vim/plugin/auto.lua38
-rw-r--r--.vim/plugin/colorscheme.lua23
-rw-r--r--.vim/plugin/diagnostics.lua59
-rw-r--r--.vim/plugin/hardmode.lua10
-rw-r--r--.vim/plugin/keymaps.lua29
-rw-r--r--.vim/plugin/options.lua27
-rw-r--r--.vim/plugin/statuscolumn.lua11
-rw-r--r--.vim/plugin/statusline.lua152
-rw-r--r--.vim/plugin/syncbg.lua53
-rw-r--r--.vim/plugin/termopen.lua59
-rw-r--r--.vim/plugin/undo.lua10
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