hansen@pegasus.UUCP (11/07/84)
< Apparently our 1981 version of 'tags.ml' is not compatible with the current < version of 'ctags', as the format of the tags file is different. For example, < tags.ml expacts to see ^A and ^B as delimiters. < Is there a more recent version of tags.ml around? Any help would be < appreciated. The ctags program does not produce a file which can be used directly by the tags package. The tags file that tags.ml creates is what produces the ^A and ^B characters; the ctags format is totally different. Enclosed below is our most recent version of the tags library plus a macro package to take a tags file created by the ctags program and convert it into a format usable by the tags package. Tony Hansen pegasus!hansen #!/bin/sh # This is a shar archive. # The rest of this file is a shell script which will extract: # tags-pkg.ml ctags.ml # Archive created: Wed Nov 7 13:25:47 EST 1984 echo x - tags-pkg.ml sed 's/^X//' > tags-pkg.ml << '~FUNKY STUFF~' ; Edit 7 ; Fri Jul 16 18:05:28 1982 ; twenex-like tags package J. Gosling, November 81 ; ; A tag file is a sequence of lines of the following forms: ; ^_filename ; ^Atagline^Bposition ; A tagline/position pair refers to the preceeding file (declare-global last-search-tag) (defun (to-tag-buffer (temp-use-buffer "*TAG*") (if (& (= (buffer-size) 0) (= (current-file-name) "")) (progn (if (error-occured (read-file ".tags")) (progn (write-named-file ".tags") (message "New tag file"))) (beginning-of-file))) )) (defun (visit-tag-table tagfn (setq tagfn (arg 1 ": visit-tag-table ")) (save-excursion (temp-use-buffer "*TAG*") (read-file tagfn)) )) (defun (goto-tag fn str pos restart (setq restart 0) (if (! prefix-argument-provided) (progn (setq last-search-tag (concat "\^A[^\^B]*" (quote (arg 1 ": goto-tag ")))) (setq restart 1))) (save-excursion (to-tag-buffer) (if restart (beginning-of-file)) (re-search-forward last-search-tag) (beginning-of-line) (re-search-forward "\^A\\([^\^B]*\\)\^B\\(.*\\)") (region-around-match 1) (setq str (region-to-string)) (region-around-match 2) (setq pos (- (region-to-string) 300)) (save-excursion (re-search-reverse "\^_\\(.*\\)") (region-around-match 1) (setq fn (region-to-string))) ) (visit-file fn) (goto-character pos) (if (error-occured (search-forward str)) (search-reverse "")) (beginning-of-line) (line-to-top-of-window) )) (defun (find-pos-str (beginning-of-line) (setq pos (+ (dot) 0)) (set-mark) (end-of-line) (setq str (region-to-string)))) (defun (store-pos-str (insert-character '^A') (insert-string str) (insert-character '^B') (insert-string pos) (newline))) (defun (add-tag (save-excursion pos str fn (find-pop-str) (setq fn (current-file-name)) (to-tag-buffer) (beginning-of-file) (if (error-occured (re-search-forward (concat "\^_" fn "[^\^_]*"))) (progn (beginning-of-file) (insert-character '^_') (insert-string fn) (newline))) (store-pos-str) (beginning-of-file)))) (defun (add-tag* pos str (find-pos-str) (save-excursion (temp-use-buffer "*TAG*") (store-pos-str)))) (defun (add-all-tags pattern fn (setq pattern (arg 1 ": add-all-tags (pattern) ")) (setq fn (current-file-name)) (save-excursion (to-tag-buffer) (if (error-occured (search-forward (concat "\^_" fn "\n"))) (progn (beginning-of-file) (insert-character '^_') (insert-string fn) (newline)) (progn (set-mark) (while (= (following-char) '^A') (next-line)) (erase-region)) ) ) (save-excursion (error-occured (beginning-of-file) (while 1 (re-search-forward pattern) (add-tag*)))) (novalue) ) ) (defun (add-typed-tags ext pattern (setq ext (substr (current-file-name) -2 2)) (add-all-tags (if (= ext ".l") "^(def" ;(= ext ".c") "^[A-z].*(.*)" ; TLH (| (= ext ".c") (= ext ".h") (= ext ".C") (= ext ".H")) "^[A-z].*(.*)\\|^#[ \t]*define[ \t][ \t]*[A-Za-z_][A-Za-z_]*(" (= ext "ml") "^(defun[ \t\n]*(" (= ext "ss") "@section\\|@chapter\\|@subsection" (= ext ".p") "function\\|procedure" (error (concat "Can't tag " (current-file-name))) ) ) )) (defun (tag-file fn cur-file ; TLH added cur-file (if (is-bound current-file) (setq cur-file current-file) (setq cur-file "")) (setq fn (arg 1 ": tag-file (filename) ")) (message (concat "Tagging " fn)) (save-window-excursion (error-occured (visit-file fn) (add-typed-tags) (if (& (!= cur-file fn) ; TLH (= buffer-is-modified 0)); TLH (delete-buffer fn)) ; TLH )))) (defun (recompute-all-tags current-file ; TLH added current-file (setq current-file (current-file-name)); TLH (save-window-excursion (to-tag-buffer) (beginning-of-file) (error-occured (while 1 (re-search-forward "\^_\\(.*\\)") (region-around-match 1) (tag-file (region-to-string))) ) (write-named-file ".tags")))) (defun (make-tag-table fns current-file ; TLH added current-file (setq fns (arg 1 ": make-tag-table (from filenames) ")) (setq current-file (current-file-name)); TLH (save-window-excursion (temp-use-buffer "*TEMP*") (erase-buffer) (set-mark) (filter-region (concat "ls " fns)) (beginning-of-file) (while (! (eobp)) (set-mark) (end-of-line) (tag-file (region-to-string)) (next-line) (beginning-of-line)) (delete-buffer "*TEMP*") (temp-use-buffer "*TAG*") (write-named-file ".tags")) (novalue) )) (defun (visit-function func (save-window-excursion (forward-character) (backward-word) (set-mark) (forward-word) (setq func (region-to-string)) (goto-tag func) (message "Type ^C to go back") (recursive-edit) ) ) ) ~FUNKY STUFF~ ls -l tags-pkg.ml echo x - ctags.ml sed 's/^X//' > ctags.ml << '~FUNKY STUFF~' ; ctags-to-tags ; - take a file created by the BSD ctags(1) program and change it into the ; format usable by the emacs tags facility. ; ; Tony Hansen, 1983 ; ctags files are made of lines of the form: ; function-name\tfilename\t?regular-expression? ; ; emacs tag files are of the form ; ^_filename ; ^Aregular-expression^Bposition ; (defun (ctags-to-tags tag-file new-tag-file (setq tag-file (arg 1 "Name of ctags file? [tags is default] ")) (if (= tag-file "") (setq tag-file "tags")) (setq new-tag-file (arg 2 "New tag file name [.tags by default] ")) (if (= new-tag-file "") (setq new-tag-file ".tags")) (message "Working....") (sit-for 0) (save-window-excursion (switch-to-buffer "*temp-ctag*") (setq needs-checkpointing 0) (erase-buffer) (insert-file tag-file) ; change over-all format from ; function-name\tfilename\t?regular-expression? ; ... ; into ; ^_filename ; ^A?regular-expression?^Bfunction-name ; ^_filename ; ^A?regular-expression?^Bfunction-name ; ... ; sorted by filenames. (progn (beginning-of-file) (re-replace-string "^\\([^\t]*\\)\t\\([^\t]*\\)\t\\(.*\\)$" "\^_\\2\^A\\3\^B\\1") (set-mark) (end-of-file) (filter-region "sort") (beginning-of-file) (re-replace-string "\\(\^_[^\^A]*\\)\^A" "\\1\n\^A")) ; Get rid of extra file names. ; from ; ^_filename ; ^A?regular-expression?^Bfunction-name ; ^_filename ; ^A?regular-expression?^Bfunction-name ; ... ; into ; ^_filename ; ^A?regular-expression?^Bfunction-name ; ^A?regular-expression?^Bfunction-name ; ^A?regular-expression?^Bfunction-name ; ... (progn last-file current-file (beginning-of-file) (setq last-file "") (while (! (error-occured (search-forward "\^_"))) (set-mark) (end-of-line) (setq current-file (region-to-string)) (if (= current-file last-file) (progn (beginning-of-line) (kill-to-end-of-line) (delete-next-character)) (setq last-file current-file)))) ; Change relative filename references into absolute ones. (progn (beginning-of-file) (re-replace-string "\^_\\([^/]\\)" (concat "\^_" (working-directory) "\\1") )) ; change ctags ?regular-expression? lines into .tags format ; and change function-name into absolute position reference ; ; from ; ^_filename ; ^A?regular-expression?^Bfunction-name ; ^A?regular-expression?^Bfunction-name ; ^A?regular-expression?^Bfunction-name ; ... ; into ; ^_filename ; ^Aregular-expression^Blocation ; ^Aregular-expression^Blocation ; ^Aregular-expression^Blocation ; ... (progn current-file last-file (setq current-file "") (beginning-of-file) (if (! (looking-at "\^_")) (error-message "Missing file name!")) (while (! (eobp)) ; looking at a file name? (if (looking-at "\^_\\(.*\\)") (progn (if (!= current-file "") (save-window-excursion (visit-file current-file) (if (! buffer-is-modified) (delete-buffer (current-buffer-name))))) (region-around-match 1) (setq current-file (region-to-string))) ; looking at a function name? (looking-at "\^A\\([^\^B]*\\)\^B\\(.*\\)") (progn pattern function-name location (region-around-match 1) (setq pattern (region-to-string)) (region-around-match 2) (setq function-name (region-to-string)) ; strip '?^' from beginning and ; strip '$?' from end. (if (= "?" (substr pattern 1 1)) (setq pattern (substr pattern 2 -1))) (if (= "^" (substr pattern 1 1)) (setq pattern (substr pattern 2 -1))) (if (= "?" (substr pattern -1 1)) (setq pattern (substr pattern 1 -1))) (if (= "$" (substr pattern -1 1)) (setq pattern (substr pattern 1 -1))) (save-excursion (visit-file current-file) (if (error-occured (re-search-forward pattern)) (if (error-occured (re-search-reverse pattern)) (if (error-occured (re-search-forward function-name)) (if (error-occured (re-search-reverse function-name)) (error-message "Cannot find " function-name " in " current-file))))) (beginning-of-line) (setq location (+ (dot) 0))) (beginning-of-line) (kill-to-end-of-line) (insert-string (concat "\^A" pattern "\^B" location)) (end-of-line)) (error-message "Mal-formed tags line") ) (error-occured (forward-character)))) (write-named-file new-tag-file)) (delete-buffer "*temp-ctag*") (message "Done!") (novalue) ) ) ~FUNKY STUFF~ ls -l ctags.ml # The following exit is to ensure that extra garbage # after the end of the shar file will be ignored. exit 0
mann@CSL-Vax.ARPA (Tim Mann) (11/08/84)
> Apparently our 1981 version of 'tags.ml' is not compatible with the current > version of 'ctags', as the format of the tags file is different. For example, > tags.ml expacts to see ^A and ^B as delimiters. > Is there a more recent version of tags.ml around? Any help would be > appreciated. Here is a version of tags.ml I hacked up to work with ctags output. (The "ved" mentioned in the comment is an editor that runs on the V-System here at Stanford.) Hope no one minds the length of this posting to net.emacs. ; twenex-like tags package J. Gosling, November 81 ; modified to use ctags files Tim Mann, 9-4-84 ; ; As a hack, I've modified the Emacs tags package to use the "tags" files ; created by the ctags program instead of building its own. This is a win for ; several reasons, the primary one being that ved (and also vi) uses this kind ; of tags file, so you only need one. Another reason is that ctags builds a ; tags file much faster than Emacs can. ; ; To use the modified tags package, add the following to your .emacs_pro file: ; ; (autoload "goto-tag" "ctags.ml") ; (autoload "goto-tag-in-buffer" "ctags.ml") ; (bind-to-key "goto-tag" "\^Xt") ; (bind-to-key "goto-tag-in-buffer" "\^X\^T") ; ; This binds "goto-tag" to ^Xt and "goto-tag-in-buffer" to ^X^T. Goto-tag ; prompts you for the name of a function or typedef, then visits the file ; containing the function or type definition at the first line of the ; definition. If there is more than one object of the same name listed in ; the tags file, ^Xt will find the first one, and repeatedly typing ^U^Xt ; will step through the others. Goto-tag-in-buffer is used when the cursor ; is positioned on or just after the name of a function or type; it finds the ; name in the buffer, then visits the file as in goto-tag. ; ; The first time you use one of these functions, it will look for the tags ; file in the current directory, and if none is found, in your home directory. ; From then on the same tags file will be used until you either exit or call ; the function "visit-tag-table" with a new file name. ; ; When you run ctags, you will probably want to use the switches -tw. This ; causes tags to be generated for typedefs as well as functions, and suppresses ; (useless) warning messages. Both emacs and ved (as of now) understand tags ; on both functions and typedefs. (Macros too, I think.) ; (declare-global last-search-tag) (defun (to-tag-buffer (temp-use-buffer "*TAG*") (if (& (= (buffer-size) 0) (= (current-file-name) "")) (progn (if (error-occured (read-file "tags")) (if (error-occured (read-file "~/tags")) (message "Can't read tags file") ) ) (beginning-of-file) (error-occured (replace-string "*" "\\*")) (setq buffer-is-modified 0) ) ) ) ) (defun (visit-tag-table tagfn (setq tagfn (arg 1 ": visit-tag-table ")) (save-excursion (temp-use-buffer "*TAG*") (read-file tagfn) (error-occured (replace-string "*" "\\*")) (setq buffer-is-modified 0) ) ) ) (defun (goto-tag fn pat restart pos (setq restart 0) (if (! prefix-argument-provided) (progn (setq last-search-tag (concat "^" (quote (arg 1 ": goto-tag ")) "[^\^I]*\^I")) (setq restart 1))) (setq pos -2) (save-excursion (to-tag-buffer) (if restart (beginning-of-file)) (re-search-forward last-search-tag) (set-mark) (search-forward "\^I") (backward-character) (setq fn (region-to-string)) (forward-character) (if (looking-at "/") (progn (forward-character) (set-mark) (end-of-line) (backward-character) (setq pat (region-to-string)) ) (progn (set-mark) (end-of-line) (setq pos (- (region-to-string) 1)) ) ) ) (visit-file fn) (if (= pos -2) (if (error-occured (re-search-forward pat)) (re-search-reverse "") ) (progn (beginning-of-file) (provide-prefix-argument pos (next-line)) ) ) (beginning-of-line) (line-to-top-of-window) )) ; goto-tag-in-buffer ; Similar to describe-word-in-buffer (defun (goto-tag-in-buffer (error-occured (forward-character)) (backward-word) (set-mark) (forward-word) (goto-tag (region-to-string)) ) )
grayson@uiucuxc.UUCP (11/08/84)
Thanks - I've learned that ctags is not part of the tags package, and that tags has a routine to make the tags table.
robert@gitpyr.UUCP (Robert Viduya) (11/09/84)
> Apparently our 1981 version of 'tags.ml' is not compatible with the current > version of 'ctags', as the format of the tags file is different. For example, > tags.ml expacts to see ^A and ^B as delimiters. > Is there a more recent version of tags.ml around? Any help would be > appreciated. For some strange reason, I thought ctags was written for vi, not emacs. -- Robert Viduya Office of Computing Services Georgia Institute of Technology, Atlanta GA 30332 Phone: (404) 894-4669 ...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!robert ...!{rlgvax,sb1,uf-cgrl,unmvax,ut-sally}!gatech!gitpyr!robert
grayson@uiucuxc.UUCP (11/13/84)
Apparently our 1981 version of 'tags.ml' is not compatible with the current version of 'ctags', as the format of the tags file is different. For example, tags.ml expacts to see ^A and ^B as delimiters. Is there a more recent version of tags.ml around? Any help would be appreciated.