diff --git a/lua/plugins/config.lua b/lua/plugins/config.lua index 7f69177..52325a4 100644 --- a/lua/plugins/config.lua +++ b/lua/plugins/config.lua @@ -6,88 +6,6 @@ local function map(mode, lhs, rhs, opts) vim.keymap.set(mode, lhs, rhs, default_opts) end -local function silent_map(mode, lhs, rhs) - map(mode, lhs, rhs, { silent = true }) -end - -local function nmap(...) - map("n", ...) -end - ----@param params { no_formatting: boolean | nil, rust_lsp: boolean | nil } | nil -local function lsp_config_defaults(params) - local rust_lsp = params and params.rust_lsp - - return { - root_dir = require("lspconfig.util").root_pattern("pyproject.toml", "package.json", ".null-ls-root", ".git"), - - on_attach = function(client, bufnr) - vim.api.nvim_set_option_value("omnifunc", "v:lua.vim.lsp.omnifunc", { buf = bufnr }) - - local opts = { noremap = true, silent = true, buffer = bufnr } - - if params and params.no_formatting then - -- diagnostics for other lsp get messed up when formatting is enabled - client.server_capabilities.documentFormattingProvider = false - client.server_capabilities.documentRangeFormattingProvider = false - end - - if rust_lsp then - nmap("gm", function() - vim.cmd.RustLsp("expandMacro") - end, opts) - - nmap("ge", function() - vim.cmd.RustLsp("relatedDiagnostics") - end, opts) - end - - nmap("K", function() - if rust_lsp then - vim.cmd.RustLsp({ "hover", "actions" }) - else - vim.lsp.buf.hover() - end - end, opts) - - nmap("[d", function() - if rust_lsp then - vim.cmd.RustLsp({ "renderDiagnostic", "cycle_prev" }) - else - vim.diagnostic.jump({ count = -1, float = true, wrap = true }) - end - end, opts) - - nmap("]d", function() - if rust_lsp then - vim.cmd.RustLsp({ "renderDiagnostic", "cycle" }) - else - vim.diagnostic.jump({ count = 1, float = true, wrap = true }) - end - end, opts) - - nmap("", vim.lsp.buf.signature_help, opts) - nmap("D", vim.lsp.buf.type_definition, opts) - nmap("ca", vim.lsp.buf.code_action, opts) - nmap("e", vim.diagnostic.open_float, opts) - nmap("q", vim.diagnostic.setloclist, opts) - nmap("rn", vim.lsp.buf.rename, opts) - nmap("wa", vim.lsp.buf.add_workspace_folder, opts) - nmap("wl", function() - print(vim.inspect(vim.lsp.buf.list_workspace_folders())) - end, opts) - nmap("wr", vim.lsp.buf.remove_workspace_folder, opts) - nmap("gD", vim.lsp.buf.declaration, opts) - nmap("gd", vim.lsp.buf.definition, opts) - nmap("gi", vim.lsp.buf.implementation, opts) - nmap("gr", vim.lsp.buf.references, opts) - nmap("f", function() - vim.lsp.buf.format({ async = true }) - end, opts) - end, - } -end - local M = {} function M.hop() @@ -142,24 +60,6 @@ function M.nvim_fzf() } end -function M.harpoon() - require("harpoon").setup({ - global_settings = { - save_on_toggle = false, - save_on_change = true, - enter_on_sendcmd = false, - tmux_autoclose_windows = false, - excluded_filetypes = { "harpoon" }, - }, - }) - nmap("a", ":lua require('harpoon.mark').add_file()") - nmap("m", ":lua require('harpoon.ui').toggle_quick_menu()") - - for i = 1, 4, 1 do - nmap("", ':lua require("harpoon.ui").nav_file(' .. i .. ")") - end -end - function M.auto_session() require("auto-session").setup({ auto_session_suppress_dirs = { "~/", "~/Projects", "~/Downloads", "/" }, @@ -192,8 +92,8 @@ function M.lualine() end -- dynamic tab - silent_map("n", "", tab) - silent_map("n", "", shift_tab) + map("n", "", tab, { silent = true }) + map("n", "", shift_tab, { silent = true }) -- config options local function buffer_window(type, cond) @@ -319,29 +219,26 @@ function M.nvim_treesitter() install_htmldjango() ts_config.setup({ - auto_install = { - "python", - - "html", - "css", - "javascript", - "typescript", - "tsx", - "svelte", + auto_install = true, + ensure_installed = { "angular", - - "json", - "query", - "bash", - "lua", - "vim", - + "css", "glimmer", - "templ", "go", - "rust", + "html", + "javascript", + "json", + "lua", "markdown", + "python", + "query", + "rust", + "svelte", + "templ", + "tsx", + "typescript", + "vim", }, highlight = { enable = true, @@ -367,24 +264,11 @@ function M.nvim_treesitter() vim.opt.foldmethod = "expr" vim.opt.foldexpr = "nvim_treesitter#foldexpr()" end - - -- potentially load .so from this repo - --print(debug.getinfo(2, "S").source:sub(2)) - --vim.fn.getchar() - - --local shared_lib = "/home/guy/code/treesitter/tree-sitter-htmldjango-myown/src/parser.so" - --if vim.fn.filereadable(shared_lib) == 1 then - -- vim.treesitter.language.add("htmldjango", { - -- path = shared_lib, - -- }) - --end end function M.null_ls() local null_ls = require("null-ls") - local config = lsp_config_defaults() - - local builtins = require("plugins.null_ls_builtins") + local builtins = require("plugins.null_ls") local formatters = builtins.formatters local diagnostics = builtins.diagnostics @@ -419,9 +303,6 @@ function M.null_ls() formatters.templ(), -- sql - -- null_ls.builtins.diagnostics.sqlfluff.with(sqlfluff_args), - -- null_ls.builtins.formatting.sqlfluff.with(sqlfluff_args), - -- null_ls.builtins.formatting.sqlfmt, null_ls.builtins.formatting.sql_formatter, -- elixir @@ -431,10 +312,11 @@ function M.null_ls() -- c_sharp null_ls.builtins.formatting.csharpier, } + null_ls.setup({ sources = sources, - on_attach = config.on_attach, - root_dir = config.root_dir, + on_attach = require("plugins.lsp_keymaps").on_attach, + root_dir = require("lspconfig.util").root_pattern(), }) end @@ -508,88 +390,8 @@ function M.gitsigns() }) end -function M.lsp_zero() - -- - -- https://github.com/VonHeikemen/lsp-zero.nvim - -- - - -- running this before starting up mason - -- somehow prevents duplicate language servers - require("mason-lspconfig").setup() - - local lsp = require("lsp-zero") - lsp.preset("recommended") - - lsp.configure("pyright", { - root_dir = lsp_config_defaults().root_dir, - }) - - lsp.configure("ts_ls", { - settings = { - implicitProjectConfiguration = { - checkJs = true, - }, - }, - }) - - local html_filetypes = { "html", "htmldjango", "templ", "glimmer", "handlebars" } - - lsp.configure("html", { filetypes = html_filetypes }) - lsp.configure("htmx", { filetypes = html_filetypes }) - - lsp.on_attach(function(client, _) - -- diagnostics for other lsp get messed up when formatting is enabled - client.server_capabilities.documentFormattingProvider = false - client.server_capabilities.documentRangeFormattingProvider = false - - if client.name == "svelte" then - vim.api.nvim_create_autocmd("BufWritePost", { - pattern = { "*.js", "*.ts" }, - callback = function(ctx) - client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.file }) - end, - }) - end - - local function filter_duplicates(array) - local unique = {} - for _, tableA in ipairs(array) do - local is_duplicate = false - for _, tableB in ipairs(unique) do - if vim.deep_equal(tableA, tableB) then - is_duplicate = true - break - end - end - if not is_duplicate then - table.insert(unique, tableA) - end - end - return unique - end - - local function on_list(options) - options.items = filter_duplicates(options.items) - vim.fn.setqflist({}, " ", options) - vim.cmd("botright copen") - end - - vim.keymap.set("n", "gr", function() - vim.lsp.log.error("GETTING REFERENCES") - vim.lsp.buf.references(nil, { on_list = on_list }) - end, { noremap = true }) - end) - - -- (Optional) Configure lua language server for neovim - lsp.nvim_workspace() - - lsp.setup() - - vim.lsp.enable("angular-language-server") -end - function M.undotree() - nmap("u", ":UndotreeToggle") + map("n", "u", ":UndotreeToggle") end function M.luasnip() @@ -603,7 +405,7 @@ end function M.rustaceanvim() vim.g.rustaceanvim = { server = { - on_attach = lsp_config_defaults({ rust_lsp = true }).on_attach, + on_attach = require("plugins.lsp_keymaps").on_attach, settings = { ["rust-analyzer"] = { cargo = { @@ -616,23 +418,7 @@ function M.rustaceanvim() end function M.tailwind_tools() - require("tailwind-tools").setup({ - server = { - init_options = { - userLanguages = { - rust = "html", - }, - }, - settings = { - includeLanguages = { - rust = "html", - }, - }, - filetypes = { - "rust", - }, - }, - }) + require("tailwind-tools").setup({}) end return M diff --git a/lua/plugins/init.lua b/lua/plugins/init.lua index b69c9e3..ea41057 100644 --- a/lua/plugins/init.lua +++ b/lua/plugins/init.lua @@ -24,9 +24,6 @@ config.rustaceanvim() -- LSP STUFF config.nvim_autopairs() config.luasnip() -config.lsp_zero() +require("plugins.lsp_setup") config.null_ls() config.tailwind_tools() - --- REMOVING ---config.harpoon() diff --git a/lua/plugins/lazy.lua b/lua/plugins/lazy.lua index 6d28330..07f0f4d 100644 --- a/lua/plugins/lazy.lua +++ b/lua/plugins/lazy.lua @@ -53,8 +53,6 @@ function M.install_plugins() }, -- LSP - --"p00f/nvim-ts-rainbow", - --"nvimtools/none-ls.nvim", { "nvim-treesitter/nvim-treesitter", build = ":TSUpdate", @@ -63,28 +61,24 @@ function M.install_plugins() "nvim-treesitter/playground", "nvimtools/none-ls.nvim", "windwp/nvim-autopairs", + "neovim/nvim-lspconfig", + "williamboman/mason.nvim", { - "guy176251/lsp-zero.nvim", - branch = "v1.x", + + "L3MON4D3/LuaSnip", dependencies = { - -- LSP Support - { "neovim/nvim-lspconfig" }, -- Required - { "williamboman/mason.nvim" }, -- Optional - { "williamboman/mason-lspconfig.nvim" }, -- Optional + "honza/vim-snippets", + }, + }, - -- Autocompletion - { "hrsh7th/nvim-cmp" }, -- Required - { "hrsh7th/cmp-nvim-lsp" }, -- Required - { "hrsh7th/cmp-buffer" }, -- Optional - { "hrsh7th/cmp-path" }, -- Optional - { "saadparwaiz1/cmp_luasnip" }, -- Optional - { "hrsh7th/cmp-nvim-lua" }, -- Optional - - -- Snippets - { "L3MON4D3/LuaSnip" }, -- Required - { "rafamadriz/friendly-snippets" }, -- Optional - { "honza/vim-snippets" }, -- Optional + { + "hrsh7th/nvim-cmp", + event = "InsertEnter", -- load cmp on InsertEnter + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-buffer", + "saadparwaiz1/cmp_luasnip", }, }, diff --git a/lua/plugins/lsp_keymaps.lua b/lua/plugins/lsp_keymaps.lua new file mode 100644 index 0000000..1e5f380 --- /dev/null +++ b/lua/plugins/lsp_keymaps.lua @@ -0,0 +1,95 @@ +local function filter_duplicates(array) + local unique = {} + for _, table_a in ipairs(array) do + local is_duplicate = false + + for _, table_b in ipairs(unique) do + if vim.deep_equal(table_a, table_b) then + is_duplicate = true + break + end + end + + if not is_duplicate then + table.insert(unique, table_a) + end + end + return unique +end + +local function on_list(options) + options.items = filter_duplicates(options.items) + vim.fn.setqflist({}, " ", options) + vim.cmd("botright copen") +end + +local M = {} + +---@param bufnr integer +---@param is_rust_analyzer boolean +function M.set_lsp_keymaps(bufnr, is_rust_analyzer) + local opts = { noremap = true, silent = true, buffer = bufnr } + + if is_rust_analyzer then + vim.keymap.set("n", "gm", function() + vim.cmd.RustLsp("expandMacro") + end, opts) + + vim.keymap.set("n", "ge", function() + vim.cmd.RustLsp("relatedDiagnostics") + end, opts) + end + + vim.keymap.set("n", "K", function() + if is_rust_analyzer then + vim.cmd.RustLsp({ "hover", "actions" }) + else + vim.lsp.buf.hover() + end + end, opts) + + vim.keymap.set("n", "[d", function() + if is_rust_analyzer then + vim.cmd.RustLsp({ "renderDiagnostic", "cycle_prev" }) + else + vim.diagnostic.jump({ count = -1, float = true, wrap = true }) + end + end, opts) + + vim.keymap.set("n", "]d", function() + if is_rust_analyzer then + vim.cmd.RustLsp({ "renderDiagnostic", "cycle" }) + else + vim.diagnostic.jump({ count = 1, float = true, wrap = true }) + end + end, opts) + + vim.keymap.set("n", "", vim.lsp.buf.signature_help, opts) + vim.keymap.set("n", "D", vim.lsp.buf.type_definition, opts) + vim.keymap.set("n", "ca", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "e", vim.diagnostic.open_float, opts) + vim.keymap.set("n", "q", vim.diagnostic.setloclist, opts) + vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "wa", vim.lsp.buf.add_workspace_folder, opts) + vim.keymap.set("n", "wl", function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, opts) + vim.keymap.set("n", "wr", vim.lsp.buf.remove_workspace_folder, opts) + vim.keymap.set("n", "gD", vim.lsp.buf.declaration, opts) + vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) + vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts) + vim.keymap.set("n", "f", function() + vim.lsp.buf.format({ async = true }) + end, opts) + + vim.keymap.set("n", "gr", function() + vim.lsp.buf.references(nil, { on_list = on_list }) + end, opts) +end + +function M.on_attach(client, bufnr) + local is_rust_analyzer = client.name == "rust-analyzer" + M.set_lsp_keymaps(bufnr, is_rust_analyzer) +end + +return M diff --git a/lua/plugins/lsp_setup.lua b/lua/plugins/lsp_setup.lua new file mode 100644 index 0000000..d024092 --- /dev/null +++ b/lua/plugins/lsp_setup.lua @@ -0,0 +1,147 @@ +local function check_back_space() + local col = vim.fn.col(".") - 1 + if col == 0 or vim.fn.getline("."):sub(col, col):match("%s") then + return true + else + return false + end +end + +-- Reserve a space in the gutter +-- This will avoid an annoying layout shift in the screen +vim.opt.signcolumn = "yes" +vim.o.winborder = "rounded" + +-- Add cmp_nvim_lsp capabilities settings to lspconfig +-- This should be executed before you configure any language server +local lspconfig_defaults = require("lspconfig").util.default_config +lspconfig_defaults.capabilities = + vim.tbl_deep_extend("force", lspconfig_defaults.capabilities, require("cmp_nvim_lsp").default_capabilities()) + +-- This is where you enable features that only work +-- if there is a language server active in the file +vim.api.nvim_create_autocmd("LspAttach", { + desc = "LSP actions", + callback = function(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + + if client == nil then + return + end + + if client:supports_method("textDocument/completion") == false then + return + end + + local is_rust_analyzer = client.name == "rust-analyzer" + require("plugins.lsp_keymaps").set_lsp_keymaps(ev.buf, is_rust_analyzer) + end, +}) + +local cmp = require("cmp") +local luasnip = require("luasnip") +local select_opts = { behavior = cmp.SelectBehavior.Select } + +local mapping = { + -- confirm selection + [""] = cmp.mapping.confirm({ select = false }), + [""] = cmp.mapping.confirm({ select = false }), + + -- navigate items on the list + [""] = cmp.mapping.select_prev_item(select_opts), + [""] = cmp.mapping.select_next_item(select_opts), + [""] = cmp.mapping.select_prev_item(select_opts), + [""] = cmp.mapping.select_next_item(select_opts), + + -- scroll up and down in the completion documentation + [""] = cmp.mapping.scroll_docs(5), + [""] = cmp.mapping.scroll_docs(-5), + + -- toggle completion + [""] = cmp.mapping(function() + if cmp.visible() then + cmp.abort() + else + cmp.complete() + end + end), + + -- when menu is visible, navigate to next item + -- when line is empty, insert a tab character + -- else, activate completion + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item(select_opts) + elseif check_back_space() then + fallback() + else + cmp.complete() + end + end, { "i", "s" }), + + -- when menu is visible, navigate to previous item on list + -- else, revert to default behavior + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item(select_opts) + else + fallback() + end + end, { "i", "s" }), + + -- go to next placeholder in the snippet + [""] = cmp.mapping(function(fallback) + if luasnip.jumpable(1) then + luasnip.jump(1) + else + fallback() + end + end, { "i", "s" }), + + -- go to previous placeholder in the snippet + [""] = cmp.mapping(function(fallback) + if luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), +} + +cmp.setup({ + sources = { + { name = "nvim_lsp" }, + { name = "buffer", keyword_length = 3 }, + { name = "luasnip", keyword_length = 2 }, + }, + window = { + completion = cmp.config.window.bordered(), + documentation = cmp.config.window.bordered(), + }, + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert(mapping), +}) + +require("mason").setup() + +vim.lsp.enable({ + "angular-language-server", + "bashls", + "clangd", + "cssls", + "gopls", + "html", + --"htmx", + "jsonls", + "lua_ls", + "pyright", + "svelte", + "tailwindcss", + "taplo", + "templ", + "ts_ls", +}) diff --git a/lua/plugins/null_ls_builtins.lua b/lua/plugins/null_ls.lua similarity index 100% rename from lua/plugins/null_ls_builtins.lua rename to lua/plugins/null_ls.lua diff --git a/lua/plugins/packer.lua b/lua/plugins/packer.lua deleted file mode 100644 index e88a335..0000000 --- a/lua/plugins/packer.lua +++ /dev/null @@ -1,117 +0,0 @@ -local M = {} - -function M.bootstrap() - local fn = vim.fn - local install_path = fn.stdpath("data") .. "/site/pack/packer/start/packer.nvim" - - if fn.empty(fn.glob(install_path)) > 0 then - fn.system({ "git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path }) - vim.cmd("packadd packer.nvim") - vim.cmd(":PackerSync") - end -end - -function M.install_plugins() - require("packer").startup(function(use) - use("wbthomason/packer.nvim") - - -- NAVIGATION - use("phaazon/hop.nvim") - - -- VIM THEMING - use("folke/tokyonight.nvim") - - -- FILE MANAGEMENT - use("junegunn/fzf") - use("junegunn/fzf.vim") - use("kevinhwang91/rnvimr") - use("vijaymarupudi/nvim-fzf") - use("vijaymarupudi/nvim-fzf-commands") - - -- SESSION - --use("ThePrimeagen/harpoon") - use("nvim-lua/plenary.nvim") - use({ - "rmagatti/auto-session", - config = function() - require("auto-session").setup({ - log_level = "error", - auto_session_suppress_dirs = { "~/", "~/Projects", "~/Downloads", "/" }, - }) - end, - }) - use("mbbill/undotree") - - -- GIT - use("tpope/vim-fugitive") - use("stsewd/fzf-checkout.vim") - use("lewis6991/gitsigns.nvim") - - -- EDITOR - use("lukas-reineke/indent-blankline.nvim") - use({ - "nvim-lualine/lualine.nvim", - requires = { "kyazdani42/nvim-web-devicons", opt = true }, - }) - - -- LSP - --use("p00f/nvim-ts-rainbow") - --use("nvimtools/none-ls.nvim") - use({ - "nvim-treesitter/nvim-treesitter", - run = ":TSUpdate", - }) - use("nvim-treesitter/nvim-treesitter-context") - use("nvim-treesitter/playground") - use("jose-elias-alvarez/null-ls.nvim") - use("windwp/nvim-autopairs") - - use({ - "VonHeikemen/lsp-zero.nvim", - branch = "v1.x", - requires = { - -- LSP Support - { "neovim/nvim-lspconfig" }, -- Required - { "williamboman/mason.nvim" }, -- Optional - { "williamboman/mason-lspconfig.nvim" }, -- Optional - - -- Autocompletion - { "hrsh7th/nvim-cmp" }, -- Required - { "hrsh7th/cmp-nvim-lsp" }, -- Required - { "hrsh7th/cmp-buffer" }, -- Optional - { "hrsh7th/cmp-path" }, -- Optional - { "saadparwaiz1/cmp_luasnip" }, -- Optional - { "hrsh7th/cmp-nvim-lua" }, -- Optional - - -- Snippets - { "L3MON4D3/LuaSnip" }, -- Required - { "rafamadriz/friendly-snippets" }, -- Optional - { "honza/vim-snippets" }, -- Optional - }, - }) - - -- JS - use("HerringtonDarkholme/yats.vim") - use("chemzqm/vim-jsx-improve") - use("yuezk/vim-js") -- js - use("maxmellon/vim-jsx-pretty") -- react/tsx syntax highlight & indent - - -- HTML/CSS - use("mattn/emmet-vim") - - -- ZIG - use("ziglang/zig.vim") - - -- C# - use("jlcrochet/vim-razor") - - -- RUST - use({ - "mrcjkb/rustaceanvim", - version = "^5", -- Recommended - lazy = false, -- This plugin is already lazy - }) - end) -end - -return M