local M = {} M.root_patterns = { ".git", "/lua" } function M.setup() require "lazyvim.utils.term" end ---@param on_attach fun(client, buffer) function M.on_attach(on_attach) vim.api.nvim_create_autocmd("LspAttach", { callback = function(args) local buffer = args.buf local client = vim.lsp.get_client_by_id(args.data.client_id) on_attach(client, buffer) end, }) end -- returns the root directory based on: -- * lsp workspace folders -- * lsp root_dir -- * root pattern of filename of the current buffer -- * root pattern of cwd ---@return string function M.get_root() ---@type string? local path = vim.api.nvim_buf_get_name(0) path = path ~= "" and vim.loop.fs_realpath(path) or nil ---@type string[] local roots = {} if path then for _, client in pairs(vim.lsp.get_clients({ bufnr = 0 })) do local workspace = client.config.workspace_folders local paths = workspace and vim.tbl_map(function(ws) return vim.uri_to_fname(ws.uri) end, workspace) or client.config.root_dir and { client.config.root_dir } or {} for _, p in ipairs(paths) do local r = vim.loop.fs_realpath(p) if path:find(r, 1, true) then roots[#roots + 1] = r end end end end table.sort(roots, function(a, b) return #a > #b end) ---@type string? local root = roots[1] if not root then path = path and vim.fs.dirname(path) or vim.loop.cwd() ---@type string? root = vim.fs.find(M.root_patterns, { path = path, upward = true })[1] root = root and vim.fs.dirname(root) or vim.loop.cwd() end ---@cast root string return root end ---@param silent boolean? ---@param values? {[1]:any, [2]:any}function function M.toggle(option, silent, values) if values then if vim.opt_local[option]:get() == values[1] then vim.opt_local[option] = values[2] else vim.opt_local[option] = values[1] end return vim.notify( "Set " .. option .. " to " .. vim.opt_local[option]:get(), vim.log.levels.INFO, { title = "Option" } ) end vim.opt_local[option] = not vim.opt_local[option]:get() if not silent then vim.notify( (vim.opt_local[option]:get() and "Enabled" or "Disabled") .. " " .. option, vim.log.levels.INFO, { title = "Option" } ) end end local diagnostics_enabled = true function M.toggle_diagnostics() diagnostics_enabled = not diagnostics_enabled if diagnostics_enabled then vim.diagnostic.enable() vim.notify("Enabled diagnostics", vim.log.levels.INFO, { title = "Diagnostics" }) else vim.diagnostic.disable() vim.notify("Disabled diagnostics", vim.log.levels.INFO, { title = "Diagnostics" }) end end function M.smart_quit() local bufnr = vim.api.nvim_get_current_buf() local modified = vim.api.nvim_buf_get_option(bufnr, "modified") if modified then vim.ui.input({ prompt = "You have unsaved changes. Quit anyway? (y/n) ", }, function(input) if input == "y" then vim.cmd("q!") end end) else vim.cmd("q!") end end function M.isempty(s) return s == nil or s == "" end function M.get_buf_option(opt) local status_ok, buf_option = pcall(vim.api.nvim_buf_get_option, 0, opt) if not status_ok then return nil else return buf_option end end function M.telescope(builtin, opts) opts = opts or {} opts.dir = opts.dir or M.get_root() return function() require("telescope.builtin")[builtin](vim.tbl_deep_extend("force", { cwd = opts.dir }, opts)) end end -- This might not be best, but it allows for easy resetting function M.setColorscheme(scheme) local colorscheme = scheme or "gruvbox-material" local okay, _ = pcall(vim.cmd, "colorscheme " .. colorscheme) if not okay then vim.notify("Colorscheme " .. colorscheme .. " not found!") vim.cmd("colorscheme habamax") end end function M.trim_whitespace() pcall(vim.cmd, 'let currPos = getpos(".")') pcall(vim.cmd, [[%s/\s\+$//e]]) pcall(vim.cmd, [[%s/\n\+\%$//e]]) pcall(vim.cmd, [[.[ch] %s/\%$/\r/e]]) pcall(vim.cmd, 'cal cursor(currPos[1], currPos[2])') end function M.exists(path) local exists = vim.fn.filereadable(vim.fn.expand(path)) if exists == 1 then vim.notify(path .. " exists", vim.log.levels.INFO) return true else vim.notify(path .. " doesn't exist", vim.log.levels.INFO) return false end end return M