comparison lisp/progmodes/etags.el @ 10661:32beb7b6dbf7

Changes to support filenames as tags too and provided a drop-in replacement for list-tags. (find-tag-noselect): Recognize filenames as valid tags too. (find-tag-file-order): New variable holds function to check for match for a file name used as a tag. (last-tag-file): New variable; stores the filename looked for via find-tag family of functions. (find-tag-in-order): If the tag is a file name, position at file beg. (etags-recognize-tags-table): Added new var find-tag-file-order to tags-table-format variables. Added tag-filename-match-p to the list for find-tag-tag-order. (tag-filename-match-p): New function. (list-tags): Rewritten for speed. (tags-list-functions-in-file): New subroutine for list-tags. (tags-locate-file-in-tags-table): New function locates a file in `tags-table-list'.
author Richard M. Stallman <rms@gnu.org>
date Sun, 05 Feb 1995 00:25:16 +0000
parents b58df8437ea1
children 69cbb0d5671d
comparison
equal deleted inserted replaced
10660:0501556eef3a 10661:32beb7b6dbf7
134 (defvar snarf-tag-function nil 134 (defvar snarf-tag-function nil
135 "Function to get info about a matched tag for `goto-tag-location-function'.") 135 "Function to get info about a matched tag for `goto-tag-location-function'.")
136 (defvar goto-tag-location-function nil 136 (defvar goto-tag-location-function nil
137 "Function of to go to the location in the buffer specified by a tag. 137 "Function of to go to the location in the buffer specified by a tag.
138 One argument, the tag info returned by `snarf-tag-function'.") 138 One argument, the tag info returned by `snarf-tag-function'.")
139 (defvar find-tag-file-order nil
140 "Function which checks for complete and correct match, for file name as tag.")
139 (defvar find-tag-regexp-search-function nil 141 (defvar find-tag-regexp-search-function nil
140 "Search function passed to `find-tag-in-order' for finding a regexp tag.") 142 "Search function passed to `find-tag-in-order' for finding a regexp tag.")
141 (defvar find-tag-regexp-tag-order nil 143 (defvar find-tag-regexp-tag-order nil
142 "Tag order passed to `find-tag-in-order' for finding a regexp tag.") 144 "Tag order passed to `find-tag-in-order' for finding a regexp tag.")
143 (defvar find-tag-regexp-next-line-after-failure-p nil 145 (defvar find-tag-regexp-next-line-after-failure-p nil
193 current-prefix-arg)) 195 current-prefix-arg))
194 (or (stringp file) (signal 'wrong-type-argument (list 'stringp file))) 196 (or (stringp file) (signal 'wrong-type-argument (list 'stringp file)))
195 ;; Bind tags-file-name so we can control below whether the local or 197 ;; Bind tags-file-name so we can control below whether the local or
196 ;; global value gets set. Calling visit-tags-table-buffer will 198 ;; global value gets set. Calling visit-tags-table-buffer will
197 ;; initialize a buffer for the file and set tags-file-name to the 199 ;; initialize a buffer for the file and set tags-file-name to the
200 ;; Calling visit-tags-table-buffer with tags-file-name set to FILE will
201 ;; initialize a buffer for FILE and set tags-file-name to the
198 ;; fully-expanded name. 202 ;; fully-expanded name.
199 (let ((tags-file-name file)) 203 (let ((tags-file-name file))
200 (save-excursion 204 (save-excursion
201 (or (visit-tags-table-buffer file) 205 (or (visit-tags-table-buffer file)
202 (signal 'file-error (list "Visiting tags table" 206 (signal 'file-error (list "Visiting tags table"
710 (interactive (find-tag-interactive "Find tag: ")) 714 (interactive (find-tag-interactive "Find tag: "))
711 715
712 (setq find-tag-history (cons tagname find-tag-history)) 716 (setq find-tag-history (cons tagname find-tag-history))
713 ;; Save the current buffer's value of `find-tag-hook' before selecting the 717 ;; Save the current buffer's value of `find-tag-hook' before selecting the
714 ;; tags table buffer. 718 ;; tags table buffer.
715 (let ((local-find-tag-hook find-tag-hook)) 719 (let ((local-find-tag-hook find-tag-hook)
720 (search-tag))
716 (if (eq '- next-p) 721 (if (eq '- next-p)
717 ;; Pop back to a previous location. 722 ;; Pop back to a previous location.
718 (if (null tags-location-stack) 723 (if (null tags-location-stack)
719 (error "No previous tag locations") 724 (error "No previous tag locations")
720 (let ((marker (car tags-location-stack))) 725 (let ((marker (car tags-location-stack)))
736 ;; Record TAGNAME for a future call with NEXT-P non-nil. 741 ;; Record TAGNAME for a future call with NEXT-P non-nil.
737 (setq last-tag tagname)) 742 (setq last-tag tagname))
738 ;; Record the location so we can pop back to it later. 743 ;; Record the location so we can pop back to it later.
739 (let ((marker (make-marker))) 744 (let ((marker (make-marker)))
740 (save-excursion 745 (save-excursion
746 (setq search-tag (if next-p last-tag tagname))
741 (set-buffer 747 (set-buffer
742 ;; find-tag-in-order does the real work. 748 ;; find-tag-in-order does the real work.
743 (find-tag-in-order 749 (find-tag-in-order
744 (if next-p last-tag tagname) 750 (if next-p last-tag tagname)
745 (if regexp-p 751 (if regexp-p
746 find-tag-regexp-search-function 752 find-tag-regexp-search-function
747 find-tag-search-function) 753 find-tag-search-function)
748 (if regexp-p 754 (if regexp-p
749 find-tag-regexp-tag-order 755 find-tag-regexp-tag-order
750 find-tag-tag-order) 756 (if (string-match "\\b.*\\.\\w*" search-tag)
757 find-tag-file-order
758 find-tag-tag-order))
751 (if regexp-p 759 (if regexp-p
752 find-tag-regexp-next-line-after-failure-p 760 find-tag-regexp-next-line-after-failure-p
753 find-tag-next-line-after-failure-p) 761 find-tag-next-line-after-failure-p)
754 (if regexp-p "matching" "containing") 762 (if regexp-p "matching" "containing")
755 (not next-p))) 763 (not next-p)))
879 tag-info ;where to find the tag in FILE 887 tag-info ;where to find the tag in FILE
880 tags-table-file ;name of tags file 888 tags-table-file ;name of tags file
881 (first-table t) 889 (first-table t)
882 (tag-order order) 890 (tag-order order)
883 goto-func 891 goto-func
892 match-type
884 ) 893 )
885 (save-excursion 894 (save-excursion
886 (or first-search ;find-tag-noselect has already done it. 895 (or first-search ;find-tag-noselect has already done it.
887 (visit-tags-table-buffer 'same)) 896 (visit-tags-table-buffer 'same))
888 897
889 ;; Get a qualified match. 898 ;; Get a qualified match.
890 (catch 'qualified-match-found 899 (setq match-type
900 (catch 'qualified-match-found
891 901
892 ;; Iterate over the list of tags tables. 902 ;; Iterate over the list of tags tables.
893 (while (or first-table 903 (while (or first-table
894 (visit-tags-table-buffer t)) 904 (visit-tags-table-buffer t))
895 905
897 (setq tag-lines-already-matched nil)) 907 (setq tag-lines-already-matched nil))
898 908
899 (and first-search first-table 909 (and first-search first-table
900 ;; Start at beginning of tags file. 910 ;; Start at beginning of tags file.
901 (goto-char (point-min))) 911 (goto-char (point-min)))
912 (or first-table
913 (goto-char (point-min)))
914
902 (setq first-table nil) 915 (setq first-table nil)
903 916
904 (setq tags-table-file buffer-file-name) 917 (setq tags-table-file buffer-file-name)
905 ;; Iterate over the list of ordering predicates. 918 ;; Iterate over the list of ordering predicates.
906 (while order 919 (while order
918 (setq order (cdr order)) 931 (setq order (cdr order))
919 (goto-char (point-min))) 932 (goto-char (point-min)))
920 (setq order tag-order)) 933 (setq order tag-order))
921 ;; We throw out on match, so only get here if there were no matches. 934 ;; We throw out on match, so only get here if there were no matches.
922 (error "No %stags %s %s" (if first-search "" "more ") 935 (error "No %stags %s %s" (if first-search "" "more ")
923 matching pattern)) 936 matching pattern)))
924 937
925 ;; Found a tag; extract location info. 938 ;; Found a tag; extract location info.
926 (beginning-of-line) 939 (beginning-of-line)
927 (setq tag-lines-already-matched (cons (point) 940 (setq tag-lines-already-matched (cons (point)
928 tag-lines-already-matched)) 941 tag-lines-already-matched))
935 948
936 ;; Find the right line in the specified file. 949 ;; Find the right line in the specified file.
937 (set-buffer (find-file-noselect file)) 950 (set-buffer (find-file-noselect file))
938 (widen) 951 (widen)
939 (push-mark) 952 (push-mark)
940 (funcall goto-func tag-info) 953 (if (eq match-type 'tag-filename-match-p)
954 (goto-char (point-min))
955 (funcall goto-func tag-info))
941 956
942 ;; Return the buffer where the tag was found. 957 ;; Return the buffer where the tag was found.
943 (current-buffer)))) 958 (current-buffer))))
944 959
945 ;; `etags' TAGS file format support. 960 ;; `etags' TAGS file format support.
960 (goto-tag-location-function . etags-goto-tag-location) 975 (goto-tag-location-function . etags-goto-tag-location)
961 (find-tag-regexp-search-function . re-search-forward) 976 (find-tag-regexp-search-function . re-search-forward)
962 (find-tag-regexp-tag-order . (tag-re-match-p)) 977 (find-tag-regexp-tag-order . (tag-re-match-p))
963 (find-tag-regexp-next-line-after-failure-p . t) 978 (find-tag-regexp-next-line-after-failure-p . t)
964 (find-tag-search-function . search-forward) 979 (find-tag-search-function . search-forward)
965 (find-tag-tag-order . (tag-exact-match-p 980 (find-tag-tag-order . (tag-filename-match-p
981 tag-exact-match-p
966 tag-symbol-match-p 982 tag-symbol-match-p
967 tag-word-match-p 983 tag-word-match-p
968 tag-any-match-p)) 984 tag-any-match-p))
985 (find-tag-file-order . (tag-filename-match-p))
969 (find-tag-next-line-after-failure-p . nil) 986 (find-tag-next-line-after-failure-p . nil)
970 (list-tags-function . etags-list-tags) 987 (list-tags-function . etags-list-tags)
971 (tags-apropos-function . etags-tags-apropos) 988 (tags-apropos-function . etags-tags-apropos)
972 (tags-included-tables-function . etags-tags-included-tables) 989 (tags-included-tables-function . etags-tags-included-tables)
973 (verify-tags-table-function . etags-verify-tags-table) 990 (verify-tags-table-function . etags-verify-tags-table)
1195 (defun tag-word-match-p (tag) 1212 (defun tag-word-match-p (tag)
1196 (and (looking-at "\\b.*\177") 1213 (and (looking-at "\\b.*\177")
1197 (save-excursion (backward-char (1+ (length tag))) 1214 (save-excursion (backward-char (1+ (length tag)))
1198 (looking-at "\\b")))) 1215 (looking-at "\\b"))))
1199 1216
1217 (defun tag-filename-match-p (tag)
1218 (and (looking-at ",")
1219 (save-excursion (backward-char (1+ (length tag)))
1220 (looking-at "\\b"))))
1221
1200 ;; t if point is in a tag line with a tag containing TAG as a substring. 1222 ;; t if point is in a tag line with a tag containing TAG as a substring.
1201 (defun tag-any-match-p (tag) 1223 (defun tag-any-match-p (tag)
1202 (looking-at ".*\177")) 1224 (looking-at ".*\177"))
1203 1225
1204 ;; t if point is at a tag line that matches RE as a regexp. 1226 ;; t if point is at a tag line that matches RE as a regexp.
1359 '(goto-char (match-beginning 0)))) 1381 '(goto-char (match-beginning 0))))
1360 tags-loop-operate (list 'perform-replace from to t t delimited)) 1382 tags-loop-operate (list 'perform-replace from to t t delimited))
1361 (tags-loop-continue (or file-list-form t))) 1383 (tags-loop-continue (or file-list-form t)))
1362 1384
1363 ;;;###autoload 1385 ;;;###autoload
1364 (defun list-tags (file) 1386 (defun list-tags (filename &optional next-match)
1365 "Display list of tags in file FILE. 1387 "Gives the list of functions available in file \"filename\"
1366 FILE should not contain a directory specification." 1388 Searches only in \"tags-file-name\"."
1367 (interactive (list (completing-read "List tags in file: " 1389 (interactive "sFunctions in File: ")
1368 (save-excursion 1390 (let (file-list)
1369 (visit-tags-table-buffer) 1391 (setq file-list (tags-locate-file-in-tags-table filename
1370 (mapcar 'list 1392 (if next-match next-match nil)))
1371 (mapcar 'file-name-nondirectory 1393 (if file-list
1372 (tags-table-files)))) 1394 (if (cdr file-list)
1373 nil t nil))) 1395 (select-tags-matched-file file-list 'extract-pos-and-tag-from-sel
1374 (with-output-to-temp-buffer "*Tags List*" 1396 'select-file-quit)
1375 (princ "Tags in file ") 1397 (tags-list-functions-in-file (nth 1 (car file-list))
1376 (princ file) 1398 (nth 2 (car file-list))))
1377 (terpri) 1399 (message (format "%s not found in tags table" filename)))))
1378 (save-excursion
1379 (let ((first-time t)
1380 (gotany nil))
1381 (while (visit-tags-table-buffer (not first-time))
1382 (setq first-time nil)
1383 (if (funcall list-tags-function file)
1384 (setq gotany t)))
1385 (or gotany
1386 (error "File %s not in current tags tables" file))))))
1387 1400
1388 ;;;###autoload 1401 ;;;###autoload
1389 (defun tags-apropos (regexp) 1402 (defun tags-apropos (regexp)
1390 "Display list of all tags in tags table REGEXP matches." 1403 "Display list of all tags in tags table REGEXP matches."
1391 (interactive "sTags apropos (regexp): ") 1404 (interactive "sTags apropos (regexp): ")
1529 (all-completions pattern 'tags-complete-tag nil))) 1542 (all-completions pattern 'tags-complete-tag nil)))
1530 (message "Making completion list...%s" "done"))))) 1543 (message "Making completion list...%s" "done")))))
1531 1544
1532 ;;;###autoload (define-key esc-map "\t" 'complete-tag) 1545 ;;;###autoload (define-key esc-map "\t" 'complete-tag)
1533 1546
1547 (defun tags-list-functions-in-file (pos tag-file)
1548 "Lists the functions for the given file. Backend for `list-tags'."
1549 (let ((tag-buf (find-file-noselect tag-file))
1550 (result-buf (get-buffer-create "*Tags Function List*"))
1551 function
1552 beg
1553 map)
1554 (save-excursion
1555 (set-buffer result-buf)
1556 (erase-buffer)
1557 (set-buffer tag-buf)
1558 (goto-char pos)
1559 (forward-line 1)
1560 (beginning-of-line)
1561 ; C-l marks end of information of a file in TAGS.
1562 (while (and (not (looking-at "^\C-l")) (not (eobp)))
1563 ; skip mere #defines, typedefs and struct definitions
1564 (if (not (or (looking-at "^#define\\s-+[a-zA-Z0-9_]+\\s-+")
1565 (looking-at "^typedef\\s-+")
1566 (looking-at "^\\s-*}")))
1567 (progn
1568 (setq beg (point))
1569 (skip-chars-forward "^\C-?(")
1570 (setq function (buffer-substring beg (point)))
1571 (save-excursion
1572 (set-buffer result-buf)
1573 (insert (concat function "\n")))))
1574 (forward-line 1)
1575 (beginning-of-line)))
1576 (switch-to-buffer "*Tags Function List*")
1577 (goto-char 1)
1578 (set-buffer-modified-p nil)
1579 (setq buffer-read-only t)))
1580
1581 (defun tags-locate-file-in-tags-table (filename first-search)
1582 "This function is used to locate `filename' in `tags-table-list'.
1583 Its internally used by the functions `find-file-from-tags' and
1584 `tags-list-tags-in-file'. If `first-search' is t, search continues from where
1585 it left off last time. Else, its a fresh search."
1586 (let (tag-list current-tags-buffer beg file found-file-list next-tag-file)
1587 (setq tag-list tags-table-list)
1588 (catch 'found-file
1589 (setq found-file-list nil
1590 next-tag-file nil)
1591 (while tag-list
1592 (setq current-tags-buffer (find-file-noselect (car tag-list)))
1593 (save-excursion
1594 (set-buffer current-tags-buffer)
1595 (if (or next-tag-file
1596 (not first-search))
1597 (goto-char (point-min)))
1598 (if (search-forward filename nil t)
1599 (if (tag-filename-match-p filename)
1600 (progn
1601 (beginning-of-line)
1602 (setq beg (point))
1603 (skip-chars-forward "^,")
1604 (or (looking-at ",include$")
1605 (setq file (expand-file-name (buffer-substring beg
1606 (point)))))
1607 (if (string-match filename (file-name-nondirectory file))
1608 (progn
1609 (setq found-file-list (cons (list file (point)
1610 (buffer-file-name))
1611 found-file-list))
1612 (throw 'found-file found-file-list))))))
1613 (setq tag-list (cdr tag-list))
1614 (setq next-tag-file 't)))
1615 (throw 'found-file found-file-list))))
1616
1534 (provide 'etags) 1617 (provide 'etags)
1535 1618
1536 ;;; etags.el ends here 1619 ;;; etags.el ends here