Mercurial > emacs
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 |