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 0mann@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.