2025-09-24 17:05:32 +01:00
|
|
|
local MAP = vim.keymap.set
|
|
|
|
|
local AUTOCMD = vim.api.nvim_create_autocmd
|
2025-09-25 16:30:14 +01:00
|
|
|
local NEWCMD = vim.api.nvim_create_user_command
|
2025-09-24 17:05:32 +01:00
|
|
|
|
2025-09-24 16:49:47 +01:00
|
|
|
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
|
|
|
|
|
|
2025-09-24 16:42:00 +01:00
|
|
|
-- 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 = "." })
|
|
|
|
|
|
2025-09-24 17:05:32 +01:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
-- Functions
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
2025-09-24 23:03:16 +01:00
|
|
|
-- 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
|
|
|
|
|
|
2025-09-25 00:04:21 +01:00
|
|
|
local function FormatJumpList()
|
|
|
|
|
local qf = vim.fn.getqflist( { winid = true, qfbufnr = true })
|
|
|
|
|
local loc = vim.fn.getloclist(0, { winid = true, qfbufnr = true })
|
|
|
|
|
|
|
|
|
|
if qf.winid ~= 0 then
|
|
|
|
|
-- This means the quickfix list is open and needs formatting
|
|
|
|
|
local ns = vim.api.nvim_create_namespace("__qf.format")
|
|
|
|
|
local bufnr = qf.qfbufnr
|
|
|
|
|
local entries = vim.fn.getqflist()
|
|
|
|
|
local text = {}
|
|
|
|
|
local max = { 0, 0, 0 }
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
|
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "modifiable", true)
|
|
|
|
|
|
|
|
|
|
for _, it in ipairs(entries) do
|
|
|
|
|
max[1] = math.max(max[1], #tostring(it.lnum))
|
|
|
|
|
max[2] = math.max(max[2], #tostring(it.col))
|
|
|
|
|
max[3] = math.max(max[3], #vim.fn.bufname(it.bufnr))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- +2 for the extra colons we put between the filename, line number and column number
|
|
|
|
|
local extformat = string.format("[%%s] %%-%ds | %%s", max[1] + max[2] + max[3] + 2)
|
|
|
|
|
|
|
|
|
|
for _, it in ipairs(entries) do
|
|
|
|
|
local sign = it.type:lower() == "e" and "!" or "#"
|
|
|
|
|
local fname = string.format("%s:%d:%d" , vim.fn.bufname(it.bufnr), it.lnum, it.col)
|
|
|
|
|
|
|
|
|
|
table.insert(text, extformat:format(sign, fname, it.text))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, text)
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "modifiable", false)
|
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "modified", false)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if loc.winid ~= 0 then
|
|
|
|
|
-- This means the location list is open and needs formatting
|
|
|
|
|
local ns = vim.api.nvim_create_namespace("__loc.format")
|
|
|
|
|
local bufnr = loc.qfbufnr
|
|
|
|
|
local entries = vim.fn.getloclist(0)
|
|
|
|
|
local text = {}
|
|
|
|
|
local max = { 0, 0 }
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
|
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "modifiable", true)
|
|
|
|
|
|
|
|
|
|
for _, it in ipairs(entries) do
|
|
|
|
|
max[1] = math.max(max[1], #vim.fn.bufname(it.bufnr))
|
|
|
|
|
max[2] = math.max(max[2], #tostring(it.lnum))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- +1 for the extra colon we put between the filename and the line number
|
|
|
|
|
local extformat = string.format("[~] %%-%ds | %%s", max[1] + max[2] + 1)
|
|
|
|
|
|
|
|
|
|
for _, it in ipairs(entries) do
|
|
|
|
|
local fname = string.format("%s:%d", vim.fn.bufname(it.bufnr), it.lnum)
|
|
|
|
|
table.insert(text, extformat:format(fname, it.text))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, text)
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "modifiable", false)
|
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "modified", false)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-09-24 17:05:32 +01:00
|
|
|
-- 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
|
|
|
|
|
|
2025-09-24 18:59:41 +01:00
|
|
|
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
|
|
|
|
|
|
2025-09-25 16:30:14 +01:00
|
|
|
local function AlignEq()
|
|
|
|
|
if vim.fn.mode():lower() == "v" then
|
|
|
|
|
-- Feed an escape to leave visual mode, this updates the '< and '> marks
|
|
|
|
|
local keys = vim.api.nvim_replace_termcodes('<Esc>', true, false, true)
|
|
|
|
|
vim.api.nvim_feedkeys(keys, 'x', true)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local st = vim.fn.getpos("'<")[2] - 1
|
|
|
|
|
local ed = vim.fn.getpos("'>")[2]
|
|
|
|
|
|
|
|
|
|
local max = 0
|
|
|
|
|
|
|
|
|
|
local lines = vim.api.nvim_buf_get_lines(0, st, ed, true)
|
|
|
|
|
local aligned = {}
|
|
|
|
|
|
|
|
|
|
for _, line in ipairs(lines) do
|
|
|
|
|
local pos = line:find('=', 1, true)
|
|
|
|
|
if pos then
|
|
|
|
|
local trimmed = line:sub(1, pos - 1):gsub("%s+$", "")
|
|
|
|
|
max = math.max(#trimmed, max)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for _, line in ipairs(lines) do
|
|
|
|
|
local text = line
|
|
|
|
|
local pos = line:find('=', 1, true)
|
|
|
|
|
if pos then
|
|
|
|
|
local before = line:sub(1, pos - 1):gsub("%s+$", "")
|
|
|
|
|
local after = line:sub(pos + 1):gsub("^%s+", "")
|
|
|
|
|
|
|
|
|
|
text = before .. string.rep(" ", max - #before + 1) .. "= " .. after
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
table.insert(aligned, text)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_set_lines(0, st, ed, true, aligned)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local _comment_leaders = {
|
|
|
|
|
lua = '--',
|
|
|
|
|
vim = '"',
|
|
|
|
|
sh = "#",
|
|
|
|
|
python = "#",
|
|
|
|
|
conf = "#",
|
|
|
|
|
yaml = "#",
|
|
|
|
|
gdscript = "#",
|
|
|
|
|
make = "#"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local function BlockComment()
|
|
|
|
|
local leader = _comment_leaders[vim.o.filetype] or '//'
|
|
|
|
|
|
|
|
|
|
local st = vim.api.nvim_win_get_cursor(0)[1] - 1
|
|
|
|
|
local ed = st + 1
|
|
|
|
|
|
|
|
|
|
if vim.fn.mode():lower() == "v" then
|
|
|
|
|
-- Feed keys to leave visual mode, this updates the '< and '> marks
|
|
|
|
|
local keys = vim.api.nvim_replace_termcodes('<Esc>', true, false, true)
|
|
|
|
|
vim.api.nvim_feedkeys(keys, 'x', true)
|
|
|
|
|
|
|
|
|
|
st = vim.fn.getpos("'<")[2] - 1
|
|
|
|
|
ed = vim.fn.getpos("'>")[2]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local lines = vim.api.nvim_buf_get_lines(0, st, ed, true)
|
|
|
|
|
local comment = false
|
|
|
|
|
|
|
|
|
|
for _, line in ipairs(lines) do
|
|
|
|
|
local pos = line:find("%S")
|
|
|
|
|
if #line > 0 and line:byte(pos) ~= leader:byte(1) then
|
|
|
|
|
comment = true
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local adjusted = {}
|
|
|
|
|
|
|
|
|
|
for _, line in ipairs(lines) do
|
|
|
|
|
local text = ""
|
|
|
|
|
if #line > 0 then
|
|
|
|
|
if comment then
|
|
|
|
|
text = leader .. " " .. line
|
|
|
|
|
else
|
|
|
|
|
local s, e = line:find(leader, 1, true)
|
|
|
|
|
|
|
|
|
|
if line:byte(e + 1) == 0x20 then e = e + 1 end
|
|
|
|
|
text = line:sub(1, s - 1) .. line:sub(e + 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
table.insert(adjusted, text)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.api.nvim_buf_set_lines(0, st, ed, true, adjusted)
|
|
|
|
|
end
|
|
|
|
|
|
2025-09-24 18:59:41 +01:00
|
|
|
-- 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
|
2025-09-25 00:04:21 +01:00
|
|
|
vim.api.nvim_win_close(w, true)
|
2025-09-24 18:59:41 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
2025-09-24 17:05:32 +01:00
|
|
|
-- Input mappings
|
2025-09-24 18:59:41 +01:00
|
|
|
--------------------------------------------------------------------------------
|
2025-09-24 17:05:32 +01:00
|
|
|
|
|
|
|
|
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 })
|
2025-09-24 18:59:41 +01:00
|
|
|
MAP("n", "<Leader>s", ManageSplit)
|
|
|
|
|
MAP("n", "<Leader>f", ProjectSearch)
|
2025-09-24 23:03:16 +01:00
|
|
|
MAP("n", "<Leader>m", PromptBuild)
|
2025-09-25 16:30:14 +01:00
|
|
|
MAP("v", "<Leader>/", BlockComment)
|
|
|
|
|
MAP("n", "<Leader>/", BlockComment)
|
|
|
|
|
MAP("v", "<Leader>=", AlignEq)
|
2025-09-24 17:05:32 +01:00
|
|
|
|
2025-09-24 18:59:41 +01:00
|
|
|
--------------------------------------------------------------------------------
|
2025-09-24 17:05:32 +01:00
|
|
|
-- Autocommands
|
2025-09-24 18:59:41 +01:00
|
|
|
--------------------------------------------------------------------------------
|
2025-09-24 17:05:32 +01:00
|
|
|
|
|
|
|
|
AUTOCMD('BufEnter', { command = "let b:man_default_sects=\"2,3\"", pattern = "*.c" })
|
|
|
|
|
AUTOCMD('BufReadPost', { command = "setlocal nornu", pattern = "quickfix" })
|
2025-09-24 16:42:00 +01:00
|
|
|
|
2025-09-25 00:04:21 +01:00
|
|
|
AUTOCMD('BufReadPost', { callback = FormatJumpList, 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 = "*" })
|
2025-09-25 16:30:14 +01:00
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
-- Custom commands
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
local function Tabber(a)
|
|
|
|
|
local count = tonumber(a.fargs[1])
|
|
|
|
|
|
|
|
|
|
if count == nil then
|
|
|
|
|
vim.notify("[Error] :: Expected number", vim.log.levels.ERROR)
|
|
|
|
|
else
|
|
|
|
|
local opts = { ts = vim.o.tabstop, et = vim.o.expandtab }
|
|
|
|
|
|
|
|
|
|
vim.o.tabstop = count
|
|
|
|
|
|
|
|
|
|
if a.bang then
|
|
|
|
|
vim.o.expandtab = true
|
|
|
|
|
vim.cmd("silent retab")
|
|
|
|
|
else
|
|
|
|
|
local pos = {
|
|
|
|
|
view = vim.fn.winsaveview(),
|
|
|
|
|
vstart = vim.fn.getpos("'<"),
|
|
|
|
|
vend = vim.fn.getpos("'>")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-- gg=G doesn't work in some niche cases so we do a full buffer select, indent and then
|
|
|
|
|
-- unindent. With expandtab disabled converts leading spaces to tabs
|
|
|
|
|
vim.o.expandtab = false
|
|
|
|
|
vim.cmd("silent normal! ggVG>VG<")
|
|
|
|
|
|
|
|
|
|
vim.fn.winrestview(pos.view)
|
|
|
|
|
vim.fn.setpos("'<", pos.vstart)
|
|
|
|
|
vim.fn.setpos("'>", pos.vend)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.o.tabstop = opts.ts
|
|
|
|
|
vim.o.expandtab = opts.et
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
NEWCMD('Tabber', Tabber, { nargs = 1, bang = true })
|