Skip to content

Commit

Permalink
Cleanup init-rtags-cmake
Browse files Browse the repository at this point in the history
  • Loading branch information
pkryger committed Nov 13, 2024
1 parent 6d7010d commit b8d0396
Showing 1 changed file with 64 additions and 56 deletions.
120 changes: 64 additions & 56 deletions modules/init-rtags-cmake.el
Original file line number Diff line number Diff line change
@@ -1,45 +1,53 @@
;;;; RTags-CMake integration
;;;
;;; This module indexes CMake-based projects with zero configuration.
;;; To enable it, set this variable in ~/.emacs.d/prefs.el:
;;;
;;; (setq exordium-rtags-cmake t)
;;;
;;; You may also set these variables:
;;; - `exordium-rtags-rdm-args': list of strings containing the arguments to
;;; rdm, empty by default. For example:
;;; '("--isystem" "/opt/bb/lib64/clang/3.6.2/include -DBAS_NOBBENV")
;;; - `exordium-rtags-cmake-build-dir': Path to your build dir, absolute or
;;; relative to the root of a project. Default "cmake.bld/<arch>" where
;;; <arch> is replaced by the uname of your OS.
;;;
;;; When you open a C++ file, it will detect if your project is CMake-enabled
;;; by looking for CMakeLists.txt files up to the root of your repo. If it
;;; finds such a file, it starts rdm if it is not running, and indexes your
;;; CMake-generated compilation database (e.g. "rd -J <build-dir>").
;;;
;;; TODO: it should work as well when creating a new file, by running "cmake"
;;; on the project to update the complation database. This can be done using an
;;; after-save-hook I think.

(require 'init-prefs)
(use-package rtags)
(use-package cl-lib :ensure nil)
;;; init-rtags-cmake.el --- RTags-CMake integration -*- lexical-binding: t -*-

;;; Commentary:
;;
;;
;; This module indexes CMake-based projects with zero configuration.
;; To enable it, set this variable in ~/.emacs.d/prefs.el:
;;
;; (setq exordium-rtags-cmake t)
;;
;; You may also set these variables:
;; - `exordium-rtags-rdm-args': list of strings containing the arguments to
;; rdm, empty by default. For example:
;; '("--isystem" "/opt/bb/lib64/clang/3.6.2/include -DBAS_NOBBENV")
;; - `exordium-rtags-cmake-build-dir': Path to your build dir, absolute or
;; relative to the root of a project. Default "cmake.bld/<arch>" where
;; <arch> is replaced by the uname of your OS.
;;
;; When you open a C++ file, it will detect if your project is CMake-enabled
;; by looking for CMakeLists.txt files up to the root of your repo. If it
;; finds such a file, it starts rdm if it is not running, and indexes your
;; CMake-generated compilation database (e.g. "rd -J <build-dir>").
;;
;; TODO: it should work as well when creating a new file, by running "cmake"
;; on the project to update the complation database. This can be done using an
;; after-save-hook I think.

(eval-when-compile
(unless (featurep 'init-require)
(load (file-name-concat (locate-user-emacs-file "modules") "init-require"))))
(exordium-require 'init-prefs)
(exordium-require 'init-rtags)

(require 'cl-lib)

;;; Code:

;; Note: for now we actually don't need to keep the build-dir of any known
;; project but we should need it later to automatically index new files created
;; from Emacs.
(defvar exordium-rtags-cmake-mode-known-projects ()
"Alist of known projects, growing as the user opens files. Each
pair is (project-dir . build-dir). Note that the build-dir
contains the compilation database.")
"Alist of known projects, growing as the user opens files.
Each pair is (PROJECT-DIR . BUILD-DIR). Note that the BUILD-DIR
contains the compilation database.")

(defvar exordium-rtags-cmake-mode-enabled nil
"Whether cmake mode is enabled")
"Whether cmake mode is enabled.")

(define-minor-mode rtags-cmake-mode
"Minor mode for using RTags with zero-configuration, for CMake
enabled projects."
"Minor mode for using RTags with zero-configuration, for CMake enabled projects."
:lighter "Cm"
:global nil ; buffer local
(when rtags-cmake-mode
Expand All @@ -61,7 +69,7 @@ enabled projects."
(exordium-rtags-cmake-index-project-maybe project-dir))))))

(defun exordium-toggle-rtags-cmake-mode ()
"Enable or disable rtags-cmake-mode for C/C++ buffers."
"Enable or disable `rtags-cmake-mode' for C/C++ buffers."
(interactive)
(cond (exordium-rtags-cmake-mode-enabled
(remove-hook 'c-mode-hook #'rtags-cmake-mode)
Expand All @@ -77,20 +85,20 @@ enabled projects."
;;; Find the (CMake) project root directory

(defun exordium-rtags-cmake-find-buffer-project-root ()
"Check if the current buffer's project is a CMake project, and
if so return the root directory of the project. Otherwise
return nil: this is a new buffer not saved or this is not a
CMake project. Note that this function stops the search as soon
as it finds a .git subdirectory."
"Find root directory of the project for current buffer.
If the current buffer's project is a CMake project, return the
directory. Otherwise return nil. This is a new buffer not saved
or this is not a CMake project. Note that this function stops
the search as soon as it finds a .git subdirectory."
(let ((filename (buffer-file-name)))
(when (and filename (file-exists-p filename))
(let ((dir (file-name-directory filename)))
(exordium-rtags-cmake-find-project-root-impl dir nil)))))

(defun exordium-rtags-cmake-find-project-root-impl (dir &optional is-cmake)
"Return the path of the git repo containing the specified dir,
if this is a CMake repo, otherwise return nil. The extra argument
is-cmake is for recursion."
"Find path of the git repo containing the specified DIR.
If the repo is a CMake repo return it. Otherwise return nil.
The extra argument IS-CMAKE is for recursion."
(unless is-cmake
(setq is-cmake (file-exists-p (concat dir "CMakeLists.txt"))))
(cond ((string= dir "/")
Expand All @@ -107,7 +115,7 @@ is-cmake is for recursion."
;;; Index the project

(defun exordium-rtags-cmake-index-project-maybe (project-dir)
"Index the project at project-dir unless we have done that before."
"Index the project at PROJECT-DIR unless we have done that before."
(unless (assoc project-dir exordium-rtags-cmake-mode-known-projects)
;; Find the build dir containing the compilation DB
(let ((build-dir (exordium-rtags-cmake-get-build-dir project-dir)))
Expand All @@ -122,20 +130,19 @@ is-cmake is for recursion."
exordium-rtags-cmake-mode-known-projects))))))

(defun exordium-rtags-cmake-index-project-impl (comp-db-dir)
"Invoke rc -J <comp-db-dir>"
"Invoke rc -J <COMP-DB-DIR>."
(message "Indexing: %s" comp-db-dir)
(with-current-buffer (rtags-get-buffer)
(rtags-call-rc "-J" comp-db-dir)))

;;; Find the compilation database (e.g. the build directory)

(defun exordium-rtags-cmake-get-build-dir (project-dir)
"Return the absolute path of the build directory for the
project located in the specified project-dir. If a file .rtags
exist at project-dir, it is expected to contain a record 'build
<dir>'. Otherwise the pref `expordium-rtags-cmake-build-dir' is
assumed to contain the relative path of any project's build
directory."
"Return absolute path of the build directory for the PROJECT-DIR.
If a file .rtags exist at project-dir, it is expected to contain
a record \\='build <dir>\\='. Otherwise the pref
`expordium-rtags-cmake-build-dir' is assumed to contain the
relative path of any project's build directory."
(let* ((rtags-file (concat project-dir ".rtags"))
(build-dir
(if (file-exists-p rtags-file)
Expand All @@ -146,19 +153,17 @@ directory."
(concat project-dir build-dir))))

(defun exordium-rtags-cmake-get-key-from-file (file key)
"Read the specified file and return the value associated with
the specified key, or nil if no such key."
"Read FILE and return value associated with KEY, or nil if no such KEY."
(let* ((records (exordium-read-file-lines file))
(matching-records (cl-remove-if-not (lambda (record)
(string-prefix-p key record))
records)))
records)))
(when matching-records
(cl-second (split-string (car matching-records) " ")))))

(defun exordium-rtags-cmake-get-expanded-build-dir ()
"Return the value of the pref `exordium-rtags-cmake-build-dir'
with any occurence of <arch> replaced by the uname of the local
OS."
"Return the value of the pref `exordium-rtags-cmake-build-dir'.
Any occurrence of <arch> replaced by the uname of the local OS."
(let ((uname (replace-regexp-in-string "\n$" "" (shell-command-to-string "uname"))))
(replace-regexp-in-string "<arch>" uname exordium-rtags-cmake-build-dir)))

Expand All @@ -167,4 +172,7 @@ the specified key, or nil if no such key."
(setq rtags-autostart-diagnostics t)
(exordium-toggle-rtags-cmake-mode))


(provide 'init-rtags-cmake)

;;; init-rtags-cmake.el ends here

0 comments on commit b8d0396

Please sign in to comment.