vim.opt.exrc = false vim.g.autoformat = true vim.g.load_doxygen_syntax = true vim.opt.fixeol = false local workspace_folder = vim.fn.getcwd() local function safe_require(module) local ok, mod = pcall(require, module) if not ok then return nil end return mod end -- C++ local default_clangd_config = vim.deepcopy(vim.lsp.config["clangd"]) or {} default_clangd_config.cmd = { "clangd", "--background-index", "--clang-tidy", "--header-insertion=iwyu", "--completion-style=detailed", string.format("--compile-commands-dir=%s/build", workspace_folder), "--query-driver=**/x86_64-pc-elf-g++" } vim.lsp.config("clangd", default_clangd_config) vim.filetype.add({ pattern = { [".*/include/kstd/.*"] = function(path, _) if not path:match("%.[^/]+$") then return "cpp" end end } }) -- Debugging local dap = require("dap") local qemu_job_id = nil local qemu_bufnr = nil local function resolve_build_paths(artifact_path) local base_path = string.gsub(artifact_path, "%.[%w]+$", "") local build_type = artifact_path:match("bin/([^/]+)/") or "Debug" return { iso = base_path .. ".iso", elf = base_path .. ".elf", sym = base_path .. ".sym", build_type = build_type, } end local function launch_qemu(artifact_path, is_debug) if qemu_job_id then vim.fn.jobstop(qemu_job_id) qemu_job_id = nil end local paths = resolve_build_paths(artifact_path) local debug_flag = is_debug and "1" or "0" local shell_cmd = string.format("%s/scripts/qemu-wrapper.sh '%s' '%s' '%s' '%s'", workspace_folder, workspace_folder, paths.build_type, paths.iso, debug_flag) vim.cmd("botright vsplit | enew") qemu_bufnr = vim.api.nvim_get_current_buf() vim.api.nvim_buf_set_name(qemu_bufnr, "TeachOS QEMU (" .. paths.build_type .. ")") vim.opt_local.number = false vim.opt_local.relativenumber = false vim.opt_local.signcolumn = "no" qemu_job_id = vim.fn.termopen(shell_cmd, { on_exit = function() qemu_job_id = nil end }) vim.cmd("wincmd p") end dap.adapters.teachos_qemu_mi = function(callback, config) local artifact_path = config.program if not artifact_path then vim.notify("Fatal: No artifact path resolved by CMake", vim.log.levels.ERROR) return end launch_qemu(artifact_path, true) local paths = resolve_build_paths(artifact_path) config.setupCommands = { { description = "Enable pretty-printing for gdb", text = "-enable-pretty-printing" }, { description = "Load code", text = string.format("-file-exec-file %s", paths.elf) }, { description = "Load symbols", text = string.format("-file-exec-and-symbols %s", paths.sym) }, } config.program = paths.sym vim.defer_fn(function() callback({ type = "executable", command = vim.fn.stdpath("data") .. "/mason/bin/OpenDebugAD7", id = "cppdbg", }) end, 500) end local function teardown_qemu() if qemu_job_id then vim.fn.jobstop(qemu_job_id) qemu_job_id = nil end if qemu_bufnr and vim.api.nvim_buf_is_valid(qemu_bufnr) then vim.api.nvim_buf_delete(qemu_bufnr, { force = true }) qemu_bufnr = nil end end dap.listeners.after.event_terminated["teachos_qemu_teardown"] = teardown_qemu dap.listeners.after.event_exited["teachos_qemu_teardown"] = teardown_qemu dap.listeners.after.disconnect["teachos_qemu_teardown"] = teardown_qemu require("cmake-tools").setup({ cmake_compile_commands_options = { action = "copy", target = string.format("%s/build", workspace_folder), }, cmake_dap_configuration = { name = "(gdb) QEMU MI Attach", type = "teachos_qemu_mi", request = "launch", MIMode = "gdb", cwd = workspace_folder, miDebuggerServerAddress = "localhost:1234", miDebuggerPath = "x86_64-pc-elf-gdb", stopAtEntry = true, } }) vim.api.nvim_create_user_command("TeachOSRun", function() local cmake = safe_require("cmake-tools") if not cmake then return end local is_ready, target = pcall(cmake.get_launch_target_path) if is_ready and target then launch_qemu(target, false) else vim.notify("Fatal: Cannot determine CMake target path.", vim.log.levels.ERROR) end end, {}) vim.keymap.set('n', '', 'TeachOSRun', { noremap = true, desc = "Run TeachOS QEMU (No Debug)" })