diff options
| author | Roland McGrath | 1992-12-21 19:08:50 +0000 |
|---|---|---|
| committer | Roland McGrath | 1992-12-21 19:08:50 +0000 |
| commit | b6176f6493b475bb44fa39bb812f47cf1df5c617 (patch) | |
| tree | a27975b11c6311c356d836f521fad6281eaeab76 | |
| parent | a42a43055f9f5b882f1d2b8aad483fe1f37100c6 (diff) | |
| download | emacs-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.el | 320 |
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. |
| 29 | To switch to a new tags table, setting this variable is sufficient. | 29 | To switch to a new tags table, setting this variable is sufficient. |
| 30 | If you set this variable, do not also set `tags-table-list'. | ||
| 30 | Use the `etags' program to make a tags table file.") | 31 | Use 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. |
| 36 | Elements that are directories mean the file \"TAGS\" in that directory. | 39 | An element that is a directory means the file \"TAGS\" in that directory. |
| 37 | An element of nil means to look for a file \"TAGS\" in the current directory. | 40 | To switch to a new list of tags tables, setting this variable is sufficient. |
| 38 | Use `visit-tags-table-buffer' to cycle through tags tables in this list.") | 41 | If you set this variable, do not also set `tags-file-name'. |
| 42 | Use 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) |
| 140 | Returns 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. |
| 302 | If optional arg is t, visit the next table in `tags-table-list'. | 329 | If optional arg is t, visit the next table in `tags-table-list'. |
| 303 | If optional arg is the atom `same', don't look for a new table; | 330 | If 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'. |
| 305 | If arg is nil or absent, choose a first buffer from information in | 332 | If 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'. |
| 307 | Returns t if it visits a tags table, or nil if there are no more in the list." | 334 | Returns 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. |
| 479 | Assumes the tags table is the current buffer. | ||
| 433 | File names returned are absolute." | 480 | File 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. |
| 487 | Assumes 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. | |||
| 526 | See documentation of variable `tags-file-name'." | 579 | See 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. | |||
| 560 | See documentation of variable `tags-file-name'." | 619 | See 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. | |||
| 578 | See documentation of variable `tags-file-name'." | 637 | See 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. | |||
| 596 | See documentation of variable `tags-file-name'." | 664 | See 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. | |||
| 614 | See documentation of variable `tags-file-name'." | 682 | See 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 |