From 8c93e97b867006116cd8da041870ee6ed5ceea42 Mon Sep 17 00:00:00 2001 From: Jeremie Fraeys Date: Tue, 7 Nov 2023 16:42:00 -0500 Subject: [PATCH] re-organized venv-selector --- init.lua | 221 --------------------------- lua/config/options.lua | 4 +- lua/custom/plugins/linting.lua | 16 +- lua/custom/plugins/lsp-config.lua | 167 +++++++++++++++++++- lua/custom/plugins/telescope.lua | 39 ++++- lua/custom/plugins/venv-selector.lua | 46 +++++- 6 files changed, 259 insertions(+), 234 deletions(-) diff --git a/init.lua b/init.lua index 5fdc1ee4..087f745f 100644 --- a/init.lua +++ b/init.lua @@ -49,224 +49,3 @@ vim.api.nvim_create_autocmd('TextYankPost', { group = highlight_group, pattern = '*', }) - - --- [[ Configure LSP ]] --- This function gets run when an LSP connects to a particular buffer. -local on_attach = function(_, bufnr) - -- NOTE: Remember that lua is a real programming language, and as such it is possible - -- to define small helper and utility functions so you don't have to repeat yourself - -- many times. - -- - -- In this case, we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - local nmap = function(keys, func, desc) - if desc then - desc = 'LSP: ' .. desc - end - - vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) - end - - nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') - nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') - - nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') - nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') - nmap('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') - nmap('D', vim.lsp.buf.type_definition, 'Type [D]efinition') - nmap('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') - nmap('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') - - -- See `:help K` for why this keymap - nmap('K', vim.lsp.buf.hover, 'Hover Documentation') - nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') - - -- Lesser used LSP functionality - nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') - nmap('wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder') - nmap('wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder') - nmap('wl', function() - print(vim.inspect(vim.lsp.buf.list_workspace_folders())) - end, '[W]orkspace [L]ist Folders') - - -- Create a command `:Format` local to the LSP buffer - vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) - vim.lsp.buf.format() - end, { desc = 'Format current buffer with LSP' }) - - -- Enable auto-formatting on save - vim.api.nvim_command([[ - augroup AutoFormatOnSave - autocmd! - autocmd BufWritePre * :Format - augroup END - ]]) -end --- NOTE: Next Step on Your Neovim Journey: Add/Configure additional "plugins" for kickstart --- Enable the following language servers --- Feel free to add/remove any LSPs that you want here. They will automatically be installed. --- --- Add any additional override configuration in the following tables. They will be passed to --- the `settings` field of the server config. You must look up that documentation yourself. --- --- If you want to override the default filetypes that your language server will attach to you can --- define the property 'filetypes' to the map in question. - --- Function to find the nearest venv path in parent directories. -local function find_nearest_venv(starting_path) - local current_path = starting_path - while current_path do - local venv_path = current_path .. '/venv/bin/python' - if vim.fn.filereadable(venv_path) == 1 then - return venv_path - end - local parent_path = vim.fn.fnamemodify(current_path, ':h') - if parent_path == current_path then - break - end - current_path = parent_path - end - return nil -end - --- Get the path of the current file. -local current_file = vim.fn.expand('%:p') - --- Get the venv path for the current project directory. -local venv_path = find_nearest_venv(current_file) - -if venv_path then - -- Use the venv path as your Python interpreter. - vim.g.python3_host_prog = venv_path -else - -- Fallback to a system-wide Python interpreter. - vim.g.python3_host_prog = '/usr/bin/python3' -end - -local servers = { - clangd = {}, - gopls = { - settings = { - plugins = { - revive = {}, - }, - gopls = { - completeUnimported = true, - usePlaceholders = true, - analysis = { - unusedarams = true, - }, - }, - }, - }, - pylsp = { - settings = { - pylsp = { - plugins = { - pycodestyle = { - ignore = { 'W391' }, - maxLineLength = 79 - }, - flake8 = {}, - black = { - lineLength = 79, - -- Configure Black to split lines without specifying a target version - blackArgs = { - "--line-length", - "79", - "--exclude", - "venv", - "--exclude", - "env", - "--exclude", - ".git", - "--exclude", - ".hg", - }, - }, - mypy = { - enabled = true, - command = 'mypy', - args = {}, - diagnostics = true, - }, - isort = { - profile = 'black', - }, - }, - python = { - -- Specify the path to your Python interpreter - pythonPath = "/usr/bin/python3", - analysis = { - autoSearchPaths = true, - diagnosticMode = 'openFilesOnly', - useLibraryCodeForTypes = true, - typeCheckingMode = 'on', - }, - }, - }, - }, - }, - -- rust_analyzer = {}, - -- tsserver = {}, - -- html = { filetypes = { 'html', 'twig', 'hbs'} }, - - lua_ls = { - Lua = { - workspace = { checkThirdParty = false }, - telemetry = { enable = false }, - }, - }, -} - --- Setup neovim lua configuration -require('neodev').setup() - --- nvim-cmp supports additional completion capabilities, so broadcast that to servers -local capabilities = vim.lsp.protocol.make_client_capabilities() -capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) --- Setup Mason condifuration -local mason = require 'mason' - -mason.setup { - ui = { - icons = { - package_installed = "✓", - package_pending = "➜", - package_uninstalled = "✗", - }, - }, -} --- Ensure the servers above are installed -local mason_lspconfig = require 'mason-lspconfig' - -mason_lspconfig.setup { - ensure_installed = vim.tbl_keys(servers) -} - -mason_lspconfig.setup_handlers { - function(server_name) - require('lspconfig')[server_name].setup { - capabilities = capabilities, - on_attach = on_attach, - settings = servers[server_name], - filetypes = (servers[server_name] or {}).filetypes, - } - end -} - --- Setup Linters -local mason_tool_installer = require("mason-tool-installer") - -mason_tool_installer.setup({ - ensure_installed = { - "prettier", - "stylua", - "isort", - "black", - "flake8", - "mypy", - "revive", - }, -}) diff --git a/lua/config/options.lua b/lua/config/options.lua index ac16718e..190f9ccc 100644 --- a/lua/config/options.lua +++ b/lua/config/options.lua @@ -1,6 +1,6 @@ local opt = vim.opt local g = vim.g -local options = { +local opts = { -- change cursor in insert mode guicursor = "", @@ -54,7 +54,7 @@ local options = { pyxversion = 3 } -for k, v in pairs(options) do +for k, v in pairs(opts) do vim.opt[k] = v end diff --git a/lua/custom/plugins/linting.lua b/lua/custom/plugins/linting.lua index b47add31..282ff8af 100644 --- a/lua/custom/plugins/linting.lua +++ b/lua/custom/plugins/linting.lua @@ -22,8 +22,18 @@ return { end, }) - vim.keymap.set("n", "ml", function() - lint.try_lint() - end, { desc = "Trigger linting for current file" }) + local mason_tool_installer = require("mason-tool-installer") + + mason_tool_installer.setup({ + ensure_installed = { + "prettier", + "stylua", + "isort", + "black", + "flake8", + "mypy", + "revive", + }, + }) end, } diff --git a/lua/custom/plugins/lsp-config.lua b/lua/custom/plugins/lsp-config.lua index af4c960a..f5a22a7a 100644 --- a/lua/custom/plugins/lsp-config.lua +++ b/lua/custom/plugins/lsp-config.lua @@ -18,5 +18,170 @@ return { -- Additional lua configuration, makes nvim stuff amazing! 'folke/neodev.nvim', }, + config = function() + -- This function gets run when an LSP connects to a particular buffer. + local on_attach = function(_, bufnr) + -- NOTE: Remember that lua is a real programming language, and as such it is possible + -- to define small helper and utility functions so you don't have to repeat yourself + -- many times. + -- + -- In this case, we create a function that lets us more easily define mappings specific + -- for LSP related items. It sets the mode, buffer and description for us each time. + local nmap = function(keys, func, desc) + if desc then + desc = 'LSP: ' .. desc + end + + vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) + end + + nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') + nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') + + nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') + nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') + nmap('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') + nmap('D', vim.lsp.buf.type_definition, 'Type [D]efinition') + nmap('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') + nmap('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') + + -- See `:help K` for why this keymap + nmap('K', vim.lsp.buf.hover, 'Hover Documentation') + nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') + + -- Lesser used LSP functionality + nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + nmap('wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder') + nmap('wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder') + nmap('wl', function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, '[W]orkspace [L]ist Folders') + + -- Create a command `:Format` local to the LSP buffer + vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) + vim.lsp.buf.format() + end, { desc = 'Format current buffer with LSP' }) + + -- Enable auto-formatting on save + vim.api.nvim_command([[ + augroup AutoFormatOnSave + autocmd! + autocmd BufWritePre * :Format + augroup END + ]]) + end + + local servers = { + clangd = {}, + gopls = { + settings = { + plugins = { + revive = {}, + }, + gopls = { + completeUnimported = true, + usePlaceholders = true, + analysis = { + unusedarams = true, + }, + }, + }, + }, + pylsp = { + settings = { + pylsp = { + plugins = { + pycodestyle = { + ignore = { 'W391' }, + maxLineLength = 79 + }, + flake8 = {}, + black = { + lineLength = 79, + -- Configure Black to split lines without specifying a target version + blackArgs = { + "--line-length", + "79", + "--exclude", + "venv", + "--exclude", + "env", + "--exclude", + ".git", + "--exclude", + ".hg", + }, + }, + mypy = { + enabled = true, + command = 'mypy', + args = {}, + diagnostics = true, + }, + isort = { + profile = 'black', + }, + }, + python = { + -- Specify the path to your Python interpreter + pythonPath = "/usr/bin/python3", + analysis = { + autoSearchPaths = true, + diagnosticMode = 'openFilesOnly', + useLibraryCodeForTypes = true, + typeCheckingMode = 'on', + }, + }, + }, + }, + }, + -- rust_analyzer = {}, + -- tsserver = {}, + -- html = { filetypes = { 'html', 'twig', 'hbs'} }, + + lua_ls = { + Lua = { + workspace = { checkThirdParty = false }, + telemetry = { enable = false }, + }, + }, + } + + -- Setup neovim lua configuration + require('neodev').setup() + + -- nvim-cmp supports additional completion capabilities, so broadcast that to servers + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) + + -- Setup Mason condifuration + local mason = require 'mason' + + mason.setup { + ui = { + icons = { + package_installed = "✓", + package_pending = "➜", + package_uninstalled = "✗", + }, + }, + } + -- Ensure the servers above are installed + local mason_lspconfig = require 'mason-lspconfig' + + mason_lspconfig.setup { + ensure_installed = vim.tbl_keys(servers) + } + + mason_lspconfig.setup_handlers { + function(server_name) + require('lspconfig')[server_name].setup { + capabilities = capabilities, + on_attach = on_attach, + settings = servers[server_name], + filetypes = (servers[server_name] or {}).filetypes, + } + end + } + end } --- These are some example plugins that I've included in the kickstart repository. diff --git a/lua/custom/plugins/telescope.lua b/lua/custom/plugins/telescope.lua index 86c3bae8..baf8fcb8 100644 --- a/lua/custom/plugins/telescope.lua +++ b/lua/custom/plugins/telescope.lua @@ -31,5 +31,42 @@ return { } -- Enable telescope fzf native, if installed pcall(require('telescope').load_extension, 'fzf') + + -- Telescope live_grep in git root + -- Function to find the git root directory based on the current buffer's path + local function find_git_root() + -- Use the current buffer's path as the starting point for the git search + local current_file = vim.api.nvim_buf_get_name(0) + local current_dir + local cwd = vim.fn.getcwd() + -- If the buffer is not associated with a file, return nil + if current_file == "" then + current_dir = cwd + else + -- Extract the directory from the current file's path + current_dir = vim.fn.fnamemodify(current_file, ":h") + end + + -- Find the Git root directory from the current file's path + local git_root = vim.fn.systemlist("git -C " .. vim.fn.escape(current_dir, " ") .. " rev-parse --show-toplevel") + [1] + if vim.v.shell_error ~= 0 then + print("Not a git repository. Searching on current working directory") + return cwd + end + return git_root + end + + -- Custom live_grep function to search in git root + local function live_grep_git_root() + local git_root = find_git_root() + if git_root then + require('telescope.builtin').live_grep({ + search_dirs = { git_root }, + }) + end + end + + vim.api.nvim_create_user_command('LiveGrepGitRoot', live_grep_git_root, {}) end, -} -- See `:help telescope` and `:help telescope.setup()` +} diff --git a/lua/custom/plugins/venv-selector.lua b/lua/custom/plugins/venv-selector.lua index 22b0db01..f604fd89 100644 --- a/lua/custom/plugins/venv-selector.lua +++ b/lua/custom/plugins/venv-selector.lua @@ -1,12 +1,46 @@ return { "linux-cultist/venv-selector.nvim", dependencies = { "neovim/nvim-lspconfig", "nvim-telescope/telescope.nvim" }, - config = true, event = "VeryLazy", -- Optional: needed only if you want to type `:VenvSelect` without a keymapping - keys = {{ - "vs", ":VenvSelect", - -- key mapping for directly retrieve from cache. You may set autocmd if you prefer the no hand approach - "vc", ":VenvSelectCached" - }} + keys = { + { + "vs", ":VenvSelect", + -- Key mapping for directly retrieving from cache. You may set an autocmd if you prefer the hands-free approach. + "vc", ":VenvSelectCached" + } + }, + config = function() + -- Function to find the nearest venv path in parent directories. + local function find_nearest_venv(starting_path) + local current_path = starting_path + while current_path do + local venv_path = current_path .. '/venv/bin/python' + if vim.fn.filereadable(venv_path) == 1 then + return venv_path + end + local parent_path = vim.fn.fnamemodify(current_path, ':h') + if parent_path == current_path then + break + end + current_path = parent_path + end + return nil + end + + -- Get the path of the current file. + local current_file = vim.fn.expand('%:p') + + -- Get the venv path for the current project directory. + local venv_path = find_nearest_venv(current_file) + + if venv_path then + -- Activate the venv and use its Python interpreter. + vim.g.venv_selector_auto_activate = 1 + vim.g.python3_host_prog = venv_path + else + -- Fallback to a system-wide Python interpreter. + vim.g.python3_host_prog = '/usr/bin/python3' + end + end }