summary refs log tree commit diff
path: root/.vim/lua/internal/plugins
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/lua/internal/plugins
parent18e3848110da0a59843058927ea04b496f5db2a5 (diff)
update nvim config
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to '.vim/lua/internal/plugins')
-rw-r--r--.vim/lua/internal/plugins/aerial.lua13
-rw-r--r--.vim/lua/internal/plugins/colorizer.lua16
-rw-r--r--.vim/lua/internal/plugins/colorschemes.lua11
-rw-r--r--.vim/lua/internal/plugins/completion.lua60
-rw-r--r--.vim/lua/internal/plugins/csv.lua20
-rw-r--r--.vim/lua/internal/plugins/gentoo.lua15
-rw-r--r--.vim/lua/internal/plugins/git.lua108
-rw-r--r--.vim/lua/internal/plugins/icons.lua12
-rw-r--r--.vim/lua/internal/plugins/indent.lua28
-rw-r--r--.vim/lua/internal/plugins/lsp.lua276
-rw-r--r--.vim/lua/internal/plugins/mediawiki.lua6
-rw-r--r--.vim/lua/internal/plugins/mini.lua35
-rw-r--r--.vim/lua/internal/plugins/oil.lua21
-rw-r--r--.vim/lua/internal/plugins/telescope.lua137
-rw-r--r--.vim/lua/internal/plugins/todo.lua46
-rw-r--r--.vim/lua/internal/plugins/treesitter.lua124
-rw-r--r--.vim/lua/internal/plugins/whichkey.lua9
-rw-r--r--.vim/lua/internal/plugins/writing.lua123
-rw-r--r--.vim/lua/internal/plugins/zk.lua35
19 files changed, 1095 insertions, 0 deletions
diff --git a/.vim/lua/internal/plugins/aerial.lua b/.vim/lua/internal/plugins/aerial.lua
new file mode 100644
index 0000000..a5fb4b3
--- /dev/null
+++ b/.vim/lua/internal/plugins/aerial.lua
@@ -0,0 +1,13 @@
+return {
+  {
+    'stevearc/aerial.nvim',
+    opts = {},
+    dependencies = {
+      'nvim-treesitter/nvim-treesitter',
+      'echasnovski/mini.icons',
+    },
+    keys = {
+      { '<leader>b', '<cmd>AerialToggle<cr>' },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/colorizer.lua b/.vim/lua/internal/plugins/colorizer.lua
new file mode 100644
index 0000000..cf55336
--- /dev/null
+++ b/.vim/lua/internal/plugins/colorizer.lua
@@ -0,0 +1,16 @@
+return {
+  {
+    'NvChad/nvim-colorizer.lua',
+    -- 'norcalli/nvim-colorizer.lua',
+    -- events = { 'VeryLazy' },
+    lazy = false,
+    opts = {
+      name = true,
+      RRGGBB = true,
+      RRGGBBAA = false,
+      rgb_fn = true,
+      hsl_fn = true,
+      mode = 'background',
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/colorschemes.lua b/.vim/lua/internal/plugins/colorschemes.lua
new file mode 100644
index 0000000..9371229
--- /dev/null
+++ b/.vim/lua/internal/plugins/colorschemes.lua
@@ -0,0 +1,11 @@
+return {
+  {
+    enabled = false,
+    'xero/evangelion.nvim',
+    lazy = false,
+    priority = 1000,
+    config = function()
+      vim.cmd('colorscheme evangelion')
+    end,
+  },
+}
diff --git a/.vim/lua/internal/plugins/completion.lua b/.vim/lua/internal/plugins/completion.lua
new file mode 100644
index 0000000..db96085
--- /dev/null
+++ b/.vim/lua/internal/plugins/completion.lua
@@ -0,0 +1,60 @@
+return {
+  {
+    -- 'hrsh7th/nvim-cmp',
+    'iguanacucumber/magazine.nvim', -- perf improvements
+    name = 'nvim-cmp',
+
+    lazy = false,
+    -- event = {'InsertEnter', 'CmdlineEnter' },
+    priority = 100,
+    dependencies = {
+      'hrsh7th/cmp-buffer',
+      'hrsh7th/cmp-nvim-lsp',
+      'https://codeberg.org/FelipeLema/cmp-async-path',
+      -- 'hrsh7th/cmp-nvim-lua',
+      'hrsh7th/cmp-nvim-lsp-signature-help', -- used to provide function signature completion
+      'hrsh7th/cmp-cmdline',
+      'dmitmel/cmp-cmdline-history',
+      'hrsh7th/cmp-nvim-lsp-document-symbol', -- used by cmdline completion
+      -- 'f3fora/cmp-spell',
+
+      { 'L3MON4D3/LuaSnip', run = 'make install_jsregexp' },
+      'saadparwaiz1/cmp_luasnip',
+
+      'onsails/lspkind.nvim',
+    },
+    config = function()
+      require('internal.snippets')
+      require('internal.completion')
+    end,
+  },
+
+  -- { -- TODO: try when it doesnt require nightly rust, i dont want binary blobs
+  --
+  --   'saghen/blink.cmp',
+  --   lazy = false,
+  --   -- use a release tag to download pre-built binaries
+  --   -- version = 'v0.*',
+  --   -- OR build from source, requires nightly: https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust
+  --   build = 'cargo build --release',
+  --
+  --   opts = {
+  --     highlight = {
+  --       -- sets the fallback highlight groups to nvim-cmp's highlight groups
+  --       -- useful for when your theme doesn't support blink.cmp
+  --       -- will be removed in a future release, assuming themes add support
+  --       use_nvim_cmp_as_default = true,
+  --     },
+  --
+  --     -- set to 'mono' for 'Nerd Font Mono' or 'normal' for 'Nerd Font'
+  --     -- adjusts spacing to ensure icons are aligned
+  --     nerd_font_variant = 'normal',
+  --
+  --     -- experimental auto-brackets support
+  --     -- accept = { auto_brackets = { enabled = true } }
+  --
+  --     -- experimental signature help support
+  --     -- trigger = { signature_help = { enabled = true } }
+  --   },
+  -- },
+}
diff --git a/.vim/lua/internal/plugins/csv.lua b/.vim/lua/internal/plugins/csv.lua
new file mode 100644
index 0000000..bc4cb2c
--- /dev/null
+++ b/.vim/lua/internal/plugins/csv.lua
@@ -0,0 +1,20 @@
+return {
+  {
+    'emmanueltouzery/decisive.nvim',
+    lazy = true,
+    ft = { 'csv' },
+    main = 'decisive',
+    keys = {
+      {
+        '<leader>a',
+        function()
+          require('decisive').align_csv({})
+          require('decisive').show_sticky_header()
+        end,
+        desc = 'decisive: Align CSV',
+      },
+      { '[,', ":lua require('decisive').align_csv_prev_col()<cr>", desc = 'decisive: Prev column' },
+      { '],', ":lua require('decisive').align_csv_next_col()<cr>", desc = 'decisive: Next column' },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/gentoo.lua b/.vim/lua/internal/plugins/gentoo.lua
new file mode 100644
index 0000000..142374c
--- /dev/null
+++ b/.vim/lua/internal/plugins/gentoo.lua
@@ -0,0 +1,15 @@
+return {
+  {
+    'gentoo/gentoo-syntax',
+    lazy = false,
+    config = function()
+      vim.api.nvim_create_autocmd('LspAttach', {
+        callback = function(args)
+          if vim.bo.filetype == 'ebuild' then
+            vim.lsp.stop_client(vim.lsp.get_clients({ bufnr = args.bufnr }))
+          end
+        end,
+      })
+    end,
+  },
+}
diff --git a/.vim/lua/internal/plugins/git.lua b/.vim/lua/internal/plugins/git.lua
new file mode 100644
index 0000000..d907161
--- /dev/null
+++ b/.vim/lua/internal/plugins/git.lua
@@ -0,0 +1,108 @@
+return {
+  {
+    'lewis6991/gitsigns.nvim',
+    lazy = false,
+    opts = {
+      signs = {
+        change = { text = '▋' },
+        add = { text = '▋' },
+      },
+    },
+    keys = {
+      {
+        ']c',
+        function()
+          if vim.wo.diff then
+            vim.cmd.normal({ ']c', bang = true })
+          else
+            require('gitsigns').nav_hunk('next')
+          end
+        end,
+        desc = 'Gitsigns: next hunk',
+      },
+      {
+        '[c',
+        function()
+          if vim.wo.diff then
+            vim.cmd.normal({ '[c', bang = true })
+          else
+            require('gitsigns').nav_hunk('prev')
+          end
+        end,
+        desc = 'Gitsigns: prev hunk',
+      },
+      { '<leader>gb', '<cmd>Gitsigns blame<cr>', desc = 'Gitsigns: blame' },
+      { '<leader>gs', '<cmd>Gitsigns<cr>', desc = 'Gitsigns: select action' },
+      {
+        ';c',
+        function()
+          require('gitsigns').setqflist('all', { open = false })
+          require('telescope.builtin').quickfix({ prompt_title = 'Git changesets' })
+        end,
+        desc = 'Telescope: list hunks via gitsigns',
+      },
+    },
+  },
+
+  {
+    'linrongbin16/gitlinker.nvim',
+    cmd = { 'GitLink' },
+    dependencies = { 'nvim-lua/plenary.nvim' },
+    opts = {
+      message = true,
+    },
+    keys = {
+      {
+        '<leader>gl',
+        vim.cmd.GitLink,
+        desc = 'gitlinker: clipboard',
+      },
+    },
+  },
+
+  {
+    'moyiz/git-dev.nvim',
+    lazy = true,
+    cmd = { 'GitDevOpen', 'GitDevCleanAll' },
+    opts = {
+      read_only = false,
+    },
+  },
+
+  {
+    'isakbm/gitgraph.nvim',
+    dependencies = { 'sindrets/diffview.nvim' },
+    opts = {
+      symbols = {
+        merge_commit = 'M',
+        commit = '∙',
+      },
+      format = {
+        timestamp = '%d-%m-%Y %H:%M:%S %z',
+        fields = { 'hash', 'timestamp', 'author', 'branch_name', 'tag' },
+      },
+    },
+    init = vim.schedule_wrap(function()
+      vim.api.nvim_set_hl(0, 'GitGraphBranch1', { fg = 'NvimLightGray1' })
+      vim.api.nvim_set_hl(0, 'GitGraphBranch2', { fg = 'NvimLightMagenta' })
+      vim.api.nvim_set_hl(0, 'GitGraphBranch3', { fg = 'NvimLightRed' })
+      vim.api.nvim_set_hl(0, 'GitGraphBranch4', { fg = 'NvimDarkCyan' })
+      vim.api.nvim_set_hl(0, 'GitGraphBranch5', { fg = 'NvimDarkYellow' })
+      vim.api.nvim_set_hl(0, 'GitGraphHash', { fg = 'NvimLightMagenta' })
+      vim.api.nvim_set_hl(0, 'GitGraphAuthor', { fg = 'NvimLightGray4', italic = true })
+      vim.api.nvim_set_hl(0, 'GitGraphTimestamp', { fg = 'NvimLightCyan' })
+      vim.api.nvim_set_hl(0, 'GitGraphBranchName', { fg = 'NvimLightYellow' })
+      vim.api.nvim_set_hl(0, 'GitGraphBranchTag', { fg = 'NvimLightYellow' })
+      vim.api.nvim_set_hl(0, 'GitGraphBranchMsg', { link = 'Normal' })
+    end),
+    keys = {
+      {
+        'g-',
+        function()
+          require('gitgraph').draw({}, { all = true, max_count = 5000 })
+        end,
+        desc = 'git graph',
+      },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/icons.lua b/.vim/lua/internal/plugins/icons.lua
new file mode 100644
index 0000000..3d503dc
--- /dev/null
+++ b/.vim/lua/internal/plugins/icons.lua
@@ -0,0 +1,12 @@
+return {
+  {
+    'echasnovski/mini.icons',
+    version = false,
+    events = { 'VeryLazy' },
+    config = function(_, opts)
+      require('mini.icons').setup(opts)
+      ---@diagnostic disable-next-line: undefined-global
+      MiniIcons.mock_nvim_web_devicons()
+    end,
+  },
+}
diff --git a/.vim/lua/internal/plugins/indent.lua b/.vim/lua/internal/plugins/indent.lua
new file mode 100644
index 0000000..a27a328
--- /dev/null
+++ b/.vim/lua/internal/plugins/indent.lua
@@ -0,0 +1,28 @@
+return {
+  -- show indents using virtual text
+  {
+    'lukas-reineke/indent-blankline.nvim',
+    lazy = false,
+    main = 'ibl',
+    opts = {
+      indent = {
+        char = '▏',
+      },
+      scope = {
+        enabled = true,
+        show_start = false,
+        show_end = false,
+      },
+    },
+  },
+  -- detect indent from the buffer contents
+  {
+    'NMAC427/guess-indent.nvim',
+    lazy = false,
+    opts = {
+      auto_cmd = true,
+      filetype_exclude = { 'netrw', 'tutor', 'dirbuf', 'nvimtree', 'oil' },
+      buftype_exclude = { 'help', 'nofile', 'terminal', 'prompt' },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/lsp.lua b/.vim/lua/internal/plugins/lsp.lua
new file mode 100644
index 0000000..d138c6c
--- /dev/null
+++ b/.vim/lua/internal/plugins/lsp.lua
@@ -0,0 +1,276 @@
+return {
+  {
+    'neovim/nvim-lspconfig',
+    lazy = false,
+    dependencies = {
+      { 'j-hui/fidget.nvim', opts = {} },
+      'stevearc/conform.nvim',
+    },
+    config = function()
+      local capabilities = nil
+      if pcall(require, 'cmp_nvim_lsp') then
+        capabilities = require('cmp_nvim_lsp').default_capabilities()
+      end
+
+      local lspconfig = require('lspconfig')
+
+      local servers = {
+        clangd = {
+          cmd = {
+            'clangd',
+            '--clang-tidy',
+            '--header-insertion=iwyu',
+            '--import-insertions',
+            '--header-insertion-decorators',
+          },
+        },
+        elixirls = {
+          cmd = { 'elixir-ls' },
+          settings = {
+            elixirLS = {
+              dialyzerEnabled = false,
+            },
+          },
+        },
+        gopls = {
+          settings = {
+            gopls = {
+              hints = {
+                assignVariableTypes = true,
+                compositeLiteralFields = true,
+                compositeLiteralTypes = true,
+                constantValues = true,
+                functionTypeParameters = true,
+                parameterNames = true,
+                rangeVariableTypes = true,
+              },
+              analyses = {
+                --  composites = false,
+                nilness = true,
+                shadow = false,
+                unusedparams = true,
+                unusedwrite = true,
+              },
+              gofumpt = true,
+              -- hoverKind = 'Structured',
+            },
+          },
+        },
+        lua_ls = {
+          cmd = { 'luals' }, -- custom firejail-wrapped
+          -- cmd = { 'lua-language-server' },
+          settings = {
+            Lua = {
+              runtime = {
+                version = 'LuaJIT',
+                path = vim.split(package.path, ';'),
+              },
+              diagnostics = {
+                globals = {
+                  '_G',
+                  'assert',
+                  'error',
+                  'os',
+                  'package',
+                  'pairs',
+                  'ipairs',
+                  'pcall',
+                  'require',
+                  'string',
+                  'table',
+                  'type',
+                  'unpack',
+                  'vim',
+                  'xpcall',
+                },
+                neededFileStatus = {
+                  ['code-style-check'] = 'Any',
+                },
+              },
+              format = {
+                enable = true,
+                defaultConfig = {
+                  indent_style = 'space',
+                  indent_size = '2',
+                },
+              },
+              workspace = {
+                library = {
+                  [vim.env.VIMRUNTIME .. '/lua'] = true,
+                  [vim.env.VIMRUNTIME .. '/lua/vim/lsp'] = true,
+                  [vim.fn.stdpath('config') .. '/lua'] = true,
+                },
+              },
+              telemetry = {
+                enable = false,
+              },
+            },
+          },
+        },
+        rust_analyzer = {
+          settings = {
+            ['rust-analyzer'] = {
+              checkOnSave = {
+                command = { 'cargo', 'clippy' },
+              },
+            },
+          },
+        },
+        ts_ls = {
+          init_options = {
+            tsserver = {
+              path = '/usr/lib/node_modules/typescript/lib',
+            },
+          },
+        },
+        pylsp = {},
+        zls = {
+          cmd = {
+            'zls',
+            '--enable-debug-log',
+            '--enable-message-tracing',
+          },
+        },
+        bashls = {},
+        cssls = {},
+        jsonls = {},
+        html = {},
+        superhtml = {},
+        kotlin_language_server = {
+          -- cmd = vim.lsp.rpc.connect('127.0.0.1', 20100),
+          cmd = {
+            'distrobox',
+            'enter',
+            '-n',
+            'android-dev',
+            '--',
+            '/usr/local/kotlin-langserver/bin/kotlin-language-server',
+          },
+          init_options = {
+            formatting = {
+              formatter = 'none', -- disable because we use ktlint via gradle
+            },
+          },
+        },
+      }
+
+      for name, opts in pairs(servers) do
+        opts = vim.tbl_deep_extend('force', {
+          capabilities = capabilities,
+        }, opts)
+        lspconfig[name].setup(opts)
+      end
+
+      vim.api.nvim_create_autocmd('LspAttach', {
+        callback = function()
+          -- local client =
+          --   assert(vim.lsp.get_client_by_id(args.data.client_id), 'must have valid client')
+
+          vim.opt_local.omnifunc = 'v:lua.vim.lsp.omnifunc'
+
+          vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { buffer = true })
+          vim.keymap.set('n', 'gR', vim.lsp.buf.references, { buffer = true })
+          vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, { buffer = true })
+          vim.keymap.set('n', 'gT', vim.lsp.buf.type_definition, { buffer = true })
+          vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = true })
+          vim.keymap.set('n', 'grr', vim.lsp.buf.rename, { buffer = true })
+          vim.keymap.set('n', 'ga', vim.lsp.buf.code_action, { buffer = true })
+        end,
+      })
+    end,
+  },
+
+  {
+    'folke/lazydev.nvim',
+    ft = 'lua',
+    -- could add a completion source to cmp?
+  },
+
+  -- formatting
+  {
+    'stevearc/conform.nvim',
+    lazy = false,
+    opts = {
+      formatters_by_ft = {
+        lua = { 'stylua' },
+        go = { 'goimports', 'gofmt' },
+        python = { 'ruff_format' },
+      },
+    },
+    config = function(_, opts)
+      require('conform').setup(opts)
+
+      vim.api.nvim_create_autocmd('BufWritePre', {
+        callback = function(args)
+          if vim.g.nofmt then
+            return
+          end
+          require('conform').format({
+            bufnr = args.buf,
+            lsp_fallback = true,
+            quiet = true,
+          })
+        end,
+      })
+    end,
+  },
+
+  -- linting
+  {
+    'nvimtools/none-ls.nvim',
+    dependencies = { 'nvim-lua/plenary.nvim' },
+    event = { 'VeryLazy' },
+    config = function()
+      local nls = require('null-ls')
+      nls.setup({
+        sources = {
+          -- https://github.com/nvimtools/none-ls.nvim/blob/main/doc/BUILTINS.md
+          -- nls.builtins.code_actions.gitsigns,
+          nls.builtins.code_actions.impl,
+
+          -- nls.builtins.completion.spell,
+
+          -- nls.builtins.diagnostics.checkmake,
+          -- nls.builtins.diagnostics.cmake_lint,
+          -- nls.builtins.diagnostics.cppcheck,
+          -- nls.builtins.diagnostics.gccdiag,
+          nls.builtins.diagnostics.golangci_lint,
+          nls.builtins.diagnostics.hadolint,
+          -- nls.builtins.diagnostics.pylint,
+          -- nls.builtins.diagnostics.selene,
+          -- nls.builtins.diagnostics.semgrep,
+          nls.builtins.diagnostics.sqlfluff,
+          -- nls.builtins.diagnostics.stylelint,
+          -- nls.builtins.diagnostics.textidote,
+          nls.builtins.diagnostics.vale,
+        },
+      })
+    end,
+  },
+
+  -- diagnostics
+  {
+    'rachartier/tiny-inline-diagnostic.nvim',
+    event = 'VeryLazy',
+    opts = {
+      signs = {
+        left = ' ',
+        right = '',
+        diag = '',
+        arrow = '◂   ',
+        up_arrow = '▴   ',
+      },
+      options = {
+        throttle = 0,
+        show_source = true,
+      },
+    },
+    config = function(_, opts)
+      vim.diagnostic.config({ virtual_text = false })
+      require('tiny-inline-diagnostic').setup(opts)
+      if vim.opt.background:get() == 'light' then
+        require('tiny-inline-diagnostic').change({}, { mixing_color = '#aaaaaa' })
+      end
+    end,
+  },
+}
diff --git a/.vim/lua/internal/plugins/mediawiki.lua b/.vim/lua/internal/plugins/mediawiki.lua
new file mode 100644
index 0000000..f557627
--- /dev/null
+++ b/.vim/lua/internal/plugins/mediawiki.lua
@@ -0,0 +1,6 @@
+return {
+  {
+    'chikamichi/mediawiki.vim',
+    ft = { 'mediawiki' },
+  },
+}
diff --git a/.vim/lua/internal/plugins/mini.lua b/.vim/lua/internal/plugins/mini.lua
new file mode 100644
index 0000000..1886766
--- /dev/null
+++ b/.vim/lua/internal/plugins/mini.lua
@@ -0,0 +1,35 @@
+return {
+  {
+    'echasnovski/mini.align',
+    version = false,
+    opts = {},
+    keys = {
+      { mode = 'n', 'ga' },
+      { mode = 'n', 'gA' },
+      { mode = 'v', 'ga' },
+      { mode = 'v', 'gA' },
+      {
+        mode = 'v',
+        '<cr>',
+        function()
+          vim.cmd([[silent! echohl ErrorMsg | echo "use ga/gA" | echohl None]])
+        end,
+      },
+    },
+  },
+  {
+    'echasnovski/mini.surround',
+    lazy = false,
+    version = false,
+    opts = {
+      mappings = {
+        delete = 'ds',
+        replace = 'cs',
+      },
+    },
+    keys = {
+      { mode = 'n', 'cs' },
+      { mode = 'n', 'ds' },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/oil.lua b/.vim/lua/internal/plugins/oil.lua
new file mode 100644
index 0000000..401fe8b
--- /dev/null
+++ b/.vim/lua/internal/plugins/oil.lua
@@ -0,0 +1,21 @@
+return {
+  {
+    'stevearc/oil.nvim',
+    lazy = false,
+    opts = {
+      keymaps = {
+        ['gt'] = {
+          function()
+            local cwd = require('oil').get_current_dir()
+            vim.cmd('silent !footclient --no-wait -D ' .. cwd)
+          end,
+          nowait = true,
+          desc = 'Open current directory with foot',
+        },
+      },
+    },
+    keys = {
+      { mode = 'n', '-', '<cmd>Oil<cr>', desc = 'oil: open parent directory' },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/telescope.lua b/.vim/lua/internal/plugins/telescope.lua
new file mode 100644
index 0000000..6339a2c
--- /dev/null
+++ b/.vim/lua/internal/plugins/telescope.lua
@@ -0,0 +1,137 @@
+return {
+  {
+    'nvim-telescope/telescope.nvim',
+    lazy = false,
+    dependencies = {
+      { 'nvim-lua/plenary.nvim' },
+      {
+        'nvim-telescope/telescope-fzf-native.nvim',
+        build = 'cmake -S. -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Release && cmake --build build --config Release',
+      },
+      { 'nvim-telescope/telescope-ui-select.nvim' },
+    },
+    config = function(spec, _)
+      require('telescope').setup({
+        defaults = require('telescope.themes').get_ivy({
+          prompt = false,
+          borderchars = {
+            preview = { '─', '│', '─', '│', '┌', '┐', '┘', '└' },
+          },
+        }),
+
+        extensions = {
+          wrap_results = true,
+
+          fzf = {},
+
+          ['ui-select'] = {
+            require('telescope.themes').get_ivy({
+              prompt = false,
+              -- sharp edges please
+              borderchars = {
+                preview = { '─', '│', '─', '│', '┌', '┐', '┘', '└' },
+              },
+              layout_config = { height = 9 },
+            }),
+          },
+        },
+      })
+
+      pcall(require('telescope').load_extension, 'fzf')
+      pcall(require('telescope').load_extension, 'ui-select')
+
+      -- user commands
+      vim.api.nvim_create_user_command(
+        'F',
+        'Telescope find_files search_dirs=<args>',
+        { desc = 'Telescope find_files', nargs = '?' }
+      )
+      vim.api.nvim_create_user_command(
+        'G',
+        'Telescope live_grep search_dirs=<args>',
+        { desc = 'Telescope live_grep', nargs = '?' }
+      )
+
+      -- keymaps
+      local builtin = require('telescope.builtin')
+      for _, o in ipairs(spec.keys) do
+        if not o[2] then
+          local mod = vim.split(o.desc, ': ')[2]
+          vim.keymap.set(o.mode, o[1], builtin[mod], { desc = o.desc })
+        end
+      end
+
+      -- highlights
+      vim.schedule(function()
+        vim.api.nvim_set_hl(0, 'TelescopeBorder', { fg = 'NvimDarkGrey4', force = true })
+        vim.api.nvim_set_hl(0, 'TelescopeTitle', { fg = 'NvimLightMagenta', force = true })
+        vim.api.nvim_set_hl(0, 'NormalFloat', { link = 'TelescopeNormal', force = true })
+      end)
+    end,
+    keys = {
+      { mode = 'n', ';/', desc = 'telescope: current_buffer_fuzzy_find' },
+      { mode = 'n', ';b', desc = 'telescope: buffers' },
+      { mode = 'n', ';f', desc = 'telescope: find_files' },
+      { mode = 'n', ';g', desc = 'telescope: live_grep' },
+      { mode = 'n', ';d', desc = 'telescope: diagnostics' },
+      {
+        mode = 'n',
+        ';v',
+        function()
+          require('telescope.builtin').find_files({
+            prompt_title = 'vimrc',
+            search_dirs = {
+              vim.fn.stdpath('config'),
+            },
+          })
+        end,
+        desc = 'telescope: vim_config',
+      },
+      {
+        mode = 'n',
+        ';;t',
+        '<cmd>Telescope<cr>',
+        desc = 'telescope: select (interactive)',
+      },
+      {
+        mode = 'n',
+        ';;f',
+        function()
+          local dir
+          if vim.opt.filetype:get() == 'oil' then
+            dir = require('oil').get_current_dir()
+          else
+            dir = vim.fn.expand('%:p')
+          end
+          _G.feedkeys(':Telescope find_files search_dirs=' .. dir)
+        end,
+        desc = 'telescope: find_files (interactive)',
+      },
+      {
+        mode = 'n',
+        ';;g',
+        function()
+          local dir
+          if vim.opt.filetype:get() == 'oil' then
+            dir = require('oil').get_current_dir()
+          else
+            dir = vim.fn.expand('%:p')
+          end
+          _G.feedkeys(':Telescope live_grep search_dirs=' .. dir)
+        end,
+        desc = 'telescope: live_grep (interactive)',
+      },
+    },
+  },
+
+  {
+    'prochri/telescope-all-recent.nvim',
+    lazy = false,
+    dependencies = {
+      'nvim-telescope/telescope.nvim',
+      'kkharji/sqlite.lua',
+    },
+    after = { 'nvim-telescope/telescope-ui-select.nvim' },
+    opts = {},
+  },
+}
diff --git a/.vim/lua/internal/plugins/todo.lua b/.vim/lua/internal/plugins/todo.lua
new file mode 100644
index 0000000..e7ae0a7
--- /dev/null
+++ b/.vim/lua/internal/plugins/todo.lua
@@ -0,0 +1,46 @@
+return {
+  {
+    'folke/todo-comments.nvim',
+    dependencies = { 'nvim-lua/plenary.nvim' },
+    lazy = false,
+    cmd = { 'TodoTelescope' },
+    opts = {
+      merge_keywords = true,
+      keywords = {
+        FIX = { icon = '󰃤' },
+        TODO = { icon = '󰸞' },
+        HACK = { icon = '󰈸' },
+        WARN = { icon = '󱇎' },
+        PERF = { icon = '󰅒' },
+        NOTE = { icon = '󰐃' },
+        TEST = { icon = '󰂓' },
+      },
+      highlight = {
+        keyword = 'bg',
+        pattern = [[<(KEYWORDS)(|\(.+\))(:|)]],
+      },
+      search = {
+        pattern = [[\b(KEYWORDS)(|\(.+\))(:|)]],
+      },
+    },
+    keys = {
+      { mode = 'n', ';t', '<cmd>TodoTelescope<cr>', desc = 'telescope: todos' },
+      {
+        mode = 'n',
+        ']t',
+        function()
+          require('todo-comments').jump_next()
+        end,
+        desc = 'todo: next',
+      },
+      {
+        mode = 'n',
+        '[t',
+        function()
+          require('todo-comments').jump_prev()
+        end,
+        desc = 'todo: prev',
+      },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/treesitter.lua b/.vim/lua/internal/plugins/treesitter.lua
new file mode 100644
index 0000000..b8b1d56
--- /dev/null
+++ b/.vim/lua/internal/plugins/treesitter.lua
@@ -0,0 +1,124 @@
+return {
+  {
+    'nvim-treesitter/nvim-treesitter',
+    dependencies = {
+      -- TODO: https://github.com/nvim-treesitter/nvim-treesitter-context
+      { 'nvim-treesitter/nvim-treesitter-refactor', lazy = false },
+      { 'nvim-treesitter/nvim-treesitter-textobjects', lazy = false },
+      { 'nvim-treesitter/playground', cmd = { 'TSPlayground' } },
+    },
+    lazy = false,
+    build = ':TSUpdate',
+    config = function(_, opts)
+      -- TODO: overwrite parser configs, insert gotmpl
+
+      require('nvim-treesitter.configs').setup(opts)
+
+      -- use bash parser for gentoo ebuilds
+      vim.treesitter.language.register('bash', 'ebuild')
+
+      -- register mediawiki parser
+      -- local parser_configs = require('nvim-treesitter.parsers').get_parser_configs()
+      -- parser_configs.mediawiki = {
+      --   install_info = {
+      --     url = 'github.com/Ordoviz/tree-sitter-mediawiki',
+      --     files = { 'src/parser.c' },
+      --     branch = 'main',
+      --     generate_requires_npm = false,
+      --     requires_generate_from_grammar = false,
+      --   },
+      --   filetype = 'mediawiki',
+      -- }
+    end,
+    opts = {
+      ensure_installed = {
+        'bash',
+        'bibtex',
+        'c',
+        'c_sharp',
+        'cmake',
+        'comment',
+        'cpp',
+        'css',
+        'dockerfile',
+        'go',
+        'gomod',
+        'gotmpl',
+        'gowork',
+        'hare',
+        'hcl',
+        'html',
+        'java',
+        'javascript',
+        'json',
+        'jsonc',
+        'kotlin',
+        'latex',
+        'ledger',
+        'lua',
+        'make',
+        'markdown',
+        'markdown_inline',
+        'ninja',
+        'norg',
+        'python',
+        'query',
+        'regex',
+        'rust',
+        'scss',
+        'sql',
+        'toml',
+        'typescript',
+        'vim',
+        'vimdoc',
+        'yaml',
+        'zig',
+
+        -- external parsers
+        -- 'mediawiki', -- TODO: missing queries
+      },
+      highlight = {
+        enable = true,
+        additional_vim_regex_highlighting = { 'markdown' },
+      },
+      indent = {
+        enable = true,
+      },
+      refactor = {
+        navigation = {
+          enable = true,
+          keymaps = {
+            goto_definition = 'gd',
+          },
+        },
+        smart_rename = {
+          enable = true,
+          keymaps = {
+            smart_rename = 'grr',
+          },
+        },
+      },
+      textobjects = {
+        select = {
+          enable = true,
+          keymaps = {
+            ['ib'] = '@block.inner',
+            ['ab'] = '@block.outer',
+            -- ['ic'] = '@conditional.inner',
+            -- ['ac'] = '@conditional.outer',
+            ['if'] = '@function.inner',
+            ['af'] = '@function.outer',
+            ['il'] = '@loop.inner',
+            ['al'] = '@loop.outer',
+            ['is'] = '@scopename.inner',
+            ['as'] = '@scopename.outer',
+            ['ic'] = '@comment.outer',
+          },
+          selection_mode = {
+            ['@comment.outer'] = 'V',
+          },
+        },
+      },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/whichkey.lua b/.vim/lua/internal/plugins/whichkey.lua
new file mode 100644
index 0000000..3c9e802
--- /dev/null
+++ b/.vim/lua/internal/plugins/whichkey.lua
@@ -0,0 +1,9 @@
+return {
+  {
+    'folke/which-key.nvim',
+    event = 'VeryLazy',
+    opts = {
+      icons = { separator = '→ ', group = '🞱 ' },
+    },
+  },
+}
diff --git a/.vim/lua/internal/plugins/writing.lua b/.vim/lua/internal/plugins/writing.lua
new file mode 100644
index 0000000..4792697
--- /dev/null
+++ b/.vim/lua/internal/plugins/writing.lua
@@ -0,0 +1,123 @@
+return {
+  {
+    'folke/zen-mode.nvim',
+    cmd = { 'ZenMode' },
+    opts = {
+      window = {
+        -- width = 0.9,
+        -- height = 0.9,
+        options = {
+          cursorline = true,
+        },
+      },
+      plugins = {
+        options = {
+          number = false,
+          ruler = false,
+          showcmd = false,
+        },
+        gitsigns = { enabled = false },
+        twilight = { enabled = true },
+      },
+      on_open = function()
+        vim.diagnostic.enable(false)
+      end,
+      on_close = function()
+        vim.diagnostic.enable(true)
+      end,
+    },
+    -- init = function()
+    --   vim.api.nvim_create_autocmd({ 'BufWinEnter', 'BufWinLeave' }, {
+    --     pattern = { '*.md' },
+    --     command = [[ZenMode]],
+    --   })
+    -- end,
+    dependencies = {
+      {
+        'folke/twilight.nvim',
+        opts = {
+          context = 24,
+          dimming = {
+            alpha = 0.5,
+            color = { 'Normal', '#ffffff' },
+          },
+        },
+      },
+    },
+  },
+  {
+    'tadmccorkle/markdown.nvim',
+    ft = { 'markdown' },
+    opts = {
+      mappings = false,
+    },
+    config = function(_, opts)
+      require('markdown').setup(opts)
+
+      local set = vim.keymap.set
+      set('n', '[[', [[<Plug>(markdown_go_prev_heading)]], { desc = 'md: previous heading' })
+      set('n', ']]', [[<Plug>(markdown_go_next_heading)]], { desc = 'md: next heading' })
+      set('n', '<s-tab>', [[:MDTaskToggle<cr>]], { desc = 'md: toggle task' })
+      set('x', '<c-l>', [[<esc>gv<Plug>(markdown_add_link_visual)]], { desc = 'md: make link' })
+      local toggle_emph = function(key)
+        return [[<esc>gv<cmd>lua require('markdown.inline').toggle_emphasis_visual(']]
+          .. key
+          .. [[')<cr>]]
+      end
+      set('x', '<c-b>', toggle_emph('b'), { desc = 'md: make bold' })
+      set('x', '<c-i>', toggle_emph('i'), { desc = 'md: make italic' })
+      set('x', '<c-s>', toggle_emph('s'), { desc = 'md: make strikethrough' })
+      set('x', '<c-c>', toggle_emph('c'), { desc = 'md: make code' })
+    end,
+  },
+  {
+    'MeanderingProgrammer/markdown.nvim',
+    name = 'render-markdown', -- needed if used together with markdown.nvim above
+    main = 'render-markdown',
+    dependencies = {
+      'nvim-treesitter/nvim-treesitter',
+      'echasnovski/mini.icons',
+    },
+    ft = { 'markdown' },
+    opts = {
+      heading = {
+        -- icons = { '❶  ', '❷  ', '❸  ', '❹  ', '❺  ', '❻  ' },
+        icons = {
+          ' ',
+          ' ',
+          ' ',
+          ' ',
+          ' ',
+          ' ',
+        },
+        signs = { 'ⅰ', 'ⅱ', 'ⅲ', 'ⅳ', 'ⅴ', 'ⅵ' },
+      },
+      bullet = {
+        icons = { '∙', '∘', '⋅', '⋄' },
+      },
+      checkbox = {
+        checked = { icon = '󰄲 ' },
+        unchecked = { icon = '󰄱 ' },
+        custom = {
+          todo = { raw = '[-]', rendered = '󰔟 ', highlight = 'RenderMarkdownTodo' },
+        },
+      },
+    },
+    init = vim.schedule_wrap(function()
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH1Bg', { bg = 'NvimDarkBlue' })
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH1Fg', { fg = 'NvimLightBlue' })
+
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH2Bg', { bg = 'NvimDarkMagenta' })
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH2Fg', { fg = 'NvimLightMagenta' })
+
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH3Bg', { bg = 'NvimDarkYellow' })
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH3Fg', { fg = 'NvimLightYellow' })
+
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH4Bg', { bg = 'NvimDarkCyan' })
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH4Fg', { fg = 'NvimLightCyan' })
+
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH6Bg', { bg = 'NvimDarkRed' })
+      vim.api.nvim_set_hl(0, 'RenderMarkdownH6Fg', { fg = 'NvimLightRed' })
+    end),
+  },
+}
diff --git a/.vim/lua/internal/plugins/zk.lua b/.vim/lua/internal/plugins/zk.lua
new file mode 100644
index 0000000..76cbcb3
--- /dev/null
+++ b/.vim/lua/internal/plugins/zk.lua
@@ -0,0 +1,35 @@
+return {
+  {
+    lazy = false,
+    'zk-org/zk-nvim',
+    main = 'zk',
+    opts = {
+      picker = 'telescope',
+    },
+    keys = {
+      -- these will work everywhere
+      { ';zc', ':ZkNew ' },
+      { ';zz', '<cmd>ZkNotes {sort={"modified"}}<cr>' },
+      { ';zl', '<cmd>ZkLinks<cr>' },
+      { ';zb', '<cmd>ZkBacklinks<cr>' },
+      { ';zt', '<cmd>ZkTags<cr>' },
+      -- { ';zj', '<cmd>ZkNotes { dir = "500_journals" }<cr>' },
+    },
+    init = function()
+      if not vim.env.ZK_NOTEBOOK_DIR then
+        return
+      end
+      vim.api.nvim_create_autocmd({ 'BufEnter' }, {
+        pattern = vim.env.ZK_NOTEBOOK_DIR .. '/*',
+        callback = function()
+          local o = { remap = true, silent = false, buffer = true }
+          -- these will only work in a zettel
+          vim.keymap.set('n', '-', ':call feedkeys(";zz")<cr>', o)
+          vim.keymap.set('n', '<cr>', '<cmd>lua vim.lsp.buf.definition()<cr>', o)
+        end,
+        group = vim.api.nvim_create_augroup('zk-binds', { clear = true }),
+        once = true,
+      })
+    end,
+  },
+}