[comp.emacs] ada tags support under gnuemacs

leake@cme-durer.ARPA (Stephe Leake) (03/08/88)

We are using the Verdix compiler on a Sun Unix system. Verdix provides
the command a.tags, which generates a tags file, using ctags format. I
would like to be able to use these tags from within gnuemacs, but that
editor only supports its own tags formats. Does anyone have a gnuemacs
utility for reading a ctags file?

Thanks
-- 
NAME:   Stephe Leake                    TELE: (301) 975-3431
USMAIL: National Bureau of Standards    ARPA: leake@cme-durer.arpa
        Rm. B-124, Bldg. 220            UUCP: uunet!cme-durer!leake
        Gaithersburg, MD  20899

jd@ncrsecp.Copenhagen.NCR.dk (Jesper Dybdal) (03/10/88)

In article <249@conky.cme-durer.ARPA>, leake@cme-durer.ARPA (Stephe Leake)
writes:
> Does anyone have a gnuemacs utility for reading a ctags file?

Yes, here it is.  It works under Emacs 17.57, and probably all newer
versions.  Set up an autoload of the functions "vi-tag" and
"set-vi-tag-file" and bind some key sequence to "vi-tag".

- - - - - - - - vi-tags.el  - - - - - - - - - - - cut here - - - - - - - -
;; The following functions implement a tag mechanism using vi-compatible
;; tag files.
;; jd 87-06-24.

;; Fixed to not clobber case-fold-search of the buffer that vi-tag is called
;; in.  jd 87-08-07.
;; Added buffer-flush-undo in get-vi-tag-buffer.  jd 87-11-27.
;; Added "(widen)" in the buffer for the file found.  jd 88-02-15.

(provide 'vi-tags)

(defvar vi-tag-file-name "tags"		; also declared in "secp.el"
	"*The name of the file to be used as a vi-like tags file.  The initial
value is \"tags\".  The value is replaced by a fully expanded file name
when vi-tag (\\[vi-tag]) or set-vi-tag-file (\\[set-vi-tag-file]) is called
for the first time.
jd 87-06-23.")

(defvar last-vi-tag nil)


(defun vi-tag (name)
	"Find the tag NAME using a vi-like tags file.  NAME is a regular
expression that must match the complete tag.
jd 88-02-15."
   (interactive (list (read-string "Tag: " last-vi-tag)))
   (let (file direction line dollar)
	(save-excursion
		(get-vi-tag-buffer)
		(if (string-equal name "")
			(setq name (or	last-vi-tag
					(error "No tag specified")))
			(setq last-vi-tag name))
		(if (and current-vi-tag-file-name
			 (string-equal current-vi-tag-file-name
				vi-tag-file-name)
			 (file-exists-p vi-tag-file-name)
			 (equal (nth 5 (file-attributes vi-tag-file-name))
			 	current-vi-tag-modif))
		   nil	;; Buffer contents are ok
		   	;; Read in a tag file:
			(while (not (file-exists-p vi-tag-file-name))
			   (and noninteractive
			        (error	"Tag file \"%s\" does not exist"
			       		vi-tag-file-name))
			   (ding)
			   (setq
			      vi-tag-file-name
			            (read-file-name
				  "Tag file does not exist - enter tag file: "
					nil
					"tags"
					t))
			   (fix-vi-tag-name))
		    	(message "Reading tag file \"%s\"" vi-tag-file-name)
			(sit-for 1)
			(setq current-vi-tag-file-name nil  ; no file in buffer
			      buffer-read-only nil)
			(erase-buffer)
			(insert-file-contents vi-tag-file-name nil)
			; ctags escapes backslashes and slashes in
			; the search strings - remove the escapes:
			(goto-char (point-min))
		  	(while (re-search-forward "\\\\\\([/\\]\\)" nil t)
				(replace-match "\\1" t nil))
			(set-buffer-modified-p nil)
			(setq buffer-read-only t
			      current-vi-tag-modif
			 	(nth 5 (file-attributes vi-tag-file-name))
			      current-vi-tag-file-name vi-tag-file-name)
		)
		(let ((str
			(concat "^" name
				;;  \1=file name     \2=[/?]     \3=line
				"\t\\([^\t\n ]*\\)\t\\([/?]\\)\\^\\(.*\\)\\2$"
			))
	   	      (case-fold-search nil))
			(message "Searching for \"%s\"" name) (sit-for 0)
			(goto-char (point-min))
			;  (message "%s" str) (sit-for 3)
		  	(or (re-search-forward str nil t)
			  (let ((case-fold-search t))
				(goto-char (point-min))
			  	(or (re-search-forward str nil t)
				    (error "Cannot find tag \"%s\"" name))))
			; expand file name in directory of tag file:
			(setq file (expand-file-name
					(buffer-match-substring 1)))
			(setq direction (buffer-match-substring 2))
			(setq line (buffer-match-substring 3))
			(if (string-match "^\\(.*\\)\\$$"  line)
				(setq dollar "$"	; trailing "$"
				      line (substring line 0 (match-end 1)))
				(setq dollar ""))	; no trailing "$"
			; (message "f=%s di=%s l=%s d=%s"
			;	file direction line dollar) (sit-for 2)
		)
	)	; end of save-excursion
	(or (file-exists-p file)
	    (error "File \"%s\" does not exist" file))
	(message "")	;; remove "searching for..." message
	(if (and (buffer-file-name)
		 (string-equal (buffer-file-name) file))
	  (push-mark)
	  (find-file file))
	(widen)			; jd 88-02-15
	(let ((str (concat "^" (regexp-quote line) dollar))
	      (case-fold-search nil))
	;  (message "%s" str) (sit-for 3)
	  (if (string-equal direction "/")
		(progn		; search forward
			(goto-char (point-min))
			(re-search-forward str))
		(progn		; search backward
			(goto-char (point-max))
			(re-search-backward str)))
	  (beginning-of-line)
	  (recenter 0))))



(defun set-vi-tag-file (file-name)
   "Set the name of the file to be used by the vi-tag function to FILE-NAME.
jd 87-06-16."
	(interactive
	    (list (let ((firsttime t)
	    		; create local versions of default-directory and
			; vi-tag-file-name to be used by fix-vi-tag-name:
	    		(default-directory default-directory)
			vi-tag-file-name)
			(while (or firsttime
				   (not (file-exists-p vi-tag-file-name)))
			   (or firsttime (ding))
			   (setq
			      vi-tag-file-name
			        (read-file-name
				   (if firsttime
				     "Tag file for vi-tag: "
				     "File does not exist - enter tag file: ")
				   nil
				   "tags"
				   t)
			      firsttime nil)
			   (fix-vi-tag-name))
		      	vi-tag-file-name)))
	(setq vi-tag-file-name file-name)
	(save-excursion (get-vi-tag-buffer))	; fix names
	(message "Tag file is \"%s\"" vi-tag-file-name))


(defun get-vi-tag-buffer ()
	(set-buffer (get-buffer-create "*vi-tags*"))
	(bury-buffer (current-buffer))
	(buffer-flush-undo (current-buffer))
	(auto-save-mode -1)
	(set-visited-file-name nil)
	; The following buffer-local variables contain the full path name
	; and last modification time of the tag file that the buffer contains.
	; If the buffer does not contain a valid tag file,
	; current-vi-tag-file-name is nil and current-vi-tag-modif is garbage.
	(make-local-variable 'current-vi-tag-file-name)
	(make-local-variable 'current-vi-tag-modif)
	(widen)
	(fix-vi-tag-name))

(defun fix-vi-tag-name ()
	; This function does the following:
	;  - append "tags" to vi-tag-file-name if it is
	;	the name of a directory (relative to default-directory).
	;  - if vi-tag-file-name is an absolute name:
	;	set default-directory from it;
	;  - otherwise:
	;	expand vi-tag-file-name using the current value of
	;	default-directory.
	(while (file-directory-p vi-tag-file-name)
	    	(setq vi-tag-file-name
			(concat vi-tag-file-name
				(if (string-match "/$" vi-tag-file-name)
					"tags"
					"/tags"))))
	(setq	vi-tag-file-name  (expand-file-name vi-tag-file-name)
	      	default-directory (file-name-directory vi-tag-file-name)))
- - - - - - - - end of vi-tags.el - - - - - - - - cut here - - - - - - - -
-- 
Jesper Dybdal                          Jesper.Dybdal@Copenhagen.NCR.dk
NCR Corporation                        Jesper.Dybdal@Copenhagen.NCR.com
Systems Engineering - Copenhagen       ...!mcvax!diku!ncrsecp!jesper.dybdal

jd@ncrsecp.Copenhagen.NCR.dk (Jesper Dybdal) (03/17/88)

In article <954@ncrsecp.Copenhagen.NCR.dk>, I write:
> In article <249@conky.cme-durer.ARPA>, leake@cme-durer.ARPA (Stephe Leake)
> writes:
> > Does anyone have a gnuemacs utility for reading a ctags file?
> 
> Yes, here it is.
> ...

However, I forgot that vi-tag uses a function which is in pure Lisp at
our site - sorry.  To make it work, please add the following simple
function definition to vi-tags.el:

(defun buffer-match-substring (n)
	"Returns (buffer-substring (match-beginning n) (match-end n))).
jd 87-06-23."
	(buffer-substring (match-beginning n) (match-end n)))

-- 
Jesper Dybdal                          Jesper.Dybdal@Copenhagen.NCR.dk
NCR Corporation                        Jesper.Dybdal@Copenhagen.NCR.com
Systems Engineering - Copenhagen       ...!mcvax!diku!ncrsecp!jesper.dybdal