feat: convert to blink, major lsp changes, lualine
This commit is contained in:
parent
82102e5e29
commit
51ab444c0d
|
@ -5,3 +5,4 @@ nvim
|
|||
|
||||
spell/
|
||||
lazy-lock.json
|
||||
.claude/
|
||||
|
|
50
README.md
50
README.md
|
@ -1,29 +1,45 @@
|
|||
## ⚙️ My Neovim Configuration
|
||||
## ⚙️ My Neovim Configuration
|
||||
|
||||
This is my personal neovim configuration and it's unlikely to be perfect
|
||||
for your use case.
|
||||
|
||||
What is in it?
|
||||
|
||||
* *Kickstart*: based configuration
|
||||
* *Neovimacs*: modeless editing support, with common Emacs bindings in insert mode
|
||||
* *Esc*: to toggle between insert (emacs bindings) and normal (neovim mode)
|
||||
* *Tabs*: Prev (F1), Next (F2), New (F3), and Close (F4) to jump around
|
||||
* *Tool Tabs*: Terminal (F5)
|
||||
* *Movement*: Arrows and Tabs (and, yes, I know)
|
||||
* *Batteries*: Python LSP, completion, treesitter
|
||||
- _Kickstart_: based configuration
|
||||
- _Neovimacs_: modeless editing support, with common Emacs bindings in insert mode
|
||||
- _Esc_: to toggle between insert (emacs bindings) and normal (neovim mode)
|
||||
- _Tabs_: Prev (F1), Next (F2), New (F3), and Close (F4) to jump around
|
||||
- _Tool Tabs_: Terminal (F5)
|
||||
- _Movement_: Arrows and Tabs (and, yes, I know)
|
||||
- _Batteries_: Python LSP, completion, treesitter
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
#### Prep
|
||||
|
||||
Suggested:
|
||||
Neovim >= 0.10 or later is required, you may need to get it from the Neovim PPA or similar:
|
||||
|
||||
```bash
|
||||
sudo apt install -y gcc python3-pip python3-venv git make unzip ripgrep gzip wget curl fd-find npm
|
||||
sudo add-apt-repository ppa:neovim-ppa/unstable
|
||||
sudo apt-get update
|
||||
sudo apt-get install neovim
|
||||
```
|
||||
|
||||
Suggested Packages:
|
||||
|
||||
```bash
|
||||
sudo apt install -y cargo gcc python3-pip python3-venv git make unzip ripgrep gzip wget curl fd-find npm xclip
|
||||
sudo npm install -g tree-sitter-cli
|
||||
```
|
||||
|
||||
If you have an old version of NodeJS, pick up a new one:
|
||||
|
||||
```bash
|
||||
sudo npm cache clean -f
|
||||
sudo npm install -g n
|
||||
sudo n stable
|
||||
```
|
||||
|
||||
Optional based on use-case:
|
||||
|
||||
```bash
|
||||
|
@ -52,9 +68,9 @@ ln -s neovimrc nvim
|
|||
Checking overall health and options:
|
||||
|
||||
```
|
||||
:CheckHealth
|
||||
:checkhealth
|
||||
:Telescope vim_options
|
||||
:lua print(vim.inspect(vim.opt.XXXX))
|
||||
:set option?
|
||||
```
|
||||
|
||||
Beyond [which-key](https://github.com/folke/which-key.nvim), you can use the following
|
||||
|
@ -65,8 +81,18 @@ nvim commands to help you track down key bindings and resolve conflicts:
|
|||
:verbose nmap <C-n> -- for normal mode
|
||||
:nmap <localleader> -- to see leader commands
|
||||
:WhichKey -- see above
|
||||
:lua = <expr> -- run lua expression
|
||||
```
|
||||
|
||||
Use `nvim -u NONE -U NONE -N -i NONE` to test with w/o config if things go wrong.
|
||||
|
||||
#### Recommended Visits
|
||||
|
||||
```
|
||||
:help <module> -- help for modules
|
||||
:help telescope.setup() -- help for the setup section
|
||||
:Telescope help_tags -- search help
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
-- Fix for nvim-cmp feedkeys issue where 'lua require"cmp.utils.feedkeys".run(#)'
|
||||
-- gets inserted into buffers instead of being executed
|
||||
-- This overrides the problematic debounce_next_tick_by_keymap function
|
||||
|
||||
local ok, async = pcall(require, 'cmp.utils.async')
|
||||
if not ok then
|
||||
return
|
||||
end
|
||||
|
||||
-- Override the problematic function with a safer implementation
|
||||
async.debounce_next_tick_by_keymap = function(callback)
|
||||
return function()
|
||||
-- Use vim.schedule instead of feedkeys to avoid inserting command text
|
||||
vim.schedule(callback)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
local builtin = require 'telescope.builtin'
|
||||
|
||||
vim.keymap.set('n', '<C-s>', function()
|
||||
builtin.current_buffer_fuzzy_find()
|
||||
end)
|
||||
-- Use vimacs version
|
||||
--
|
||||
-- vim.keymap.set('i', '<C-s>', function()
|
||||
-- builtin.current_buffer_fuzzy_find()
|
||||
--end)
|
234
init.lua
234
init.lua
|
@ -1,18 +1,38 @@
|
|||
-- NOTE: Leader before plugins are loaded (otherwise wrong leader will be used)
|
||||
|
||||
-- Check Neovim version requirement
|
||||
if vim.fn.has 'nvim-0.11' == 0 then
|
||||
vim.api.nvim_err_writeln 'Error: Neovim 0.11 or higher is required for this configuration.'
|
||||
vim.api.nvim_err_writeln('Current version: ' .. vim.version().major .. '.' .. vim.version().minor .. '.' .. vim.version().patch)
|
||||
vim.api.nvim_err_writeln 'Please update Neovim to continue.'
|
||||
return
|
||||
end
|
||||
|
||||
vim.g.mapleader = ' '
|
||||
vim.g.maplocalleader = ' '
|
||||
vim.g.have_nerd_font = true
|
||||
|
||||
-- User settings
|
||||
vim.g.tabnine_enable = true -- JCM
|
||||
vim.g.autocomplete_enable = true
|
||||
-- vim.o.autochdir = true -- to open from buffer dir
|
||||
vim.g.format_on_save_enabled = true
|
||||
|
||||
-- Add emacs/rl keybindings to this configuration?
|
||||
vim.g.neovimacs_bindings = true
|
||||
vim.g.neovimacs_insert = true
|
||||
|
||||
-- Margins
|
||||
vim.opt.title = false -- in status, not great with tmux
|
||||
vim.opt.number = true -- show line number
|
||||
vim.opt.relativenumber = false
|
||||
vim.opt.showmode = false
|
||||
vim.opt.signcolumn = 'yes'
|
||||
vim.opt.cursorline = true
|
||||
vim.opt.scrolloff = 10
|
||||
vim.opt.colorcolumn = '120'
|
||||
-- vim.opt.breakindent = true
|
||||
vim.o.title = false -- in status, not great with tmux
|
||||
vim.o.number = true -- show line number
|
||||
vim.o.relativenumber = false
|
||||
vim.o.showmode = false
|
||||
vim.o.signcolumn = 'yes'
|
||||
vim.o.cursorline = true
|
||||
vim.o.scrolloff = 10
|
||||
vim.o.colorcolumn = '120'
|
||||
vim.o.guicursor = 'n-v-i-c:block-Cursor' -- keep block cursor
|
||||
-- vim.o.breakindent = true
|
||||
|
||||
-- TODO: replace with osc52 provider once iTerm2 supports it better
|
||||
if vim.env.DISPLAY then
|
||||
|
@ -21,61 +41,66 @@ if vim.env.DISPLAY then
|
|||
vim.opt.clipboard:append { 'unnamed', 'unnamedplus' }
|
||||
end)
|
||||
end
|
||||
vim.opt.mouse = 'nvi'
|
||||
vim.o.mouse = 'nvi'
|
||||
end
|
||||
|
||||
-- File related
|
||||
vim.opt.autochdir = false
|
||||
vim.opt.swapfile = false
|
||||
vim.opt.backup = false
|
||||
vim.opt.writebackup = false
|
||||
vim.opt.undofile = true
|
||||
vim.opt.undodir = os.getenv 'HOME' .. '/.vim/undodir'
|
||||
vim.o.swapfile = false
|
||||
vim.o.backup = false
|
||||
vim.o.writebackup = false
|
||||
vim.o.undofile = true
|
||||
vim.o.undodir = os.getenv 'HOME' .. '/.vim/undodir'
|
||||
if vim.fn.has 'win32' == 1 or vim.fn.has 'win64' == 1 then
|
||||
vim.opt.fileformats = 'dos,unix,mac'
|
||||
vim.o.fileformats = 'dos,unix,mac'
|
||||
elseif vim.fn.has 'mac' == 1 then
|
||||
vim.opt.fileformats = 'mac,unix,dos'
|
||||
vim.o.fileformats = 'mac,unix,dos'
|
||||
else
|
||||
vim.opt.fileformats = 'unix,dos,mac'
|
||||
vim.o.fileformats = 'unix,dos,mac'
|
||||
end
|
||||
vim.opt.wildmenu = true
|
||||
vim.opt.wildmode = 'list:longest,list:full' -- list choices, expand singles
|
||||
vim.o.wildmenu = true
|
||||
vim.o.wildmode = 'list:longest,list:full' -- expand to longest match, then list choices
|
||||
vim.keymap.set('n', '<leader>p', '', { desc = '[P] +Explore' })
|
||||
vim.keymap.set('n', '<leader>pv', vim.cmd.Ex, { desc = 'Open explorer [V]' })
|
||||
|
||||
-- Search
|
||||
vim.opt.ignorecase = true
|
||||
vim.opt.smartcase = true
|
||||
vim.opt.wrapscan = false
|
||||
vim.opt.inccommand = 'split' -- preview
|
||||
vim.o.ignorecase = true
|
||||
vim.o.smartcase = true
|
||||
vim.o.wrapscan = false
|
||||
vim.o.inccommand = 'split' -- preview
|
||||
|
||||
-- Performance
|
||||
vim.opt.updatetime = 250
|
||||
vim.opt.timeoutlen = 300
|
||||
vim.o.updatetime = 250
|
||||
vim.o.timeoutlen = 3000
|
||||
|
||||
-- Windows
|
||||
-- :sp/:vsp to split windows
|
||||
-- C-w to jump between them
|
||||
vim.opt.splitright = true
|
||||
vim.opt.splitbelow = true
|
||||
vim.o.splitright = true
|
||||
vim.o.splitbelow = true
|
||||
|
||||
-- Whitespace
|
||||
vim.opt.list = true
|
||||
vim.o.list = true
|
||||
vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' }
|
||||
|
||||
-- Spelling: "z=" in normal to suggest replacements
|
||||
vim.opt.spelllang = 'en_us'
|
||||
vim.opt.spell = true
|
||||
vim.o.spelllang = 'en_us'
|
||||
vim.o.spell = true
|
||||
|
||||
-- Diagnostics
|
||||
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' })
|
||||
vim.keymap.set('n', '<leader>td', function()
|
||||
vim.diagnostic.enable(not vim.diagnostic.is_enabled())
|
||||
end, { silent = true, noremap = true, desc = 'Toggle [D]iagnostics' })
|
||||
-- Quick diagnostics
|
||||
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = '[Q]uickfix diagnostics' })
|
||||
|
||||
-- Allow 'q' to close simple diagnostic windows
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'qf', 'help', 'checkhealth' },
|
||||
callback = function()
|
||||
vim.keymap.set('n', 'q', '<cmd>bd<cr>', { silent = true, buffer = true })
|
||||
end,
|
||||
})
|
||||
|
||||
-- Highlight when yanking (copying) text - "yap"
|
||||
vim.api.nvim_create_autocmd('TextYankPost', {
|
||||
desc = 'Highlight when yanking (copying) text',
|
||||
group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }),
|
||||
group = vim.api.nvim_create_augroup('ks-highlight-yank', { clear = true }),
|
||||
callback = function()
|
||||
vim.highlight.on_yank()
|
||||
end,
|
||||
|
@ -83,16 +108,17 @@ vim.api.nvim_create_autocmd('TextYankPost', {
|
|||
|
||||
-- Install Lazy from Github
|
||||
local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
|
||||
local uv = vim.uv or vim.loop
|
||||
|
||||
if not uv.fs_stat(lazypath) then
|
||||
if not vim.uv.fs_stat(lazypath) then
|
||||
local lazyrepo = 'https://github.com/folke/lazy.nvim.git'
|
||||
local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath }
|
||||
if vim.v.shell_error ~= 0 then
|
||||
error('Error cloning lazy.nvim:\n' .. out)
|
||||
end
|
||||
end ---@diagnostic disable-next-line: undefined-field
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
local rtp = vim.opt.rtp
|
||||
rtp:prepend(lazypath)
|
||||
|
||||
-- :Lazy
|
||||
require('lazy').setup({
|
||||
|
@ -104,26 +130,19 @@ require('lazy').setup({
|
|||
require 'plugins.gitsigns', -- Add git changes to gutter
|
||||
require 'plugins.which-key', -- Show keybindings as you go
|
||||
require 'plugins.telescope', -- Fuzzy finder (file & LSP search)
|
||||
require 'plugins.lsp', -- Language server (types, errors, signatures)
|
||||
require 'plugins.lualine', -- Statusbar at bottom
|
||||
require 'plugins.mason', -- Mason: LSP/DAP/Linter/Formatter installer
|
||||
require 'plugins.conform', -- Auto-reformat files on save
|
||||
require 'plugins.claude-code', -- LLM: Claude Code
|
||||
require 'plugins.venv', -- Virtual environment selection
|
||||
require 'plugins.autocomplete', -- Auto-completion
|
||||
require 'plugins.autocomplete-blink', -- Auto-completion (new, incomplete)
|
||||
require 'plugins.colorscheme', -- Color scheme
|
||||
require 'plugins.misc', -- Misc small plugins
|
||||
require 'plugins.mini', -- Misc small plugins
|
||||
require 'plugins.treesitter', -- Code highlights and reference navigation
|
||||
require 'plugins.todo', -- Highlight todo, notes in comments
|
||||
require 'plugins.tabnine', -- Tabnine LLM coding assistant
|
||||
|
||||
-- Treesitter navigation
|
||||
-- :help nvim-treesitter
|
||||
-- :Telescope help_tags
|
||||
-- See `:help telescope` and `:help telescope.setup()`
|
||||
-- To see keymaps do this:
|
||||
-- - Insert mode: <c-/>
|
||||
-- - Normal mode: ?
|
||||
-- Venv selector
|
||||
-- WIP: https://github.com/linux-cultist/venv-selector.nvim/tree/regexp
|
||||
-- Wait for a updated release
|
||||
require 'plugins.avante', -- LLM: Cursor alternative
|
||||
require 'plugins.tabnine', -- LLM: Tabnine coding assistant
|
||||
require 'plugins.tiny-inline-diagnostics', -- Better diagnostics
|
||||
}, {
|
||||
ui = {
|
||||
-- If you are using a Nerd Font: set icons to an empty table which will use the
|
||||
|
@ -166,12 +185,15 @@ local function recenter_and_refresh()
|
|||
end
|
||||
vim.keymap.set('n', '<C-l>', recenter_and_refresh, { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<C-l>', recenter_and_refresh, { noremap = true, silent = true })
|
||||
vim.keymap.set('c', '<C-s>', '<CR>n', { expr = true })
|
||||
|
||||
--- (Re)Undefine undesirable behavior
|
||||
vim.api.nvim_set_keymap('i', '<Esc>', '<Esc>', { noremap = true })
|
||||
vim.api.nvim_set_keymap('n', '<C-a>', '<Nop>', { noremap = true })
|
||||
vim.api.nvim_set_keymap('n', '<C-x>', '<Nop>', { noremap = true })
|
||||
if vim.g.neovimacs_bindings then
|
||||
vim.api.nvim_set_keymap('i', '<Esc>', '<Esc>', { noremap = true })
|
||||
vim.api.nvim_set_keymap('n', '<C-a>', '<Nop>', { noremap = true })
|
||||
vim.api.nvim_set_keymap('n', '<C-x><C-c>', ':confirm qall<CR>', { noremap = true })
|
||||
vim.api.nvim_set_keymap('n', '<C-x><C-s>', ':update<CR>', { noremap = true })
|
||||
vim.api.nvim_set_keymap('n', '<C-x><C-f>', ':hide edit ', { noremap = true })
|
||||
end
|
||||
|
||||
-- Terminals/Shell
|
||||
-- :terminal
|
||||
|
@ -181,55 +203,53 @@ vim.keymap.set('c', '<Up>', 'pumvisible() ? "<C-p>" : "<Up>"', { expr = true, no
|
|||
vim.keymap.set('c', '<Down>', 'pumvisible() ? "<C-n>" : "<Down>"', { expr = true, noremap = true })
|
||||
vim.keymap.set('c', '<Left>', 'pumvisible() ? "<C-b>" : "<Left>"', { expr = true, noremap = true })
|
||||
vim.keymap.set('c', '<Right>', 'pumvisible() ? "<C-f>" : "<Right>"', { expr = true, noremap = true })
|
||||
-- vim.opt.wildcharm = '<Tab>' -- set wildcharm=<C-Z>
|
||||
|
||||
-- LSP in insert mode
|
||||
vim.lsp.handlers['textDocument/publishDiagnostics'] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
|
||||
update_in_insert = false,
|
||||
})
|
||||
-- LSP diagnostics configuration
|
||||
vim.diagnostic.config { virtual_text = false }
|
||||
|
||||
-- Tab management keys
|
||||
-- F1-Prev, F2-Next, F3-New, F4-Close
|
||||
--
|
||||
local function safe_tabclose()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local buf_windows = vim.call('win_findbuf', bufnr)
|
||||
local modified = vim.api.nvim_get_option_value('modified', { buf = bufnr })
|
||||
-- vim.diagnostic.config {
|
||||
-- virtual_text = {
|
||||
-- source = 'if_many',
|
||||
-- },
|
||||
-- signs = true,
|
||||
-- underline = true,
|
||||
-- update_in_insert = true,
|
||||
-- severity_sort = true,
|
||||
--}
|
||||
|
||||
if vim.fn.tabpagenr '$' == 1 then
|
||||
-- last tab, no-op
|
||||
return
|
||||
elseif modified and #buf_windows == 1 then
|
||||
vim.ui.input({
|
||||
prompt = 'Buffer modified, are you sure? ',
|
||||
}, function(input)
|
||||
if input == 'y' then
|
||||
vim.cmd 'tabclose'
|
||||
end
|
||||
end)
|
||||
else
|
||||
vim.cmd 'tabclose'
|
||||
-- Register and enable LSP servers
|
||||
-- See https://github.com/neovim/nvim-lspconfig/tree/master/lua/lspconfig/configs
|
||||
-- for sample starter configurations.
|
||||
local lsp_servers = {
|
||||
'ast_grep',
|
||||
'clangd',
|
||||
'lua_ls',
|
||||
'bashls',
|
||||
'marksman',
|
||||
'python',
|
||||
'taplo',
|
||||
'yamlls',
|
||||
'ts_ls',
|
||||
'dockerls',
|
||||
}
|
||||
-- Conditional on executables
|
||||
if vim.fn.executable 'go' == 1 then
|
||||
table.insert(lsp_servers, 'gopls')
|
||||
end
|
||||
if vim.fn.executable 'nixd' == 1 then
|
||||
table.insert(lsp_servers, 'nil_ls')
|
||||
end
|
||||
|
||||
require 'lsp/keybindings'
|
||||
for _, server in ipairs(lsp_servers) do
|
||||
local ok, config = pcall(require, 'lsp.' .. server)
|
||||
if ok and config.name then
|
||||
vim.lsp.config[config.name] = config
|
||||
vim.lsp.enable(server)
|
||||
end
|
||||
end
|
||||
vim.keymap.set('t', '<F1>', vim.cmd.tabp, { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F2>', vim.cmd.tabn, { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F3>', '<C-\\><C-n>:tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '', '<C-\\><C-n>:tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F4>', safe_tabclose, { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F5>', '<C-\\><C-n><Esc>:tab new<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F1>', vim.cmd.tabp, { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F2>', vim.cmd.tabn, { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F3>', ':tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '', ':tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F4>', safe_tabclose, { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F5>', ':tab term<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F1>', vim.cmd.tabp, { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F2>', vim.cmd.tabn, { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F3>', '<Esc>:tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '', '<Esc>:tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F4>', safe_tabclose, { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F5>', '<Esc>:tab term<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<leader>tp', vim.cmd.tabn, { desc = 'Tab [p]revious' })
|
||||
vim.keymap.set('n', '<leader>tn', vim.cmd.tabp, { desc = 'Tab [n]ext' })
|
||||
vim.keymap.set('n', '<leader>to', vim.cmd.tabnew, { desc = 'Tab [o]pen' })
|
||||
vim.keymap.set('n', '<leader>tc', safe_tabclose, { desc = 'Tab [c]lose' })
|
||||
|
||||
-- Inlay hints?
|
||||
vim.lsp.inlay_hint.enable(true)
|
||||
|
||||
require 'utils/windows'
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
--[[
|
||||
--
|
||||
-- This file is not required for your own configuration,
|
||||
-- but helps people determine if their system is setup correctly.
|
||||
--
|
||||
--]]
|
||||
|
||||
local check_version = function()
|
||||
local verstr = tostring(vim.version())
|
||||
if not vim.version.ge then
|
||||
vim.health.error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr))
|
||||
return
|
||||
end
|
||||
|
||||
if vim.version.ge(vim.version(), '0.10-dev') then
|
||||
vim.health.ok(string.format("Neovim version is: '%s'", verstr))
|
||||
else
|
||||
vim.health.error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr))
|
||||
end
|
||||
end
|
||||
|
||||
local check_external_reqs = function()
|
||||
-- Basic utils: `git`, `make`, `unzip`
|
||||
for _, exe in ipairs { 'git', 'make', 'unzip', 'rg' } do
|
||||
local is_executable = vim.fn.executable(exe) == 1
|
||||
if is_executable then
|
||||
vim.health.ok(string.format("Found executable: '%s'", exe))
|
||||
else
|
||||
vim.health.warn(string.format("Could not find executable: '%s'", exe))
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return {
|
||||
check = function()
|
||||
vim.health.start 'kickstart.nvim'
|
||||
|
||||
vim.health.info [[NOTE: Not every warning is a 'must-fix' in `:checkhealth`
|
||||
|
||||
Fix only warnings for plugins and languages you intend to use.
|
||||
Mason will give warnings for languages that are not installed.
|
||||
You do not need to install, unless you want to use those languages!]]
|
||||
|
||||
local uv = vim.uv or vim.loop
|
||||
vim.health.info('System Information: ' .. vim.inspect(uv.os_uname()))
|
||||
|
||||
check_version()
|
||||
check_external_reqs()
|
||||
end,
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
-- debug.lua
|
||||
--
|
||||
-- Shows how to use the DAP plugin to debug your code.
|
||||
--
|
||||
-- Primarily focused on configuring the debugger for Go, but can
|
||||
-- be extended to other languages as well. That's why it's called
|
||||
-- kickstart.nvim and not kitchen-sink.nvim ;)
|
||||
|
||||
return {
|
||||
-- NOTE: Yes, you can install new plugins here!
|
||||
'mfussenegger/nvim-dap',
|
||||
-- NOTE: And you can specify dependencies as well
|
||||
dependencies = {
|
||||
-- Creates a beautiful debugger UI
|
||||
'rcarriga/nvim-dap-ui',
|
||||
|
||||
-- Required dependency for nvim-dap-ui
|
||||
'nvim-neotest/nvim-nio',
|
||||
|
||||
-- Installs the debug adapters for you
|
||||
'williamboman/mason.nvim',
|
||||
'jay-babu/mason-nvim-dap.nvim',
|
||||
|
||||
-- Add your own debuggers here
|
||||
'leoluz/nvim-dap-go',
|
||||
},
|
||||
keys = function(_, keys)
|
||||
local dap = require 'dap'
|
||||
local dapui = require 'dapui'
|
||||
return {
|
||||
-- Basic debugging keymaps, feel free to change to your liking!
|
||||
{ '<F5>', dap.continue, desc = 'Debug: Start/Continue' },
|
||||
{ '<F1>', dap.step_into, desc = 'Debug: Step Into' },
|
||||
{ '<F2>', dap.step_over, desc = 'Debug: Step Over' },
|
||||
{ '<F3>', dap.step_out, desc = 'Debug: Step Out' },
|
||||
{ '<leader>b', dap.toggle_breakpoint, desc = 'Debug: Toggle Breakpoint' },
|
||||
{
|
||||
'<leader>B',
|
||||
function()
|
||||
dap.set_breakpoint(vim.fn.input 'Breakpoint condition: ')
|
||||
end,
|
||||
desc = 'Debug: Set Breakpoint',
|
||||
},
|
||||
-- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception.
|
||||
{ '<F7>', dapui.toggle, desc = 'Debug: See last session result.' },
|
||||
unpack(keys),
|
||||
}
|
||||
end,
|
||||
config = function()
|
||||
local dap = require 'dap'
|
||||
local dapui = require 'dapui'
|
||||
|
||||
require('mason-nvim-dap').setup {
|
||||
-- Makes a best effort to setup the various debuggers with
|
||||
-- reasonable debug configurations
|
||||
automatic_installation = true,
|
||||
|
||||
-- You can provide additional configuration to the handlers,
|
||||
-- see mason-nvim-dap README for more information
|
||||
handlers = {},
|
||||
|
||||
-- You'll need to check that you have the required things installed
|
||||
-- online, please don't ask me how to install them :)
|
||||
ensure_installed = {
|
||||
-- Update this to ensure that you have the debuggers for the langs you want
|
||||
'delve',
|
||||
},
|
||||
}
|
||||
|
||||
-- Dap UI setup
|
||||
-- For more information, see |:help nvim-dap-ui|
|
||||
dapui.setup {
|
||||
-- Set icons to characters that are more likely to work in every terminal.
|
||||
-- Feel free to remove or use ones that you like more! :)
|
||||
-- Don't feel like these are good choices.
|
||||
icons = { expanded = '▾', collapsed = '▸', current_frame = '*' },
|
||||
controls = {
|
||||
icons = {
|
||||
pause = '⏸',
|
||||
play = '▶',
|
||||
step_into = '⏎',
|
||||
step_over = '⏭',
|
||||
step_out = '⏮',
|
||||
step_back = 'b',
|
||||
run_last = '▶▶',
|
||||
terminate = '⏹',
|
||||
disconnect = '⏏',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
dap.listeners.after.event_initialized['dapui_config'] = dapui.open
|
||||
dap.listeners.before.event_terminated['dapui_config'] = dapui.close
|
||||
dap.listeners.before.event_exited['dapui_config'] = dapui.close
|
||||
|
||||
-- Install golang specific config
|
||||
require('dap-go').setup {
|
||||
delve = {
|
||||
-- On Windows delve must be run attached or it crashes.
|
||||
-- See https://github.com/leoluz/nvim-dap-go/blob/main/README.md#configuring
|
||||
detached = vim.fn.has 'win32' == 0,
|
||||
},
|
||||
}
|
||||
end,
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
-- Adds git related signs to the gutter, as well as utilities for managing changes
|
||||
-- NOTE: gitsigns is already included in init.lua but contains only the base
|
||||
-- config. This will add also the recommended keymaps.
|
||||
|
||||
return {
|
||||
{
|
||||
'lewis6991/gitsigns.nvim',
|
||||
opts = {
|
||||
on_attach = function(bufnr)
|
||||
local gitsigns = require 'gitsigns'
|
||||
|
||||
local function map(mode, l, r, opts)
|
||||
opts = opts or {}
|
||||
opts.buffer = bufnr
|
||||
vim.keymap.set(mode, l, r, opts)
|
||||
end
|
||||
|
||||
-- Navigation
|
||||
map('n', ']c', function()
|
||||
if vim.wo.diff then
|
||||
vim.cmd.normal { ']c', bang = true }
|
||||
else
|
||||
gitsigns.nav_hunk 'next'
|
||||
end
|
||||
end, { desc = 'Jump to next git [c]hange' })
|
||||
|
||||
map('n', '[c', function()
|
||||
if vim.wo.diff then
|
||||
vim.cmd.normal { '[c', bang = true }
|
||||
else
|
||||
gitsigns.nav_hunk 'prev'
|
||||
end
|
||||
end, { desc = 'Jump to previous git [c]hange' })
|
||||
|
||||
-- Actions
|
||||
-- visual mode
|
||||
map('v', '<leader>hs', function()
|
||||
gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' }
|
||||
end, { desc = 'stage git hunk' })
|
||||
map('v', '<leader>hr', function()
|
||||
gitsigns.reset_hunk { vim.fn.line '.', vim.fn.line 'v' }
|
||||
end, { desc = 'reset git hunk' })
|
||||
-- normal mode
|
||||
map('n', '<leader>hs', gitsigns.stage_hunk, { desc = 'git [s]tage hunk' })
|
||||
map('n', '<leader>hr', gitsigns.reset_hunk, { desc = 'git [r]eset hunk' })
|
||||
map('n', '<leader>hS', gitsigns.stage_buffer, { desc = 'git [S]tage buffer' })
|
||||
map('n', '<leader>hu', gitsigns.undo_stage_hunk, { desc = 'git [u]ndo stage hunk' })
|
||||
map('n', '<leader>hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' })
|
||||
map('n', '<leader>hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' })
|
||||
map('n', '<leader>hb', gitsigns.blame_line, { desc = 'git [b]lame line' })
|
||||
map('n', '<leader>hd', gitsigns.diffthis, { desc = 'git [d]iff against index' })
|
||||
map('n', '<leader>hD', function()
|
||||
gitsigns.diffthis '@'
|
||||
end, { desc = 'git [D]iff against last commit' })
|
||||
-- Toggles
|
||||
map('n', '<leader>tb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' })
|
||||
map('n', '<leader>tD', gitsigns.toggle_deleted, { desc = '[T]oggle git show [D]eleted' })
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
return {
|
||||
{ -- Add indentation guides even on blank lines
|
||||
'lukas-reineke/indent-blankline.nvim',
|
||||
-- Enable `lukas-reineke/indent-blankline.nvim`
|
||||
-- See `:help ibl`
|
||||
main = 'ibl',
|
||||
opts = {},
|
||||
},
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
return {
|
||||
|
||||
{ -- Linting
|
||||
'mfussenegger/nvim-lint',
|
||||
event = { 'BufReadPre', 'BufNewFile' },
|
||||
config = function()
|
||||
local lint = require 'lint'
|
||||
lint.linters_by_ft = {
|
||||
markdown = { 'markdownlint' },
|
||||
}
|
||||
|
||||
-- To allow other plugins to add linters to require('lint').linters_by_ft,
|
||||
-- instead set linters_by_ft like this:
|
||||
-- lint.linters_by_ft = lint.linters_by_ft or {}
|
||||
-- lint.linters_by_ft['markdown'] = { 'markdownlint' }
|
||||
--
|
||||
-- However, note that this will enable a set of default linters,
|
||||
-- which will cause errors unless these tools are available:
|
||||
-- {
|
||||
-- clojure = { "clj-kondo" },
|
||||
-- dockerfile = { "hadolint" },
|
||||
-- inko = { "inko" },
|
||||
-- janet = { "janet" },
|
||||
-- json = { "jsonlint" },
|
||||
-- markdown = { "vale" },
|
||||
-- rst = { "vale" },
|
||||
-- ruby = { "ruby" },
|
||||
-- terraform = { "tflint" },
|
||||
-- text = { "vale" }
|
||||
-- }
|
||||
--
|
||||
-- You can disable the default linters by setting their filetypes to nil:
|
||||
-- lint.linters_by_ft['clojure'] = nil
|
||||
-- lint.linters_by_ft['dockerfile'] = nil
|
||||
-- lint.linters_by_ft['inko'] = nil
|
||||
-- lint.linters_by_ft['janet'] = nil
|
||||
-- lint.linters_by_ft['json'] = nil
|
||||
-- lint.linters_by_ft['markdown'] = nil
|
||||
-- lint.linters_by_ft['rst'] = nil
|
||||
-- lint.linters_by_ft['ruby'] = nil
|
||||
-- lint.linters_by_ft['terraform'] = nil
|
||||
-- lint.linters_by_ft['text'] = nil
|
||||
|
||||
-- Create autocommand which carries out the actual linting
|
||||
-- on the specified events.
|
||||
local lint_augroup = vim.api.nvim_create_augroup('lint', { clear = true })
|
||||
vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, {
|
||||
group = lint_augroup,
|
||||
callback = function()
|
||||
lint.try_lint()
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
-- Neo-tree is a Neovim plugin to browse the file system
|
||||
-- https://github.com/nvim-neo-tree/neo-tree.nvim
|
||||
|
||||
return {
|
||||
'nvim-neo-tree/neo-tree.nvim',
|
||||
version = '*',
|
||||
dependencies = {
|
||||
'nvim-lua/plenary.nvim',
|
||||
'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended
|
||||
'MunifTanjim/nui.nvim',
|
||||
},
|
||||
cmd = 'Neotree',
|
||||
keys = {
|
||||
{ '\\', ':Neotree reveal<CR>', desc = 'NeoTree reveal' },
|
||||
},
|
||||
opts = {
|
||||
filesystem = {
|
||||
window = {
|
||||
mappings = {
|
||||
['\\'] = 'close_window',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
return {
|
||||
cmd = { 'ast-grep', 'lsp' },
|
||||
filetypes = { 'java', 'javascript', 'html' },
|
||||
root_dir = function(fname)
|
||||
return require('lspconfig.util').find_git_ancestor(fname) or vim.fn.getcwd()
|
||||
end,
|
||||
settings = {
|
||||
['ast-grep'] = {
|
||||
enable = true,
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
return {
|
||||
name = 'bashls',
|
||||
cmd = { 'bash-language-server', 'start' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ '.git' }, { upward = true })[1]),
|
||||
filetypes = { 'sh', 'bash' },
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
local tools = require 'utils.tools'
|
||||
|
||||
-- Get LSP capabilities with cmp support
|
||||
local capabilities = tools.get_lsp_capabilities()
|
||||
|
||||
-- Setup clangd LSP using autocmd
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'c', 'cpp', 'h', 'hpp' },
|
||||
callback = function()
|
||||
local clangd_path = tools.find_executable 'clangd'
|
||||
|
||||
if clangd_path then
|
||||
vim.lsp.start {
|
||||
name = 'clangd',
|
||||
cmd = {
|
||||
clangd_path,
|
||||
'--background-index',
|
||||
'--clang-tidy',
|
||||
'--header-insertion=iwyu',
|
||||
'--completion-style=detailed',
|
||||
'--function-arg-placeholders',
|
||||
'--fallback-style=llvm',
|
||||
},
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ 'compile_commands.json', 'compile_flags.txt', '.clangd', '.git' }, { upward = true })[1]),
|
||||
capabilities = capabilities,
|
||||
init_options = {
|
||||
usePlaceholders = true,
|
||||
completeUnimported = true,
|
||||
clangdFileStatus = true,
|
||||
},
|
||||
}
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Return empty config since we handle clangd LSP manually via autocmd above
|
||||
return {}
|
|
@ -0,0 +1,6 @@
|
|||
return {
|
||||
name = 'dockerls',
|
||||
cmd = { 'docker-langserver', '--stdio' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ 'Dockerfile', 'dockerfile', '.dockerignore' }, { upward = true })[1]),
|
||||
filetypes = { 'dockerfile', 'Dockerfile' },
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
local tools = require 'utils.tools'
|
||||
|
||||
-- Get LSP capabilities with cmp support
|
||||
local capabilities = tools.get_lsp_capabilities()
|
||||
|
||||
-- Setup gopls LSP using autocmd
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'go',
|
||||
callback = function()
|
||||
local gopls_path = tools.find_executable 'gopls'
|
||||
|
||||
if gopls_path then
|
||||
vim.lsp.start {
|
||||
name = 'gopls',
|
||||
cmd = { gopls_path },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ 'go.mod', 'go.work', '.git' }, { upward = true })[1]),
|
||||
capabilities = capabilities,
|
||||
settings = {
|
||||
gopls = {
|
||||
analyses = {
|
||||
unusedparams = true,
|
||||
},
|
||||
staticcheck = true,
|
||||
gofumpt = true,
|
||||
completeUnimported = true,
|
||||
usePlaceholders = true,
|
||||
experimentalPostfixCompletions = true,
|
||||
hints = {
|
||||
assignVariableTypes = true,
|
||||
compositeLiteralFields = true,
|
||||
compositeLiteralTypes = true,
|
||||
constantValues = true,
|
||||
functionTypeParameters = true,
|
||||
parameterNames = true,
|
||||
rangeVariableTypes = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Return empty config since we handle gopls LSP manually via autocmd above
|
||||
return {}
|
|
@ -0,0 +1,68 @@
|
|||
-- LSP keybindings and autocmds
|
||||
-- Extracted from legacy lsp.lua plugin configuration
|
||||
|
||||
-- LSP attach autocmd with keybindings
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }),
|
||||
callback = function(event)
|
||||
local map = function(keys, func, desc)
|
||||
vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc })
|
||||
end
|
||||
|
||||
-- Navigation keybindings
|
||||
map('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition')
|
||||
map('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
|
||||
map('<leader>D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition')
|
||||
map('<leader>ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols')
|
||||
map('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols')
|
||||
map('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
|
||||
map('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
|
||||
|
||||
-- LSP gr
|
||||
map('grn', vim.lsp.buf.rename, '[R]e[n]ame') -- rename
|
||||
map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' })
|
||||
map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
|
||||
map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
|
||||
map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') -- func def
|
||||
map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') -- header def
|
||||
map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition')
|
||||
map('gO', require('telescope.builtin').lsp_document_symbols, 'Open Document Symbols') -- open symbols
|
||||
map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Open Workspace Symbols') -- open ws
|
||||
|
||||
-- Document highlighting
|
||||
local client = vim.lsp.get_client_by_id(event.data.client_id)
|
||||
if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_documentHighlight) then
|
||||
local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false })
|
||||
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.document_highlight,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.clear_references,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd('LspDetach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }),
|
||||
callback = function(event2)
|
||||
vim.lsp.buf.clear_references()
|
||||
vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf }
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Inlay hints toggle
|
||||
if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then
|
||||
map('<leader>th', function()
|
||||
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf })
|
||||
end, '[T]oggle Inlay [H]ints')
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
vim.keymap.set('n', '<leader>td', function()
|
||||
vim.diagnostic.enable(not vim.diagnostic.is_enabled())
|
||||
end, { silent = true, noremap = true, desc = '[d]iagnostics' })
|
|
@ -0,0 +1,32 @@
|
|||
-- Get LSP capabilities with cmp support
|
||||
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
||||
local ok, cmp_nvim_lsp = pcall(require, 'cmp_nvim_lsp')
|
||||
if ok then
|
||||
capabilities = vim.tbl_deep_extend('force', capabilities, cmp_nvim_lsp.default_capabilities())
|
||||
end
|
||||
|
||||
-- Lua LSP configuration for vim.lsp.enable()
|
||||
return {
|
||||
name = 'lua_ls',
|
||||
cmd = { 'lua-language-server' },
|
||||
filetypes = { 'lua' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ '.luarc.json', '.luarc.jsonc', '.stylua.toml', 'stylua.toml', 'selene.toml' }, { upward = true })[1]),
|
||||
capabilities = capabilities,
|
||||
settings = {
|
||||
Lua = {
|
||||
completion = {
|
||||
callSnippet = 'Replace',
|
||||
},
|
||||
diagnostics = {
|
||||
globals = { 'vim' },
|
||||
},
|
||||
workspace = {
|
||||
library = vim.api.nvim_get_runtime_file('', true),
|
||||
checkThirdParty = false,
|
||||
},
|
||||
telemetry = {
|
||||
enable = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
return {
|
||||
name = 'marksman',
|
||||
cmd = { 'marksman', 'server' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ '.git', '.marksman.toml' }, { upward = true })[1]),
|
||||
filetypes = { 'markdown', 'md' },
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
return {
|
||||
name = 'nixd',
|
||||
cmd = { 'nixd' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ 'flake.nix', 'default.nix', 'shell.nix' }, { upward = true })[1]),
|
||||
filetypes = { 'nix' },
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
local tools = require 'utils.tools'
|
||||
|
||||
-- Get LSP capabilities with cmp support
|
||||
local capabilities = tools.get_lsp_capabilities()
|
||||
|
||||
-- Setup multiple Python LSP servers using autocmd (not via vim.lsp.enable)
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'python',
|
||||
callback = function()
|
||||
-- Stop any unwanted Python LSPs that may have been auto-started
|
||||
local unwanted_lsps = { 'pylsp', 'pyright', 'mypy' }
|
||||
local clients = vim.lsp.get_clients { bufnr = 0 }
|
||||
|
||||
for _, client in ipairs(clients) do
|
||||
for _, unwanted in ipairs(unwanted_lsps) do
|
||||
if client.name == unwanted then
|
||||
vim.lsp.stop_client(client.id, true)
|
||||
vim.notify('Stopped unwanted LSP: ' .. client.name, vim.log.levels.INFO)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Common root directory lookup for all Python LSPs
|
||||
local current_file = vim.api.nvim_buf_get_name(0)
|
||||
local file_dir = vim.fs.dirname(current_file)
|
||||
local root_dir = vim.fs.dirname(
|
||||
vim.fs.find(
|
||||
{ 'pyproject.toml', 'setup.py', 'setup.cfg', 'requirements.txt', 'Pipfile', 'pyrightconfig.json', 'ruff.toml', '.ruff.toml' },
|
||||
{ path = file_dir, upward = true }
|
||||
)[1]
|
||||
)
|
||||
|
||||
local pyright_path = tools.find_tool 'basedpyright-langserver'
|
||||
local ruff_path = tools.find_tool 'ruff'
|
||||
local jedi_path = tools.find_tool 'jedi-language-server'
|
||||
local python3_path = tools.find_tool 'python3'
|
||||
|
||||
-- Setup pyright (hover and type checking)
|
||||
-- https://docs.basedpyright.com/dev/
|
||||
if pyright_path then
|
||||
local pyright_capabilities = vim.tbl_deep_extend('force', capabilities, {})
|
||||
|
||||
vim.lsp.start {
|
||||
name = 'basedpyright',
|
||||
cmd = { pyright_path, '--stdio' },
|
||||
root_dir = root_dir,
|
||||
capabilities = pyright_capabilities,
|
||||
settings = {
|
||||
basedpyright = {
|
||||
analysis = {
|
||||
autoImportCompletion = true,
|
||||
autoSearchPaths = true,
|
||||
diagnosticMode = 'openFilesOnly',
|
||||
typeCheckingMode = 'off', -- 'basic',
|
||||
useLibraryCodeForTypes = true,
|
||||
inlayHints = {
|
||||
callArgumentNames = true,
|
||||
},
|
||||
},
|
||||
pythonPath = python3_path,
|
||||
extraPaths = vim.list_extend(
|
||||
vim.fn.isdirectory(root_dir .. '/python') == 1 and { root_dir .. '/python' } or {},
|
||||
vim.split(vim.env.PYTHONPATH or '', ':')
|
||||
),
|
||||
},
|
||||
},
|
||||
handlers = {
|
||||
['textDocument/publishDiagnostics'] = function() end,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
-- Setup ruff (linting and formatting)
|
||||
if ruff_path then
|
||||
local ruff_capabilities = vim.tbl_deep_extend('force', capabilities, {})
|
||||
ruff_capabilities.textDocument.completion = nil
|
||||
ruff_capabilities.hoverProvider = false
|
||||
|
||||
vim.lsp.start {
|
||||
name = 'ruff',
|
||||
cmd = { ruff_path, 'server' },
|
||||
root_dir = root_dir,
|
||||
capabilities = ruff_capabilities,
|
||||
handlers = {
|
||||
['textDocument/hover'] = function() end,
|
||||
['textDocument/completion'] = function() end,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
-- Setup jedi language server (completions)
|
||||
if jedi_path then
|
||||
local jedi_capabilities = vim.tbl_deep_extend('force', capabilities, {})
|
||||
jedi_capabilities.hoverProvider = false
|
||||
|
||||
vim.lsp.start {
|
||||
name = 'jedi_language_server',
|
||||
cmd = { jedi_path },
|
||||
root_dir = root_dir,
|
||||
capabilities = jedi_capabilities,
|
||||
init_options = {
|
||||
diagnostics = {
|
||||
enable = false,
|
||||
didOpen = false,
|
||||
didChange = false,
|
||||
didSave = false,
|
||||
},
|
||||
},
|
||||
handlers = {
|
||||
['textDocument/publishDiagnostics'] = function() end,
|
||||
['textDocument/hover'] = function() end,
|
||||
},
|
||||
}
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Return empty config since we handle Python LSP manually via autocmd above
|
||||
return {}
|
|
@ -0,0 +1,6 @@
|
|||
return {
|
||||
name = 'taplo',
|
||||
cmd = { 'taplo', 'lsp', 'stdio' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ '.git', '*.toml' }, { upward = true })[1]),
|
||||
filetypes = { 'toml' },
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
-- Get LSP capabilities with cmp support
|
||||
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
||||
local ok, cmp_nvim_lsp = pcall(require, 'cmp_nvim_lsp')
|
||||
if ok then
|
||||
capabilities = vim.tbl_deep_extend('force', capabilities, cmp_nvim_lsp.default_capabilities())
|
||||
end
|
||||
|
||||
return {
|
||||
name = 'ts_ls',
|
||||
cmd = { 'typescript-language-server', '--stdio' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ 'package.json', 'tsconfig.json', 'jsconfig.json', '.git' }, { upward = true })[1]),
|
||||
filetypes = { 'ts' },
|
||||
capabilities = capabilities,
|
||||
settings = {
|
||||
typescript = {
|
||||
inlayHints = {
|
||||
includeInlayParameterNameHints = 'all',
|
||||
includeInlayParameterNameHintsWhenArgumentMatchesName = false,
|
||||
includeInlayFunctionParameterTypeHints = true,
|
||||
includeInlayVariableTypeHints = true,
|
||||
includeInlayPropertyDeclarationTypeHints = true,
|
||||
includeInlayFunctionLikeReturnTypeHints = true,
|
||||
includeInlayEnumMemberValueHints = true,
|
||||
},
|
||||
},
|
||||
javascript = {
|
||||
inlayHints = {
|
||||
includeInlayParameterNameHints = 'all',
|
||||
includeInlayParameterNameHintsWhenArgumentMatchesName = false,
|
||||
includeInlayFunctionParameterTypeHints = true,
|
||||
includeInlayVariableTypeHints = true,
|
||||
includeInlayPropertyDeclarationTypeHints = true,
|
||||
includeInlayFunctionLikeReturnTypeHints = true,
|
||||
includeInlayEnumMemberValueHints = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
-- Get LSP capabilities with cmp support
|
||||
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
||||
local ok, cmp_nvim_lsp = pcall(require, 'cmp_nvim_lsp')
|
||||
if ok then
|
||||
capabilities = vim.tbl_deep_extend('force', capabilities, cmp_nvim_lsp.default_capabilities())
|
||||
end
|
||||
|
||||
return {
|
||||
name = 'yamlls',
|
||||
cmd = { 'yaml-language-server', '--stdio' },
|
||||
filetypes = { 'yaml', 'yml' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find({ '.git', 'docker-compose.yml', 'docker-compose.yaml' }, { upward = true })[1]),
|
||||
capabilities = capabilities,
|
||||
settings = {
|
||||
telemetry = {
|
||||
enabled = false,
|
||||
},
|
||||
yaml = {
|
||||
schemas = {
|
||||
['https://json.schemastore.org/github-workflow.json'] = '/.github/workflows/*',
|
||||
['https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json'] = '/docker-compose*.{yml,yaml}',
|
||||
['https://json.schemastore.org/kustomization.json'] = 'kustomization.{yml,yaml}',
|
||||
['https://json.schemastore.org/chart.json'] = '/Chart.{yml,yaml}',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
-- TODO: blink is faster than nvim-cmp, but still missing integration
|
||||
-- with a good number of other plugins. fuzzy is still being improved.
|
||||
|
||||
return {
|
||||
{
|
||||
'saghen/blink.cmp',
|
||||
-- branch = 'fuzzy-scoring',
|
||||
-- commit = 'b9cca35c503f6d220b1162e604e06477db02a23c',
|
||||
version = 'v1.*',
|
||||
branch = 'main',
|
||||
commit = '2c3d276',
|
||||
event = 'InsertEnter',
|
||||
enabled = function()
|
||||
return vim.g.autocomplete_enable
|
||||
end,
|
||||
dependencies = {
|
||||
'saghen/blink.compat',
|
||||
{
|
||||
'L3MON4D3/LuaSnip',
|
||||
build = (function()
|
||||
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
|
||||
return
|
||||
end
|
||||
return 'make install_jsregexp'
|
||||
end)(),
|
||||
dependencies = {
|
||||
-- `friendly-snippets` contains a variety of premade snippets.
|
||||
-- See the README about individual language/framework/plugin snippets:
|
||||
-- https://github.com/rafamadriz/friendly-snippets
|
||||
-- {
|
||||
-- 'rafamadriz/friendly-snippets',
|
||||
-- config = function()
|
||||
-- require('luasnip.loaders.from_vscode').lazy_load()
|
||||
-- end,
|
||||
-- },
|
||||
},
|
||||
},
|
||||
},
|
||||
opts = {
|
||||
--cmdline = { enabled = false },
|
||||
cmdline = {
|
||||
keymap = {
|
||||
-- recommended, as the default keymap will only show and select the next item
|
||||
['<Tab>'] = { 'show', 'accept' },
|
||||
['<down>'] = { 'select_next', 'fallback' },
|
||||
['<up>'] = { 'select_prev', 'fallback' },
|
||||
['<left>'] = { 'scroll_documentation_up', 'fallback' },
|
||||
['<right>'] = { 'scroll_documentation_down', 'fallback' },
|
||||
['<C-g>'] = { 'cancel', 'fallback' },
|
||||
['<C-h>'] = { 'show', 'fallback' },
|
||||
},
|
||||
completion = {
|
||||
menu = {
|
||||
auto_show = true,
|
||||
},
|
||||
list = {
|
||||
selection = {
|
||||
preselect = true,
|
||||
auto_insert = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fuzzy = {
|
||||
implementation = 'lua', -- slower, more flexible, patchable
|
||||
sorts = { 'exact', 'score', 'sort_text' },
|
||||
use_frecency = false,
|
||||
use_proximity = false,
|
||||
max_typos = function()
|
||||
return 0
|
||||
end,
|
||||
},
|
||||
completion = {
|
||||
keyword = { range = 'full' },
|
||||
-- list = { selection = 'auto_insert' },
|
||||
trigger = {
|
||||
show_on_insert_on_trigger_character = false, -- Use C-Space
|
||||
},
|
||||
accept = {
|
||||
auto_brackets = {
|
||||
enabled = true,
|
||||
},
|
||||
},
|
||||
menu = {
|
||||
border = 'single',
|
||||
draw = {
|
||||
columns = {
|
||||
{ 'kind_icon' },
|
||||
-- { 'source_name' },
|
||||
{ 'label', 'label_description', gap = 1 },
|
||||
},
|
||||
},
|
||||
},
|
||||
documentation = {
|
||||
window = {
|
||||
border = 'single',
|
||||
},
|
||||
},
|
||||
},
|
||||
keymap = {
|
||||
preset = 'default',
|
||||
-- Disable conflicting emacs keys - let neovimacs handle them
|
||||
['<C-k>'] = {}, -- Remove C-k (emacs: kill to end of line)
|
||||
['<C-b>'] = {}, -- Remove C-b (emacs: backward char)
|
||||
['<C-f>'] = {}, -- Remove C-f (emacs: forward char)
|
||||
['<C-p>'] = {}, -- Remove C-p (emacs: previous line)
|
||||
['<C-n>'] = {}, -- Remove C-n (emacs: next line)
|
||||
['<C-e>'] = {}, -- Remove C-e (emacs: end of line)
|
||||
['<C-y>'] = {}, -- Remove C-y (emacs: yank)
|
||||
['<C-Space>'] = {}, -- Remove C-Space (emacs: highlight)
|
||||
|
||||
-- Alternative completion navigation
|
||||
['<M-j>'] = { 'select_next', 'fallback' }, -- Alt-j for next
|
||||
['<M-k>'] = { 'select_prev', 'fallback' }, -- Alt-k for prev
|
||||
['<M-h>'] = { 'scroll_documentation_up', 'fallback' }, -- Alt-h for doc up
|
||||
['<M-l>'] = { 'scroll_documentation_down', 'fallback' }, -- Alt-l for doc down
|
||||
|
||||
-- Keep arrow keys and other non-conflicting bindings
|
||||
['<down>'] = { 'select_next', 'fallback' },
|
||||
['<up>'] = { 'select_prev', 'fallback' },
|
||||
['<left>'] = { 'scroll_documentation_up', 'fallback' },
|
||||
['<right>'] = { 'scroll_documentation_down', 'fallback' },
|
||||
['<Tab>'] = { 'accept', 'fallback' },
|
||||
['<C-g>'] = { 'cancel', 'fallback' },
|
||||
['<C-h>'] = { 'show', 'fallback' },
|
||||
['<C-right>'] = {
|
||||
function(cmp)
|
||||
local luasnip = require 'luasnip'
|
||||
if luasnip.expand_or_locally_jumpable() then
|
||||
luasnip.expand_or_jump()
|
||||
else
|
||||
return cmp.fallback()
|
||||
end
|
||||
end,
|
||||
'fallback',
|
||||
},
|
||||
['<C-left>'] = {
|
||||
function(cmp)
|
||||
local luasnip = require 'luasnip'
|
||||
if luasnip.locally_jumpable(-1) then
|
||||
luasnip.jump(-1)
|
||||
else
|
||||
return cmp.fallback()
|
||||
end
|
||||
end,
|
||||
'fallback',
|
||||
},
|
||||
},
|
||||
signature = {
|
||||
enabled = true,
|
||||
window = {
|
||||
border = 'single',
|
||||
},
|
||||
},
|
||||
sources = {
|
||||
default = { 'lsp', 'path', 'snippets', 'buffer' },
|
||||
per_filetype = {},
|
||||
-- TODO: broken
|
||||
providers = {
|
||||
tabnine = {
|
||||
name = 'Tabnine',
|
||||
module = 'blink.compat.source',
|
||||
},
|
||||
},
|
||||
},
|
||||
snippets = {
|
||||
preset = 'luasnip',
|
||||
},
|
||||
},
|
||||
config = function(_, opts)
|
||||
local luasnip = require 'luasnip'
|
||||
luasnip.config.setup {}
|
||||
|
||||
require('blink.cmp').setup(opts)
|
||||
end,
|
||||
},
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
return {
|
||||
{
|
||||
'hrsh7th/nvim-cmp',
|
||||
event = 'InsertEnter',
|
||||
dependencies = {
|
||||
{
|
||||
'L3MON4D3/LuaSnip',
|
||||
build = (function()
|
||||
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
|
||||
return
|
||||
end
|
||||
return 'make install_jsregexp'
|
||||
end)(),
|
||||
dependencies = {
|
||||
-- `friendly-snippets` contains a variety of premade snippets.
|
||||
-- See the README about individual language/framework/plugin snippets:
|
||||
-- https://github.com/rafamadriz/friendly-snippets
|
||||
-- {
|
||||
-- 'rafamadriz/friendly-snippets',
|
||||
-- config = function()
|
||||
-- require('luasnip.loaders.from_vscode').lazy_load()
|
||||
-- end,
|
||||
-- },
|
||||
},
|
||||
},
|
||||
'saadparwaiz1/cmp_luasnip',
|
||||
|
||||
-- Other completions
|
||||
'hrsh7th/cmp-nvim-lsp',
|
||||
'hrsh7th/cmp-path',
|
||||
},
|
||||
config = function()
|
||||
-- See `:help cmp`
|
||||
local cmp = require 'cmp'
|
||||
local luasnip = require 'luasnip'
|
||||
luasnip.config.setup {}
|
||||
|
||||
cmp.setup {
|
||||
snippet = {
|
||||
expand = function(args)
|
||||
luasnip.lsp_expand(args.body)
|
||||
end,
|
||||
},
|
||||
completion = {
|
||||
autocomplete = false, -- Use C-Space
|
||||
completeopt = 'menu,menuone,noinsert',
|
||||
},
|
||||
-- `:help ins-completion`
|
||||
mapping = cmp.mapping.preset.insert {
|
||||
['<down>'] = cmp.mapping.select_next_item(),
|
||||
['<up>'] = cmp.mapping.select_prev_item(),
|
||||
['<left>'] = cmp.mapping.scroll_docs(-4),
|
||||
['<right>'] = cmp.mapping.scroll_docs(4),
|
||||
['<Tab>'] = cmp.mapping.confirm { select = true },
|
||||
['<C-g>'] = cmp.mapping.abort(),
|
||||
['<C-h>'] = cmp.mapping.complete {},
|
||||
['<C-right>'] = cmp.mapping(function()
|
||||
if luasnip.expand_or_locally_jumpable() then
|
||||
luasnip.expand_or_jump()
|
||||
end
|
||||
end, { 'i', 's' }),
|
||||
['<C-left>'] = cmp.mapping(function()
|
||||
if luasnip.locally_jumpable(-1) then
|
||||
luasnip.jump(-1)
|
||||
end
|
||||
end, { 'i', 's' }),
|
||||
['<C-n>'] = cmp.config.disable,
|
||||
['<C-p>'] = cmp.config.disable,
|
||||
},
|
||||
sources = {
|
||||
{
|
||||
name = 'lazydev',
|
||||
-- set group index to 0 to skip loading LuaLS completions as lazydev recommends it
|
||||
group_index = 0,
|
||||
},
|
||||
{ name = 'nvim_lsp' },
|
||||
{ name = 'luasnip' },
|
||||
{ name = 'path' },
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
return {
|
||||
{
|
||||
'yetone/avante.nvim',
|
||||
event = 'VeryLazy',
|
||||
lazy = false,
|
||||
version = false,
|
||||
opts = {
|
||||
-- Use ANTHROPIC_API_KEY=your-api-key
|
||||
providers = {
|
||||
claude = {
|
||||
auto_suggestions_provider = 'claude', -- high-frequency provider (free recommended)
|
||||
claude = {
|
||||
endpoint = 'https://api.anthropic.com',
|
||||
model = 'claude-3-5-sonnet-20241022',
|
||||
temperature = 0,
|
||||
max_tokens = 4096,
|
||||
},
|
||||
},
|
||||
},
|
||||
hints = { enabled = false },
|
||||
},
|
||||
build = 'make', -- BUILD_FROM_SOURCE=true
|
||||
dependencies = {
|
||||
'stevearc/dressing.nvim',
|
||||
'nvim-lua/plenary.nvim',
|
||||
'MunifTanjim/nui.nvim',
|
||||
--- The below dependencies are optional,
|
||||
'hrsh7th/nvim-cmp', -- autocompletion for avante commands and mentions
|
||||
'echasnovski/mini.icons',
|
||||
{
|
||||
-- support for image pasting
|
||||
'HakonHarnes/img-clip.nvim',
|
||||
event = 'VeryLazy',
|
||||
opts = {
|
||||
default = {
|
||||
embed_image_as_base64 = false,
|
||||
prompt_for_file_name = false,
|
||||
drag_and_drop = {
|
||||
insert_mode = true,
|
||||
},
|
||||
use_absolute_path = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
-- Make sure to set this up properly if you have lazy=true
|
||||
'MeanderingProgrammer/render-markdown.nvim',
|
||||
opts = {
|
||||
file_types = { 'markdown', 'Avante' },
|
||||
},
|
||||
ft = { 'markdown', 'Avante' },
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
{ '<leader>la', '<cmd>AvanteChat<cr>', desc = '[A]vante Chat' },
|
||||
},
|
||||
},
|
||||
}
|
|
@ -1 +1,13 @@
|
|||
return {
'akinsho/bufferline.nvim',
dependencies = { 'nvim-tree/nvim-web-devicons' },
version = '*',
opts = {
options = {
always_show_bufferline = false,
mode = 'tabs',
},
},
}
|
||||
return {
|
||||
{
|
||||
'akinsho/bufferline.nvim',
|
||||
dependencies = { 'nvim-tree/nvim-web-devicons' },
|
||||
version = '*',
|
||||
opts = {
|
||||
options = {
|
||||
always_show_bufferline = false,
|
||||
mode = 'tabs',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
return {
|
||||
'greggh/claude-code.nvim',
|
||||
dependencies = {
|
||||
'nvim-lua/plenary.nvim', -- Required for git operations
|
||||
},
|
||||
config = function()
|
||||
require('claude-code').setup {
|
||||
window = {
|
||||
split_ratio = 0.5,
|
||||
position = 'botright',
|
||||
enter_insert = true,
|
||||
hide_numbers = true,
|
||||
hide_signcolumn = true,
|
||||
},
|
||||
}
|
||||
end,
|
||||
keys = {
|
||||
{ '<leader>lc', '<cmd>ClaudeCode<cr>', desc = '[C]laude Code' },
|
||||
},
|
||||
}
|
|
@ -2,9 +2,22 @@ return {
|
|||
{
|
||||
'folke/tokyonight.nvim',
|
||||
priority = 1000, -- Make sure to load this before all the other start plugins.
|
||||
init = function()
|
||||
config = function()
|
||||
---@diagnostic disable-next-line: missing-fields
|
||||
require('tokyonight').setup {
|
||||
styles = {
|
||||
comments = { italic = false }, -- Disable italics in comments
|
||||
},
|
||||
}
|
||||
|
||||
vim.cmd.colorscheme 'tokyonight-night'
|
||||
-- vim.cmd.hi 'Comment gui=none'
|
||||
end,
|
||||
opts = {
|
||||
on_highlights = function(hl, c)
|
||||
hl.TelescopeNormal = {
|
||||
fg = c.fg_dark,
|
||||
}
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -12,28 +12,63 @@ return {
|
|||
mode = '',
|
||||
desc = '[Fo]rmat Buffer',
|
||||
},
|
||||
{
|
||||
'<leader>tf',
|
||||
function()
|
||||
vim.g.format_on_save_enabled = not vim.g.format_on_save_enabled
|
||||
vim.notify('Format on save: ' .. (vim.g.format_on_save_enabled and 'enabled' or 'disabled'))
|
||||
end,
|
||||
mode = '',
|
||||
desc = '[F]ormat on save',
|
||||
},
|
||||
},
|
||||
opts = {
|
||||
notify_on_error = false,
|
||||
format_on_save = function(bufnr)
|
||||
local disable_filetypes = { c = true, cpp = true, sh = true }
|
||||
return {
|
||||
timeout_ms = 500,
|
||||
lsp_fallback = not disable_filetypes[vim.bo[bufnr].filetype],
|
||||
}
|
||||
if not vim.g.format_on_save_enabled then
|
||||
return false
|
||||
end
|
||||
|
||||
local disable_filetypes = { c = true, cpp = true, sh = true, nix = true, md = true }
|
||||
if disable_filetypes[vim.bo[bufnr].filetype] then
|
||||
return nil
|
||||
else
|
||||
return {
|
||||
async = false,
|
||||
timeout_ms = 3000,
|
||||
lsp_fallback = not disable_filetypes[vim.bo[bufnr].filetype],
|
||||
}
|
||||
end
|
||||
end,
|
||||
formatters_by_ft = {
|
||||
c = { 'clangd-format', 'cpplint' },
|
||||
cs = { 'ast-grep' }, -- c#
|
||||
css = { 'prettier' },
|
||||
cmake = { 'cmakelang' },
|
||||
cpp = { 'clangd-format', 'cpplint' },
|
||||
flow = { 'prettier' },
|
||||
go = { 'ast-grep', 'golangci-lint' }, -- gofumpt requires go
|
||||
html = { 'prettier' },
|
||||
h = { 'clangd-format', 'cpplint' },
|
||||
hpp = { 'clangd-format', 'cpplint' },
|
||||
java = { 'ast-grep' },
|
||||
javascript = { 'prettier' },
|
||||
javascriptreact = { 'prettier' },
|
||||
-- jinja = { 'djlint' },
|
||||
json = { 'prettier' },
|
||||
-- latex = { 'tex-fmt' },
|
||||
lua = { 'stylua' },
|
||||
python = {
|
||||
'black',
|
||||
'isort',
|
||||
'ruff_format',
|
||||
'pyright',
|
||||
},
|
||||
-- php = { 'php-cs-fixer' },
|
||||
markdown = { 'prettier' },
|
||||
md = { 'prettier' },
|
||||
nix = { 'nixfmt' },
|
||||
yaml = { 'yamlfmt' },
|
||||
nix = { 'alejandra' },
|
||||
python = { 'isort', 'ruff_format' },
|
||||
-- r = { 'air' },
|
||||
sh = { 'shfmt' },
|
||||
-- tf = { 'terraform' },
|
||||
typescript = { 'prettier' },
|
||||
typescriptreact = { 'prettier' },
|
||||
yaml = { 'prettier' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -10,5 +10,21 @@ return {
|
|||
changedelete = { text = '~' },
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
{
|
||||
'<leader>tB',
|
||||
function()
|
||||
require('gitsigns').toggle_current_line_blame()
|
||||
end,
|
||||
desc = 'Git [B]lame',
|
||||
},
|
||||
{
|
||||
'<leader>tD',
|
||||
function()
|
||||
require('gitsigns').toggle_deleted()
|
||||
end,
|
||||
desc = '[D]eleted git lines',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
return {
|
||||
{ -- properly configures LuaLS
|
||||
'folke/lazydev.nvim',
|
||||
ft = 'lua',
|
||||
opts = {
|
||||
library = {
|
||||
-- Load luvit types when the `vim.uv` word is found
|
||||
{ path = 'luvit-meta/library', words = { 'vim%.uv' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
{ 'Bilal2453/luvit-meta', lazy = true },
|
||||
{
|
||||
-- Main LSP Configuration
|
||||
'neovim/nvim-lspconfig',
|
||||
dependencies = {
|
||||
-- Automatically install LSPs and related tools to stdpath for Neovim
|
||||
{ 'williamboman/mason.nvim', config = true }, -- NOTE: Must be loaded before dependants
|
||||
'williamboman/mason-lspconfig.nvim',
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
|
||||
-- Useful status updates for LSP.
|
||||
-- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})`
|
||||
{ 'j-hui/fidget.nvim', opts = {} },
|
||||
|
||||
-- Allows extra capabilities provided by nvim-cmp
|
||||
'hrsh7th/cmp-nvim-lsp',
|
||||
},
|
||||
config = function()
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }),
|
||||
callback = function(event)
|
||||
local map = function(keys, func, desc)
|
||||
vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc })
|
||||
end
|
||||
|
||||
map('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition')
|
||||
map('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
|
||||
map('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
|
||||
map('<leader>D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition')
|
||||
map('<leader>ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols')
|
||||
map('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols')
|
||||
map('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
|
||||
map('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
|
||||
map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
|
||||
|
||||
-- :help CursorHold
|
||||
local client = vim.lsp.get_client_by_id(event.data.client_id)
|
||||
if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_documentHighlight) then
|
||||
local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false })
|
||||
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.document_highlight,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
|
||||
buffer = event.buf,
|
||||
group = highlight_augroup,
|
||||
callback = vim.lsp.buf.clear_references,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd('LspDetach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }),
|
||||
callback = function(event2)
|
||||
vim.lsp.buf.clear_references()
|
||||
vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf }
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Inlay hints
|
||||
if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then
|
||||
map('<leader>th', function()
|
||||
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf })
|
||||
end, '[T]oggle Inlay [H]ints')
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
||||
capabilities = vim.tbl_deep_extend('force', capabilities, require('cmp_nvim_lsp').default_capabilities())
|
||||
|
||||
local servers = {
|
||||
clangd = {},
|
||||
pyright = {},
|
||||
black = {},
|
||||
isort = {},
|
||||
taplo = {},
|
||||
-- rust_analyzer = {},
|
||||
lua_ls = {
|
||||
-- cmd = {...},
|
||||
-- filetypes = { ...},
|
||||
-- capabilities = {},
|
||||
settings = {
|
||||
Lua = {
|
||||
completion = {
|
||||
callSnippet = 'Replace',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
-- Ensure the servers and tools above are installed
|
||||
-- :Mason
|
||||
require('mason').setup()
|
||||
|
||||
-- You can add other tools here that you want Mason to install
|
||||
-- for you, so that they are available from within Neovim.
|
||||
local ensure_installed = vim.tbl_keys(servers or {})
|
||||
vim.list_extend(ensure_installed, {
|
||||
'bashls', -- bash
|
||||
'black', -- python format
|
||||
'cmake', -- cmake
|
||||
'clangd', -- cpp
|
||||
'debugpy', -- debugger
|
||||
'dockerls', -- docker
|
||||
'golangci-lint', -- go
|
||||
'isort', -- python sorting
|
||||
'jedi-language-server', -- jedi completion
|
||||
'jsonls', -- json
|
||||
'lua_ls', -- lua
|
||||
'marksman', -- markdown
|
||||
'mypy', -- python checking
|
||||
'nixpkgs-fmt', -- Nix
|
||||
'prettier', -- md
|
||||
'pyright', -- python lsp
|
||||
'ruff', -- lint and format for python
|
||||
'rust-analyzer', -- rust
|
||||
'shfmt', -- shell
|
||||
'stylua', -- Used to format Lua code
|
||||
'taplo', -- LSP for toml files
|
||||
'tree-sitter-cli', -- treesitter
|
||||
'ts_ls', -- typescript
|
||||
'yamllint', -- yaml
|
||||
'yamlfmt', -- yaml
|
||||
'yamlls', -- yaml
|
||||
})
|
||||
require('mason-tool-installer').setup { ensure_installed = ensure_installed }
|
||||
|
||||
require('mason-lspconfig').setup {
|
||||
handlers = {
|
||||
function(server_name)
|
||||
local server = servers[server_name] or {}
|
||||
server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {})
|
||||
require('lspconfig')[server_name].setup(server)
|
||||
end,
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
return {
|
||||
{
|
||||
'nvim-lualine/lualine.nvim',
|
||||
dependencies = { 'nvim-tree/nvim-web-devicons' },
|
||||
config = function()
|
||||
local mode_map = {
|
||||
['NORMAL'] = 'N',
|
||||
['O-PENDING'] = 'N?',
|
||||
['INSERT'] = 'I',
|
||||
['VISUAL'] = 'V',
|
||||
['V-BLOCK'] = 'VB',
|
||||
['V-LINE'] = 'VL',
|
||||
['V-REPLACE'] = 'VR',
|
||||
['REPLACE'] = 'R',
|
||||
['COMMAND'] = '!',
|
||||
['SHELL'] = 'SH',
|
||||
['TERMINAL'] = 'T',
|
||||
['EX'] = 'X',
|
||||
['S-BLOCK'] = 'SB',
|
||||
['S-LINE'] = 'SL',
|
||||
['SELECT'] = 'S',
|
||||
['CONFIRM'] = 'Y?',
|
||||
['MORE'] = 'M',
|
||||
}
|
||||
require('lualine').setup {
|
||||
options = {
|
||||
icons_enabled = true,
|
||||
theme = 'auto',
|
||||
component_separators = { left = '', right = '' },
|
||||
section_separators = { left = '', right = '' },
|
||||
disabled_filetypes = {
|
||||
statusline = {},
|
||||
winbar = {},
|
||||
},
|
||||
ignore_focus = {},
|
||||
always_divide_middle = true,
|
||||
always_show_tabline = true,
|
||||
globalstatus = false,
|
||||
refresh = {
|
||||
statusline = 100,
|
||||
tabline = 100,
|
||||
winbar = 100,
|
||||
},
|
||||
},
|
||||
sections = {
|
||||
lualine_a = { {
|
||||
'mode',
|
||||
fmt = function(s)
|
||||
return mode_map[s] or s
|
||||
end,
|
||||
} },
|
||||
lualine_b = { 'branch', 'diff', 'diagnostics' },
|
||||
lualine_c = { 'filename' },
|
||||
lualine_x = {
|
||||
'encoding',
|
||||
'fileformat',
|
||||
'filetype',
|
||||
{
|
||||
'tabnine',
|
||||
fmt = function(s)
|
||||
if string.match(s, 'disabled') or s == '' then
|
||||
return '-'
|
||||
else
|
||||
return '⌬'
|
||||
end
|
||||
end,
|
||||
},
|
||||
{
|
||||
function()
|
||||
return vim.g.format_on_save_enabled and '' or ''
|
||||
end,
|
||||
color = { fg = '#98c379' },
|
||||
},
|
||||
},
|
||||
lualine_y = { 'progress' },
|
||||
lualine_z = { 'location' },
|
||||
},
|
||||
inactive_sections = {
|
||||
lualine_a = {},
|
||||
lualine_b = {},
|
||||
lualine_c = { 'filename' },
|
||||
lualine_x = { 'location' },
|
||||
lualine_y = {},
|
||||
lualine_z = {},
|
||||
},
|
||||
tabline = {},
|
||||
winbar = {},
|
||||
inactive_winbar = {},
|
||||
extensions = {},
|
||||
-- '' or ''
|
||||
}
|
||||
end,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
return {
|
||||
-- Mason: LSP/DAP/Linter/Formatter installer
|
||||
{
|
||||
'mason-org/mason.nvim',
|
||||
config = function()
|
||||
require('mason').setup()
|
||||
|
||||
-- Add Mason bin directory to PATH
|
||||
local mason_bin = vim.fn.stdpath 'data' .. '/mason/bin'
|
||||
local current_path = vim.env.PATH or ''
|
||||
if not string.find(current_path, mason_bin, 1, true) then
|
||||
vim.env.PATH = mason_bin .. ':' .. current_path
|
||||
end
|
||||
|
||||
-- Auto-cleanup unused packages (add when deprecating packages)
|
||||
--
|
||||
vim.defer_fn(function()
|
||||
local registry = require 'mason-registry'
|
||||
local unused_packages = {
|
||||
'black',
|
||||
'mypy',
|
||||
'pyright',
|
||||
'nixpkgs-fmt',
|
||||
'python-lsp-server',
|
||||
'pyflakes',
|
||||
'pylint',
|
||||
'pep8',
|
||||
}
|
||||
|
||||
for _, package_name in ipairs(unused_packages) do
|
||||
if registry.is_installed(package_name) then
|
||||
local package = registry.get_package(package_name)
|
||||
package:uninstall():once('closed', function()
|
||||
vim.notify('Removed unused package: ' .. package_name, vim.log.levels.INFO)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end, 1000)
|
||||
end,
|
||||
},
|
||||
|
||||
-- Mason tool installer for formatters/linters
|
||||
-- Note: mason-lspconfig.nvim is not used for LSP beyond installs, we use vim.lsp fot that
|
||||
{
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
dependencies = { 'williamboman/mason.nvim', 'williamboman/mason-lspconfig.nvim' },
|
||||
config = function()
|
||||
-- Function to translate LSP server names to Mason package names using mason-lspconfig
|
||||
local function translate_lsp_names(lsp_servers)
|
||||
local mason_packages = {}
|
||||
local ok, mason_lspconfig = pcall(require, 'mason-lspconfig')
|
||||
|
||||
if ok then
|
||||
for _, server in ipairs(lsp_servers) do
|
||||
local success, package_name = pcall(mason_lspconfig.get_mason_package, server)
|
||||
if success and package_name then
|
||||
table.insert(mason_packages, package_name.name)
|
||||
else
|
||||
-- Fallback to original name if no mapping found
|
||||
table.insert(mason_packages, server)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- If mason-lspconfig not available, use original names
|
||||
mason_packages = lsp_servers
|
||||
end
|
||||
|
||||
return mason_packages
|
||||
end
|
||||
|
||||
-- LSP servers to install (using mason-lspconfig names)
|
||||
local lsp_servers = {
|
||||
'clangd',
|
||||
'basedpyright',
|
||||
'bashls', -- bash-language-server
|
||||
'dockerls', -- dockerfile-language-server
|
||||
-- 'gopls', -- go
|
||||
'jedi_language_server',
|
||||
'lua_ls', -- lua-language-server
|
||||
'marksman',
|
||||
'rust_analyzer',
|
||||
'taplo',
|
||||
'ts_ls', -- typescript-language-server
|
||||
'yamlls', -- yaml-language-server
|
||||
}
|
||||
|
||||
-- Other tools
|
||||
local other_tools = {
|
||||
-- Formatters
|
||||
'alejandra', -- nix
|
||||
'ast-grep',
|
||||
'clang-format',
|
||||
'cmakelang',
|
||||
'isort', -- python
|
||||
'prettier',
|
||||
'ruff', -- python
|
||||
'shfmt',
|
||||
'stylua',
|
||||
|
||||
-- Linters
|
||||
'ast-grep',
|
||||
'cmakelint',
|
||||
'cpplint',
|
||||
'golangci-lint',
|
||||
'ruff', -- python
|
||||
'yamllint',
|
||||
'golangci-lint',
|
||||
|
||||
-- Debuggers
|
||||
'debugpy',
|
||||
|
||||
-- Additional tools
|
||||
'tree-sitter-cli',
|
||||
}
|
||||
|
||||
-- Combine translated LSP servers with other tools
|
||||
local all_tools = {}
|
||||
vim.list_extend(all_tools, translate_lsp_names(lsp_servers))
|
||||
vim.list_extend(all_tools, other_tools)
|
||||
|
||||
require('mason-tool-installer').setup {
|
||||
ensure_installed = all_tools,
|
||||
auto_update = false,
|
||||
run_on_start = true,
|
||||
}
|
||||
end,
|
||||
},
|
||||
}
|
|
@ -16,13 +16,6 @@ return {
|
|||
-- - sd' - [S]urround [D]elete [']quotes
|
||||
-- - sr)' - [S]urround [R]eplace [)] [']
|
||||
require('mini.surround').setup()
|
||||
|
||||
local statusline = require 'mini.statusline'
|
||||
statusline.setup { use_icons = vim.g.have_nerd_font }
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
statusline.section_location = function()
|
||||
return '%2l:%-2v'
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
|
@ -1,6 +1,11 @@
|
|||
return {
|
||||
{ -- Emacs-style keybindings in insert mode
|
||||
{
|
||||
'millerjason/neovimacs.nvim',
|
||||
opts = {},
|
||||
opts = {
|
||||
VM_Enabled = vim.g.neovimacs_bindings,
|
||||
VM_StartInsert = vim.g.neovimacs_insert,
|
||||
VM_UnixConsoleMetaSendsEsc = false,
|
||||
TabIndentStyle = 'none', -- 'emacs', 'never', 'whitespace', 'startofline'
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -13,12 +13,17 @@ return {
|
|||
log_file_path = nil,
|
||||
ignore_certificate_errors = false,
|
||||
}
|
||||
require('tabnine.status').disable_tabnine()
|
||||
if vim.g.tabnine_enable then
|
||||
require('tabnine.status').enable_tabnine()
|
||||
else
|
||||
require('tabnine.status').disable_tabnine()
|
||||
end
|
||||
end,
|
||||
lazy = false,
|
||||
keys = {
|
||||
{ '<leader>lc', '<cmd>TabnineChat<cr>', desc = '[L]LM [C]hat' },
|
||||
{ '<leader>lt', '<cmd>TabnineToggle<cr>', desc = '[L]LM [T]oggle' },
|
||||
{ '<leader>ls', '<cmd>TabnineStatus<cr>', desc = '[L]LM [S]tatus' },
|
||||
{ '<leader>t9', '<cmd>TabnineToggle<cr>', desc = '[T]oggle' },
|
||||
{ '<leader>l9e', '<cmd>TabnineEnable<cr>', desc = 'T9 [E]nable' },
|
||||
{ '<leader>l9c', '<cmd>TabnineChat<cr>', desc = 'T9 [C]hat' },
|
||||
{ '<leader>l9s', '<cmd>TabnineStatus<cr>', desc = 'T9 [S]tatus' },
|
||||
},
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@ return {
|
|||
vim.keymap.set('n', '<leader>fg', builtin.live_grep, { desc = 'Find [G]rep' })
|
||||
vim.keymap.set('n', '<leader>fb', builtin.buffers, { desc = 'Find [B]uffers' })
|
||||
vim.keymap.set('n', '<leader>fh', builtin.help_tags, { desc = 'Find [H]elp tags' })
|
||||
vim.keymap.set('n', '<leader><leader>', builtin.buffers, { desc = '[ ] Find existing buffers' })
|
||||
|
||||
-- Slightly advanced example of overriding default behavior and theme
|
||||
vim.keymap.set('n', '<leader>/', function()
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
return {
|
||||
{
|
||||
'rachartier/tiny-inline-diagnostic.nvim',
|
||||
event = 'VeryLazy',
|
||||
priority = 1000, -- needs to be loaded in first
|
||||
config = function(_, opts)
|
||||
vim.opt.updatetime = 100
|
||||
vim.api.nvim_set_hl(0, 'DiagnosticError', { fg = '#f76464' })
|
||||
vim.api.nvim_set_hl(0, 'DiagnosticWarn', { fg = '#f7bf64' })
|
||||
vim.api.nvim_set_hl(0, 'DiagnosticInfo', { fg = '#64bcf7' })
|
||||
vim.api.nvim_set_hl(0, 'DiagnosticHint', { fg = '#64f79d' })
|
||||
require('tiny-inline-diagnostic').setup(opts)
|
||||
end,
|
||||
opts = {
|
||||
enable_on_insert = true,
|
||||
multiple_diag_under_cursor = true,
|
||||
show_all_diags_on_cursorline = true,
|
||||
multilines = {
|
||||
enabled = false,
|
||||
always_show = true,
|
||||
},
|
||||
signs = {
|
||||
left = '',
|
||||
right = '',
|
||||
diag = '',
|
||||
arrow = ' ',
|
||||
up_arrow = ' ',
|
||||
vertical = ' │',
|
||||
vertical_end = ' └',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
return {
|
||||
'linux-cultist/venv-selector.nvim',
|
||||
'linux-cultist/venv-selector.nvim',
|
||||
branch = 'regexp',
|
||||
dependencies = {
|
||||
'neovim/nvim-lspconfig',
|
||||
|
|
|
@ -2,18 +2,26 @@ return {
|
|||
{ -- Shows keybindings as you go
|
||||
'folke/which-key.nvim',
|
||||
event = 'VimEnter',
|
||||
config = function()
|
||||
require('which-key').setup()
|
||||
-- Document existing key chains
|
||||
require('which-key').add {
|
||||
opts = {
|
||||
delay = 0,
|
||||
icons = {
|
||||
mappings = vim.g.have_nerd_font,
|
||||
},
|
||||
spec = {
|
||||
{ '<leader>a', group = '[A]vante' },
|
||||
{ '<leader>c', group = '[C]ode' },
|
||||
{ '<leader>d', group = '[D]ocument' },
|
||||
{ '<leader>r', group = '[R]ename' },
|
||||
{ '<leader>s', group = '[S]earch' },
|
||||
{ '<leader>w', group = '[W]orkspace' },
|
||||
{ '<leader>w', group = '[W]indow' },
|
||||
{ '<leader>t', group = '[T]oggle' },
|
||||
{ '<leader>l', group = '[L]LM Assist' },
|
||||
{ '<leader>l9', group = 'Tab[9]' },
|
||||
{ '<leader>h', group = 'Git [H]unk', mode = { 'n', 'v' } },
|
||||
}
|
||||
end,
|
||||
{ '<leader>p', group = '[P] Explore', mode = { 'n' } },
|
||||
{ '<leader>f', group = '[F]ind/Grep' },
|
||||
{ '<leader>i', group = '[I]ndent' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
local M = {}
|
||||
|
||||
-- Helper function to find the executable in path, prioritizing non-mason paths
|
||||
function M.find_executable(executable)
|
||||
-- First try with PATH environment variable
|
||||
local paths = vim.split(vim.env.PATH, ':', { plain = true })
|
||||
for _, dir in ipairs(paths) do
|
||||
if dir ~= '' and not string.find(dir, 'mason') then
|
||||
local path = dir .. '/' .. executable
|
||||
if vim.fn.filereadable(path) == 1 and vim.fn.executable(path) == 1 then
|
||||
return path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback to mason path if needed
|
||||
local path = vim.fn.exepath(executable)
|
||||
return path ~= '' and path or nil
|
||||
end
|
||||
|
||||
-- Function to detect python venv path
|
||||
function M.get_python_venv_path()
|
||||
-- Get the directory of the current file
|
||||
local current_file = vim.api.nvim_buf_get_name(0)
|
||||
local current_dir = vim.fn.fnamemodify(current_file, ':h')
|
||||
|
||||
-- Function to find git root
|
||||
local function find_git_root(path)
|
||||
local git_dir = vim.fn.finddir('.git', path .. ';')
|
||||
if git_dir ~= '' then
|
||||
return vim.fn.fnamemodify(git_dir, ':h')
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Search paths in order: current directory, git root, user path
|
||||
local search_paths = {
|
||||
current_dir,
|
||||
find_git_root(current_dir),
|
||||
vim.fn.expand '~',
|
||||
}
|
||||
|
||||
-- Check each search path for .venv
|
||||
for _, path in ipairs(search_paths) do
|
||||
if path then
|
||||
local venv_path = path .. '/.venv'
|
||||
if vim.fn.isdirectory(venv_path) == 1 then
|
||||
return venv_path .. '/bin'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for VIRTUAL_ENV environment variable (set by direnv or manually)
|
||||
local virtual_env = vim.env.VIRTUAL_ENV
|
||||
if virtual_env and virtual_env ~= '' then
|
||||
return virtual_env .. '/bin'
|
||||
end
|
||||
|
||||
-- Default to system path
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Helper function to find executable in both venv and system PATH
|
||||
function M.find_tool(tool_name)
|
||||
-- First check virtual env path
|
||||
local venv_path = M.get_python_venv_path()
|
||||
if venv_path then
|
||||
local tool_path = venv_path .. '/' .. tool_name
|
||||
if vim.fn.filereadable(tool_path) == 1 then
|
||||
return tool_path
|
||||
end
|
||||
end
|
||||
|
||||
-- Fall back to executable in PATH
|
||||
return M.find_executable(tool_name)
|
||||
end
|
||||
|
||||
-- Get LSP capabilities with cmp support
|
||||
function M.get_lsp_capabilities()
|
||||
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
||||
local ok, cmp_nvim_lsp = pcall(require, 'cmp_nvim_lsp')
|
||||
if ok then
|
||||
capabilities = vim.tbl_deep_extend('force', capabilities, cmp_nvim_lsp.default_capabilities())
|
||||
end
|
||||
return capabilities
|
||||
end
|
||||
|
||||
-- Get LSP root directory for current buffer
|
||||
function M.get_lsp_root()
|
||||
local buf = vim.api.nvim_get_current_buf()
|
||||
local clients = vim.lsp.get_clients { bufnr = buf }
|
||||
|
||||
for _, client in ipairs(clients) do
|
||||
if client.config.root_dir then
|
||||
return client.config.root_dir
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback to git root or current working directory
|
||||
local current_file = vim.api.nvim_buf_get_name(buf)
|
||||
local current_dir = vim.fn.fnamemodify(current_file, ':h')
|
||||
|
||||
local git_root = vim.fs.dirname(vim.fs.find({ '.git' }, { path = current_dir, upward = true })[1])
|
||||
if git_root then
|
||||
return git_root
|
||||
end
|
||||
|
||||
return vim.fn.getcwd()
|
||||
end
|
||||
|
||||
return M
|
|
@ -0,0 +1,42 @@
|
|||
-- Tab management keys
|
||||
-- F1-Prev, F2-Next, F3-New, F4-Close
|
||||
--
|
||||
local function safe_tabclose()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local buf_windows = vim.call('win_findbuf', bufnr)
|
||||
local modified = vim.bo[bufnr].modified
|
||||
|
||||
if vim.fn.tabpagenr '$' == 1 then
|
||||
-- last tab, no-op
|
||||
return
|
||||
elseif modified and #buf_windows == 1 then
|
||||
vim.ui.input({
|
||||
prompt = 'Buffer modified, are you sure? ',
|
||||
}, function(input)
|
||||
if input == 'y' then
|
||||
vim.cmd 'tabclose'
|
||||
end
|
||||
end)
|
||||
else
|
||||
vim.cmd 'tabclose'
|
||||
end
|
||||
end
|
||||
vim.keymap.set('t', '<F1>', vim.cmd.tabp, { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F2>', vim.cmd.tabn, { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F3>', '<C-\\><C-n>:tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F4>', safe_tabclose, { noremap = true, silent = true })
|
||||
vim.keymap.set('t', '<F5>', '<C-\\><C-n><Esc>:tab new<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F1>', vim.cmd.tabp, { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F2>', vim.cmd.tabn, { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F3>', ':tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F4>', safe_tabclose, { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<F5>', ':tab term<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F1>', vim.cmd.tabp, { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F2>', vim.cmd.tabn, { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F3>', '<Esc>:tabnew<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F4>', safe_tabclose, { noremap = true, silent = true })
|
||||
vim.keymap.set('i', '<F5>', '<Esc>:tab term<CR>', { noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<leader>wp', vim.cmd.tabn, { desc = '[p]revious' })
|
||||
vim.keymap.set('n', '<leader>wn', vim.cmd.tabp, { desc = '[n]ext' })
|
||||
vim.keymap.set('n', '<leader>wo', vim.cmd.tabnew, { desc = '[o]pen' })
|
||||
vim.keymap.set('n', '<leader>wc', safe_tabclose, { desc = '[c]lose' })
|
Loading…
Reference in New Issue