aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath1992-12-21 19:08:50 +0000
committerRoland McGrath1992-12-21 19:08:50 +0000
commitb6176f6493b475bb44fa39bb812f47cf1df5c617 (patch)
treea27975b11c6311c356d836f521fad6281eaeab76
parenta42a43055f9f5b882f1d2b8aad483fe1f37100c6 (diff)
downloademacs-b6176f6493b475bb44fa39bb812f47cf1df5c617.tar.gz
emacs-b6176f6493b475bb44fa39bb812f47cf1df5c617.zip
Many comments added and docstrings fixed.
(tags-table-list): Elt of nil is not special. (tags-expand-table-name): Value of nil is not special. (tags-next-table): Removed arg RESET; no caller used it. (visit-tags-table-buffer): Don't need to do tags-expand-table-name in or form. When table is invalid, only set tags-file-name to nil globally if its global value contained the losing table file name. (find-tag-tag): Return a string, not a list. (find-tag-noselect, find-tag, find-tag-other-window, find-tag-other-frame): Changed callers. (etags-recognize-tags-table): Call etags-verify-tags-table, rather than duplicating its functionality. (visit-tags-table-buffer): When CONT is 'same, set it to nil after the cond. We want the normal list frobbing to take place in this case. (find-tag-other-window): Save and restore window-point around call to find-tag-noselect.
-rw-r--r--lisp/progmodes/etags.el320
1 files changed, 197 insertions, 123 deletions
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index ee1c0267296..8ffa931592b 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -24,18 +24,22 @@
24;;; Code: 24;;; Code:
25 25
26;;;###autoload 26;;;###autoload
27(defvar tags-file-name nil "\ 27(defvar tags-file-name nil
28*File name of tags table. 28 "*File name of tags table.
29To switch to a new tags table, setting this variable is sufficient. 29To switch to a new tags table, setting this variable is sufficient.
30If you set this variable, do not also set `tags-table-list'.
30Use the `etags' program to make a tags table file.") 31Use the `etags' program to make a tags table file.")
32;; Make M-x set-variable tags-file-name like M-x visit-tags-table.
31;;;###autoload (put 'tags-file-name 'variable-interactive "fVisit tags table: ") 33;;;###autoload (put 'tags-file-name 'variable-interactive "fVisit tags table: ")
32 34
33;;;###autoload 35;;;###autoload
36;; Use `visit-tags-table-buffer' to cycle through tags tables in this list.
34(defvar tags-table-list nil 37(defvar tags-table-list nil
35 "*List of names of tags table files which are currently being searched. 38 "*List of file names of tags tables to search.
36Elements that are directories mean the file \"TAGS\" in that directory. 39An element that is a directory means the file \"TAGS\" in that directory.
37An element of nil means to look for a file \"TAGS\" in the current directory. 40To switch to a new list of tags tables, setting this variable is sufficient.
38Use `visit-tags-table-buffer' to cycle through tags tables in this list.") 41If you set this variable, do not also set `tags-file-name'.
42Use the `etags' program to make a tags table file.")
39 43
40(defvar tags-table-list-pointer nil 44(defvar tags-table-list-pointer nil
41 "Pointer into `tags-table-list' where the current state of searching is. 45 "Pointer into `tags-table-list' where the current state of searching is.
@@ -135,17 +139,15 @@ One argument, the tag info returned by `snarf-tag-function'.")
135 "Function to return t iff the current buffer vontains a valid 139 "Function to return t iff the current buffer vontains a valid
136\(already initialized\) tags file.") 140\(already initialized\) tags file.")
137 141
142;; Initialize the tags table in the current buffer.
143;; Returns non-nil iff it is a valid tags table. On
144;; non-nil return, the tags table state variable are
145;; made buffer-local and initialized to nil.
138(defun initialize-new-tags-table () 146(defun initialize-new-tags-table ()
139 "Initialize the tags table in the current buffer. 147 (set (make-local-variable 'tag-lines-already-matched) nil)
140Returns non-nil iff it is a valid tags table." 148 (set (make-local-variable 'tags-table-files) nil)
141 (make-local-variable 'tag-lines-already-matched) 149 (set (make-local-variable 'tags-completion-table) nil)
142 (make-local-variable 'tags-table-files) 150 (set (make-local-variable 'tags-included-tables) nil)
143 (make-local-variable 'tags-completion-table)
144 (make-local-variable 'tags-included-tables)
145 (setq tags-table-files nil
146 tag-lines-already-matched nil
147 tags-completion-table nil
148 tags-included-tables nil)
149 ;; Value is t if we have found a valid tags table buffer. 151 ;; Value is t if we have found a valid tags table buffer.
150 (let ((hooks tags-table-format-hooks)) 152 (let ((hooks tags-table-format-hooks))
151 (while (and hooks 153 (while (and hooks
@@ -170,68 +172,79 @@ file the tag was in."
170 default-directory) 172 default-directory)
171 t) 173 t)
172 current-prefix-arg)) 174 current-prefix-arg))
175 ;; Calling visit-tags-table-buffer with tags-file-name set to FILE will
176 ;; initialize a buffer for FILE and set tags-file-name to the
177 ;; fully-expanded name.
173 (let ((tags-file-name file)) 178 (let ((tags-file-name file))
174 (save-excursion 179 (save-excursion
175 (or (visit-tags-table-buffer 'same) 180 (or (visit-tags-table-buffer 'same)
176 (signal 'file-error (list "Visiting tags table" 181 (signal 'file-error (list "Visiting tags table"
177 "file does not exist" 182 "file does not exist"
178 file))) 183 file)))
184 ;; Set FILE to the expanded name.
179 (setq file tags-file-name))) 185 (setq file tags-file-name)))
180 (if local 186 (if local
187 ;; Set the local value of tags-file-name.
181 (set (make-local-variable 'tags-file-name) file) 188 (set (make-local-variable 'tags-file-name) file)
189 ;; Set the global value of tags-file-name.
182 (setq-default tags-file-name file))) 190 (setq-default tags-file-name file)))
183 191
184;; Move tags-table-list-pointer along and set tags-file-name. 192;; Move tags-table-list-pointer along and set tags-file-name.
193;; If NO-INCLUDES is non-nil, ignore included tags tables.
185;; Returns nil when out of tables. 194;; Returns nil when out of tables.
186(defun tags-next-table (&optional reset no-includes) 195(defun tags-next-table (&optional no-includes)
187 (if reset 196 ;; Do we have any included tables?
188 (setq tags-table-list-pointer tags-table-list) 197 (if (and (not no-includes)
189 198 (visit-tags-table-buffer 'same)
190 (if (and (not no-includes) 199 (tags-included-tables))
191 (visit-tags-table-buffer 'same) 200
192 (tags-included-tables)) 201 ;; Move into the included tags tables.
193 ;; Move into the included tags tables. 202 (setq tags-table-parent-pointer-list
194 (setq tags-table-parent-pointer-list 203 ;; Save the current state of what table we are in.
195 (cons (cons tags-table-list-pointer tags-table-list-started-at) 204 (cons (cons tags-table-list-pointer tags-table-list-started-at)
196 tags-table-parent-pointer-list) 205 tags-table-parent-pointer-list)
197 tags-table-list-pointer tags-included-tables 206 ;; Start the pointer in the list of included tables.
198 tags-table-list-started-at tags-included-tables) 207 tags-table-list-pointer tags-included-tables
199 208 tags-table-list-started-at tags-included-tables)
200 ;; Go to the next table in the list. 209
201 (setq tags-table-list-pointer 210 ;; No included tables. Go to the next table in the list.
202 (cdr tags-table-list-pointer)) 211 (setq tags-table-list-pointer
203 (or tags-table-list-pointer 212 (cdr tags-table-list-pointer))
204 ;; Wrap around. 213 (or tags-table-list-pointer
205 (setq tags-table-list-pointer tags-table-list)) 214 ;; Wrap around.
206 215 (setq tags-table-list-pointer tags-table-list))
207 (if (eq tags-table-list-pointer tags-table-list-started-at) 216
208 ;; We have come full circle. 217 (if (eq tags-table-list-pointer tags-table-list-started-at)
209 (if tags-table-parent-pointer-list 218 ;; We have come full circle. No more tables.
210 ;; Pop back to the tags table which includes this one. 219 (if tags-table-parent-pointer-list
211 (progn 220 ;; Pop back to the tags table which includes this one.
212 (setq tags-table-list-pointer 221 (progn
213 (car (car tags-table-parent-pointer-list)) 222 ;; Restore the state variables.
214 tags-table-list-started-at 223 (setq tags-table-list-pointer
215 (cdr (car tags-table-parent-pointer-list)) 224 (car (car tags-table-parent-pointer-list))
216 tags-table-parent-pointer-list 225 tags-table-list-started-at
217 (cdr tags-table-parent-pointer-list)) 226 (cdr (car tags-table-parent-pointer-list))
218 (tags-next-table nil t)) 227 tags-table-parent-pointer-list
219 ;; All out of tags tables. 228 (cdr tags-table-parent-pointer-list))
220 (setq tags-table-list-pointer nil)))) 229 ;; Recurse to skip to the next table after the parent.
221 230 (tags-next-table t))
222 (and tags-table-list-pointer 231 ;; All out of tags tables.
223 (setq tags-file-name 232 (setq tags-table-list-pointer nil))))
224 (tags-expand-table-name (car tags-table-list-pointer)))))) 233
225 234 (and tags-table-list-pointer
235 ;; Set tags-file-name to the fully-expanded name.
236 (setq tags-file-name
237 (tags-expand-table-name (car tags-table-list-pointer)))))
238
239;; Expand tags table name FILE into a complete file name.
226(defun tags-expand-table-name (file) 240(defun tags-expand-table-name (file)
227 (or file
228 ;; nil means look for TAGS in current directory.
229 (setq file default-directory))
230 (setq file (expand-file-name file)) 241 (setq file (expand-file-name file))
231 (if (file-directory-p file) 242 (if (file-directory-p file)
232 (expand-file-name "TAGS" file) 243 (expand-file-name "TAGS" file)
233 file)) 244 file))
234 245
246;; Return the cdr of LIST (default: tags-table-list) whose car
247;; is equal to FILE after tags-expand-table-name on both sides.
235(defun tags-table-list-member (file &optional list) 248(defun tags-table-list-member (file &optional list)
236 (or list 249 (or list
237 (setq list tags-table-list)) 250 (setq list tags-table-list))
@@ -242,15 +255,17 @@ file the tag was in."
242 list) 255 list)
243 256
244;; Subroutine of visit-tags-table-buffer. Frobs its local vars. 257;; Subroutine of visit-tags-table-buffer. Frobs its local vars.
245;; Search TABLES for one that has tags for THIS-FILE. 258;; Search TABLES for one that has tags for THIS-FILE. Recurses
246;; Recurses on included tables. 259;; on included tables. Returns the tail of TABLES (or of an
260;; inner included list) whose car is a table listing THIS-FILE.
247(defun tags-table-including (this-file tables &optional recursing) 261(defun tags-table-including (this-file tables &optional recursing)
248 (let ((found nil)) 262 (let ((found nil))
263 ;; Loop over TABLES, looking for one containing tags for THIS-FILE.
249 (while (and (not found) 264 (while (and (not found)
250 tables) 265 tables)
251 (let ((tags-file-name (tags-expand-table-name (car tables)))) 266 (let ((tags-file-name (tags-expand-table-name (car tables))))
252 (if (or (get-file-buffer tags-file-name) 267 (if (or (get-file-buffer tags-file-name)
253 (file-exists-p tags-file-name)) 268 (file-exists-p tags-file-name)) ;XXX check all in core first.
254 (progn 269 (progn
255 ;; Select the tags table buffer and get the file list up to date. 270 ;; Select the tags table buffer and get the file list up to date.
256 (visit-tags-table-buffer 'same) 271 (visit-tags-table-buffer 'same)
@@ -263,6 +278,7 @@ file the tag was in."
263 (setq found tables)) 278 (setq found tables))
264 279
265 ((tags-included-tables) 280 ((tags-included-tables)
281 ;; This table has included tables. Check them.
266 (let ((old tags-table-parent-pointer-list)) 282 (let ((old tags-table-parent-pointer-list))
267 (unwind-protect 283 (unwind-protect
268 (progn 284 (progn
@@ -272,24 +288,35 @@ file the tag was in."
272 ;; collect just the elts from this run. 288 ;; collect just the elts from this run.
273 (setq tags-table-parent-pointer-list nil)) 289 (setq tags-table-parent-pointer-list nil))
274 (setq found 290 (setq found
291 ;; Recurse on the list of included tables.
275 (tags-table-including this-file 292 (tags-table-including this-file
276 tags-included-tables 293 tags-included-tables
277 t)) 294 t))
278 (if found 295 (if found
279 (progn 296 ;; One of them lists THIS-FILE.
280 (setq tags-table-parent-pointer-list 297 ;; Set the table list state variables to move
281 (cons 298 ;; us inside the list of included tables.
282 (cons tags-table-list-pointer 299 (setq tags-table-parent-pointer-list
283 tags-table-list-started-at) 300 (cons
284 tags-table-parent-pointer-list) 301 (cons tags-table-list-pointer
285 tags-table-list-pointer found 302 tags-table-list-started-at)
286 tags-table-list-started-at found 303 tags-table-parent-pointer-list)
287 ;; Don't frob lists later. 304 tags-table-list-pointer found
288 cont 'included)))) 305 tags-table-list-started-at found
306 ;; CONT is a local variable of
307 ;; our caller, visit-tags-table-buffer.
308 ;; Set it so we won't frob lists later.
309 cont 'included)))
289 (or recursing 310 (or recursing
290 ;; Recursive calls have consed onto the front 311 ;; tags-table-parent-pointer-list now describes
291 ;; of the list, so it is now outermost first. 312 ;; the path of included tables taken by recursive
292 ;; We want it innermost first. 313 ;; invocations of this function. The recursive
314 ;; calls have consed onto the front of the list,
315 ;; so it is now outermost first. We want it
316 ;; innermost first, so reverse it. Then append
317 ;; the old list (from before we were called the
318 ;; outermost time), to get the complete current
319 ;; state of included tables.
293 (setq tags-table-parent-pointer-list 320 (setq tags-table-parent-pointer-list
294 (nconc (nreverse 321 (nconc (nreverse
295 tags-table-parent-pointer-list) 322 tags-table-parent-pointer-list)
@@ -301,13 +328,19 @@ file the tag was in."
301 "Select the buffer containing the current tags table. 328 "Select the buffer containing the current tags table.
302If optional arg is t, visit the next table in `tags-table-list'. 329If optional arg is t, visit the next table in `tags-table-list'.
303If optional arg is the atom `same', don't look for a new table; 330If optional arg is the atom `same', don't look for a new table;
304 just select the buffer. 331 just select the buffer visiting `tags-file-name'.
305If arg is nil or absent, choose a first buffer from information in 332If arg is nil or absent, choose a first buffer from information in
306`tags-file-name', `tags-table-list', `tags-table-list-pointer'. 333 `tags-file-name', `tags-table-list', `tags-table-list-pointer'.
307Returns t if it visits a tags table, or nil if there are no more in the list." 334Returns t if it visits a tags table, or nil if there are no more in the list."
308 (cond ((eq cont 'same)) 335
336 ;; Set tags-file-name to the tags table file we want to visit.
337 (cond ((eq cont 'same)
338 ;; Use the ambient value of tags-file-name. Set CONT to nil so the
339 ;; code below will make sure tags-file-name is in tags-table-list.
340 (setq cont nil))
309 341
310 (cont 342 (cont
343 ;; Find the next table.
311 (if (tags-next-table) 344 (if (tags-next-table)
312 ;; Skip over nonexistent files. 345 ;; Skip over nonexistent files.
313 (while (and (let ((file (tags-expand-table-name tags-file-name))) 346 (while (and (let ((file (tags-expand-table-name tags-file-name)))
@@ -316,35 +349,44 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
316 (tags-next-table))))) 349 (tags-next-table)))))
317 350
318 (t 351 (t
352 ;; Pick a table out of our hat.
319 (setq tags-file-name 353 (setq tags-file-name
320 (or (cdr (assq 'tags-file-name (buffer-local-variables))) 354 (or
321 (and default-tags-table-function 355 ;; First, try a local variable.
322 (funcall default-tags-table-function)) 356 (cdr (assq 'tags-file-name (buffer-local-variables)))
323 ;; Look for a tags table that contains 357 ;; Second, try a user-specified function to guess.
324 ;; tags for the current buffer's file. 358 (and default-tags-table-function
325 ;; If one is found, the lists will be frobnicated, 359 (funcall default-tags-table-function))
326 ;; and CONT will be set non-nil so we don't do it below. 360 ;; Third, look for a tags table that contains
327 (let ((found (save-excursion 361 ;; tags for the current buffer's file.
328 (tags-table-including buffer-file-name 362 ;; If one is found, the lists will be frobnicated,
329 tags-table-list)))) 363 ;; and CONT will be set non-nil so we don't do it below.
330 (and found 364 (car (save-excursion (tags-table-including buffer-file-name
331 ;; Expand it so it won't be nil. 365 tags-table-list)))
332 (tags-expand-table-name (car found)))) 366 ;; Fourth, use the user variable tags-file-name, if it is not
333 (tags-expand-table-name (car tags-table-list)) 367 ;; already in tags-table-list.
334 (tags-expand-table-name tags-file-name) 368 (and (not (tags-table-list-member tags-file-name))
335 (expand-file-name 369 tags-file-name)
336 (read-file-name "Visit tags table: (default TAGS) " 370 ;; Fifth, use the user variable giving the table list.
337 default-directory 371 (car tags-table-list)
338 "TAGS" 372 ;; Finally, prompt the user for a file name.
339 t)))))) 373 (expand-file-name
340 374 (read-file-name "Visit tags table: (default TAGS) "
375 default-directory
376 "TAGS"
377 t))))))
378
379 ;; Expand the table name into a full file name.
341 (setq tags-file-name (tags-expand-table-name tags-file-name)) 380 (setq tags-file-name (tags-expand-table-name tags-file-name))
342 381
343 (if (and (eq cont t) (null tags-table-list-pointer)) 382 (if (and (eq cont t) (null tags-table-list-pointer))
344 ;; All out of tables. 383 ;; All out of tables.
345 nil 384 nil
346 385
386 ;; Verify that tags-file-name is a valid tags table.
347 (if (if (get-file-buffer tags-file-name) 387 (if (if (get-file-buffer tags-file-name)
388 ;; The file is already in a buffer. Check for the visited file
389 ;; having changed since we last used it.
348 (let (win) 390 (let (win)
349 (set-buffer (get-file-buffer tags-file-name)) 391 (set-buffer (get-file-buffer tags-file-name))
350 (setq win (or verify-tags-table-function 392 (setq win (or verify-tags-table-function
@@ -358,7 +400,7 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
358 (set-buffer (find-file-noselect tags-file-name)) 400 (set-buffer (find-file-noselect tags-file-name))
359 (or (string= tags-file-name buffer-file-name) 401 (or (string= tags-file-name buffer-file-name)
360 ;; find-file-noselect has changed the file name. 402 ;; find-file-noselect has changed the file name.
361 ;; Propagate change to tags-file-name and tags-table-list. 403 ;; Propagate the change to tags-file-name and tags-table-list.
362 (let ((tail (member file tags-table-list))) 404 (let ((tail (member file tags-table-list)))
363 (if tail 405 (if tail
364 (setcar tail buffer-file-name)) 406 (setcar tail buffer-file-name))
@@ -386,8 +428,8 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
386 tags-file-name (car sets))))) 428 tags-file-name (car sets)))))
387 (setq sets (cdr sets))) 429 (setq sets (cdr sets)))
388 (if sets 430 (if sets
431 ;; Found in some other set. Switch to that set.
389 (progn 432 (progn
390 ;; Found in some other set. Switch to that set.
391 (or (memq tags-table-list tags-table-set-list) 433 (or (memq tags-table-list tags-table-set-list)
392 ;; Save the current list. 434 ;; Save the current list.
393 (setq tags-table-set-list 435 (setq tags-table-set-list
@@ -410,6 +452,8 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
410 (setq tags-table-list (list tags-file-name))) 452 (setq tags-table-list (list tags-file-name)))
411 (setq elt tags-table-list)))) 453 (setq elt tags-table-list))))
412 454
455 ;; Set the tags table list state variables to point at the table
456 ;; we want to use first.
413 (setq tags-table-list-started-at elt 457 (setq tags-table-list-started-at elt
414 tags-table-list-pointer elt))) 458 tags-table-list-pointer elt)))
415 459
@@ -417,8 +461,10 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
417 t) 461 t)
418 462
419 ;; The buffer was not valid. Don't use it again. 463 ;; The buffer was not valid. Don't use it again.
420 (kill-local-variable 'tags-file-name) 464 (let ((file tags-file-name))
421 (setq tags-file-name nil) 465 (kill-local-variable 'tags-file-name)
466 (if (eq file tags-file-name)
467 (setq tags-file-name nil)))
422 (error "File %s is not a valid tags table" buffer-file-name)))) 468 (error "File %s is not a valid tags table" buffer-file-name))))
423 469
424(defun file-of-tag () 470(defun file-of-tag ()
@@ -430,13 +476,15 @@ File name returned is relative to tags table file's directory."
430;;;###autoload 476;;;###autoload
431(defun tags-table-files () 477(defun tags-table-files ()
432 "Return a list of files in the current tags table. 478 "Return a list of files in the current tags table.
479Assumes the tags table is the current buffer.
433File names returned are absolute." 480File names returned are absolute."
434 (or tags-table-files 481 (or tags-table-files
435 (setq tags-table-files 482 (setq tags-table-files
436 (funcall tags-table-files-function)))) 483 (funcall tags-table-files-function))))
437 484
438(defun tags-included-tables () 485(defun tags-included-tables ()
439 "Return a list of tags tables included by the current table." 486 "Return a list of tags tables included by the current table.
487Assumes the tags table is the current buffer."
440 (or tags-included-tables 488 (or tags-included-tables
441 (setq tags-included-tables (funcall tags-included-tables-function)))) 489 (setq tags-included-tables (funcall tags-included-tables-function))))
442 490
@@ -451,10 +499,15 @@ File names returned are absolute."
451 (let ((included (tags-included-tables)) 499 (let ((included (tags-included-tables))
452 (table (funcall tags-completion-table-function))) 500 (table (funcall tags-completion-table-function)))
453 (save-excursion 501 (save-excursion
502 ;; Iterate over the list of included tables, and combine each
503 ;; included table's completion obarray to the parent obarray.
454 (while included 504 (while included
505 ;; Visit the buffer.
455 (let ((tags-file-name (car included))) 506 (let ((tags-file-name (car included)))
456 (visit-tags-table-buffer 'same)) 507 (visit-tags-table-buffer 'same))
508 ;; Recurse in that buffer to compute its completion table.
457 (if (tags-completion-table) 509 (if (tags-completion-table)
510 ;; Combine the tables.
458 (mapatoms (function 511 (mapatoms (function
459 (lambda (sym) 512 (lambda (sym)
460 (intern (symbol-name sym) table))) 513 (intern (symbol-name sym) table)))
@@ -503,9 +556,9 @@ File names returned are absolute."
503 (format "%s(default %s) " string default) 556 (format "%s(default %s) " string default)
504 string) 557 string)
505 'tags-complete-tag))) 558 'tags-complete-tag)))
506 (list (if (equal spec "") 559 (if (equal spec "")
507 (or default (error "There is no default tag")) 560 (or default (error "There is no default tag"))
508 spec)))) 561 spec)))
509 562
510(defvar last-tag nil 563(defvar last-tag nil
511 "Last tag found by \\[find-tag].") 564 "Last tag found by \\[find-tag].")
@@ -526,13 +579,19 @@ If third arg REGEXP-P is non-nil, treat TAGNAME as a regexp.
526See documentation of variable `tags-file-name'." 579See documentation of variable `tags-file-name'."
527 (interactive (if current-prefix-arg 580 (interactive (if current-prefix-arg
528 '(nil t) 581 '(nil t)
529 (find-tag-tag "Find tag: "))) 582 (list (find-tag-tag "Find tag: "))))
583 ;; Save the current buffer's value of `find-tag-hook' before selecting the
584 ;; tags table buffer.
530 (let ((local-find-tag-hook find-tag-hook)) 585 (let ((local-find-tag-hook find-tag-hook))
531 (if next-p 586 (if next-p
587 ;; Find the same table we last used.
532 (visit-tags-table-buffer 'same) 588 (visit-tags-table-buffer 'same)
533 (setq last-tag tagname) 589 ;; Pick a table to use.
534 (visit-tags-table-buffer)) 590 (visit-tags-table-buffer)
591 ;; Record TAGNAME for a future call with NEXT-P non-nil.
592 (setq last-tag tagname))
535 (prog1 593 (prog1
594 ;; find-tag-in-order does the real work.
536 (find-tag-in-order (if next-p last-tag tagname) 595 (find-tag-in-order (if next-p last-tag tagname)
537 (if regexp-p 596 (if regexp-p
538 find-tag-regexp-search-function 597 find-tag-regexp-search-function
@@ -560,7 +619,7 @@ multiple matches, more exact matches are found first.
560See documentation of variable `tags-file-name'." 619See documentation of variable `tags-file-name'."
561 (interactive (if current-prefix-arg 620 (interactive (if current-prefix-arg
562 '(nil t) 621 '(nil t)
563 (find-tag-tag "Find tag: "))) 622 (list (find-tag-tag "Find tag: "))))
564 (switch-to-buffer (find-tag-noselect tagname next-p))) 623 (switch-to-buffer (find-tag-noselect tagname next-p)))
565;;;###autoload (define-key esc-map "." 'find-tag) 624;;;###autoload (define-key esc-map "." 'find-tag)
566 625
@@ -578,8 +637,17 @@ multiple matches, more exact matches are found first.
578See documentation of variable `tags-file-name'." 637See documentation of variable `tags-file-name'."
579 (interactive (if current-prefix-arg 638 (interactive (if current-prefix-arg
580 '(nil t) 639 '(nil t)
581 (find-tag-tag "Find tag other window: "))) 640 (list (find-tag-tag "Find tag other window: "))))
582 (switch-to-buffer-other-window (find-tag-noselect tagname next-p))) 641 ;; This hair is to deal with the case where the tag is found in the
642 ;; selected window's buffer; without the hair, point is moved in both
643 ;; windows. To prevent this, we save the selected window's point before
644 ;; doing find-tag-noselect, and restore it after.
645 (let* ((window-point (window-point (selected-window)))
646 (tagbuf (find-tag-noselect tagname next-p)))
647 (set-window-point (prog1
648 (selected-window)
649 (switch-to-buffer-other-window tagbuf))
650 window-point)))
583;;;###autoload (define-key ctl-x-4-map "." 'find-tag-other-window) 651;;;###autoload (define-key ctl-x-4-map "." 'find-tag-other-window)
584 652
585;;;###autoload 653;;;###autoload
@@ -596,7 +664,7 @@ that matches the tagname used in the previous find-tag.
596See documentation of variable `tags-file-name'." 664See documentation of variable `tags-file-name'."
597 (interactive (if current-prefix-arg 665 (interactive (if current-prefix-arg
598 '(nil t) 666 '(nil t)
599 (find-tag-tag "Find tag other window: "))) 667 (list (find-tag-tag "Find tag other window: "))))
600 (let ((pop-up-frames t)) 668 (let ((pop-up-frames t))
601 (find-tag-other-window tagname next-p))) 669 (find-tag-other-window tagname next-p)))
602;;;###autoload (define-key ctl-x-5-map "." 'find-tag-other-frame) 670;;;###autoload (define-key ctl-x-5-map "." 'find-tag-other-frame)
@@ -614,7 +682,7 @@ If third arg OTHER-WINDOW is non-nil, select the buffer in another window.
614See documentation of variable `tags-file-name'." 682See documentation of variable `tags-file-name'."
615 (interactive (if current-prefix-arg 683 (interactive (if current-prefix-arg
616 '(nil t) 684 '(nil t)
617 (read-string "Find tag regexp: "))) 685 (list (read-string "Find tag regexp: "))))
618 (funcall (if other-window 'switch-to-buffer-other-window 'switch-to-buffer) 686 (funcall (if other-window 'switch-to-buffer-other-window 'switch-to-buffer)
619 (find-tag-noselect regexp next-p t))) 687 (find-tag-noselect regexp next-p t)))
620 688
@@ -657,6 +725,7 @@ See documentation of variable `tags-file-name'."
657 ;; Get a qualified match. 725 ;; Get a qualified match.
658 (catch 'qualified-match-found 726 (catch 'qualified-match-found
659 727
728 ;; Iterate over the list of tags tables.
660 (while (or first-table 729 (while (or first-table
661 (visit-tags-table-buffer t)) 730 (visit-tags-table-buffer t))
662 731
@@ -669,6 +738,7 @@ See documentation of variable `tags-file-name'."
669 (setq first-table nil) 738 (setq first-table nil)
670 739
671 (setq tags-table-file buffer-file-name) 740 (setq tags-table-file buffer-file-name)
741 ;; Iterate over the list of ordering predicates.
672 (while order 742 (while order
673 (while (funcall search-forward-func pattern nil t) 743 (while (funcall search-forward-func pattern nil t)
674 ;; Naive match found. Qualify the match. 744 ;; Naive match found. Qualify the match.
@@ -696,7 +766,7 @@ See documentation of variable `tags-file-name'."
696 (setq file (expand-file-name (file-of-tag)) 766 (setq file (expand-file-name (file-of-tag))
697 tag-info (funcall snarf-tag-function)) 767 tag-info (funcall snarf-tag-function))
698 768
699 ;; Get the local value in the tags table buffer. 769 ;; Get the local value in the tags table buffer before switching buffers.
700 (setq goto-func goto-tag-location-function) 770 (setq goto-func goto-tag-location-function)
701 771
702 ;; Find the right line in the specified file. 772 ;; Find the right line in the specified file.
@@ -716,14 +786,15 @@ See documentation of variable `tags-file-name'."
716 786
717;; `etags' TAGS file format support. 787;; `etags' TAGS file format support.
718 788
789;; If the current buffer is a valid etags TAGS file, give it local values of
790;; the tags table format variables, and return non-nil.
719(defun etags-recognize-tags-table () 791(defun etags-recognize-tags-table ()
720 (and (eq (char-after 1) ?\f) 792 (and (etags-verify-tags-table)
721 ;; It is annoying to flash messages on the screen briefly, 793 ;; It is annoying to flash messages on the screen briefly,
722 ;; and this message is not useful. -- rms 794 ;; and this message is not useful. -- rms
723 ;; (message "%s is an `etags' TAGS file" buffer-file-name) 795 ;; (message "%s is an `etags' TAGS file" buffer-file-name)
724 (mapcar (function (lambda (elt) 796 (mapcar (function (lambda (elt)
725 (make-local-variable (car elt)) 797 (set (make-local-variable (car elt)) (cdr elt))))
726 (set (car elt) (cdr elt))))
727 '((file-of-tag-function . etags-file-of-tag) 798 '((file-of-tag-function . etags-file-of-tag)
728 (tags-table-files-function . etags-tags-table-files) 799 (tags-table-files-function . etags-tags-table-files)
729 (tags-completion-table-function . etags-tags-completion-table) 800 (tags-completion-table-function . etags-tags-completion-table)
@@ -742,6 +813,7 @@ See documentation of variable `tags-file-name'."
742 (verify-tags-table-function . etags-verify-tags-table) 813 (verify-tags-table-function . etags-verify-tags-table)
743 )))) 814 ))))
744 815
816;; Return non-nil iff the current buffer is a valid etags TAGS file.
745(defun etags-verify-tags-table () 817(defun etags-verify-tags-table ()
746 (= (char-after 1) ?\f)) 818 (= (char-after 1) ?\f))
747 819
@@ -866,11 +938,12 @@ See documentation of variable `tags-file-name'."
866 938
867;; Empty tags file support. 939;; Empty tags file support.
868 940
941;; Recognize an empty file and give it local values of the tags table format
942;; variables which do nothing.
869(defun recognize-empty-tags-table () 943(defun recognize-empty-tags-table ()
870 (and (zerop (buffer-size)) 944 (and (zerop (buffer-size))
871 (mapcar (function (lambda (sym) 945 (mapcar (function (lambda (sym)
872 (make-local-variable sym) 946 (set (make-local-variable sym) 'ignore)))
873 (set sym 'ignore)))
874 '(tags-table-files-function 947 '(tags-table-files-function
875 tags-completion-table-function 948 tags-completion-table-function
876 find-tag-regexp-search-function 949 find-tag-regexp-search-function
@@ -882,6 +955,7 @@ See documentation of variable `tags-file-name'."
882 (zerop (buffer-size))))))) 955 (zerop (buffer-size)))))))
883 956
884;;; Match qualifier functions for tagnames. 957;;; Match qualifier functions for tagnames.
958;;; XXX these functions assume etags file format.
885 959
886;; This might be a neat idea, but it's too hairy at the moment. 960;; This might be a neat idea, but it's too hairy at the moment.
887;;(defmacro tags-with-syntax (&rest body) 961;;(defmacro tags-with-syntax (&rest body)
@@ -940,6 +1014,7 @@ if the file was newly read in, the value is the filename."
940 (interactive "P") 1014 (interactive "P")
941 (and initialize 1015 (and initialize
942 (save-excursion 1016 (save-excursion
1017 ;; Visit the tags table buffer to get its list of files.
943 (visit-tags-table-buffer) 1018 (visit-tags-table-buffer)
944 (setq next-file-list (tags-table-files)))) 1019 (setq next-file-list (tags-table-files))))
945 (or next-file-list 1020 (or next-file-list
@@ -1020,7 +1095,6 @@ If the latter returns non-nil, we exit; otherwise we scan the next file."
1020 (and messaged 1095 (and messaged
1021 (null tags-loop-operate) 1096 (null tags-loop-operate)
1022 (message "Scanning file %s...found" buffer-file-name)))) 1097 (message "Scanning file %s...found" buffer-file-name))))
1023
1024;;;###autoload (define-key esc-map "," 'tags-loop-continue) 1098;;;###autoload (define-key esc-map "," 'tags-loop-continue)
1025 1099
1026;;;###autoload 1100;;;###autoload
@@ -1033,7 +1107,7 @@ See documentation of variable `tags-file-name'."
1033 (interactive "sTags search (regexp): ") 1107 (interactive "sTags search (regexp): ")
1034 (if (and (equal regexp "") 1108 (if (and (equal regexp "")
1035 (eq (car tags-loop-scan) 're-search-forward) 1109 (eq (car tags-loop-scan) 're-search-forward)
1036 (eq tags-loop-operate t)) 1110 (null tags-loop-operate))
1037 ;; Continue last tags-search as if by M-,. 1111 ;; Continue last tags-search as if by M-,.
1038 (tags-loop-continue nil) 1112 (tags-loop-continue nil)
1039 (setq tags-loop-scan 1113 (setq tags-loop-scan