]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/ggtags/ggtags.el
Add *.info and dir to debbugs
[gnu-emacs-elpa] / packages / ggtags / ggtags.el
index efbab00f5b892961ea20fcd631b4696cf21fdcb7..d3973b213feeba40572de59d09859923cf1ddb07 100644 (file)
@@ -1,9 +1,9 @@
 ;;; ggtags.el --- emacs frontend to GNU Global source code tagging system  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2014  Free Software Foundation, Inc.
+;; Copyright (C) 2013-2015  Free Software Foundation, Inc.
 
 ;; Author: Leo Liu <sdl.web@gmail.com>
-;; Version: 0.8.7
+;; Version: 0.8.9
 ;; Keywords: tools, convenience
 ;; Created: 2013-01-29
 ;; URL: https://github.com/leoliu/ggtags
 ;;
 ;; All commands are available from the `Ggtags' menu in `ggtags-mode'.
 
-;;; NEWS 0.8.7 (2014-11-10):
+;;; NEWS 0.8.9 (2015-01-16):
 
-;; - New navigation command `ggtags-navigation-start-file'.
-;; - New variable `ggtags-use-sqlite3' to enable sqlite3 storage.
+;; - `ggtags-visit-project-root' can visit past projects.
+;; - `eldoc' support enabled for emacs 24.4+.
 ;;
 ;; See full NEWS on https://github.com/leoliu/ggtags#news
 
@@ -65,6 +65,9 @@
       (list 'progn (list 'defvar var val docstring)
             (list 'make-variable-buffer-local (list 'quote var)))))
 
+  (or (fboundp 'add-function) (defmacro add-function (&rest _))) ;24.4
+  (or (fboundp 'remove-function) (defmacro remove-function (&rest _)))
+
   (defmacro ignore-errors-unless-debug (&rest body)
     "Ignore all errors while executing BODY unless debug is on."
     (declare (debug t) (indent 0))
@@ -546,12 +549,10 @@ Value is new modtime if updated."
 
 (defun ggtags-ensure-project ()
   (or (ggtags-find-project)
-      (when (or (yes-or-no-p "File GTAGS not found; run gtags? ")
-                (user-error "Aborted"))
-        (call-interactively #'ggtags-create-tags)
-        ;; Need checking because `ggtags-create-tags' can create tags
-        ;; in any directory.
-        (ggtags-check-project))))
+      (progn (call-interactively #'ggtags-create-tags)
+             ;; Need checking because `ggtags-create-tags' can create
+             ;; tags in any directory.
+             (ggtags-check-project))))
 
 (defvar delete-trailing-lines)          ;new in 24.3
 
@@ -608,10 +609,15 @@ Value is new modtime if updated."
       (message "Project read-only-mode is %s" (if val "on" "off")))
     val))
 
-(defun ggtags-visit-project-root ()
-  (interactive)
-  (ggtags-ensure-project)
-  (dired (ggtags-current-project-root)))
+(defun ggtags-visit-project-root (&optional project)
+  "Visit the root directory of (current) PROJECT in dired.
+When called with a prefix \\[universal-argument], choose from past projects."
+  (interactive (list (and current-prefix-arg
+                          (completing-read "Project: " ggtags-projects))))
+  (dired (cl-typecase project
+           (string project)
+           (ggtags-project (ggtags-project-root project))
+           (t (ggtags-ensure-project) (ggtags-current-project-root)))))
 
 (defmacro ggtags-with-current-project (&rest body)
   "Eval BODY in current project's `process-environment'."
@@ -654,8 +660,11 @@ Value is new modtime if updated."
   (when (ggtags-find-project)
     (with-temp-buffer
       (ggtags-with-current-project
-        (process-file (ggtags-program-path "global") nil t nil
-                      "-vP" (concat "^" (ggtags-project-relative-file file) "$")))
+        ;; NOTE: `process-file' requires all files in ARGS be relative
+        ;; to `default-directory'; see its doc string for details.
+        (let ((default-directory (ggtags-current-project-root)))
+          (process-file (ggtags-program-path "global") nil t nil
+                        "-vP" (concat "^" (ggtags-project-relative-file file) "$"))))
       (goto-char (point-min))
       (not (re-search-forward "^file not found" nil t)))))
 
@@ -714,20 +723,38 @@ source trees. See Info node `(global)gtags' for details."
 
 (defun ggtags-update-tags (&optional force)
   "Update GNU Global tag database.
-Do nothing if GTAGS exceeds the oversize limit unless FORCE."
+Do nothing if GTAGS exceeds the oversize limit unless FORCE.
+
+When called interactively on large (per `ggtags-oversize-limit')
+projects, the update process runs in the background without
+blocking emacs."
   (interactive (progn
                  (ggtags-check-project)
                  ;; Mark project info expired.
                  (setf (ggtags-project-timestamp (ggtags-find-project)) -1)
-                 (list t)))
-  (when (or force (and (ggtags-find-project)
-                       (not (ggtags-project-oversize-p))
-                       (ggtags-project-dirty-p (ggtags-find-project))))
-    (ggtags-with-current-project
-      (ggtags-with-temp-message "`global -u' in progress..."
-        (ggtags-process-string "global" "-u")
-        (setf (ggtags-project-dirty-p (ggtags-find-project)) nil)
-        (setf (ggtags-project-mtime (ggtags-find-project)) (float-time))))))
+                 (list 'interactive)))
+  (cond ((and (eq force 'interactive) (ggtags-project-oversize-p))
+         (ggtags-with-current-project
+           (with-display-buffer-no-window
+             (with-current-buffer (compilation-start "global -u")
+               ;; A hack to fool compilation mode to display `global
+               ;; -u finished' on finish.
+               (setq mode-name "global -u")
+               (add-hook 'compilation-finish-functions
+                         #'ggtags-update-tags-finish nil t)))))
+        ((or force (and (ggtags-find-project)
+                        (not (ggtags-project-oversize-p))
+                        (ggtags-project-dirty-p (ggtags-find-project))))
+         (ggtags-with-current-project
+           (ggtags-with-temp-message "`global -u' in progress..."
+             (ggtags-process-string "global" "-u")
+             (ggtags-update-tags-finish))))))
+
+(defun ggtags-update-tags-finish (&optional buf how)
+  (if (and how buf (string-prefix-p "exited abnormally" how))
+      (display-buffer buf)
+    (setf (ggtags-project-dirty-p (ggtags-find-project)) nil)
+    (setf (ggtags-project-mtime (ggtags-find-project)) (float-time))))
 
 (defun ggtags-update-tags-single (file &optional nowait)
   ;; NOTE: NOWAIT is ignored if file is remote file; see
@@ -735,8 +762,10 @@ Do nothing if GTAGS exceeds the oversize limit unless FORCE."
   (cl-check-type file string)
   (let ((nowait (unless (file-remote-p file) nowait)))
     (ggtags-with-current-project
-      (process-file (ggtags-program-path "global") nil (and nowait 0) nil
-                    "--single-update" (ggtags-project-relative-file file)))))
+      ;; See comment in `ggtags-project-file-p'.
+      (let ((default-directory (ggtags-current-project-root)))
+        (process-file (ggtags-program-path "global") nil (and nowait 0) nil
+                      "--single-update" (ggtags-project-relative-file file))))))
 
 (defun ggtags-delete-tags ()
   "Delete file GTAGS, GRTAGS, GPATH, ID etc. generated by gtags."
@@ -2142,6 +2171,12 @@ to nil disables displaying this information.")
         ;; Append to serve as a fallback method.
         (add-hook 'completion-at-point-functions
                   #'ggtags-completion-at-point t t)
+        ;; Work around http://debbugs.gnu.org/19324
+        (or eldoc-documentation-function
+            (setq-local eldoc-documentation-function #'ignore))
+        (add-function :after-until (local 'eldoc-documentation-function)
+                      #'ggtags-eldoc-function '((name . ggtags-eldoc-function)
+                                                (depth . -100)))
         (unless (memq 'ggtags-mode-line-project-name
                       mode-line-buffer-identification)
           (setq mode-line-buffer-identification
@@ -2149,6 +2184,7 @@ to nil disables displaying this information.")
                         '(ggtags-mode-line-project-name)))))
     (remove-hook 'after-save-hook 'ggtags-after-save-function t)
     (remove-hook 'completion-at-point-functions #'ggtags-completion-at-point t)
+    (remove-function (local 'eldoc-documentation-function) 'ggtags-eldoc-function)
     (setq mode-line-buffer-identification
           (delq 'ggtags-mode-line-project-name mode-line-buffer-identification))
     (and (overlayp ggtags-highlight-tag-overlay)