local M = {} function M.map(mode, shortcut, command, description, buffer) local opts = { noremap = true, silent = true } opts.desc = description or nil opts.buffer = buffer or nil vim.keymap.set(mode, shortcut, command, opts) end function M.remove_trailing_whitespace() if vim.b.cleanup_file == false then return end local curpos = vim.api.nvim_win_get_cursor(0) vim.cmd([[keeppatterns %s/\s\+$//e]]) vim.api.nvim_win_set_cursor(0, curpos) end vim.api.nvim_create_augroup('config_functions', { clear = true }) vim.api.nvim_create_autocmd({ 'BufWritePre' }, { group = 'config_functions', pattern = { '*.lua', '*.cpp', '*.hpp', '*.conf', '*.cfg', '*.ini', '*.adoc' }, callback = M.remove_trailing_whitespace }) -- Insert or update a modeline at the bottom of the buffer function M.insert_modeline() local comment_string = vim.o.commentstring if comment_string == '' then comment_string = '%s' end local space_maybe = '' if string.match(comment_string, '%%s(.*)') ~= '' then space_maybe = ' ' end local fenc = vim.o.fileencoding if fenc == '' then fenc = 'utf-8' end local modeline_elements = { ' vim: set', ' ts=' .. vim.o.tabstop, ' sw=' .. vim.o.shiftwidth, (vim.o.expandtab and ' et' or ' noet'), ' tw=' .. vim.o.textwidth, ' ft=' .. vim.o.filetype, (vim.o.spell and ' spell' .. ' spl=' .. vim.o.spelllang or ''), (vim.o.wrap and ' wrap' or ' nowrap'), ':', space_maybe } local modeline = comment_string:gsub('%%s', table.concat(modeline_elements)) modeline = modeline:gsub(' ', ' ') local buffer = vim.api.nvim_win_get_buf(0) local current = vim.api.nvim_buf_get_lines(buffer, -2, -1, true)[1] if current == modeline then print('modeline already exists') elseif string.match(current, 'vim:') then vim.api.nvim_buf_set_lines(buffer, -2, -1, true, { modeline }) print('modeline updated') else vim.api.nvim_buf_set_lines(buffer, -1, -1, true, { '', modeline }) print('modeline inserted') end end vim.api.nvim_create_user_command('ModelineInsert', M.insert_modeline, {}) -- Files that could indicate the project's root directory M.project_root_markers = { '.git', '.hg', '.svn', '.bzr', '_darcs', '.projectile', '.luarc.json', '.editorconfig', 'Cargo.toml' } function M.get_project_root() local lsp_root = vim.lsp.buf.list_workspace_folders()[1] if lsp_root ~= nil then return lsp_root end local path = vim.api.nvim_buf_get_name(0) local sep = '/' repeat path = path:gsub(string.format('%s[^%s]*$', sep, sep), '') for _, marker in ipairs(M.project_root_markers) do if path ~= os.getenv('HOME') and io.open(path .. sep .. marker) then return path end end until path == '' return nil end function M.shell_capture(command) local handle = io.popen(command) if not handle then return nil end local result = handle:read() or nil handle:close() return result end -- return colours from highlight groups in web notation (#rrggbb) function M.get_hl_hex(hl_group) local hl = vim.api.nvim_get_hl_by_name(hl_group, true) local hl_hex = {} if hl.foreground then hl_hex.foreground = string.format('#%.6x', hl.foreground) end if hl.background then hl_hex.background = string.format('#%.6x', hl.background) end return hl_hex end -- return true if 'Symbols Nerd Font' is known to fontconfig function M.nerdfont_installed() if vim.fn.executable('fc-list') == 1 and os.execute([[fc-list -q 'Symbols Nerd Font']]) == 0 then return true end return false end -- return LSP status function M.lsp_status() local status = '' for _, msg in ipairs(require('lsp-status/messaging').messages()) do if msg.progress then status = '⏳' elseif msg.status then -- clangd parsing includes and whatnot if msg.content ~= 'idle' then status = '⌛' end end end return status end function M.lsp_sig_status() if not vim.lsp.buf.server_ready() then return "" end local width = vim.o.columns / 3 if width < 40 then return "" end if width > 50 then width = width * 1.5 end local label = require('lsp_signature').status_line().label if label:len() > width then label = label:sub(1, math.floor(width)) .. '…' end return label end function M.not_firenvim() return vim.g.started_by_firenvim == nil end -- returns the name of the current function in brackets or an empty string function M.current_function() local curfun = vim.b.lsp_current_function if curfun and curfun ~= '' then return '(' .. curfun .. ')' end return '' end return M