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", { -- group = vim.api.nvim_create_augroup("my.lsp", {}), callback = function(args) local buffer = args.buf local client = assert(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 local format = string.format local rep = string.rep local write = io.write ---Recursively print the table, if not table value is just printed. ---@param t any ---@param level? number function M.print_table(t, level) level = level or 0 if type(t) == "table" then -- do not print new line on the level 0 if level ~= 0 then print("\n") end print(rep("\t", level), "{\n") level = level + 1 for key, value in pairs(t) do print(rep("\t", level) .. format("[%s] = ", key)) M.print_table(value, level) end level = level - 1 print(rep("\t", level), "}") else print(tostring(t)) end -- print new line on the level 0 if level == 0 then print("\n") end end return M