changeset 26720:32e893b03ad2

(etags-tags-completion-table): Modified the regexp to allow for the CL symbols starting with `+*'. (tags-completion-table): Doc fix (it's an obarray, not an alist). (tags-completion-table, tags-recognize-empty-tags-table): Remove `function' quoting lambda. (tags-with-face): New macro. (list-tags, tags-apropos): Use it. (tags-apropos-additional-actions): New user option. (etags-tags-apropos-additional): Use it. (tags-apropos): Call etags-tags-apropos-additional. (tags-apropos-verbose): New user option. (etags-tags-apropos): Use it. (visit-tags-table-buffer, next-file): Use `unless'. (recognize-empty-tags-table): Renamed to tags-recognize-empty-tags-table. (complete-tag): Call tags-complete-tag bypassing try-completion.
author Gerd Moellmann <gerd@gnu.org>
date Mon, 06 Dec 1999 13:13:39 +0000
parents 8a6fd8991465
children 13132a2907aa
files lisp/progmodes/etags.el
diffstat 1 files changed, 139 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/progmodes/etags.el	Mon Dec 06 13:12:38 1999 +0000
+++ b/lisp/progmodes/etags.el	Mon Dec 06 13:13:39 1999 +0000
@@ -25,6 +25,7 @@
 ;;; Code:
 
 (require 'ring)
+(eval-when-compile (require 'cl)) ; for `gensym'
 
 ;;;###autoload
 (defvar tags-file-name nil
@@ -113,6 +114,39 @@
   :type 'integer
   :version "20.3")
 
+(defcustom tags-tag-face 'default
+  "*Face for tags in the output of `tags-apropos'."
+  :group 'etags
+  :type 'face
+  :version "21.1")
+
+(defcustom tags-apropos-verbose nil
+  "If non-nil, print the name of the tags file in the *Tags List* buffer."
+  :group 'etags
+  :type 'boolean
+  :version "21.1")
+
+(defcustom tags-apropos-additional-actions nil
+  "Specify additional actions for `tags-apropos'.
+
+If non-nil, value should be a list of triples (TITLE FUNCTION
+TO-SEARCH).  For each triple, `tags-apropos' processes TO-SEARCH and
+lists tags from it.  TO-SEARCH should be an alist, obarray, or symbol.
+If it is a symbol, the symbol's value is used.
+TITLE. a string, is a title used to label the additional list of tags.
+FUNCTION is a function to call when a symbol is selected in the
+*Tags List* buffer.  It will be called with one argument SYMBOL which
+is the symbol being selected.
+
+Example value:
+
+  '((\"Emacs Lisp\" Info-goto-emacs-command-node obarray)
+    (\"Common Lisp\" common-lisp-hyperspec common-lisp-hyperspec-obarray)
+    (\"SCWM\" scwm-documentation scwm-obarray))"
+  :group 'etags
+  :type 'list
+  :version "21.1")
+
 (defvar find-tag-marker-ring (make-ring find-tag-marker-ring-length)
   "Ring of markers which are locations from which \\[find-tag] was invoked.")
 
@@ -133,7 +167,7 @@
 nil means it has not yet been computed; use `tags-table-files' to do so.")
 
 (defvar tags-completion-table nil
-  "Alist of tag names defined in current tags table.")
+  "Obarray of tag names defined in current tags table.")
 
 (defvar tags-included-tables nil
   "List of tags tables included by the current tags table.")
@@ -144,7 +178,7 @@
 ;; Hooks for file formats.
 
 (defvar tags-table-format-hooks '(etags-recognize-tags-table
-				  recognize-empty-tags-table)
+				  tags-recognize-empty-tags-table)
   "List of functions to be called in a tags table buffer to identify the type of tags table.  
 The functions are called in order, with no arguments,
 until one returns non-nil.  The function should make buffer-local bindings
@@ -525,11 +559,7 @@
   ;; Expand the table name into a full file name.
   (setq tags-file-name (tags-expand-table-name tags-file-name))
 
-  (if (and (eq cont t)
-	   (null tags-table-list-pointer))
-      ;; All out of tables.
-      nil
-
+  (unless (and (eq cont t) (null tags-table-list-pointer))
     ;; Verify that tags-file-name names a valid tags table.
     ;; Bind another variable with the value of tags-file-name
     ;; before we switch buffers, in case tags-file-name is buffer-local.
@@ -675,9 +705,7 @@
 		 ;; Recurse in that buffer to compute its completion table.
 		 (if (tags-completion-table)
 		     ;; Combine the tables.
-		     (mapatoms (function
-				(lambda (sym)
-				  (intern (symbol-name sym) table)))
+		     (mapatoms (lambda (sym) (intern (symbol-name sym) table))
 			       tags-completion-table))
 		 (setq included (cdr included))))
 	     (setq tags-completion-table table))
@@ -1066,8 +1094,7 @@
        ;; It is annoying to flash messages on the screen briefly,
        ;; and this message is not useful.  -- rms
        ;; (message "%s is an `etags' TAGS file" buffer-file-name)
-       (mapcar (function (lambda (elt)
-			   (set (make-local-variable (car elt)) (cdr elt))))
+       (mapcar (lambda (elt) (set (make-local-variable (car elt)) (cdr elt)))
 	       '((file-of-tag-function . etags-file-of-tag)
 		 (tags-table-files-function . etags-tags-table-files)
 		 (tags-completion-table-function . etags-tags-completion-table)
@@ -1114,9 +1141,9 @@
       ;;   \6 is the line to start searching at;
       ;;   \7 is the char to start searching at.
       (while (re-search-forward
-	      "^\\(\\([^\177]+[^-a-zA-Z0-9_$\177]+\\)?\\([-a-zA-Z0-9_$?:]+\\)\
-\[^-a-zA-Z0-9_$?:\177]*\\)\177\\(\\([^\n\001]+\\)\001\\)?\
-\\([0-9]+\\)?,\\([0-9]+\\)?\n"
+	      "^\\(\\([^\177]+[^-a-zA-Z0-9_+*$\177]+\\)?\
+\\([-a-zA-Z0-9_+*$?:]+\\)[^-a-zA-Z0-9_+*$?:\177]*\\)\177\
+\\(\\([^\n\001]+\\)\001\\)?\\([0-9]+\\)?,\\([0-9]+\\)?\n"
 	      nil t)
 	(intern	(if (match-beginning 5)
 		    ;; There is an explicit tag name.
@@ -1219,32 +1246,86 @@
 
 (defun etags-list-tags (file)
   (goto-char 1)
-  (if (not (search-forward (concat "\f\n" file ",") nil t))
-      nil
+  (when (search-forward (concat "\f\n" file ",") nil t)
     (forward-line 1)
     (while (not (or (eobp) (looking-at "\f")))
       (let ((tag (buffer-substring (point)
 				   (progn (skip-chars-forward "^\177")
-					  (point)))))
-	(princ (if (looking-at "[^\n]+\001")
-		   ;; There is an explicit tag name; use that.
-		   (buffer-substring (1+ (point)) ;skip \177
-				     (progn (skip-chars-forward "^\001")
-					    (point)))
-		 tag)))
+					  (point))))
+            (props `(action find-tag-other-window mouse-face highlight
+			    face ,tags-tag-face))
+            (pt (with-current-buffer standard-output (point))))
+        (when (looking-at "[^\n]+\001")
+	  ;; There is an explicit tag name; use that.
+          (setq tag (buffer-substring (1+ (point)) ; skip \177
+				      (progn (skip-chars-forward "^\001")
+                                             (point)))))
+        (princ tag)
+        (when (= (aref tag 0) ?\() (princ " ...)"))
+        (add-text-properties pt (with-current-buffer standard-output (point))
+                             (cons 'item (cons tag props)) standard-output))
       (terpri)
       (forward-line 1))
     t))
 
+(defmacro tags-with-face (face &rest body)
+  "Execute BODY, give output to `standard-output' face FACE."
+  (let ((pp (gensym "twf-")))
+    `(let ((,pp (with-current-buffer standard-output (point))))
+       ,@body
+       (put-text-property ,pp (with-current-buffer standard-output (point))
+			  'face ,face standard-output))))
+
+(defun etags-tags-apropos-additional (regexp)
+  "Display tags matching REGEXP from `tags-apropos-additional-actions'."
+  (with-current-buffer standard-output
+    (dolist (oba tags-apropos-additional-actions)
+      (princ "\n\n")
+      (tags-with-face 'highlight (princ (car oba)))
+      (princ":\n\n")
+      (let* ((props `(action ,(cadr oba) mouse-face highlight face
+			     ,tags-tag-face))
+             (beg (point))
+	     (symbs (car (cddr oba)))
+             (ins-symb (lambda (sy)
+                         (let ((sn (symbol-name sy)))
+                           (when (string-match regexp sn)
+                             (add-text-properties (point)
+						  (progn (princ sy) (point))
+						  (cons 'item (cons sn props)))
+                             (terpri))))))
+        (when (symbolp symbs)
+          (if (boundp symbs)
+	      (setq symbs (symbol-value symbs))
+	    (insert "symbol `" (symbol-name symbs) "' has no value\n")
+	    (setq symbs nil)))
+        (if (vectorp symbs)
+	    (mapatoms ins-symb symbs)
+	  (dolist (sy symbs)
+	    (funcall ins-symb (car sy))))
+        (sort-lines nil beg (point))))))
+
 (defun etags-tags-apropos (string)
+  (when tags-apropos-verbose
+    (princ "Tags in file `")
+    (tags-with-face 'highlight (princ buffer-file-name))
+    (princ "':\n\n"))
   (goto-char 1)
   (while (re-search-forward string nil t)
     (beginning-of-line)
-    (princ (buffer-substring (point)
-			     (progn (skip-chars-forward "^\177")
-				    (point))))
+    (let ((tag (buffer-substring (point)
+				 (progn (skip-chars-forward "^\177")
+					(point))))
+          (props `(action find-tag-other-window mouse-face highlight
+			  face ,tags-tag-face))
+          (pt (with-current-buffer standard-output (point))))
+      (princ tag)
+      (when (= (aref tag 0) ?\() (princ " ...)"))
+      (add-text-properties pt (with-current-buffer standard-output (point))
+                           `(item ,tag ,@props) standard-output))
     (terpri)
-    (forward-line 1)))
+    (forward-line 1))
+  (when tags-apropos-verbose (princ "\n")))
 
 (defun etags-tags-table-files ()
   (let ((files nil)
@@ -1276,10 +1357,9 @@
 
 ;; Recognize an empty file and give it local values of the tags table format
 ;; variables which do nothing.
-(defun recognize-empty-tags-table ()
+(defun tags-recognize-empty-tags-table ()
   (and (zerop (buffer-size))
-       (mapcar (function (lambda (sym)
-			   (set (make-local-variable sym) 'ignore)))
+       (mapcar (lambda (sym) (set (make-local-variable sym) 'ignore))
 	       '(tags-table-files-function
 		 tags-completion-table-function
 		 find-tag-regexp-search-function
@@ -1287,15 +1367,14 @@
 		 tags-apropos-function
 		 tags-included-tables-function))
        (set (make-local-variable 'verify-tags-table-function)
-	    (function (lambda ()
-			(zerop (buffer-size)))))))
+            (lambda () (zerop (buffer-size))))))
 
-;;; Match qualifier functions for tagnames.
-;;; XXX these functions assume etags file format.
+;; Match qualifier functions for tagnames.
+;; XXX these functions assume etags file format.
 
 ;; This might be a neat idea, but it's too hairy at the moment.
 ;;(defmacro tags-with-syntax (&rest body)
-;;  (` (let ((current (current-buffer))
+;;   `(let ((current (current-buffer))
 ;;	   (otable (syntax-table))
 ;;	   (buffer (find-file-noselect (file-of-tag)))
 ;;	   table)
@@ -1305,8 +1384,8 @@
 ;;	     (setq table (syntax-table))
 ;;	     (set-buffer current)
 ;;	     (set-syntax-table table)
-;;	     (,@ body))
-;;	 (set-syntax-table otable)))))
+;;            ,@body)
+;;       (set-syntax-table otable))))
 ;;(put 'tags-with-syntax 'edebug-form-spec '(&rest form))
 
 ;; t if point is at a tag line that matches TAG exactly.
@@ -1402,8 +1481,7 @@
 	(t
 	 ;; Initialize the list by evalling the argument.
 	 (setq next-file-list (eval initialize))))
-  (if next-file-list
-      ()
+  (unless next-file-list
     (and novisit
 	 (get-buffer " *next-file*")
 	 (kill-buffer " *next-file*"))
@@ -1557,9 +1635,9 @@
 				      'tags-complete-tags-table-file
 				      nil t nil)))
   (with-output-to-temp-buffer "*Tags List*"
-    (princ "Tags in file ")
-    (princ file)
-    (terpri)
+    (princ "Tags in file `")
+    (tags-with-face 'highlight (princ file))
+    (princ "':\n\n")
     (save-excursion
       (let ((first-time t)
 	    (gotany nil))
@@ -1568,21 +1646,28 @@
 	  (if (funcall list-tags-function file)
 	      (setq gotany t)))
 	(or gotany
-	    (error "File %s not in current tags tables" file))))))
+	    (error "File %s not in current tags tables" file)))))
+  (with-current-buffer "*Tags List*"
+    (setq buffer-read-only t)
+    (apropos-mode)))
 
 ;;;###autoload
 (defun tags-apropos (regexp)
   "Display list of all tags in tags table REGEXP matches."
   (interactive "sTags apropos (regexp): ")
   (with-output-to-temp-buffer "*Tags List*"
-    (princ "Tags matching regexp ")
-    (prin1 regexp)
-    (terpri)
+    (princ "Click mouse-2 to follow tags.\n\nTags matching regexp `")
+    (tags-with-face 'highlight (princ regexp))
+    (princ "':\n\n")
     (save-excursion
       (let ((first-time t))
 	(while (visit-tags-table-buffer (not first-time))
 	  (setq first-time nil)
-	  (funcall tags-apropos-function regexp))))))
+	  (funcall tags-apropos-function regexp))))
+    (etags-tags-apropos-additional regexp))
+  (with-current-buffer "*Tags List*"
+    (setq buffer-read-only t)
+    (apropos-mode)))
 
 ;;; XXX Kludge interface.
 
@@ -1598,29 +1683,25 @@
   (erase-buffer)
   (let ((set-list tags-table-set-list)
 	(desired-point nil))
-    (if tags-table-list
-	(progn
+    (when tags-table-list
 	  (setq desired-point (point-marker))
 	  (princ tags-table-list (current-buffer))
 	  (insert "\C-m")
 	  (prin1 (car tags-table-list) (current-buffer)) ;invisible
-	  (insert "\n")))
+      (insert "\n"))
     (while set-list
-      (if (eq (car set-list) tags-table-list)
-	  ;; Already printed it.
-	  ()
+      (unless (eq (car set-list) tags-table-list)
 	(princ (car set-list) (current-buffer))
 	(insert "\C-m")
 	(prin1 (car (car set-list)) (current-buffer)) ;invisible
 	(insert "\n"))
       (setq set-list (cdr set-list)))
-    (if tags-file-name
-	(progn
+    (when tags-file-name
 	  (or desired-point
 	      (setq desired-point (point-marker)))
 	  (insert tags-file-name "\C-m")
 	  (prin1 tags-file-name (current-buffer)) ;invisible
-	  (insert "\n")))
+      (insert "\n"))
     (setq set-list (delete tags-file-name
 			   (apply 'nconc (cons (copy-sequence tags-table-list)
 					       (mapcar 'copy-sequence
@@ -1699,7 +1780,7 @@
     (search-backward pattern)
     (setq beg (point))
     (forward-char (length pattern))
-    (setq completion (try-completion pattern 'tags-complete-tag nil))
+    (setq completion (tags-complete-tag pattern nil nil))
     (cond ((eq completion t))
 	  ((null completion)
 	   (message "Can't find completion for \"%s\"" pattern)