local M = {} ---Check if path exists ---@param p string|nil ---@return boolean local function path_exists(p) return p and p ~= '' and vim.uv.fs_stat(p) ~= nil end ---Get Mason binary path ---@param name string ---@return string local function mason_bin(name) local p = vim.fs.joinpath(vim.fn.stdpath('data'), 'mason', 'bin', name) if path_exists(p) then return p end return name end ---Find Julia binary ---@return string local function julia_bin() local home = vim.env.HOME or '' local candidates = { vim.fn.exepath('julia'), vim.fs.joinpath(home, '.juliaup', 'bin', 'julia'), '/opt/homebrew/bin/julia', '/usr/local/bin/julia', } for _, p in ipairs(candidates) do if path_exists(p) then return p end end return 'julia' end local julia_cmd = julia_bin() local julia_ls_project = vim.fn.expand('~/.julia/environments/nvim-lsp') -- Servers that should provide formatting M.format_enabled_servers = { bashls = true, clangd = true, gopls = true, html = true, htmx = true, jsonls = true, lua_ls = true, marksman = true, pyright = true, ruff = true, rust_analyzer = true, taplo = true, texlab = true, yamlls = true, zls = true, } -- Server-specific configurations M.servers = { bashls = { filetypes = { 'sh', 'bash', 'zsh' }, }, html = { filetypes = { 'html', 'htmldjango' }, init_options = { configurationSection = { 'html', 'css', 'javascript' }, embeddedLanguages = { css = true, javascript = true, }, }, }, htmx = { cmd = { 'htmx-lsp' }, filetypes = { 'html', 'htmx' }, }, gopls = { settings = { gopls = { gofumpt = true, staticcheck = true, completeUnimported = true, usePlaceholders = true, analyses = { unusedparams = true }, }, }, }, clangd = { cmd = { 'clangd', '--background-index', '--clang-tidy', '--header-insertion=iwyu', '--completion-style=detailed', '--header-insertion-decorators', '--query-driver=/usr/bin/clang,/usr/bin/clang++', '--enable-config', }, settings = { formatting = true, inlayHints = { designators = true, enabled = true, parameterNames = true, deducedTypes = true, }, }, filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'h', 'hpp', 'hxx' }, }, marksman = { filetypes = { 'markdown' }, settings = { marksman = { extensions = { 'mdx' }, }, }, }, jsonls = { cmd = { 'vscode-json-language-server', '--stdio' }, settings = { json = { validate = { enable = true }, }, }, }, julials = { filetypes = { 'julia' }, cmd = { julia_cmd, '--project=' .. julia_ls_project, '--startup-file=no', '--history-file=no', '-e', [[ using Logging using LanguageServer using SymbolServer global_logger(ConsoleLogger(stderr, Logging.Warn)) function project_path() try return LanguageServer.find_project_path(pwd()) catch return pwd() end end depot_path = get(ENV, "JULIA_DEPOT_PATH", "") server = LanguageServer.LanguageServerInstance( stdin, stdout, something(project_path(), pwd()), depot_path, ) server.runlinter = true run(server) ]], }, settings = { julia = { lint = { run = true, }, }, }, }, pyright = { settings = { python = { analysis = { autoSearchPaths = true, diagnosticMode = 'workspace', useLibraryCodeForTypes = true, typeCheckingMode = 'none', reportGeneralTypeIssues = false, }, }, }, }, ruff = { filetypes = { 'python' }, on_init = function() vim.api.nvim_create_autocmd('LspAttach', { group = vim.api.nvim_create_augroup('lsp_attach_disable_ruff_hover', { clear = true }), callback = function(args) local client = vim.lsp.get_client_by_id(args.data.client_id) if client and client.name == 'ruff' then client.server_capabilities.hoverProvider = false end end, desc = 'LSP: Disable hover capability from Ruff', }) end, }, rust_analyzer = { settings = { ['rust-analyzer'] = { imports = { granularity = { group = 'module' }, prefix = 'self' }, cargo = { buildScripts = { enable = true } }, procMacro = { enable = true }, checkOnSave = { command = 'clippy' }, }, }, }, taplo = { filetypes = { 'toml' }, }, yamlls = { settings = { yaml = { schemaStore = { enable = true }, validate = true, }, }, }, texlab = { filetypes = { 'tex', 'plaintex', 'bib', 'cls', 'sty' }, settings = { texlab = { build = { onSave = false, }, diagnostics = { ignoredPatterns = { '^Overfull \\hbox', '^Underfull \\hbox', '^Package.*Warning', }, }, auxDirectory = 'output', }, }, }, lua_ls = { cmd = { mason_bin('lua-language-server') }, settings = { Lua = { workspace = { checkThirdParty = false }, telemetry = { enable = false }, diagnostics = { globals = { 'vim' } }, }, }, }, sqls = { filetypes = { 'sql', 'mysql', 'plsql', 'postgresql' }, settings = { sql = { connections = { { driver = 'sqlite3', dataSourceName = 'file::memory:?cache=shared', }, }, }, }, on_init = function(client) local root_dir = client.config.root_dir or vim.fn.getcwd() local db_files = vim.fn.globpath(root_dir, '*.db', false, true) vim.list_extend(db_files, vim.fn.globpath(root_dir, '*.sqlite', false, true)) if #db_files > 0 then local connections = {} for _, path in ipairs(db_files) do table.insert(connections, { driver = 'sqlite3', dataSourceName = vim.fn.fnamemodify(path, ':p'), }) end client.config.settings.sql.connections = connections client.notify('workspace/didChangeConfiguration', { settings = client.config.settings }) end end, }, zls = { filetypes = { 'zig' }, }, } return M