summaryrefslogtreecommitdiff
path: root/.config/nvim/lua/lang/clang.lua
blob: 702d6f44b7e77ca070c3eb5f45650edcc3d94e9c (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
local M = {}

M.config = function()
  O.lang.clang = {
    diagnostics = {
      virtual_text = { spacing = 0, prefix = "" },
      signs = true,
      underline = true,
    },
    cross_file_rename = true,
    header_insertion = "never",
    filetypes = { "c", "cpp", "objc" },
    formatter = {
      exe = "clang-format",
      args = {},
      stdin = true,
    },
    linters = {
      "cppcheck",
      "clangtidy",
    },
    debug = {
      adapter = {
        command = "/usr/bin/lldb-vscode",
      },
      stop_on_entry = false,
    },
  }
end

M.format = function()
  local shared_config = {
    function()
      return {
        exe = O.lang.clang.formatter.exe,
        args = O.lang.clang.formatter.args,
        stdin = O.lang.clang.formatter.stdin,
        cwd = vim.fn.expand "%:h:p",
      }
    end,
  }
  O.formatters.filetype["c"] = shared_config
  O.formatters.filetype["cpp"] = shared_config
  O.formatters.filetype["objc"] = shared_config

  require("formatter.config").set_defaults {
    logging = false,
    filetype = O.formatters.filetype,
  }
end

M.lint = function()
  require("lint").linters_by_ft = {
    c = O.lang.clang.linters,
    cpp = O.lang.clang.linters,
  }
end

M.lsp = function()
  if require("utils").check_lsp_client_active "clangd" then
    return
  end
  local clangd_flags = { "--background-index" }

  if O.lang.clang.cross_file_rename then
    table.insert(clangd_flags, "--cross-file-rename")
  end

  table.insert(clangd_flags, "--header-insertion=" .. O.lang.clang.header_insertion)

  require("lspconfig").clangd.setup {
    cmd = { DATA_PATH .. "/lspinstall/cpp/clangd/bin/clangd", unpack(clangd_flags) },
    on_attach = require("lsp").common_on_attach,
    handlers = {
      ["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
        virtual_text = O.lang.clang.diagnostics.virtual_text,
        signs = O.lang.clang.diagnostics.signs,
        underline = O.lang.clang.diagnostics.underline,
        update_in_insert = true,
      }),
    },
  }
end

M.dap = function()
  if O.plugin.dap.active then
    local dap_install = require "dap-install"
    local dap = require "dap"
    dap_install.config("ccppr_vsc_dbg", {})
    dap.adapters.lldb = {
      type = "executable",
      command = O.lang.clang.debug.adapter.command,
      name = "lldb",
    }
    local shared_dap_config = {
      {
        name = "Launch",
        type = "lldb",
        request = "launch",
        program = function()
          return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/", "file")
        end,
        cwd = "${workspaceFolder}",
        stopOnEntry = O.lang.clang.debug.stop_on_entry,
        args = {},
        env = function()
          local variables = {}
          for k, v in pairs(vim.fn.environ()) do
            table.insert(variables, string.format("%s=%s", k, v))
          end
          return variables
        end,
        runInTerminal = false,
      },
      {
        -- If you get an "Operation not permitted" error using this, try disabling YAMA:
        --  echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
        name = "Attach to process",
        type = "lldb", -- Adjust this to match your adapter name (`dap.adapters.<name>`)
        request = "attach",
        pid = function()
          local output = vim.fn.system { "ps", "a" }
          local lines = vim.split(output, "\n")
          local procs = {}
          for _, line in pairs(lines) do
            -- output format
            --    " 107021 pts/4    Ss     0:00 /bin/zsh <args>"
            local parts = vim.fn.split(vim.fn.trim(line), " \\+")
            local pid = parts[1]
            local name = table.concat({ unpack(parts, 5) }, " ")
            if pid and pid ~= "PID" then
              pid = tonumber(pid)
              if pid ~= vim.fn.getpid() then
                table.insert(procs, { pid = tonumber(pid), name = name })
              end
            end
          end
          local choices = { "Select process" }
          for i, proc in ipairs(procs) do
            table.insert(choices, string.format("%d: pid=%d name=%s", i, proc.pid, proc.name))
          end
          local choice = vim.fn.inputlist(choices)
          if choice < 1 or choice > #procs then
            return nil
          end
          return procs[choice].pid
        end,
        args = {},
      },
    }
    dap.configurations.c = shared_dap_config
    dap.configurations.cpp = shared_dap_config
  end
end

return M