branch: externals/gtags-mode commit 777c51d63036581942d61cc31ba9c64ccb7b66c2 Author: Jimmy Aguilar Mena <kratsbinov...@gmail.com> Commit: Jimmy Aguilar Mena <kratsbinov...@gmail.com>
Convert the mode in a global mode. Set the mode as global and set the hooks globaly. This will solve the problems of lazy loading in temporal buffers. Simplifies the mode implementation. (gtags-mode--buffers-in-root) : Removed (gtags-mode--set-local-plist) : (gtags-mode--update-buffers-plist) : New function Fall back to use the command symbol name. Simplify the minor mode code. --- gtags-mode.el | 126 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/gtags-mode.el b/gtags-mode.el index 3416e15088..d4945152a8 100644 --- a/gtags-mode.el +++ b/gtags-mode.el @@ -161,7 +161,7 @@ On success return a list of strings or nil if any error occurred." ;; Utilities functions (a bit less low level) ======================== (defun gtags-mode--get-plist (file) - "Apply ACTION on a plist with known prefix FILE from `gtags-mode--alist'." + "Return a plist for a FILE when it is known in `gtags-mode--alist'." (let ((truename (file-truename file))) (catch 'found (mapc (lambda (plist) @@ -171,7 +171,8 @@ On success return a list of strings or nil if any error occurred." nil))) (defun gtags-mode--find-or-create-plist () - "Return the GLOBAL project root. Return nil if none." + "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))) (or (gtags-mode--get-plist root) ;; already exist @@ -185,18 +186,9 @@ completions usually from the cache when possible." ((and (stringp prefix) (not (string-blank-p prefix)) (gtags-mode--exec-sync '("--ignore-case" "--completion") prefix))) ((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--buffers-in-root (plist) - "Return a list of buffers which variable `buffer-file-name' is inside PLIST." - (when-let ((root (plist-get plist :gtagsroot))) - (mapcan (lambda (buf) - (and-let* ((bname (buffer-local-value 'buffer-file-name buf)) - (tname (file-truename bname)) - ((string-prefix-p root tname)) - (`(,buf))))) - (buffer-list)))) + (gtags-mode--plist + (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. @@ -215,34 +207,55 @@ name, code, file, 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))))) + +(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." + (unless gtags-mode--plist + (kill-local-variable 'gtags-mode--plist) + (gtags-mode--set-local-plist) + (when-let ((plist gtags-mode--plist) + (root (plist-get gtags-mode--plist :root))) + (mapc (lambda (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) + (gtags-mode--set-local-plist)))) + (buffer-list))))) + ;; Interactive commands ============================================== (defun gtags-mode-create (root-dir) "Create a GLOBAL GTAGS file in ROOT-DIR asynchronously." (interactive "DCreate GLOBAL files in directory: ") (let ((default-directory root-dir)) - (gtags-mode--exec-async gtags-mode--gtags nil))) + (process-put (gtags-mode--exec-async 'gtags-mode--gtags nil) + :extra-sentinel #'gtags-mode--update-buffers-plist))) (defun gtags-mode-update () "Update GLOBAL project database." (interactive) (if gtags-mode--plist - (gtags-mode--exec-async gtags-mode--global '("--update")) + (gtags-mode--exec-async 'gtags-mode--global '("--update")) (error "Not under a GLOBAL project"))) ;; Hooks ============================================================= (defun gtags-mode--after-save-hook () "After save hook to update GLOBAL database with changed data." - (when (and buffer-file-name (plist-get gtags-mode--plist :gtagsroot)) + (when (and buffer-file-name gtags-mode--plist) (gtags-mode--exec-async - gtags-mode--global - `("--single-update" ,(file-name-nondirectory buffer-file-name))))) + 'gtags-mode--global + `("--single-update") ,(file-name-nondirectory buffer-file-name)))) -(defun gtags-mode--find-file-hook () - "Try to enable `gtags' when opening a file. -Check the roots list and enable `gtags' if the open file is in -one of them." - (when (gtags-mode--get-plist buffer-file-name) - (gtags-mode 1))) +(defalias 'gtags-mode--find-file-hook #'gtags-mode--set-local-plist) ;; xref integration ================================================== (defun gtags-mode--xref-find-symbol (args symbol) @@ -255,9 +268,7 @@ Return as a list of xref location objects." (concat (file-remote-p default-directory) file) line 0))))) -(defun gtags-xref-backend () - "Gtags backend for Xref." - gtags-mode--plist) +(defalias 'gtags-xref-backend #'gtags-mode--set-local-plist) (cl-defmethod xref-backend-identifier-completion-table ((_backend (head :gtagsroot))) "List all symbols." @@ -276,7 +287,7 @@ Return as a list of xref location objects." (gtags-mode--xref-find-symbol '("--grep") symbol)) ;; imenu integration ================================================= -(defvar-local gtags-mode--imenu-default-function nil) +(defvar gtags-mode--imenu-default-function nil) (defun gtags-mode--imenu-goto-function (_name line) "Function to goto with imenu when LINE info." @@ -320,50 +331,43 @@ 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." - (gtags-mode--buffers-in-root 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)))) ;; Completion-at-point-function (capf) =============================== (defun gtags-mode-completion-function () "Generate completion list." - (when-let (bounds (bounds-of-thing-at-point 'symbol)) - (list (car bounds) (cdr bounds) - (completion-table-dynamic #'gtags-mode--list-completions) - :exclusive 'no))) + (if (gtags-mode--set-local-plist) + (when-let ((bounds (bounds-of-thing-at-point 'symbol))) + (list (car bounds) (cdr bounds) + (completion-table-dynamic #'gtags-mode--list-completions) + :exclusive 'no)))) ;;;###autoload (define-minor-mode gtags-mode "Use GNU Global as backend for several Emacs features in this buffer." - :global nil + :global t :lighter gtags-mode-lighter (cond (gtags-mode - (gtags-mode--set-connection-locals) - (if (setq gtags-mode--plist (gtags-mode--find-or-create-plist)) - (progn - (add-hook 'find-file-hook #'gtags-mode--find-file-hook) - (add-hook 'project-find-functions #'gtags-mode-project-backend) - (add-hook 'xref-backend-functions #'gtags-xref-backend nil t) - (add-hook 'after-save-hook #'gtags-mode--after-save-hook nil t) - (add-hook 'completion-at-point-functions #'gtags-mode-completion-function nil t) - (setq gtags-mode--imenu-default-function imenu-create-index-function) - (setq imenu-create-index-function #'gtags-mode-imenu-create-index-function) - ;; Enable the mode in all the files inside `gtags-mode--plist' - (when (called-interactively-p 'all) - (mapc (lambda (buff) - (unless (buffer-local-value 'gtags-mode buff) - (with-current-buffer buff - (gtags-mode 1)))) - (gtags-mode--buffers-in-root gtags-mode--plist)))) - (when (called-interactively-p 'all) - (message "Couldn't enable gtags-mode. Not root found.")) - (setq gtags-mode -1))) + (add-hook 'find-file-hook #'gtags-mode--find-file-hook) + (add-hook 'project-find-functions #'gtags-mode-project-backend) + (add-hook 'xref-backend-functions #'gtags-xref-backend) + (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)) (t - (setq gtags-mode--plist nil) - ;; (remove-hook 'find-file-hook #'gtags-mode--find-file-hook) - ;; (remove-hook 'project-find-functions #'gtags-mode-project-backend) - (remove-hook 'xref-backend-functions #'gtags-xref-backend t) - (remove-hook 'after-save-hook #'gtags-mode--after-save-hook t) - (remove-hook 'completion-at-point-functions #'gtags-mode-completion-function t) + (remove-hook 'find-file-hook #'gtags-mode--find-file-hook) + (remove-hook 'project-find-functions #'gtags-mode-project-backend) + (remove-hook 'xref-backend-functions #'gtags-xref-backend) + (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)))) (provide 'gtags-mode)