branch: externals/gtags-mode
commit 148041bbe92952d808dcb5dd50b4a7ba2b1a8890
Author: Jimmy Aguilar Mena <kratsbinov...@gmail.com>
Commit: Jimmy Aguilar Mena <kratsbinov...@gmail.com>

    Cleanup and reorder code.
    
    Also fix some corner cases and add advise to imenu because the variable
    is buffer local.
---
 gtags-mode.el | 138 ++++++++++++++++++++++++++--------------------------------
 1 file changed, 62 insertions(+), 76 deletions(-)

diff --git a/gtags-mode.el b/gtags-mode.el
index 4cfc89a9ec..e06bd6a5b3 100644
--- a/gtags-mode.el
+++ b/gtags-mode.el
@@ -125,7 +125,6 @@ This is the sentinel set in `gtags-mode--exec-async'."
 Start an asynchronous process and sets
 `gtags-mode--exec-async-sentinel' as the process sentinel.
 Returns the process object."
-  (gtags-mode--set-connection-locals)
   (if-let* ((cmd (buffer-local-value cmd (current-buffer)))
            (command (gtags-mode--quote (append `(,cmd) args) target))
            (pr (make-process :name (format "%s-async" cmd)
@@ -143,7 +142,6 @@ Returns the process object."
 (defun gtags-mode--exec-sync (args &optional target)
   "Run global with ARGS on TARGET synchronously.
 On success return a list of strings or nil if any error occurred."
-  (gtags-mode--set-connection-locals)
   (if-let ((cmd gtags-mode--global) ;; Required for with-temp-buffer
           (cargs (gtags-mode--quote args target)))
       (with-temp-buffer
@@ -159,75 +157,70 @@ On success return a list of strings or nil if any error 
occurred."
     nil))
 
 ;; Utilities functions (a bit less low level) ========================
-(defun gtags-mode--get-plist (file)
-  "Return a plist for a FILE when it is known in `gtags-mode--alist'."
-  (let ((truename (file-truename file)))
+(defun gtags-mode--get-plist (directory)
+  "Return the plist for DIRECTORY from `gtags-mode--alist'."
+  (let ((truename (file-truename directory)))
     (catch 'found
-      (mapc (lambda (plist)
-             (when (string-prefix-p (plist-get plist :gtagsroot) truename)
-               (throw 'found plist)))
-           gtags-mode--alist)
+      (dolist (plist gtags-mode--alist)
+       (when (string-prefix-p (plist-get plist :gtagsroot) truename)
+         (throw 'found plist)))
       nil)))
 
-(defun gtags-mode--find-or-create-plist ()
-  "Return the GLOBAL project root for `default-directory'.
-Return nil if none."
-  (when-let* ((root (car (gtags-mode--exec-sync '("--print-dbpath")))))
-    (setq root (concat (file-remote-p default-directory) (file-truename root)))
+(defun gtags-mode--create-plist (directory)
+  "Return dbpath for DIRECTORY or nil if none."
+  (when-let* ((default-directory (file-truename directory))
+             (root (car (gtags-mode--exec-sync '("--print-dbpath")))))
+    (setq root (file-truename (concat (file-remote-p default-directory) root)))
     (or (gtags-mode--get-plist root)   ;; already exist
        (car (push `(:gtagsroot ,root :cache nil) gtags-mode--alist)))))
 
+(defun gtags-mode--local-plist ()
+  "Set and return the buffer local value of `gtags-mode--plist'."
+  (if (local-variable-p 'gtags-mode--plist)
+      gtags-mode--plist
+    (gtags-mode--set-connection-locals)
+    (setq-local gtags-mode--plist (or (gtags-mode--get-plist default-directory)
+                                     (gtags-mode--create-plist 
default-directory)))))
+
 (defun gtags-mode--list-completions (prefix)
   "Get the list of completions for PREFIX.
 When PREFIX is nil or empty; return the entire list of
 completions usually from the cache when possible."
   (cond ;; TODO: use with-memoization in the future it will be on emacs 29.1
+   ((not (gtags-mode--local-plist))
+    (error "Calling `gtags-mode--list-completions' with no gtags-mode--plist"))
    ((and (stringp prefix) (not (string-blank-p prefix))
         (gtags-mode--exec-sync '("--ignore-case" "--completion") prefix)))
    ((plist-get gtags-mode--plist :cache))
-   (gtags-mode--plist
-    (plist-put gtags-mode--plist :cache (gtags-mode--exec-sync 
'("--completion")))
-    (plist-get gtags-mode--plist :cache))))
+   (t (plist-put gtags-mode--plist :cache (gtags-mode--exec-sync 
'("--completion")))
+      (plist-get gtags-mode--plist :cache))))
 
 (defun gtags-mode--filter-find-symbol (args symbol creator)
   "Run `gtags-mode--exec-sync' with ARGS on SYMBOL and filter output with 
CREATOR.
 Returns the results as a list of CREATORS outputs similar to
 `mapcar'.  Creator should be a function with 4 input arguments:
 name, code, file, line."
-  (delete nil
-         (mapcar
-          (lambda (line)
-            (when (string-match gtags-mode--output-format-regex line)
-              (funcall creator
-                       (match-string-no-properties 1 line)   ;; name
-                       (match-string-no-properties 4 line)   ;; code
-                       (match-string-no-properties 3 line)   ;; file
-                       (string-to-number (match-string-no-properties 2 
line))))) ;; line
-          (gtags-mode--exec-sync
-           (append args gtags-mode--output-format-options) symbol))))
-
-(defun gtags-mode--set-local-plist ()
-  "Set `gtags-mode--plist' for the current file.
-Return the buffer local value of `gtags-mode--plist'."
-  (if (local-variable-p 'gtags-mode--plist)
-      gtags-mode--plist
-    (setq-local gtags-mode--plist (or (gtags-mode--get-plist default-directory)
-                                     (gtags-mode--find-or-create-plist)))))
+  (delete nil (mapcar
+              (lambda (line)
+                (when (string-match gtags-mode--output-format-regex line)
+                  (funcall creator
+                           (match-string-no-properties 1 line)   ;; name
+                           (match-string-no-properties 4 line)   ;; code
+                           (match-string-no-properties 3 line)   ;; file
+                           (string-to-number (match-string-no-properties 2 
line))))) ;; line
+              (gtags-mode--exec-sync
+               (append args gtags-mode--output-format-options) symbol))))
 
 (defun gtags-mode--update-buffers-plist ()
   "Actions to perform after creating a database.
-This runs only when the process exits successfully and is
-executed in the parent buffer."
-  (when-let ((currbuff (current-buffer))
-            (root (plist-get (gtags-mode--set-local-plist) :root)))
-    (mapc (lambda (buff)
-           (unless (eq currbuff buff)
-             (with-current-buffer buff
-               (when (and (not gtags-mode--plist)
-                          (string-prefix-p root (file-truename 
default-directory)))
-                 (kill-local-variable 'gtags-mode--plist) ;; kill the local to 
reset it
-                 (gtags-mode--set-local-plist)))))
-         (buffer-list))))
+This iterates over the buffers and tries to reset
+`gtags-mode--plist' when it is nil."
+  (dolist (buff (buffer-list))
+    (unless (buffer-local-value 'gtags-mode--plist buff)
+      (with-current-buffer buff
+       (gtags-mode--set-connection-locals)
+       (kill-local-variable 'gtags-mode--plist) ;; kill the local to reset it
+       (gtags-mode--local-plist)))))
 
 ;; Interactive commands ==============================================
 (defun gtags-mode-create (root-dir)
@@ -240,13 +233,13 @@ executed in the parent buffer."
 (defun gtags-mode-update ()
   "Update GLOBAL project database."
   (interactive)
-  (when gtags-mode--plist
+  (when (gtags-mode--local-plist)
     (gtags-mode--exec-async 'gtags-mode--global '("--update"))))
 
 ;; Hooks =============================================================
 (defun gtags-mode--after-save-hook ()
   "After save hook to update GLOBAL database with changed data."
-  (when (and buffer-file-name gtags-mode--plist)
+  (when (and buffer-file-name (gtags-mode--local-plist))
     (gtags-mode--exec-async
      'gtags-mode--global
      '("--single-update") (file-name-nondirectory buffer-file-name))))
@@ -279,22 +272,17 @@ Return as a list of xref location objects."
   (gtags-mode--xref-find-symbol '("--grep") symbol))
 
 ;; imenu integration =================================================
-(defvar gtags-mode--imenu-default-function nil)
-
 (defun gtags-mode--imenu-goto-function (_name line)
   "Function to goto with imenu when LINE info."
   (funcall-interactively #'goto-line line))
 
-(defun gtags-mode-imenu-create-index-function ()
+(defun gtags-mode--imenu-advice ()
   "Make imenu use Global."
-  (if (and buffer-file-name gtags-mode--plist)
-      (gtags-mode--filter-find-symbol
-       '("--file") (file-name-nondirectory buffer-file-name)
-       (lambda (name _code _file line)
-        (list name line #'gtags-mode--imenu-goto-function)))
-    ;; Else try to use the default function.
-    (when (functionp gtags-mode--imenu-default-function)
-      (funcall gtags-mode--imenu-default-function))))
+  (when (and buffer-file-name (gtags-mode--local-plist))
+    (gtags-mode--filter-find-symbol
+     '("--file") (file-name-nondirectory buffer-file-name)
+     (lambda (name _code _file line)
+       (list name line #'gtags-mode--imenu-goto-function)))))
 
 ;; project integration ===============================================
 (defun gtags-mode-project-backend (dir)
@@ -323,18 +311,19 @@ Return as a list of xref location objects."
 
 (cl-defmethod project-buffers ((project (head :gtagsroot)))
   "Return the list of all live buffers that belong to PROJECT."
-  (when-let ((root (plist-get project :gtagsroot)))
-    (mapcar (lambda (buf)
-             (when-let* ((bname (buffer-local-value 'buffer-file-name buf))
-                         (tname (file-truename bname))
-                         ((string-prefix-p root tname)))
-               buf))
-           (buffer-list))))
+  (mapcar (lambda (buff)
+           (cond
+            ((eq (buffer-local-value 'gtags-mode--plist buff) project) buff)
+            ((local-variable-p 'gtags-mode--plist buff) nil)
+            (t (with-current-buffer buff
+                 (when (eq (gtags-mode--local-plist) project)
+                   (current-buffer))))))
+         (buffer-list)))
 
 ;; Completion-at-point-function (capf) ===============================
 (defun gtags-mode-completion-function ()
   "Generate completion list."
-  (if (gtags-mode--set-local-plist)
+  (if (gtags-mode--local-plist)
       (when-let ((bounds (bounds-of-thing-at-point 'symbol)))
        (list (car bounds) (cdr bounds)
              (completion-table-dynamic #'gtags-mode--list-completions)
@@ -347,20 +336,17 @@ Return as a list of xref location objects."
   :lighter gtags-mode-lighter
   (cond
    (gtags-mode
-    (add-hook 'find-file-hook #'gtags-mode--set-local-plist)
     (add-hook 'project-find-functions #'gtags-mode-project-backend)
-    (add-hook 'xref-backend-functions #'gtags-mode--set-local-plist)
+    (add-hook 'xref-backend-functions #'gtags-mode--local-plist)
     (add-hook 'completion-at-point-functions #'gtags-mode-completion-function)
     (add-hook 'after-save-hook #'gtags-mode--after-save-hook)
-    (setq gtags-mode--imenu-default-function imenu-create-index-function)
-    (setq imenu-create-index-function 
#'gtags-mode-imenu-create-index-function))
+    (advice-add imenu-create-index-function :before-until 
#'gtags-mode--imenu-advice))
    (t
-    (remove-hook 'find-file-hook #'gtags-mode--set-local-plist)
     (remove-hook 'project-find-functions #'gtags-mode-project-backend)
-    (remove-hook 'xref-backend-functions #'gtags-mode--set-local-plist)
+    (remove-hook 'xref-backend-functions #'gtags-mode--local-plist)
     (remove-hook 'completion-at-point-functions 
#'gtags-mode-completion-function)
     (remove-hook 'after-save-hook #'gtags-mode--after-save-hook)
-    (setq imenu-create-index-function gtags-mode--imenu-default-function))))
+    (advice-remove imenu-create-index-function #'gtags-mode--imenu-advice))))
 
 (provide 'gtags-mode)
 ;;; gtags-mode.el ends here

Reply via email to