root/trunk/lisp/progmodes/etags.el

Revision 4220, 79.0 kB (checked in by miyoshi, 9 months ago)

Sync up with Emacs22.2.

  • Property svn:eol-style set to LF
Line 
1 ;;; etags.el --- etags facility for Emacs
2
3 ;; Copyright (C) 1985, 1986, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
4 ;;               2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 ;;      Free Software Foundation, Inc.
6
7 ;; Author: Roland McGrath <roland@gnu.org>
8 ;; Maintainer: FSF
9 ;; Keywords: tools
10
11 ;; This file is part of GNU Emacs.
12
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 3, or (at your option)
16 ;; any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 ;; Boston, MA 02110-1301, USA.
27
28 ;;; Commentary:
29
30 ;;; Code:
31
32 (require 'ring)
33 (require 'button)
34
35 ;;;###autoload
36 (defvar tags-file-name nil
37   "*File name of tags table.
38 To switch to a new tags table, setting this variable is sufficient.
39 If you set this variable, do not also set `tags-table-list'.
40 Use the `etags' program to make a tags table file.")
41 ;; Make M-x set-variable tags-file-name like M-x visit-tags-table.
42 ;;;###autoload (put 'tags-file-name 'variable-interactive "fVisit tags table: ")
43
44 (defgroup etags nil "Tags tables."
45   :group 'tools)
46
47 ;;;###autoload
48 (defcustom tags-case-fold-search 'default
49   "*Whether tags operations should be case-sensitive.
50 A value of t means case-insensitive, a value of nil means case-sensitive.
51 Any other value means use the setting of `case-fold-search'."
52   :group 'etags
53   :type '(choice (const :tag "Case-sensitive" nil)
54                  (const :tag "Case-insensitive" t)
55                  (other :tag "Use default" default))
56   :version "21.1")
57
58 ;;;###autoload
59 ;; Use `visit-tags-table-buffer' to cycle through tags tables in this list.
60 (defcustom tags-table-list nil
61   "*List of file names of tags tables to search.
62 An element that is a directory means the file \"TAGS\" in that directory.
63 To switch to a new list of tags tables, setting this variable is sufficient.
64 If you set this variable, do not also set `tags-file-name'.
65 Use the `etags' program to make a tags table file."
66   :group 'etags
67   :type '(repeat file))
68
69 ;;;###autoload
70 (defcustom tags-compression-info-list '("" ".Z" ".bz2" ".gz" ".tgz")
71   "*List of extensions tried by etags when jka-compr is used.
72 An empty string means search the non-compressed file.
73 These extensions will be tried only if jka-compr was activated
74 \(i.e. via customize of `auto-compression-mode' or by calling the function
75 `auto-compression-mode')."
76   :type  '(repeat string)
77   :group 'etags)
78
79 ;; !!! tags-compression-info-list should probably be replaced by access
80 ;; to directory list and matching jka-compr-compression-info-list. Currently,
81 ;; this implementation forces each modification of
82 ;; jka-compr-compression-info-list to be reflected in this var.
83 ;; An alternative could be to say that introducing a special
84 ;; element in this list (e.g. t) means : try at this point
85 ;; using directory listing and regexp matching using
86 ;; jka-compr-compression-info-list.
87
88
89 ;;;###autoload
90 (defcustom tags-add-tables 'ask-user
91   "*Control whether to add a new tags table to the current list.
92 t means do; nil means don't (always start a new list).
93 Any other value means ask the user whether to add a new tags table
94 to the current list (as opposed to starting a new list)."
95   :group 'etags
96   :type '(choice (const :tag "Do" t)
97                  (const :tag "Don't" nil)
98                  (other :tag "Ask" ask-user)))
99
100 (defcustom tags-revert-without-query nil
101   "*Non-nil means reread a TAGS table without querying, if it has changed."
102   :group 'etags
103   :type 'boolean)
104
105 (defvar tags-table-computed-list nil
106   "List of tags tables to search, computed from `tags-table-list'.
107 This includes tables implicitly included by other tables.  The list is not
108 always complete: the included tables of a table are not known until that
109 table is read into core.  An element that is t is a placeholder
110 indicating that the preceding element is a table that has not been read
111 into core and might contain included tables to search.
112 See `tags-table-check-computed-list'.")
113
114 (defvar tags-table-computed-list-for nil
115   "Value of `tags-table-list' that `tags-table-computed-list' corresponds to.
116 If `tags-table-list' changes, `tags-table-computed-list' is thrown away and
117 recomputed; see `tags-table-check-computed-list'.")
118
119 (defvar tags-table-list-pointer nil
120   "Pointer into `tags-table-computed-list' for the current state of searching.
121 Use `visit-tags-table-buffer' to cycle through tags tables in this list.")
122
123 (defvar tags-table-list-started-at nil
124   "Pointer into `tags-table-computed-list', where the current search started.")
125
126 (defvar tags-table-set-list nil
127   "List of sets of tags table which have been used together in the past.
128 Each element is a list of strings which are file names.")
129
130 ;;;###autoload
131 (defcustom find-tag-hook nil
132   "*Hook to be run by \\[find-tag] after finding a tag.  See `run-hooks'.
133 The value in the buffer in which \\[find-tag] is done is used,
134 not the value in the buffer \\[find-tag] goes to."
135   :group 'etags
136   :type 'hook)
137
138 ;;;###autoload
139 (defcustom find-tag-default-function nil
140   "*A function of no arguments used by \\[find-tag] to pick a default tag.
141 If nil, and the symbol that is the value of `major-mode'
142 has a `find-tag-default-function' property (see `put'), that is used.
143 Otherwise, `find-tag-default' is used."
144   :group 'etags
145   :type '(choice (const nil) function))
146
147 (defcustom find-tag-marker-ring-length 16
148   "*Length of marker rings `find-tag-marker-ring' and `tags-location-ring'."
149   :group 'etags
150   :type 'integer
151   :version "20.3")
152
153 (defcustom tags-tag-face 'default
154   "*Face for tags in the output of `tags-apropos'."
155   :group 'etags
156   :type 'face
157   :version "21.1")
158
159 (defcustom tags-apropos-verbose nil
160   "If non-nil, print the name of the tags file in the *Tags List* buffer."
161   :group 'etags
162   :type 'boolean
163   :version "21.1")
164
165 (defcustom tags-apropos-additional-actions nil
166   "Specify additional actions for `tags-apropos'.
167
168 If non-nil, value should be a list of triples (TITLE FUNCTION
169 TO-SEARCH).  For each triple, `tags-apropos' processes TO-SEARCH and
170 lists tags from it.  TO-SEARCH should be an alist, obarray, or symbol.
171 If it is a symbol, the symbol's value is used.
172 TITLE, a string, is a title used to label the additional list of tags.
173 FUNCTION is a function to call when a symbol is selected in the
174 *Tags List* buffer.  It will be called with one argument SYMBOL which
175 is the symbol being selected.
176
177 Example value:
178
179   '((\"Emacs Lisp\" Info-goto-emacs-command-node obarray)
180     (\"Common Lisp\" common-lisp-hyperspec common-lisp-hyperspec-obarray)
181     (\"SCWM\" scwm-documentation scwm-obarray))"
182   :group 'etags
183   :type '(repeat (list (string :tag "Title")
184                        function
185                        (sexp :tag "Tags to search")))
186   :version "21.1")
187
188 (defvar find-tag-marker-ring (make-ring find-tag-marker-ring-length)
189   "Ring of markers which are locations from which \\[find-tag] was invoked.")
190
191 (defvar default-tags-table-function nil
192   "If non-nil, a function to choose a default tags file for a buffer.
193 This function receives no arguments and should return the default
194 tags table file to use for the current buffer.")
195
196 (defvar tags-location-ring (make-ring find-tag-marker-ring-length)
197   "Ring of markers which are locations visited by \\[find-tag].
198 Pop back to the last location with \\[negative-argument] \\[find-tag].")
199
200 ;; Tags table state.
201 ;; These variables are local in tags table buffers.
202
203 (defvar tags-table-files nil
204   "List of file names covered by current tags table.
205 nil means it has not yet been computed; use `tags-table-files' to do so.")
206
207 (defvar tags-completion-table nil
208   "Obarray of tag names defined in current tags table.")
209
210 (defvar tags-included-tables nil
211   "List of tags tables included by the current tags table.")
212
213 (defvar next-file-list nil
214   "List of files for \\[next-file] to process.")
215
216 ;; Hooks for file formats.
217
218 (defvar tags-table-format-functions '(etags-recognize-tags-table
219                                       tags-recognize-empty-tags-table)
220   "Hook to be called in a tags table buffer to identify the type of tags table.
221 The functions are called in order, with no arguments,
222 until one returns non-nil.  The function should make buffer-local bindings
223 of the format-parsing tags function variables if successful.")
224
225 (defvar file-of-tag-function nil
226   "Function to do the work of `file-of-tag' (which see).
227 One optional argument, a boolean specifying to return complete path (nil) or
228 relative path (non-nil).")
229 (defvar tags-table-files-function nil
230   "Function to do the work of `tags-table-files' (which see).")
231 (defvar tags-completion-table-function nil
232   "Function to build the `tags-completion-table'.")
233 (defvar snarf-tag-function nil
234   "Function to get info about a matched tag for `goto-tag-location-function'.
235 One optional argument, specifying to use explicit tag (non-nil) or not (nil).
236 The default is nil.")
237 (defvar goto-tag-location-function nil
238   "Function of to go to the location in the buffer specified by a tag.
239 One argument, the tag info returned by `snarf-tag-function'.")
240 (defvar find-tag-regexp-search-function nil
241   "Search function passed to `find-tag-in-order' for finding a regexp tag.")
242 (defvar find-tag-regexp-tag-order nil
243   "Tag order passed to `find-tag-in-order' for finding a regexp tag.")
244 (defvar find-tag-regexp-next-line-after-failure-p nil
245   "Flag passed to `find-tag-in-order' for finding a regexp tag.")
246 (defvar find-tag-search-function nil
247   "Search function passed to `find-tag-in-order' for finding a tag.")
248 (defvar find-tag-tag-order nil
249   "Tag order passed to `find-tag-in-order' for finding a tag.")
250 (defvar find-tag-next-line-after-failure-p nil
251   "Flag passed to `find-tag-in-order' for finding a tag.")
252 (defvar list-tags-function nil
253   "Function to do the work of `list-tags' (which see).")
254 (defvar tags-apropos-function nil
255   "Function to do the work of `tags-apropos' (which see).")
256 (defvar tags-included-tables-function nil
257   "Function to do the work of `tags-included-tables' (which see).")
258 (defvar verify-tags-table-function nil
259   "Function to return t if current buffer contains valid tags file.")
260
261 ;; Initialize the tags table in the current buffer.
262 ;; Returns non-nil if it is a valid tags table.  On
263 ;; non-nil return, the tags table state variable are
264 ;; made buffer-local and initialized to nil.
265 (defun initialize-new-tags-table ()
266   (set (make-local-variable 'tags-table-files) nil)
267   (set (make-local-variable 'tags-completion-table) nil)
268   (set (make-local-variable 'tags-included-tables) nil)
269   ;; We used to initialize find-tag-marker-ring and tags-location-ring
270   ;; here, to new empty rings.  But that is wrong, because those
271   ;; are global.
272
273   ;; Value is t if we have found a valid tags table buffer.
274   (run-hook-with-args-until-success 'tags-table-format-functions))
275
276 ;;;###autoload
277 (defun tags-table-mode ()
278   "Major mode for tags table file buffers."
279   (interactive)
280   (setq major-mode 'tags-table-mode
281         mode-name "Tags Table"
282         buffer-undo-list t)
283   (initialize-new-tags-table))
284
285 ;;;###autoload
286 (defun visit-tags-table (file &optional local)
287   "Tell tags commands to use tags table file FILE.
288 FILE should be the name of a file created with the `etags' program.
289 A directory name is ok too; it means file TAGS in that directory.
290
291 Normally \\[visit-tags-table] sets the global value of `tags-file-name'.
292 With a prefix arg, set the buffer-local value instead.
293 When you find a tag with \\[find-tag], the buffer it finds the tag
294 in is given a local value of this variable which is the name of the tags
295 file the tag was in."
296   (interactive (list (read-file-name "Visit tags table (default TAGS): "
297                                      default-directory
298                                      (expand-file-name "TAGS"
299                                                        default-directory)
300                                      t)
301                      current-prefix-arg))
302   (or (stringp file) (signal 'wrong-type-argument (list 'stringp file)))
303   ;; Bind tags-file-name so we can control below whether the local or
304   ;; global value gets set.  Calling visit-tags-table-buffer will
305   ;; initialize a buffer for the file and set tags-file-name to the
306   ;; Calling visit-tags-table-buffer with tags-file-name set to FILE will
307   ;; initialize a buffer for FILE and set tags-file-name to the
308   ;; fully-expanded name.
309   (let ((tags-file-name file))
310     (save-excursion
311       (or (visit-tags-table-buffer file)
312           (signal 'file-error (list "Visiting tags table"
313                                     "file does not exist"
314                                     file)))
315       ;; Set FILE to the expanded name.
316       (setq file tags-file-name)))
317   (if local
318       ;; Set the local value of tags-file-name.
319       (set (make-local-variable 'tags-file-name) file)
320     ;; Set the global value of tags-file-name.
321     (setq-default tags-file-name file)))
322
323 (defun tags-table-check-computed-list ()
324   "Compute `tags-table-computed-list' from `tags-table-list' if necessary."
325   (let ((expanded-list (mapcar 'tags-expand-table-name tags-table-list)))
326     (or (equal tags-table-computed-list-for expanded-list)
327         ;; The list (or default-directory) has changed since last computed.
328         (let* ((compute-for (mapcar 'copy-sequence expanded-list))
329                (tables (copy-sequence compute-for)) ;Mutated in the loop.
330                (computed nil)
331                table-buffer)
332
333           (while tables
334             (setq computed (cons (car tables) computed)
335                   table-buffer (get-file-buffer (car tables)))
336             (if (and table-buffer
337                      ;; There is a buffer visiting the file.  Now make sure
338                      ;; it is initialized as a tag table buffer.
339                      (save-excursion
340                        (tags-verify-table (buffer-file-name table-buffer))))
341                 (save-excursion
342                   (set-buffer table-buffer)
343                   (if (tags-included-tables)
344                       ;; Insert the included tables into the list we
345                       ;; are processing.
346                       (setcdr tables (nconc (mapcar 'tags-expand-table-name
347                                                     (tags-included-tables))
348                                             (cdr tables)))))
349               ;; This table is not in core yet.  Insert a placeholder
350               ;; saying we must read it into core to check for included
351               ;; tables before searching the next table in the list.
352               (setq computed (cons t computed)))
353             (setq tables (cdr tables)))
354
355           ;; Record the tags-table-list value (and the context of the
356           ;; current directory) we computed from.
357           (setq tags-table-computed-list-for compute-for
358                 tags-table-computed-list (nreverse computed))))))
359
360 ;; Extend `tags-table-computed-list' to remove the first `t' placeholder.
361 ;; An element of the list that is `t' is a placeholder indicating that the
362 ;; preceding element is a table that has not been read into core and might
363 ;; contain included tables to search.  On return, the first placeholder
364 ;; element will be gone and the element before it read into core and its
365 ;; included tables inserted into the list.
366 (defun tags-table-extend-computed-list ()
367   (let ((list tags-table-computed-list))
368     (while (not (eq (nth 1 list) t))
369       (setq list (cdr list)))
370     (save-excursion
371       (if (tags-verify-table (car list))
372           ;; We are now in the buffer visiting (car LIST).  Extract its
373           ;; list of included tables and insert it into the computed list.
374           (let ((tables (tags-included-tables))
375                 (computed nil)
376                 table-buffer)
377             (while tables
378               (setq computed (cons (car tables) computed)
379                     table-buffer (get-file-buffer (car tables)))
380               (if table-buffer
381                   (save-excursion
382                     (set-buffer table-buffer)
383                     (if (tags-included-tables)
384                         ;; Insert the included tables into the list we
385                         ;; are processing.
386                         (setcdr tables (append (tags-included-tables)
387                                                tables))))
388                 ;; This table is not in core yet.  Insert a placeholder
389                 ;; saying we must read it into core to check for included
390                 ;; tables before searching the next table in the list.
391                 (setq computed (cons t computed)))
392               (setq tables (cdr tables)))
393             (setq computed (nreverse computed))
394             ;; COMPUTED now contains the list of included tables (and
395             ;; tables included by them, etc.).  Now splice this into the
396             ;; current list.
397             (setcdr list (nconc computed (cdr (cdr list)))))
398         ;; It was not a valid table, so just remove the following placeholder.
399         (setcdr list (cdr (cdr list)))))))
400
401 ;; Expand tags table name FILE into a complete file name.
402 (defun tags-expand-table-name (file)
403   (setq file (expand-file-name file))
404   (if (file-directory-p file)
405       (expand-file-name "TAGS" file)
406     file))
407
408 ;; Like member, but comparison is done after tags-expand-table-name on both
409 ;; sides and elements of LIST that are t are skipped.
410 (defun tags-table-list-member (file list)
411   (setq file (tags-expand-table-name file))
412   (while (and list
413               (or (eq (car list) t)
414                   (not (string= file (tags-expand-table-name (car list))))))
415     (setq list (cdr list)))
416   list)
417
418 (defun tags-verify-table (file)
419   "Read FILE into a buffer and verify that it is a valid tags table.
420 Sets the current buffer to one visiting FILE (if it exists).
421 Returns non-nil if it is a valid table."
422   (if (get-file-buffer file)
423       ;; The file is already in a buffer.  Check for the visited file
424       ;; having changed since we last used it.
425       (let (win)
426         (set-buffer (get-file-buffer file))
427         (setq win (or verify-tags-table-function (tags-table-mode)))
428         (if (or (verify-visited-file-modtime (current-buffer))
429                 ;; Decide whether to revert the file.
430                 ;; revert-without-query can say to revert
431                 ;; or the user can say to revert.
432                 (not (or (let ((tail revert-without-query)
433                                (found nil))
434                            (while tail
435                              (if (string-match (car tail) buffer-file-name)
436                                  (setq found t))
437                              (setq tail (cdr tail)))
438                            found)
439                          tags-revert-without-query
440                          (yes-or-no-p
441                           (format "Tags file %s has changed, read new contents? "
442                                   file)))))
443             (and verify-tags-table-function
444                  (funcall verify-tags-table-function))
445           (revert-buffer t t)
446           (tags-table-mode)))
447     (and (file-exists-p file)
448          (progn
449            (set-buffer (find-file-noselect file))
450            (or (string= file buffer-file-name)
451                ;; find-file-noselect has changed the file name.
452                ;; Propagate the change to tags-file-name and tags-table-list.
453                (let ((tail (member file tags-table-list)))
454                  (if tail
455                      (setcar tail buffer-file-name))
456                  (if (eq file tags-file-name)
457                      (setq tags-file-name buffer-file-name))))
458            (tags-table-mode)))))
459
460 ;; Subroutine of visit-tags-table-buffer.  Search the current tags tables
461 ;; for one that has tags for THIS-FILE (or that includes a table that
462 ;; does).  Return the name of the first table table listing THIS-FILE; if
463 ;; the table is one included by another table, it is the master table that
464 ;; we return.  If CORE-ONLY is non-nil, check only tags tables that are
465 ;; already in buffers--don't visit any new files.
466 (defun tags-table-including (this-file core-only)
467   (let ((tables tags-table-computed-list)
468         (found nil))
469     ;; Loop over the list, looking for a table containing tags for THIS-FILE.
470     (while (and (not found)
471                 tables)
472
473       (if core-only
474           ;; Skip tables not in core.
475           (while (eq (nth 1 tables) t)
476             (setq tables (cdr (cdr tables))))
477         (if (eq (nth 1 tables) t)
478             ;; This table has not been read into core yet.  Read it in now.
479             (tags-table-extend-computed-list)))
480
481       (if tables
482           ;; Select the tags table buffer and get the file list up to date.
483           (let ((tags-file-name (car tables)))
484             (visit-tags-table-buffer 'same)
485             (if (member this-file (mapcar 'expand-file-name
486                                           (tags-table-files)))
487                 ;; Found it.
488                 (setq found tables))))
489       (setq tables (cdr tables)))
490     (if found
491         ;; Now determine if the table we found was one included by another
492         ;; table, not explicitly listed.  We do this by checking each
493         ;; element of the computed list to see if it appears in the user's
494         ;; explicit list; the last element we will check is FOUND itself.
495         ;; Then we return the last one which did in fact appear in
496         ;; tags-table-list.
497         (let ((could-be nil)
498               (elt tags-table-computed-list))
499           (while (not (eq elt (cdr found)))
500             (if (tags-table-list-member (car elt) tags-table-list)
501                 ;; This table appears in the user's list, so it could be
502                 ;; the one which includes the table we found.
503                 (setq could-be (car elt)))
504             (setq elt (cdr elt))
505             (if (eq t (car elt))
506                 (setq elt (cdr elt))))
507           ;; The last element we found in the computed list before FOUND
508           ;; that appears in the user's list will be the table that
509           ;; included the one we found.
510           could-be))))
511
512 ;; Subroutine of visit-tags-table-buffer.  Move tags-table-list-pointer
513 ;; along and set tags-file-name.  Returns nil when out of tables.
514 (defun tags-next-table ()
515   ;; If there is a placeholder element next, compute the list to replace it.
516   (while (eq (nth 1 tags-table-list-pointer) t)
517     (tags-table-extend-computed-list))
518
519   ;; Go to the next table in the list.
520   (setq tags-table-list-pointer (cdr tags-table-list-pointer))
521   (or tags-table-list-pointer
522       ;; Wrap around.
523       (setq tags-table-list-pointer tags-table-computed-list))
524
525   (if (eq tags-table-list-pointer tags-table-list-started-at)
526       ;; We have come full circle.  No more tables.
527       (setq tags-table-list-pointer nil)
528     ;; Set tags-file-name to the name from the list.  It is already expanded.
529     (setq tags-file-name (car tags-table-list-pointer))))
530
531 ;;;###autoload
532 (defun visit-tags-table-buffer (&optional cont)
533   "Select the buffer containing the current tags table.
534 If optional arg is a string, visit that file as a tags table.
535 If optional arg is t, visit the next table in `tags-table-list'.
536 If optional arg is the atom `same', don't look for a new table;
537  just select the buffer visiting `tags-file-name'.
538 If arg is nil or absent, choose a first buffer from information in
539  `tags-file-name', `tags-table-list', `tags-table-list-pointer'.
540 Returns t if it visits a tags table, or nil if there are no more in the list."
541
542   ;; Set tags-file-name to the tags table file we want to visit.
543   (cond ((eq cont 'same)
544          ;; Use the ambient value of tags-file-name.
545          (or tags-file-name
546              (error "%s"
547                     (substitute-command-keys
548                      (concat "No tags table in use; "
549                              "use \\[visit-tags-table] to select one")))))
550
551         ((eq t cont)
552          ;; Find the next table.
553          (if (tags-next-table)
554              ;; Skip over nonexistent files.
555              (while (and (not (or (get-file-buffer tags-file-name)
556                                   (file-exists-p tags-file-name)))
557                          (tags-next-table)))))
558
559         (t
560          ;; Pick a table out of our hat.
561          (tags-table-check-computed-list) ;Get it up to date, we might use it.
562          (setq tags-file-name
563                (or
564                 ;; If passed a string, use that.
565                 (if (stringp cont)
566                     (prog1 cont
567                       (setq cont nil)))
568                 ;; First, try a local variable.
569                 (cdr (assq 'tags-file-name (buffer-local-variables)))
570                 ;; Second, try a user-specified function to guess.
571                 (and default-tags-table-function
572                      (funcall default-tags-table-function))
573                 ;; Third, look for a tags table that contains tags for the
574                 ;; current buffer's file.  If one is found, the lists will
575                 ;; be frobnicated, and CONT will be set non-nil so we don't
576                 ;; do it below.
577                 (and buffer-file-name
578                      (or
579                       ;; First check only tables already in buffers.
580                       (tags-table-including buffer-file-name t)
581                       ;; Since that didn't find any, now do the
582                       ;; expensive version: reading new files.
583                       (tags-table-including buffer-file-name nil)))
584                 ;; Fourth, use the user variable tags-file-name, if it is
585                 ;; not already in the current list.
586                 (and tags-file-name
587                      (not (tags-table-list-member tags-file-name
588                                                   tags-table-computed-list))
589                      tags-file-name)
590                 ;; Fifth, use the user variable giving the table list.
591                 ;; Find the first element of the list that actually exists.
592                 (let ((list tags-table-list)
593                       file)
594                   (while (and list
595                               (setq file (tags-expand-table-name (car list)))
596                               (not (get-file-buffer file))
597                               (not (file-exists-p file)))
598                     (setq list (cdr list)))
599                   (car list))
600                 ;; Finally, prompt the user for a file name.
601                 (expand-file-name
602                  (read-file-name "Visit tags table (default TAGS): "
603                                  default-directory
604                                  "TAGS"
605                                  t))))))
606
607   ;; Expand the table name into a full file name.
608   (setq tags-file-name (tags-expand-table-name tags-file-name))
609
610   (unless (and (eq cont t) (null tags-table-list-pointer))
611     ;; Verify that tags-file-name names a valid tags table.
612     ;; Bind another variable with the value of tags-file-name
613     ;; before we switch buffers, in case tags-file-name is buffer-local.
614     (let ((curbuf (current-buffer))
615           (local-tags-file-name tags-file-name))
616       (if (tags-verify-table local-tags-file-name)
617
618           ;; We have a valid tags table.
619           (progn
620             ;; Bury the tags table buffer so it
621             ;; doesn't get in the user's way.
622             (bury-buffer (current-buffer))
623
624             ;; If this was a new table selection (CONT is nil), make
625             ;; sure tags-table-list includes the chosen table, and
626             ;; update the list pointer variables.
627             (or cont
628                 ;; Look in the list for the table we chose.
629                 (let ((found (tags-table-list-member
630                               local-tags-file-name
631                               tags-table-computed-list)))
632                   (if found
633                       ;; There it is.  Just switch to it.
634                       (setq tags-table-list-pointer found
635                             tags-table-list-started-at found)
636
637                     ;; The table is not in the current set.
638                     ;; Try to find it in another previously used set.
639                     (let ((sets tags-table-set-list))
640                       (while (and sets
641                                   (not (tags-table-list-member
642                                         local-tags-file-name
643                                         (car sets))))
644                         (setq sets (cdr sets)))
645                       (if sets
646                           ;; Found in some other set.  Switch to that set.
647                           (progn
648                             (or (memq tags-table-list tags-table-set-list)
649                                 ;; Save the current list.
650                                 (setq tags-table-set-list
651                                       (cons tags-table-list
652                                             tags-table-set-list)))
653                             (setq tags-table-list (car sets)))
654
655                         ;; Not found in any existing set.
656                         (if (and tags-table-list
657                                  (or (eq t tags-add-tables)
658                                      (and tags-add-tables
659                                           (y-or-n-p
660                                            (concat "Keep current list of "
661                                                    "tags tables also? ")))))
662                             ;; Add it to the current list.
663                             (setq tags-table-list (cons local-tags-file-name
664                                                         tags-table-list))
665
666                           ;; Make a fresh list, and store the old one.
667                           (message "Starting a new list of tags tables")
668                           (or (null tags-table-list)
669                               (memq tags-table-list tags-table-set-list)
670                               (setq tags-table-set-list
671                                     (cons tags-table-list
672                                           tags-table-set-list)))
673                           ;; Clear out buffers holding old tables.
674                           (dolist (table tags-table-list)
675                             ;; The list can contain items `t'.
676                             (if (stringp table)
677                                 (let ((buffer (find-buffer-visiting table)))
678                               (if buffer
679                                   (kill-buffer buffer)))))
680                           (setq tags-table-list (list local-tags-file-name))))
681
682                       ;; Recompute tags-table-computed-list.
683                       (tags-table-check-computed-list)
684                       ;; Set the tags table list state variables to start
685                       ;; over from tags-table-computed-list.
686                       (setq tags-table-list-started-at tags-table-computed-list
687                             tags-table-list-pointer
688                             tags-table-computed-list)))))
689
690             ;; Return of t says the tags table is valid.
691             t)
692
693         ;; The buffer was not valid.  Don't use it again.
694         (set-buffer curbuf)
695         (kill-local-variable 'tags-file-name)
696         (if (eq local-tags-file-name tags-file-name)
697             (setq tags-file-name nil))
698         (error "File %s is not a valid tags table" local-tags-file-name)))))
699
700 (defun tags-reset-tags-tables ()
701   "Reset tags state to cancel effect of any previous \\[visit-tags-table] or \\[find-tag]."
702   (interactive)
703   ;; Clear out the markers we are throwing away.
704   (let ((i 0))
705     (while (< i find-tag-marker-ring-length)
706       (if (aref (cddr tags-location-ring) i)
707           (set-marker (aref (cddr tags-location-ring) i) nil))
708       (if (aref (cddr find-tag-marker-ring) i)
709           (set-marker (aref (cddr find-tag-marker-ring) i) nil))
710       (setq i (1+ i))))
711   (setq tags-file-name nil
712         tags-location-ring (make-ring find-tag-marker-ring-length)
713         find-tag-marker-ring (make-ring find-tag-marker-ring-length)
714         tags-table-list nil
715         tags-table-computed-list nil
716         tags-table-computed-list-for nil
717         tags-table-list-pointer nil
718         tags-table-list-started-at nil
719         tags-table-set-list nil))
720
721 (defun file-of-tag (&optional relative)
722   "Return the file name of the file whose tags point is within.
723 Assumes the tags table is the current buffer.
724 If RELATIVE is non-nil, file name returned is relative to tags
725 table file's directory. If RELATIVE is nil, file name returned
726 is complete."
727   (funcall file-of-tag-function relative))
728
729 ;;;###autoload
730 (defun tags-table-files ()
731   "Return a list of files in the current tags table.
732 Assumes the tags table is the current buffer.  The file names are returned
733 as they appeared in the `etags' command that created the table, usually
734 without directory names."
735   (or tags-table-files
736       (setq tags-table-files
737             (funcall tags-table-files-function))))
738
739 (defun tags-included-tables ()
740   "Return a list of tags tables included by the current table.
741 Assumes the tags table is the current buffer."
742   (or tags-included-tables
743       (setq tags-included-tables (funcall tags-included-tables-function))))
744
745 ;; Build tags-completion-table on demand.  The single current tags table
746 ;; and its included tags tables (and their included tables, etc.) have
747 ;; their tags included in the completion table.
748 (defun