diff --git a/init.lua b/init.lua index 6471a2c..84722e4 100755 --- a/init.lua +++ b/init.lua @@ -1,2 +1,2 @@ require("core") -- load basic configs -require("plugins.ui.theme") -- load theme/color configs +require("plugins") diff --git a/lua/core/bindings/bindings.lua b/lua/core/bindings/bindings.lua deleted file mode 100755 index b21af9b..0000000 --- a/lua/core/bindings/bindings.lua +++ /dev/null @@ -1,23 +0,0 @@ -local bind = vim.keymap.set -local set = vim.g - --- Leader bind -set.mapleader = " " - --- Buffer manager -bind("n", "", ":bn") -- Buffer Switch -bind("n", "", ":bd") -- Buffer Close - --- Auto comment -bind("v", "", ":s/^/#") - --- Save mode -bind("n", "", ":w") -bind("i", "C-s", ":w") - - --- auto format -bind("n", "", ":lua vim.lsp.buf.format({ async = true})", { silent = true }) --- deselect on search -bind("n", "/", "noh", { silent = true}) - diff --git a/lua/core/init.lua b/lua/core/init.lua index 2b203b2..a01686f 100755 --- a/lua/core/init.lua +++ b/lua/core/init.lua @@ -1,5 +1,3 @@ -- Basic configs require("core.basic") require("core.bindings") --- Setup Rocks Package Manager -require("core.rocks") diff --git a/lua/core/rocks.lua b/lua/core/rocks.lua deleted file mode 100644 index 9d43954..0000000 --- a/lua/core/rocks.lua +++ /dev/null @@ -1,51 +0,0 @@ -do - -- Specifies where to install/use rocks.nvim - local install_location = vim.fs.joinpath(vim.fn.stdpath("data"), "rocks") - - -- Set up configuration options related to rocks.nvim (recommended to leave as default) - local rocks_config = { - rocks_path = vim.fs.normalize(install_location), - } - - vim.g.rocks_nvim = rocks_config - - -- Configure the package path (so that plugin code can be found) - local luarocks_path = { - vim.fs.joinpath(rocks_config.rocks_path, "share", "lua", "5.1", "?.lua"), - vim.fs.joinpath(rocks_config.rocks_path, "share", "lua", "5.1", "?", "init.lua"), - } - package.path = package.path .. ";" .. table.concat(luarocks_path, ";") - - -- Configure the C path (so that e.g. tree-sitter parsers can be found) - local luarocks_cpath = { - vim.fs.joinpath(rocks_config.rocks_path, "lib", "lua", "5.1", "?.so"), - vim.fs.joinpath(rocks_config.rocks_path, "lib64", "lua", "5.1", "?.so"), - } - package.cpath = package.cpath .. ";" .. table.concat(luarocks_cpath, ";") - - -- Load all installed plugins, including rocks.nvim itself - vim.opt.runtimepath:append(vim.fs.joinpath(rocks_config.rocks_path, "lib", "luarocks", "rocks-5.1", "rocks.nvim", "*")) -end - --- If rocks.nvim is not installed then install it! -if not pcall(require, "rocks") then - local rocks_location = vim.fs.joinpath(vim.fn.stdpath("cache"), "rocks.nvim") - - if not vim.uv.fs_stat(rocks_location) then - -- Pull down rocks.nvim - vim.fn.system({ - "git", - "clone", - "--filter=blob:none", - "https://github.com/nvim-neorocks/rocks.nvim", - rocks_location, - }) - end - - -- If the clone was successful then source the bootstrapping script - assert(vim.v.shell_error == 0, "rocks.nvim installation failed. Try exiting and re-entering Neovim!") - - vim.cmd.source(vim.fs.joinpath(rocks_location, "bootstrap.lua")) - - vim.fn.delete(rocks_location, "rf") -end diff --git a/lua/plugins/autocomplete/cmp/bindings.lua b/lua/plugins/autocomplete/cmp/bindings.lua deleted file mode 100644 index 07e6e68..0000000 --- a/lua/plugins/autocomplete/cmp/bindings.lua +++ /dev/null @@ -1,33 +0,0 @@ -local function setup_mapping(cmp) - cmp.setup({ - mapping = { - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.close(), - [""] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }), - [""] = cmp.mapping.select_prev_item(), - [""] = cmp.mapping.select_next_item(), - [""] = function(fallback) - if cmp.visible() then - cmp.select_next_item() - else - fallback() - end - end, - [""] = function(fallback) - if cmp.visible() then - cmp.select_prev_item() - else - fallback() - end - end, - [""] = cmp.mapping.confirm({ - behavior = cmp.ConfirmBehavior.Insert, - select = true, - }), - }, - }) -end - -return { setup_mapping = setup_mapping } diff --git a/lua/plugins/autocomplete/cmp/cmdline.lua b/lua/plugins/autocomplete/cmp/cmdline.lua index 3277431..b8a05c1 100644 --- a/lua/plugins/autocomplete/cmp/cmdline.lua +++ b/lua/plugins/autocomplete/cmp/cmdline.lua @@ -1,21 +1,6 @@ -local function setup_cmdline(cmp) - cmp.setup.cmdline("/", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ - { name = "nvim_lsp_document_symbol" }, - }, { - { name = "buffer" }, - }), - }) - - cmp.setup.cmdline(":", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ - { name = "path" }, - }, { - { name = "cmdline" }, - }), - }) +local M = {} +function M.setup_cmdline(cmp) + cmp.setup.cmdline('/', { mapping = cmp.mapping.preset.cmdline(), sources = {{name='nvim_lsp_document_symbol'},{name='buffer'}} }) + cmp.setup.cmdline(':', { mapping = cmp.mapping.preset.cmdline(), sources = {{name='path'},{name='cmdline'}} }) end - -return { setup_cmdline = setup_cmdline } +return M diff --git a/lua/plugins/autocomplete/cmp/formatting.lua b/lua/plugins/autocomplete/cmp/formatting.lua index 85bd73e..6c03650 100644 --- a/lua/plugins/autocomplete/cmp/formatting.lua +++ b/lua/plugins/autocomplete/cmp/formatting.lua @@ -1,34 +1,17 @@ -local function setup_formatting(cmp, lspkind) - cmp.setup({ - formatting = { - fields = { - cmp.ItemField.Abbr, - cmp.ItemField.Kind, - cmp.ItemField.Menu, - }, - format = lspkind.cmp_format({ - mode = "symbol_text", - maxwidth = 40, - before = function(entry, vim_item) - local source_mapping = { - nvim_lsp = "[LSP]", - spell = "[SPL]", - dictionary = "[DCT]", - path = "[FIL]", - luasnip = "[SNP]", - buffer = "[BUF]", - } - - -- Use `kind` to set the appropriate icon - vim_item.kind = lspkind.presets.default[vim_item.kind] or vim_item.kind - -- Set the menu text based on the source - vim_item.menu = source_mapping[entry.source.name] or "" - - return vim_item - end, - }), - }, - }) +local lspkind = require('lspkind') +local M = {} +function M.get_formatting() + return { + fields = { cmp.ItemField.Abbr, cmp.ItemField.Kind, cmp.ItemField.Menu }, + format = lspkind.cmp_format({ + mode = 'symbol_text', maxwidth = 40, + before = function(entry, item) + local icons = { nvim_lsp='[LSP]', mini_snippets='[SNP]', buffer='[BUF]', path='[FIL]' } + item.kind = lspkind.presets.default[item.kind] or item.kind + item.menu = icons[entry.source.name] or '' + return item + end, + }), + } end - -return { setup_formatting = setup_formatting } +return M diff --git a/lua/plugins/autocomplete/cmp/init.lua b/lua/plugins/autocomplete/cmp/init.lua index 3abe7af..45f115f 100644 --- a/lua/plugins/autocomplete/cmp/init.lua +++ b/lua/plugins/autocomplete/cmp/init.lua @@ -1,3 +1 @@ require("plugins.autocomplete.cmp.main") -require("plugins.autocomplete.cmp.snippets") - diff --git a/lua/plugins/autocomplete/cmp/main.lua b/lua/plugins/autocomplete/cmp/main.lua index 222618c..2c56715 100755 --- a/lua/plugins/autocomplete/cmp/main.lua +++ b/lua/plugins/autocomplete/cmp/main.lua @@ -1,30 +1,21 @@ --- Required modules -local cmp = require("cmp") -local lspkind = require("lspkind") -local luasnip = require("luasnip") -local compare = require("cmp.config.compare") +local cmp = require("cmp") +local mapping = require("plugins.autocomplete.cmp.mapping").setup_mapping(cmp) +local sources = require("plugins.autocomplete.cmp.sources").get_sources() +local formatting = require("plugins.autocomplete.cmp.formatting").get_formatting() +local sorting = require("plugins.autocomplete.cmp.sorting").get_sorting() +local window = require("plugins.autocomplete.cmp.window").get_window() +local cmdline = require("plugins.autocomplete.cmp.cmdline").setup_cmdline +local snippet = require("plugins.autocomplete.cmp.snippet").get_snippet() +-- Single cmp.setup with all modules combined +cmp.setup({ + snippet = snippet, + mapping = mapping, + sources = sources, + formatting = formatting, + sorting = sorting, + window = window, +}) --- Import setup functions from separate modules -local sorting = require("plugins.autocomplete.cmp.sorting").setup_sorting -local snippet = require("plugins.autocomplete.cmp.snippets.cmp_snippet").setup_snippet -local window = require("plugins.autocomplete.cmp.window").setup_window -local sources = require("plugins.autocomplete.cmp.sources").setup_sources -local bindings = require("plugins.autocomplete.cmp.bindings").setup_mapping -local formatting = require("plugins.autocomplete.cmp.formatting").setup_formatting -local cmdline = require("plugins.autocomplete.cmp.cmdline").setup_cmdline - --- Main setup function -local function setup() - sorting(cmp, compare) - snippet(cmp, luasnip) - window(cmp) - sources(cmp) - bindings(cmp) - formatting(cmp, lspkind) - cmdline(cmp) -end - - --- Run setup -setup() +-- Setup cmdline completion +cmdline(cmp) diff --git a/lua/plugins/autocomplete/cmp/mapping.lua b/lua/plugins/autocomplete/cmp/mapping.lua new file mode 100644 index 0000000..df66b49 --- /dev/null +++ b/lua/plugins/autocomplete/cmp/mapping.lua @@ -0,0 +1,15 @@ +local M = {} +function M.setup_mapping(cmp) + return cmp.mapping.preset.insert({ + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.select_prev_item(), + [""] = function(fallback) if cmp.visible() then cmp.select_next_item() else fallback() end end, + [""] = function(fallback) if cmp.visible() then cmp.select_prev_item() else fallback() end end, + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.close(), + [""] = cmp.mapping.confirm({ select = true }), + }) +end +return M diff --git a/lua/plugins/autocomplete/cmp/snippet.lua b/lua/plugins/autocomplete/cmp/snippet.lua new file mode 100644 index 0000000..4add92d --- /dev/null +++ b/lua/plugins/autocomplete/cmp/snippet.lua @@ -0,0 +1,44 @@ +local M = {} +function M.get_snippet() + local ms = require('mini.snippets') + local loader = ms.gen_loader + ms.setup({ + snippets = { + loader.from_file(vim.fn.stdpath('config') .. '/snippets/global.json'), + loader.from_lang(), + }, + }) + -- Auto-create stub on MasonInstallEnd + vim.api.nvim_create_autocmd('User', { + pattern = 'MasonInstallEnd', + callback = function(evt) + local lang = evt.data[1] + local dir = vim.fn.stdpath('config') .. '/snippets' + vim.fn.mkdir(dir, 'p') + local file = dir .. '/' .. lang .. '.json' + if vim.fn.filereadable(file) == 0 then + vim.fn.writefile({"{}"}, file) + vim.notify('Created snippet config: ' .. file) + end + end, + }) + -- SnipEdit command + vim.api.nvim_create_user_command('SnipEdit', function(opts) + local lang = opts.args + local file = vim.fn.stdpath('config') .. '/snippets/' .. lang .. '.json' + if vim.fn.filereadable(file) == 0 then + vim.fn.writefile({"{}"}, file) + vim.notify('Stub created: ' .. file) + end + vim.cmd('edit ' .. file) + end, { + nargs = 1, + complete = function(_, input) + return vim.fn.readdir(vim.fn.stdpath('config') .. '/snippets') + end, + }) + -- Return snippet expansion table + return { expand = function(args) require('mini.snippets').default_expand(args) end } +end +return M + diff --git a/lua/plugins/autocomplete/cmp/snippets/cmp_snippet.lua b/lua/plugins/autocomplete/cmp/snippets/cmp_snippet.lua deleted file mode 100644 index eb08e97..0000000 --- a/lua/plugins/autocomplete/cmp/snippets/cmp_snippet.lua +++ /dev/null @@ -1,11 +0,0 @@ -local function setup_snippet(cmp, luasnip) - cmp.setup({ - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - }) -end - -return { setup_snippet = setup_snippet } diff --git a/lua/plugins/autocomplete/cmp/snippets/init.lua b/lua/plugins/autocomplete/cmp/snippets/init.lua deleted file mode 100644 index 3ab7630..0000000 --- a/lua/plugins/autocomplete/cmp/snippets/init.lua +++ /dev/null @@ -1 +0,0 @@ -require("plugins.autocomplete.cmp.snippets.main") diff --git a/lua/plugins/autocomplete/cmp/snippets/main.lua b/lua/plugins/autocomplete/cmp/snippets/main.lua deleted file mode 100644 index 8c58378..0000000 --- a/lua/plugins/autocomplete/cmp/snippets/main.lua +++ /dev/null @@ -1,18 +0,0 @@ --- Load snippets from VS Code -require("luasnip.loaders.from_vscode").lazy_load({ - include = nil, -- Load all languages - exclude = {}, -}) - --- Define Django snippet for Python and HTML files -local DJANGO = "djangohtml" -local snippets = { - python = { "django" }, - html = { DJANGO, "html" }, - htmldjango = { DJANGO, "html" }, -- for files with .html and .django extension -} - --- Extend file types with snippets -for filetype, snips in pairs(snippets) do - require("luasnip").filetype_extend(filetype, snips) -end diff --git a/lua/plugins/autocomplete/cmp/sorting.lua b/lua/plugins/autocomplete/cmp/sorting.lua index 6cf9f23..90ebf87 100644 --- a/lua/plugins/autocomplete/cmp/sorting.lua +++ b/lua/plugins/autocomplete/cmp/sorting.lua @@ -1,22 +1,14 @@ -local function setup_sorting(cmp, compare) - cmp.setup({ - sorting = { - priority_weight = 1.0, - comparators = { - compare.offset, -- prioritizes items closer to the cursor - compare.exact, -- prioritizes items starting with exactly the same prefix - compare.score, -- prioritizes item similarity score - compare.recently_used, -- prioritizes recently used items - compare.kind, -- prioritizes items with the same kind - compare.sort_text, -- prioritizes prefix matches within completion items - compare.length, -- prioritizes shorter completion items - compare.order, -- prioritizes items in the same received order - }, - debug = { - priority = true, - }, - }, - }) +local cmp_compare = require('cmp.config.compare') +local M = {} +function M.get_sorting() + return { + priority_weight = 1.0, + comparators = { + cmp_compare.offset, cmp_compare.exact, cmp_compare.score, + cmp_compare.recently_used, cmp_compare.kind, + cmp_compare.sort_text, cmp_compare.length, cmp_compare.order, + }, + debug = { priority = true }, + } end - -return { setup_sorting = setup_sorting } +return M diff --git a/lua/plugins/autocomplete/cmp/sources.lua b/lua/plugins/autocomplete/cmp/sources.lua index d819b57..c42a94a 100644 --- a/lua/plugins/autocomplete/cmp/sources.lua +++ b/lua/plugins/autocomplete/cmp/sources.lua @@ -1,50 +1,23 @@ -local function setup_sources(cmp) - cmp.setup({ - sources = { - { - name = "nvim_lsp", - keyword_length = 1, - max_item_count = 11, - }, - { - name = "luasnip", - keyword_length = 2, - max_item_count = 2, - }, - { - name = "buffer", - keyword_length = 3, - option = { - get_bufnrs = function() - local bufs = {} - for _, win in ipairs(vim.api.nvim_list_wins()) do - bufs[vim.api.nvim_win_get_buf(win)] = true - end - return vim.tbl_keys(bufs) - end, - }, - max_item_count = 10, - }, - { - name = "path", - keyword_length = 3, - max_item_count = 5, - }, - { - name = "spell", - keyword_length = 3, - option = { - keep_all_entries = false, - enable_in_context = function() - return true - end, - }, - }, - { - name = "nvim_lsp_signature_help", - }, - }, - }) +local M = {} +function M.get_sources() + return cmp.config.sources({ + { name = 'nvim_lsp', keyword_length = 1, max_item_count = 11 }, + { name = 'mini_snippets', keyword_length = 2, max_item_count = 5 }, + }, { + { + name = 'buffer', keyword_length = 3, max_item_count = 10, + option = { get_bufnrs = function() + local bufs = {} + for _, w in ipairs(vim.api.nvim_list_wins()) do bufs[vim.api.nvim_win_get_buf(w)] = true end + return vim.tbl_keys(bufs) + end } + }, + { name = 'path', keyword_length = 3, max_item_count = 5 }, + { name = 'spell', keyword_length = 3, option = { + keep_all_entries = false, + enable_in_context = function() return true end, + }}, + { name = 'nvim_lsp_signature_help' }, + }) end - -return { setup_sources = setup_sources } +return M diff --git a/lua/plugins/autocomplete/cmp/window.lua b/lua/plugins/autocomplete/cmp/window.lua index 5d5bf0b..9a8363e 100644 --- a/lua/plugins/autocomplete/cmp/window.lua +++ b/lua/plugins/autocomplete/cmp/window.lua @@ -1,10 +1,8 @@ -local function setup_window(cmp) - cmp.setup({ - window = { - completion = cmp.config.window.bordered(), - documentation = cmp.config.window.bordered(), - }, - }) +local M = {} +function M.get_window() + return { + completion = require('cmp').config.window.bordered(), + documentation = require('cmp').config.window.bordered(), + } end - -return { setup_window = setup_window } +return M diff --git a/lua/plugins/autocomplete/lspconfig/main.lua b/lua/plugins/autocomplete/lspconfig/main.lua index fb8a461..b47cf24 100755 --- a/lua/plugins/autocomplete/lspconfig/main.lua +++ b/lua/plugins/autocomplete/lspconfig/main.lua @@ -1,127 +1,106 @@ -local mason = require("mason") -local mason_lspconfig = require("mason-lspconfig") -local nvim_lsp = require("lspconfig") +-- Import dependencies +local mason = require("mason") +local mason_lsp = require("mason-lspconfig") +local lspconfig = require("lspconfig") -local on_attach = function(client, bufnr) - -- Enable hover preview - vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') +-- Utility: get server config directory +local function get_servers_path() + return vim.fn.stdpath("config") .. "/lua/plugins/autocomplete/lspconfig/servers" +end - -- Display error and warning indicators +-- Common on_attach for all LSP servers +local function on_attach(client, bufnr) + vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') if client.server_capabilities.documentHighlightProvider then vim.api.nvim_create_augroup("LspDocumentHighlight", { clear = true }) vim.api.nvim_clear_autocmds({ buffer = bufnr, group = "LspDocumentHighlight" }) vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, { buffer = bufnr, - group = "LspDocumentHighlight", - callback = function() - vim.lsp.buf.document_highlight() - end, + group = "LspDocumentHighlight", + callback = vim.lsp.buf.document_highlight, }) end end --- Define capabilities with snippet and resolve support -local capabilities = vim.lsp.protocol.make_client_capabilities() -capabilities.textDocument.completion.completionItem.snippetSupport = true -capabilities.textDocument.completion.completionItem.resolveSupport = { - properties = { "documentation", "detail", "additionalTextEdits" }, -} +-- Build capabilities merged with nvim-cmp +local function make_capabilities() + local caps = vim.lsp.protocol.make_client_capabilities() + caps.textDocument.completion.completionItem.snippetSupport = true + caps.textDocument.completion.completionItem.resolveSupport = { + properties = { "documentation", "detail", "additionalTextEdits" } + } + return require("cmp_nvim_lsp").default_capabilities(caps) +end --- Merge in capabilities from cmp_nvim_lsp -capabilities = require("cmp_nvim_lsp").default_capabilities(capabilities) +-- Initialize Mason and ensure installation +local function init_mason(servers) + mason.setup({ ui = { icons = { server_installed = "✓", server_pending = "➜", server_uninstalled = "✗" } } }) + mason_lsp.setup({ ensure_installed = servers, automatic_installation = true }) +end -mason.setup({ - ui = { - icons = { - server_installed = "✓", - server_pending = "➜", - server_uninstalled = "✗", - }, - }, -}) +-- Load server configs from `servers/` folder +local function load_server_configs(on_attach, capabilities) + local handlers = { function(server) + lspconfig[server].setup({ on_attach = on_attach, capabilities = capabilities }) + end } --- Setup LSP configurations after installation -mason_lspconfig.setup({ + local dir = get_servers_path() + for _, file in ipairs(vim.fn.readdir(dir)) do + local name = file:match('^(.*)%.lua$') + if name then + local opts = require("plugins.autocomplete.lspconfig.servers." .. name) + handlers[name] = function() + local cfg = vim.tbl_deep_extend("force", { on_attach = on_attach, capabilities = capabilities }, opts) + lspconfig[name].setup(cfg) + end + end + end - ensure_installed = { - "lua_ls", - "pylsp" - }, + mason_lsp.setup_handlers(handlers) +end - automatic_installation = true, +-- Auto-create config file stub after Mason install +local function init_autogen() + vim.api.nvim_create_autocmd("User", { + pattern = "MasonInstallEnd", + callback = function(event) + local pkg = event.data[1] + local path = get_servers_path() .. "/" .. pkg .. ".lua" + if lspconfig[pkg] and vim.fn.filereadable(path) == 0 then + vim.fn.writefile({ "return {}" }, path) + vim.notify("Created LSP config: " .. path) + end + end, + }) +end - handlers = { - function (server_name) - nvim_lsp[server_name].setup {} - end, +-- Command to edit a server config +local function init_edit_command(handlers) + vim.api.nvim_create_user_command("LspEdit", function(opts) + local name = opts.args + local path = get_servers_path() .. "/" .. name .. ".lua" + if vim.fn.filereadable(path) == 0 then + vim.fn.writefile({ "return {}" }, path) + vim.notify("Stub created: " .. path) + end + vim.cmd("edit " .. path) + end, { nargs = 1, complete = function(_, line) + return vim.tbl_filter(function(k) return k:match("^" .. line) end, vim.tbl_keys(handlers)) + end }) +end - ["lua_ls"] = function() - nvim_lsp.lua_ls.setup({ - settings = { - Lua = { - completion = { - callSnippet = "Replace", - }, - diagnostics = { - enable = true, - globals = { "vim" }, - underline = true, -- underline errors/warnings in the code - severity_sort = true, -- sort errors/warnings by severity - signs = true, -- add signs in the gutter for errors/warnings - }, - workspace = { checkThirdParty = false }, - }, - }, - on_attach = on_attach, - capabilities = capabilities, - }) - end, +-- Main setup +local function setup() + local servers = { "lua_ls", "pylsp", "html", "cssls" } + local caps = make_capabilities() + + init_mason(servers) + load_server_configs(on_attach, caps) + init_autogen() + init_edit_command(lspconfig) +end - ["pylsp"] = { - ensure_installed = { - "pylsp_mypy", - "pylsp_black", - "pylsp_isort", - }, - }, - ["pylsp"] = function() - nvim_lsp.pylsp.setup({ - cmd = { "pylsp" }, - filetypes = { "python" }, - root_dir = nvim_lsp.util.root_pattern(".git", "venv", ".env", "main.py"), - settings = { - pylsp = { - plugins = { - pylsp_mypy = { enabled = true }, - pylsp_black = { enabled = true }, - pylsp_isort = { enabled = true }, - -- disabled standard plugins - autopep8 = { enabled = false }, -- covered by black - yapf = { enabled = false }, -- covered by black - pycodestyle = { enabled = false }, - pydocstyle = { enabled = false }, - }, - }, - }, - single_file_support = true, - on_attach = on_attach, - capabilities = capabilities, - }) - end, - ["html"] = function() - nvim_lsp.html.setup({ - on_attach = on_attach, - capabilities = capabilities, - }) - end, - ["cssls"] = function() - nvim_lsp.cssls.setup({ - on_attach = on_attach, - capabilities = capabilities, - }) - end, - }, -}) +-- Execute setup +setup() --- Set logging level for LSP messages --- vim.lsp.set_log_level("debug") -- Uncomment this line for debugging +return { setup = setup } diff --git a/lua/plugins/autocomplete/lspconfig/servers/lua_ls.lua b/lua/plugins/autocomplete/lspconfig/servers/lua_ls.lua new file mode 100644 index 0000000..df67fd9 --- /dev/null +++ b/lua/plugins/autocomplete/lspconfig/servers/lua_ls.lua @@ -0,0 +1,16 @@ +return { + settings = { + Lua = { + completion = { callSnippet = "Replace" }, + diagnostics = { + enable = true, + globals = { "vim" }, + underline = true, + severity_sort = true, + signs = true, + }, + workspace = { checkThirdParty = false }, + }, + }, +} + diff --git a/lua/plugins/autocomplete/lspconfig/servers/pylsp.lua b/lua/plugins/autocomplete/lspconfig/servers/pylsp.lua new file mode 100644 index 0000000..dabb46d --- /dev/null +++ b/lua/plugins/autocomplete/lspconfig/servers/pylsp.lua @@ -0,0 +1,25 @@ +return { + -- command and filetypes + cmd = { "pylsp" }, + filetypes = { "python" }, + root_dir = require("lspconfig.util").root_pattern(".git", "venv", ".env", "main.py"), + + -- settings for pylsp plugins + settings = { + pylsp = { + plugins = { + pylsp_mypy = { enabled = true }, + pylsp_black = { enabled = true }, + pylsp_isort = { enabled = true }, + autopep8 = { enabled = false }, + yapf = { enabled = false }, + pycodestyle = { enabled = false }, + }, + }, + }, + + -- you can also override on_attach or capabilities here if needed + -- on_attach = function(client, bufnr) ... end, + -- capabilities = some_other_capabilities, +} + diff --git a/lua/plugins/init.lua b/lua/plugins/init.lua new file mode 100644 index 0000000..efedf1c --- /dev/null +++ b/lua/plugins/init.lua @@ -0,0 +1,4 @@ +-- Setup Rocks Package Manager +require("plugins.rocks") +require("plugins.theme") + diff --git a/lua/plugins/rocks.lua b/lua/plugins/rocks.lua new file mode 100644 index 0000000..a6177b1 --- /dev/null +++ b/lua/plugins/rocks.lua @@ -0,0 +1,55 @@ +local fn = vim.fn +local uv = vim.uv +local fs = vim.fs + +-- Determine OS-specific library extension +local is_windows = vim.loop.os_uname().sysname == "Windows_NT" +local lib_ext = is_windows and "dll" or "so" + +-- Base paths +local data_dir = fn.stdpath("data") +local cache_dir = fn.stdpath("cache") +local rocks_root = fs.joinpath(data_dir, "rocks") + +-- rocks.nvim config +vim.g.rocks_nvim = { + rocks_path = fs.normalize(rocks_root), +} + +-- Extend Lua module search path +do + local rp = vim.g.rocks_nvim.rocks_path + local lua_paths = { + fs.joinpath(rp, "share", "lua", "5.1", "?.lua"), + fs.joinpath(rp, "share", "lua", "5.1", "?", "init.lua"), + } + package.path = package.path .. ";" .. table.concat(lua_paths, ";") + + local c_paths = { + fs.joinpath(rp, "lib", "lua", "5.1", "?." .. lib_ext), + fs.joinpath(rp, "lib64","lua", "5.1", "?." .. lib_ext), + } + package.cpath = package.cpath .. ";" .. table.concat(c_paths, ";") + + -- Add all installed rocks (including rocks.nvim) to runtimepath + local bundle = fs.joinpath(rp, "lib", "luarocks", "rocks-5.1", "rocks.nvim", "*") + vim.opt.runtimepath:append(bundle) +end + +-- Bootstrap rocks.nvim if not already installed +if not pcall(require, "rocks") then + local bootstrap_dir = fs.joinpath(cache_dir, "rocks.nvim") + + if not uv.fs_stat(bootstrap_dir) then + vim.fn.system({ + "git", "clone", "--filter=blob:none", + "https://github.com/nvim-neorocks/rocks.nvim", + bootstrap_dir, + }) + end + + assert(vim.v.shell_error == 0, "rocks.nvim installation failed") + vim.cmd.source(fs.joinpath(bootstrap_dir, "bootstrap.lua")) + vim.fn.delete(bootstrap_dir, "rf") +end + diff --git a/lua/plugins/theme/commands.lua b/lua/plugins/theme/commands.lua new file mode 100644 index 0000000..22cfd4d --- /dev/null +++ b/lua/plugins/theme/commands.lua @@ -0,0 +1,34 @@ +local M = {} +local manager = require("plugins.theme.manager") + +function M.setup() + vim.api.nvim_create_user_command("SetTheme", function(opts) + manager.set_theme(opts.args) + end, { + nargs = 1, + complete = function() return manager.list_installed_themes() end, + desc = "Set current theme", + }) + + vim.api.nvim_create_user_command("CurrentTheme", function() + local theme = manager.get_current_theme() or "(none)" + vim.notify("Current theme: " .. theme) + end, { desc = "Show current theme" }) + + vim.api.nvim_create_user_command("EditTheme", function() + local theme = manager.get_current_theme() + if theme then + local path = config.user_theme_config(theme) + if vim.loop.fs_stat(path) then + vim.cmd("edit " .. path) + else + vim.notify("User config for theme '"..theme.."' not found.", vim.log.levels.WARN) + end + else + vim.notify("No theme is set yet.", vim.log.levels.WARN) + end + end, { desc = "Edit current theme config" }) +end + +return M + diff --git a/lua/plugins/theme/config.lua b/lua/plugins/theme/config.lua new file mode 100644 index 0000000..901a1b9 --- /dev/null +++ b/lua/plugins/theme/config.lua @@ -0,0 +1,25 @@ +local vim = vim +local fn = vim.fn + +local M = {} + +-- Directory under stdpath("data") to store user theme settings +M.user_dir = fn.stdpath("data") .. "/nvpak/themes" + +-- Path to plain file storing current theme name +M.user_theme_file = M.user_dir .. "/current_theme" + +-- Path to user-editable theme config for a given theme +M.user_theme_config = function(theme) + return M.user_dir .. "/" .. theme .. ".lua" +end + +-- Module path prefix for bundled theme definitions +M.plugin_theme_module = function(theme) + return "plugins.theme.themes." .. theme +end + +-- Directory where bundled themes reside +M.plugin_themes_dir = fn.stdpath("config") .. "/lua/plugins/theme/themes" + +return M diff --git a/lua/plugins/theme/init.lua b/lua/plugins/theme/init.lua new file mode 100644 index 0000000..0c6da33 --- /dev/null +++ b/lua/plugins/theme/init.lua @@ -0,0 +1,14 @@ +-- File: lua/plugins/theme/init.lua + +local M = {} + +local manager = require("plugins.theme.manager") +local commands = require("plugins.theme.commands") + +-- Load user preferred theme on startup +manager.load_current_theme() + +-- Register user commands +commands.setup() + +return M diff --git a/lua/plugins/theme/loader.lua b/lua/plugins/theme/loader.lua new file mode 100644 index 0000000..44c3809 --- /dev/null +++ b/lua/plugins/theme/loader.lua @@ -0,0 +1,35 @@ +local config = require("plugins.theme.config") +local M = {} + +-- Load the theme module +function M.load(theme) + local ok, err = pcall(require, config.plugin_theme_module(theme)) + if not ok then + vim.notify("Failed to load theme '" .. theme .. "': " .. err, vim.log.levels.ERROR) + end +end + +-- Check if theme module exists +function M.is_theme_available(theme) + local ok = pcall(require, config.plugin_theme_module(theme)) + return ok +end + +-- List all *.lua files under plugin themes directory (without extension) +function M.list_available_themes() + local list = {} + local scan = vim.loop.fs_scandir(config.plugin_themes_dir) + if scan then + while true do + local name, t = vim.loop.fs_scandir_next(scan) + if not name then break end + if t == "file" and name:match("(.*)%.lua$") then + table.insert(list, name:match("(.*)%.lua$")) + end + end + end + return list +end + +return M + diff --git a/lua/plugins/theme/manager.lua b/lua/plugins/theme/manager.lua new file mode 100644 index 0000000..496b1f6 --- /dev/null +++ b/lua/plugins/theme/manager.lua @@ -0,0 +1,34 @@ +local config = require("plugins.theme.config") +local loader = require("plugins.theme.loader") +local user = require("plugins.theme.user") + +local M = {} + +-- Set and apply a new theme +function M.set_theme(name) + if not loader.is_theme_available(name) then + vim.notify("Theme '" .. name .. "' not found. Please install it.", vim.log.levels.ERROR) + return + end + loader.load(name) + user.save_theme(name) +end + +-- Get saved theme name +function M.get_current_theme() + return user.get_saved_theme() +end + +-- Load saved theme on startup +function M.load_current_theme() + local name = user.get_saved_theme() + if name then loader.load(name) end +end + +-- List all bundled themes +function M.list_installed_themes() + return loader.list_available_themes() +end + +return M + diff --git a/lua/plugins/ui/colors/catppuccin.lua b/lua/plugins/theme/themes/catppuccin.lua similarity index 100% rename from lua/plugins/ui/colors/catppuccin.lua rename to lua/plugins/theme/themes/catppuccin.lua diff --git a/lua/plugins/ui/colors/dracula.lua b/lua/plugins/theme/themes/dracula.lua similarity index 100% rename from lua/plugins/ui/colors/dracula.lua rename to lua/plugins/theme/themes/dracula.lua diff --git a/lua/plugins/ui/colors/monokia.lua b/lua/plugins/theme/themes/monokia.lua similarity index 100% rename from lua/plugins/ui/colors/monokia.lua rename to lua/plugins/theme/themes/monokia.lua diff --git a/lua/plugins/ui/colors/nord.lua b/lua/plugins/theme/themes/nord.lua similarity index 100% rename from lua/plugins/ui/colors/nord.lua rename to lua/plugins/theme/themes/nord.lua diff --git a/lua/plugins/ui/colors/onedarkpro.lua b/lua/plugins/theme/themes/onedarkpro.lua similarity index 100% rename from lua/plugins/ui/colors/onedarkpro.lua rename to lua/plugins/theme/themes/onedarkpro.lua diff --git a/lua/plugins/ui/colors/rose-pine.lua b/lua/plugins/theme/themes/rose-pine.lua similarity index 100% rename from lua/plugins/ui/colors/rose-pine.lua rename to lua/plugins/theme/themes/rose-pine.lua diff --git a/lua/plugins/theme/user.lua b/lua/plugins/theme/user.lua new file mode 100644 index 0000000..4cd1df1 --- /dev/null +++ b/lua/plugins/theme/user.lua @@ -0,0 +1,23 @@ +local config = require("plugins.theme.config") +local io = io + +local M = {} + +-- Save current theme name to user file +function M.save_theme(theme) + vim.fn.mkdir(config.user_dir, "p") + local f = io.open(config.user_theme_file, "w") + if f then f:write(theme); f:close() end +end + +-- Retrieve saved theme name, or nil +function M.get_saved_theme() + local f = io.open(config.user_theme_file, "r") + if f then + local theme = f:read("*l") + f:close() + return theme + end +end + +return M diff --git a/lua/plugins/ui/theme.lua b/lua/plugins/ui/theme.lua deleted file mode 100755 index 2280218..0000000 --- a/lua/plugins/ui/theme.lua +++ /dev/null @@ -1,16 +0,0 @@ -local set = vim.o -local vimscript = vim.cmd - --- chack found themes -local themes_status = pcall(require, "onedarkpro") - --- auto load theme -if themes_status then - require("plugins.ui.colors.onedarkpro") -end - -set.syntax = "Enable" - --- vimscript([[ --- highlight NvimTreeFolderIcon guibg=NONE --- ]]) diff --git a/rocks.toml b/rocks.toml index 85b5f50..bd2761b 100644 --- a/rocks.toml +++ b/rocks.toml @@ -1,136 +1,154 @@ -# This is your rocks.nvim plugins declaration file. -# Here is a small yet pretty detailed example on how to use it: +# rocks.toml — Plugin declaration for rocks.nvim -# This includes things like `toml` or other lua packages. +# ----------------------------------------------------------------------------- +# LuaRocks dependencies (pure Lua modules, non-Neovim plugins) +# ----------------------------------------------------------------------------- [rocks] +# e.g. toml parser for Lua scripts +# toml = "0.1.0" -# List of Neovim plugins to install alongside their versions. -# If the plugin name contains a dot then you must add quotes to the key name! +# ----------------------------------------------------------------------------- +# Neovim plugins (core plugins, installed via rocks.nvim) +# ----------------------------------------------------------------------------- [plugins] -"rocks.nvim" = "2.37.0" -"rocks-edit.nvim" = "scm" -"rocks-treesitter.nvim" = "1.0.3" -"rocks-git.nvim" = "2.0.1" -"rocks-config.nvim" = "2.2.0" -tree-sitter-toml = "0.0.2" -"neodev.nvim" = "3.0.0" -neorg = "9.1.1" -nvim-cmp = "scm" -cmp-nvim-lsp = "scm" -"lspkind.nvim" = "scm" -cmp-buffer = "scm" -cmp-path = "scm" -cmp-cmdline = "scm" -cmp_luasnip = "scm" -luasnip = "2.3.0" -friendly-snippets = "scm" -nvim-web-devicons = "0.100" -tree-sitter-python = "0.0.2" -"dracula.nvim" = "scm" -catppuccin = "0.1.0" -"onedarkpro.nvim" = "0.8.0" -"monokai.nvim" = "scm" +"rocks.nvim" = "2.44.0" +"rocks-edit.nvim" = "scm" +"rocks-treesitter.nvim" = "1.3.0" +"rocks-git.nvim" = "2.5.3" +"rocks-config.nvim" = "3.1.1" +tree-sitter-toml = "0.0.31" +"neodev.nvim" = "3.0.0" +neorg = "9.3.0" +nvim-cmp = "scm" +cmp-nvim-lsp = "scm" +"lspkind.nvim" = "scm" +cmp-buffer = "scm" +cmp-path = "scm" +cmp-cmdline = "scm" +friendly-snippets = "scm" +nvim-web-devicons = "0.100" +tree-sitter-python = "0.0.46" +"mini.nvim" = "scm" +"cmp-mini-snippets" = "scm" + + +# Theme plugins (some available via rocks, others only via git) +"dracula.nvim" = "scm" +catppuccin = "0.1.0" +"onedarkpro.nvim" = "2.17.1" +"monokai.nvim" = "scm" +"rose-pine" = { git = "rose-pine/neovim", rev = "v3.0.2" } +"nord" = { git = "shaunsingh/nord.nvim", rev = "80c1e5321505aeb22b7a9f23eb82f1e193c12470" } +"iceberg" = { git = "cocopon/iceberg.vim", rev = "1.0^{}" } + +# Telescope extensions +"telescope.nvim" = "scm" "telescope-ui-select.nvim" = "scm" -"telescope.nvim" = "scm" +# ----------------------------------------------------------------------------- +# Plugin-specific Git refs (for non-rocks plugins or custom forks) +# ----------------------------------------------------------------------------- [plugins.nvim-terminal] git = "s1n7ax/nvim-terminal" -config = "plugins.ui.nvim-terminal.config" +rev = "e058de4b8029d7605b17275f30f83be8f8df5f62" + [plugins.cmp-nvim-lua] git = "hrsh7th/cmp-nvim-lua" +rev = "f12408bdb54c39c23e67cab726264c10db33ada8" + [plugins.cmp-spell] git = "f3fora/cmp-spell" +rev = "694a4e50809d6d645c1ea29015dad0c293f019d6" + [plugins.cmp-nvim-lsp-document-symbol] git = "hrsh7th/cmp-nvim-lsp-document-symbol" +rev = "f94f7ba948e32cd302caba1c2ca3f7c697fb4fcf" + [plugins.cmp-nvim-lsp-signature-help] git = "hrsh7th/cmp-nvim-lsp-signature-help" -[plugins.iceberg] # Theme/ColorSchrome -git = "cocopon/iceberg.vim" -[plugins.nord] # Theme/ColorSchrome -git = "shaunsingh/nord.nvim" -[plugins.rose-pine] # Theme/ColorSchrome -git = "rose-pine/neovim" -name = "rose-pine" - +rev = "031e6ba70b0ad5eee49fd2120ff7a2e325b17fa7" +# ----------------------------------------------------------------------------- +# Treesitter settings (parser installation) +# ----------------------------------------------------------------------------- [treesitter] -# auto_highlight = "all" -# NOTE: These are parsers, not filetypes. +auto_install = "prompt" # options: true | false | "prompt" auto_highlight = [ - "haskell", - "dhall", + "lua", + "python", "rust", + "haskell", "toml", - "python", - "lua" + "dhall" ] -auto_install = "prompt" # true | false - [treesitter.parser_map] -# You can add custom filetype to parser mappings. -# Determine the filetype with ':lua =vim.bo[0].filetype'. -# NOTE: You don't actually have to add these examples. -# They are added by default. PKGBUILD = "bash" -cls = "latex" -sty = "latex" +cls = "latex" +sty = "latex" +# ----------------------------------------------------------------------------- +# Core config +# ----------------------------------------------------------------------------- [config] plugins_dir = "plugins/" -auto_setup = false +auto_setup = false -# User Interface Plugins Settings +# ----------------------------------------------------------------------------- +# Plugin configuration (via rocks-config.nvim) +# ----------------------------------------------------------------------------- [plugins.nvim-notify] -version = "3.13.5" -config = "plugins.ui.nvim-notify.config" +version = "3.15.0" +config = "plugins.ui.nvim-notify.config" + [plugins."nvim-tree.lua"] version = "1.6.0" -config = "plugins.ui.nvim-tree.config" +config = "plugins.ui.nvim-tree.config" + [plugins."staline.nvim"] version = "scm" -config = "plugins.ui.staline.config" +config = "plugins.ui.staline.config" + [plugins.dashboard-nvim] version = "scm" -config = "plugins.ui.dashboard.config" +config = "plugins.ui.dashboard.config" + [plugins."indent-blankline.nvim"] version = "3.9.0" -config = "plugins.autocomplete.indent.config" +config = "plugins.autocomplete.indent.config" [bundles.telescope] -items = [ - "telescope.nvim", - "telescope-ui-select.nvim" -] +items = ["telescope.nvim", "telescope-ui-select.nvim"] config = "plugins.ui.telescope.config" [plugins."ultimate-autopair.nvim"] version = "scm" -config = "plugins.autocomplete.autopair.config" - +config = "plugins.autocomplete.autopair.config" -# LSP & autocomplete System Plugins Settings +# ----------------------------------------------------------------------------- +# LSP & completion +# ----------------------------------------------------------------------------- [plugins."mason-lspconfig.nvim"] -config = "plugins.autocomplete.lspconfig" version = "scm" +config = "plugins.autocomplete.lspconfig" - -[bundles.cmp] # Create a bundle called `cmp` +[bundles.cmp] items = [ - "lspkind.nvim", - "nvim-cmp", - "cmp-nvim-lsp", - "cmp-buffer", - "cmp-path", - "cmp-cmdline", - "luasnip", - "cmp_luasnip", - "friendly-snippets", - "neodev.nvim", - ] - config = "plugins.autocomplete.cmp" + "lspkind.nvim", + "nvim-cmp", + "cmp-nvim-lsp", + "cmp-buffer", + "cmp-path", + "cmp-cmdline", + "luasnip", + "cmp_luasnip", + "friendly-snippets", + "neodev.nvim" +] +config = "plugins.autocomplete.cmp" [plugins."trouble.nvim"] -config = "plugins.autocomplete.trouble.config" -version = "3.6.0" +version = "3.7.1" +config = "plugins.autocomplete.trouble.config" +