diff --git a/clients/lsp-clangd.el b/clients/lsp-clangd.el index a032836c40b..9fcad8d020c 100644 --- a/clients/lsp-clangd.el +++ b/clients/lsp-clangd.el @@ -178,6 +178,48 @@ This must be set only once after loading the clang client.") :risky t :type '(repeat string)) +(defun lsp-clangd-find-compile-commands-dir () + "Return the full directory path (or nil) that contain a compile_commands.json. + +If multiple compile_commands.json files are +found in the project directory tree - ask the user to choose." + ;; TODO lsp-workspace-root won't find anything at the start of the workspace + (let ((candidate-dirs (directory-files-recursively (lsp-workspace-root) "compile_commands.json"))) + (pcase (length candidate-dirs) + ;; TODO can I lsp--warn-user-in-message-and-log at the same time + (`0 (lsp--warn "Cannot find compile_commands.json - intellisense might not work") + nil) + ;; if you find 1 only - assume it's correct and strip the dirname from the full path + ;; happy path + (`1 (file-name-directory (car candidate-dirs))) + ;; if you have several - ask the user to choose with lsp--completing-read + ;; TODO if Ctrl-G from inside this completing read still falls to default lsp-clients-clangd-args + (_ (file-name-directory (lsp--completing-read + "Found compile_commands.json in several directories, which one do you want to use?" + candidate-dirs + (lambda (candidate) candidate))))))) + + +(defun lsp-clangd-update-args-with-compile-commands () + "Return the default or updated clangd-args for the start command. +If --compile-commands-dir is already set - return it. +Else run a potentially interactive search for the directory +that contains compile_commands.json. + +Then return either the default args or the modified args" + (if (-first + ;; lsp-client-clangd-args might already lists a "--compile-commands-dir=build/" and will fail if we pass another one + ;; trust the user - if it's already set, don't mess around + (lambda (arg) (string-prefix-p "--compile-commands-dir" arg)) + lsp-clients-clangd-args) + ((lsp--info "compilation_commands_dir set in clangd-args") + lsp-clients-clangd-args) + (if-let (found-dir (lsp-clangd-find-compile-commands-dir)) + ;; TODO expensive to create a list from 1 element - how to append atom to list + (append lsp-clients-clangd-args (list (concat "--compile-commands-dir=" found-dir))) + lsp-clients-clangd-args))) + + (defun lsp-clients--clangd-command () "Generate the language server startup command." (unless lsp-clients--clangd-default-executable @@ -190,7 +232,7 @@ This must be set only once after loading the clang client.") (lsp-clients-executable-find "xcrun" "--find" "clangd")))) `(,(or lsp-clients-clangd-executable lsp-clients--clangd-default-executable "clangd") - ,@lsp-clients-clangd-args)) + ,@(lsp-clangd-update-args-with-compile-commands))) (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection