-- Load persistent configuration from .workspace.lua local ws_file = "./.nvim.workspace.lua" local loaded, workspace = pcall(dofile, ws_file) if not loaded then workspace = { args = {}, build_type = "debug", binary = "blog-server" } end local build_folder local bin_target local bin_name local function updateBuildEnv() build_folder = './target/' .. workspace.build_type bin_target = workspace.binary bin_name = build_folder .. '/' .. bin_target -- The run (F6) arguments vim.opt.makeprg = "cargo build" vim.g.cargo_makeprg_params = 'build' if workspace.build_type == "release" then vim.opt.makeprg = vim.opt.makeprg .. " --release" vim.g.cargo_makeprg_params = vim.g.cargo_makeprg_params .. " --release" end -- Rust compiler error format vim.opt.errorformat = { -- Main error/warning line with file:line:col format '%E%>error%m,' .. -- Start of error block '%W%>warning: %m,' .. -- Start of warning block '%-G%>help: %m,' .. -- Ignore help lines '%-G%>note: %m,' .. -- Ignore note lines '%C%> --> %f:%l:%c,' .. -- Continuation: file location '%Z%>%p^%m,' .. -- End: column pointer (^^^) '%C%>%s%#|%.%#,' .. -- Continuation: context lines with | '%C%>%s%#%m,' .. -- Continuation: other context '%-G%.%#' -- Ignore everything else } end updateBuildEnv() -- Prevent Vim's built-in rust ftplugin from loading the cargo compiler vim.api.nvim_create_autocmd("FileType", { pattern = "rust", callback = function() vim.b.current_compiler = 'custom' end, }) local function writeWorkspace() -- A very minimal serializer for workspace configuration local s = { l = "", ls = {}, i = "" } local function w(v) s.l = s.l .. v end local function nl() s.ls[#s.ls + 1] = s.l; s.l = s.i; end local function wv(v) local t = type(v) if t == 'table' then w('{'); local pi = s.i; s.i = s.i .. " " for k1, v1 in pairs(v) do nl(); w('['); wv(k1); w('] = '); wv(v1); w(',') end s.i = pi; nl(); w('}'); elseif t == 'number' then w(tostring(v)) elseif t == 'string' then w('"' .. v .. '"') else w(tostring(v)) end end -- Write the workspace file w("return "); wv(workspace); nl() vim.fn.writefile(s.ls, ws_file) end -- nvim-dap configuration local dap_ok, dap = pcall(require, "dap") local dap_def_cfg local dap_configs -- Update args for both run and debug configs local function updateArgs(args) workspace.args = args if dap_configs ~= nil then dap_configs[1].args = args end writeWorkspace() end -- Find terminal tab or create new one, then run command local function TermRun(cmd) local found = false for i = 1, vim.fn.tabpagenr('$') do vim.cmd('tabnext ' .. i) if vim.bo.buftype == 'terminal' then found = true break end end if not found then vim.cmd('tabnew | terminal') end vim.fn.chansend(vim.b.terminal_job_id, '' .. cmd .. '\n') vim.fn.feedkeys("G", "n") end -- The Configure command vim.api.nvim_create_user_command("Configure", function(a) local args = {} local bt = "debug" if #a.args > 0 then bt = a.args end workspace.build_type = bt updateBuildEnv() writeWorkspace() end, { nargs = '?', desc = "Update run/debug arguments" }) vim.api.nvim_create_user_command("Args", function(a) updateArgs(a.fargs) end, { nargs = '*', desc = "Update run/debug arguments" }) if dap_ok then local rust_path = vim.fn.system("rustc --print sysroot") -- We need to query this to get the sysroot rust_path = string.sub(rust_path, 1, #rust_path - 1) -- trim trailing newline local lldb_init = { "command script import " .. rust_path .. "/lib/rustlib/etc/lldb_lookup.py", "command source " .. rust_path .. "/lib/rustlib/etc/lldb_commands", } dap_configs = { { name = 'test all', type = 'codelldb', request = 'launch', program = bin_name, args = workspace.args, cwd = '${workspaceFolder}', stopOnEntry = false, initCommands = lldb_init } } dap_def_cfg = dap_configs[1] dap.providers.configs["project"] = function() return dap_configs end -- DebugArgs to set debugger arguments and run immediately vim.api.nvim_create_user_command("DebugArgs", function(a) updateArgs(a.fargs) dap.run(dap_configs[1]) end, { nargs = '*', desc = "Starts debugging with specified arguments" }) end if MakeAnd then local r = function() MakeAnd(function() TermRun(bin_name .. " " .. table.concat(workspace.args, " ")) end) end -- RunArgs sets the run arguments that F6 uses and reruns immediately vim.api.nvim_create_user_command("RunArgs", function(a) updateArgs(a.fargs) r() end, { nargs = '*', desc = "Starts debugging with specified arguments" }) -- F6 to run the application vim.keymap.set('n', '', r) if dap_ok then -- Shift-F5 to launch default config vim.keymap.set('n', '', function() MakeAnd(function() dap.run(dap_def_cfg) end) end) end end