aboutsummaryrefslogtreecommitdiff
path: root/.nvim.lua
blob: 14ca59caf6df2815d77423847d36d766b5b98c83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
local workspace_folder = vim.fn.getcwd()

-- Formatting
vim.g.autoformat = true
vim.opt.fixeol = false

-- Enable Doxygen
vim.g.load_doxygen_syntax = true

-- C++
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 cmd_args = {
    workspace_folder .. "/scripts/qemu-wrapper.sh",
    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.jobstart(cmd_args, {
    term = true,
    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

vim.api.nvim_create_user_command("TeachOSRun", function()
  local cmake = require("cmake-tools")
  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', '<S-F5>', '<cmd>TeachOSRun<CR>', { noremap = true, desc = "Run TeachOS QEMU (No Debug)" })