Display diagnostics inline to buffer List compile errors/warnings in quickfix list Added 'push' command to install script Make sure install script executes from the correct directory
287 lines
8.5 KiB
Lua
287 lines
8.5 KiB
Lua
local MAP = vim.keymap.set
|
|
local AUTOCMD = vim.api.nvim_create_autocmd
|
|
|
|
vim.cmd("colorscheme scheme")
|
|
vim.cmd("filetype indent on")
|
|
|
|
-- Language people you have more important things to do than police the code style, if people
|
|
-- want consistent styling it should be done at a project level using a linter or .editorconfig
|
|
vim.g.rust_recommended_style = false
|
|
vim.g.python_recommended_style = false
|
|
vim.g.go_recommended_style = false
|
|
vim.g.zig_recommended_style = false
|
|
vim.g.markdown_recommended_style = false
|
|
vim.g.arduino_recommended_style = false
|
|
vim.g.gdscript_recommended_style = false
|
|
vim.g.yaml_recommended_style = false
|
|
|
|
-- Basic options
|
|
vim.o.tabstop = 2
|
|
vim.o.shiftwidth = 0
|
|
vim.o.expandtab = false
|
|
vim.o.list = true
|
|
vim.o.clipboard = "unnamedplus"
|
|
vim.o.ff = "unix"
|
|
vim.o.ffs = "unix,dos"
|
|
vim.o.switchbuf = "useopen,uselast"
|
|
vim.o.textwidth = 95
|
|
vim.o.wrapmargin = 5
|
|
vim.o.number = true
|
|
vim.o.relativenumber = true
|
|
vim.o.splitbelow = true
|
|
vim.o.splitright = true
|
|
vim.o.autoread = true
|
|
vim.o.lazyredraw = true
|
|
vim.o.cursorline = true
|
|
vim.o.ignorecase = true
|
|
vim.o.wrap = false
|
|
vim.o.wildmenu = false
|
|
vim.o.termguicolors = true
|
|
vim.o.cindent = true
|
|
vim.o.timeoutlen = 1500
|
|
vim.o.completeopt = "preview"
|
|
vim.o.wildmode = "full"
|
|
vim.o.cinoptions = "l1,b-s"
|
|
vim.o.statusline = "%#LineNr# [%n] %#Default# %f%m%r %= %#StatusLineNC# %w[%{&ft == '' ? 'None' : ''}%Y] %#LineNr# Line: %l Column: %c "
|
|
|
|
vim.opt.errorformat = {
|
|
"%f:%l:%c: fatal %trror: %m", -- gcc/clang fatal error
|
|
"%f:%l:%c: %trror: %m", -- gcc/clang error
|
|
"%f:%l:%c: %tarning: %m", -- gcc/clang warning
|
|
"%-G%m" -- Ignore anything else
|
|
}
|
|
|
|
vim.opt.formatoptions:append("/")
|
|
vim.opt.cinkeys:append("0=break")
|
|
vim.opt.listchars:append({ lead = "." })
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Functions
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Building & Errors
|
|
|
|
-- Diagnostics configuration
|
|
vim.diagnostic.config({
|
|
signs = {
|
|
text = {
|
|
[vim.diagnostic.severity.ERROR] = "",
|
|
[vim.diagnostic.severity.WARN] = ""
|
|
},
|
|
linehl = {
|
|
[vim.diagnostic.severity.ERROR] = "DiagnosticLineError",
|
|
[vim.diagnostic.severity.WARN] = "DiagnosticLineWarn"
|
|
},
|
|
},
|
|
virtual_text = {
|
|
virt_text_pos = "eol_right_align",
|
|
prefix =
|
|
function(d, i, total)
|
|
return d.severity == vim.diagnostic.severity.ERROR and "!" or "#"
|
|
end
|
|
},
|
|
underline = false,
|
|
severity_sort = true
|
|
})
|
|
|
|
local _last_build = ""
|
|
local _quickfix = {}
|
|
local _namespace = vim.api.nvim_create_namespace("__qf.buffer.errors")
|
|
|
|
local function LoadDiagnostics(args)
|
|
local bufnr = args.buf
|
|
|
|
if _quickfix[bufnr] then
|
|
vim.diagnostic.set(_namespace, bufnr, _quickfix[bufnr])
|
|
end
|
|
end
|
|
|
|
local function ExecuteBuild()
|
|
vim.cmd("silent make")
|
|
|
|
-- Reset currently displayed diagnostics
|
|
_quickfix = {}
|
|
vim.diagnostic.reset()
|
|
|
|
local entries = vim.fn.getqflist()
|
|
if #entries ~= 0 then
|
|
-- Group diagnostics by buffer number
|
|
local diagnostics = vim.diagnostic.fromqflist(entries)
|
|
for _, d in ipairs(diagnostics) do
|
|
if not _quickfix[d.bufnr] then
|
|
_quickfix[d.bufnr] = {}
|
|
end
|
|
|
|
table.insert(_quickfix[d.bufnr], d)
|
|
end
|
|
|
|
-- Display the new diagnostics
|
|
for it, v in pairs(_quickfix) do
|
|
vim.diagnostic.set(_namespace, it, v)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function PromptBuild()
|
|
vim.ui.input(
|
|
{
|
|
prompt = "Compile: ",
|
|
completion = "shellcmdline",
|
|
default = _last_build
|
|
},
|
|
function(input)
|
|
if input ~= nil then
|
|
local makeprg = vim.o.makeprg
|
|
vim.o.makeprg = input
|
|
|
|
ExecuteBuild()
|
|
|
|
_last_build = input
|
|
vim.o.makeprg = makeprg
|
|
end
|
|
end
|
|
)
|
|
end
|
|
|
|
-- Buffers
|
|
|
|
local function BufferComplete()
|
|
local pos = vim.api.nvim_win_get_cursor(0)
|
|
local line = vim.fn.getline('.')
|
|
local ident = line:sub(1, pos[2]):match("[^ \t]*$")
|
|
|
|
return #ident ~= 0 and "<C-P>" or "<Tab>"
|
|
end
|
|
|
|
local function TrimBuffer()
|
|
local view = vim.fn.winsaveview()
|
|
vim.cmd("%s/\\s\\+$//e")
|
|
vim.fn.winrestview(view)
|
|
end
|
|
|
|
local function MakeScratch()
|
|
local bufnr = vim.api.nvim_create_buf(true, true)
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "buftype", "nofile")
|
|
vim.api.nvim_buf_set_option(bufnr, "bufhidden", "hide")
|
|
vim.api.nvim_buf_set_option(bufnr, "swapfile", false)
|
|
vim.api.nvim_buf_set_option(bufnr, "modified", false)
|
|
|
|
vim.api.nvim_buf_set_name(bufnr, "scratch")
|
|
|
|
vim.api.nvim_buf_set_text(bufnr, 0, 0, 0, -1, { "-*- Scratch Buffer -*-" })
|
|
|
|
-- @Hack: There isn't really any way to get the fullscreen size, 150 greater than the
|
|
-- half-screen width on all of my devices as we don't want to split in that case
|
|
if vim.o.columns > 150 then
|
|
vim.cmd(string.format("vsplit #%d", bufnr))
|
|
vim.cmd("wincmd p")
|
|
end
|
|
end
|
|
|
|
-- Windowing
|
|
|
|
local _is_help = { help = true, man = true, qf = true }
|
|
|
|
function ManageSplit()
|
|
local windows = vim.api.nvim_tabpage_list_wins(0)
|
|
local bufnr = vim.api.nvim_win_get_buf(windows[#windows])
|
|
local filetype = vim.bo[bufnr].filetype
|
|
|
|
local target_count = _is_help[filetype] and 3 or 2
|
|
|
|
if #windows == target_count then
|
|
-- We already have the target number of windows open so we should close our split window,
|
|
-- always close 2 because that is the right-most split. The third window if it exists is
|
|
-- the bottom most window and is a "help" window
|
|
vim.api.nvim_win_close(windows[2], false)
|
|
else
|
|
-- We have less than the required windows open so split the first window, we open the
|
|
-- "scratch" buffer in this new window, if it is still open. Otherwise the same buffer in
|
|
-- the first window is opened.
|
|
local scratch = vim.fn.bufnr("scratch")
|
|
local first = vim.api.nvim_win_get_buf(windows[1])
|
|
|
|
bufnr = vim.api.nvim_buf_is_loaded(scratch) and scratch or first
|
|
vim.api.nvim_open_win(bufnr, true, { split = "right", win = windows[1] })
|
|
end
|
|
end
|
|
|
|
local function ProjectSearch()
|
|
local input = vim.fn.input("Search: ")
|
|
|
|
if input and input ~= "" then
|
|
vim.cmd("silent lgrep! \"" .. input .. "\" **")
|
|
vim.cmd("lopen | lfirst | wincmd p")
|
|
end
|
|
end
|
|
|
|
local function ExpandHelp(a)
|
|
local winid = vim.api.nvim_get_current_win()
|
|
local filetype = vim.bo[vim.api.nvim_win_get_buf(winid)].filetype
|
|
local height = a.event == "WinEnter" and math.floor(0.8 * vim.o.lines) or 5
|
|
|
|
if _is_help[filetype] then
|
|
vim.api.nvim_win_set_height(winid, height)
|
|
end
|
|
end
|
|
|
|
local function LayoutHelp(a)
|
|
if _is_help[vim.bo.filetype] then
|
|
local winid = vim.api.nvim_get_current_win()
|
|
local windows = vim.api.nvim_tabpage_list_wins(0)
|
|
|
|
-- We need to close other "help" windows that may be open so search through the open
|
|
-- windows. There *should* only ever be 3 windows open if my window handling is working
|
|
-- correctly
|
|
for _, w in ipairs(windows) do
|
|
if w ~= winid then
|
|
local bufnr = vim.api.nvim_win_get_buf(w)
|
|
if _is_help[vim.bo[bufnr].filetype] then
|
|
vim.api.nvim_win_close(wi.winid, true)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Force the new window to the bottom and expand it to be 80% of the height
|
|
vim.cmd("wincmd J")
|
|
vim.cmd(string.format("resize %d", math.floor(0.8 * vim.o.lines)))
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Input mappings
|
|
--------------------------------------------------------------------------------
|
|
|
|
vim.g.mapleader = " "
|
|
|
|
MAP("n", "<A-j>", "mz:m+<CR>")
|
|
MAP("n", "<A-k>", "mz:m-2<CR>")
|
|
MAP("n", "<Esc>", ":nohl<CR>")
|
|
MAP("n", "<Leader>n", ":cnext<CR>")
|
|
MAP("n", "<Leader>N", ":cprev<CR>")
|
|
MAP("n", "J", "}")
|
|
MAP("v", "J", "}")
|
|
MAP("n", "K", "{")
|
|
MAP("v", "K", "{")
|
|
MAP("n", "<Leader>k", ":Man<CR>")
|
|
MAP("i", "<S-Tab>", "<C-o><<")
|
|
MAP("i", "<Tab>", BufferComplete, { expr = true })
|
|
MAP("n", "<Leader>s", ManageSplit)
|
|
MAP("n", "<Leader>f", ProjectSearch)
|
|
MAP("n", "<Leader>m", PromptBuild)
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Autocommands
|
|
--------------------------------------------------------------------------------
|
|
|
|
AUTOCMD('BufEnter', { command = "let b:man_default_sects=\"2,3\"", pattern = "*.c" })
|
|
AUTOCMD('BufReadPost', { command = "setlocal nornu", pattern = "quickfix" })
|
|
|
|
AUTOCMD('BufWritePre', { callback = TrimBuffer, pattern = "*" })
|
|
AUTOCMD('VimEnter', { callback = MakeScratch, pattern = "*" })
|
|
AUTOCMD('BufWinEnter', { callback = LayoutHelp, pattern = "*" })
|
|
AUTOCMD('WinEnter', { callback = ExpandHelp, pattern = "*" })
|
|
AUTOCMD('WinLeave', { callback = ExpandHelp, pattern = "*" })
|
|
AUTOCMD('BufRead', { callback = LoadDiagnostics, pattern = "*" })
|