% -*-LaTeX-*- % TECOTAGS.LTX.37, 27-Sep-86 19:30:57, Edit by BEEBE % TECOTAGS.LTX.35, 30-May-86 11:06:37, Edit by BEEBE % This is part of TECO.LTX Although keeping a document or program in a single large file during writing and development is convenient for editing and searching, it is an invitation to disaster, particularly under an operating system which does not support multiple file generations like the \TWENTY{} does. However, splitting the work up into multiple files makes it hard to constantly jump back and forth between them. The \TAGS{} package was developed in \EMACS{} to deal with this. It uses a special file of keywords, or tags, which additionally contains the name of the file, and if possible, the approximate position the tag is found in the file. A \EC{goto-tag} command bound to a convenient key prompts for a tag, then searches for it in the relatively small tags file kept in a permanent edit buffer, extracts the filename, visits it in a new buffer if necessary, positions to the tag, and finally selects the buffer in the current window. This is marginally less convenient than an incremental search, since the prompt waits for a complete string, but the response can be quite rapid. Having the approximate tag position available speeds the search even further. The tags file is created outside the editor by a separate program, which has some notion of how to deal with files containing assorted programming languages and document formatters. The \TWENTY{} version is written entirely in assembly language. For \EPSILON{}, I decided to take a different approach. Initially, I wrote a small program, \TX{ctags.c}, which recognizes macro definitions and function headers and outputs a tags file containing the complete line for each such match, along with the file name and byte position within the file. However, it seemed wise to make this format similar to the output of the {\sc unix} {\sc egrep} \INDEX{\sf egrep}{egrep} utility which is available on many systems, and for which several public domain versions have been published in personal computer magazines. {\sc egrep} outputs lines of the form \begin{verbatim} filename:matchingline filename:linenumber:matchingline \end{verbatim} in response to a regular expression given on the command line. For example, regular expressions that might be suitable for identifying routine headers in {\sc fortran} programs could be \begin{verbatim*} ^ [ ]*BLOCK[ ]*DATA ^ [ ]*CHARACTER[ ]*FUNCTION ^ [ ]*COMPLEX[ ]*FUNCTION ^ [ ]*DOUBLE[ ]*PRECISION[ ]*FUNCTION ^ [ ]*INTEGER[ ]*FUNCTION ^ [ ]*LOGICAL[ ]*FUNCTION ^ [ ]*PROGRAM ^ [ ]*REAL[ ]*FUNCTION ^ [ ]*SUBROUTINE[ ]* \end{verbatim*} It does not matter much if a few extra lines get matched and inserted in the tags file this way, and it is clearly much easier to write a collection of regular expressions to identify tag lines in files, rather than to write a separate program for each type. It also makes it simple for the user to add new regular expressions to pick up extra tags which might not have been envisioned by the author of the tags program. The \TAGS{} package for \EPSILON{} recognizes lines of the form \begin{verbatim} filename:matchingline filename:linenum:matchingline filename:linenum:pagenum:matchingline filename:bytenum:linenum:pagenum:matchingline \end{verbatim} where none of the colon-separated fields, except the last, may contain blanks. In fact, any number of digit fields can be present; if there are three of them, like \T{ctags.c} outputs, then the first is assumed to be a byte position. Otherwise, they are ignored and a brute force search in made in the file. Here is a complete list of the functions available in the \TAGS{} package: \begin{commandtable} \item[tags-add]\NEWLINE{} % missing NEWLINE at 0.02 \begin{commandentry} \item[Action] Add the current line to the \T{*TAGS*} buffer. The \T{*TAGS*} buffer does not usually have a file connected with it, so the first time you execute this command, it will prompt for a file name to be connected to the buffer. The changes are not automatically saved, but when you exit from the editor, you will be asked if you want to save the new tags file. \item[Key Binding] \T{M-+} \end{commandentry} \item[tags-apropos]\NEWLINE{} \begin{commandentry} \item[Action] Display a list of all tag lines containing the string which is prompted for. Since filenames are also present on these lines, this command can be used to find what files contain a particular tag. \item[Key Binding] \T{M-,} \end{commandentry} \item[tags-goto]\NEWLINE{} \begin{commandentry} \item[Action] Prompt for a tag and find it. If no tags file has been loaded into the \T{*TAGS*} buffer yet, then it will ring the bell and prompt for a tags file name first. If for some reason you need to change tag files, you can just kill the \T{*TAGS*} buffer before invoking this function. If necessary, a new buffer for the file containing a match for the tag will be created. The buffer is selected in the current window, with \POINT{} at the beginning of the line containing the tag. The tag name is remembered, so that if you subsequently give a null string in response to the tag prompt, the saved name will be used. If no argument is given, the tag search will be forward from the current point in the \T{*TAGS*} buffer. If this search fails, it will be restarted from the beginning of the buffer, unless the search began there. If a buffer switch does not happen, then {\em mark} is set where the function was invoked. With a zero argument, the tags search is forced to start at the beginning of the \T{*TAGS*} buffer. With a non-zero argument, the tags search goes backward from the current point, and if it reaches the beginning of the \T{*TAGS*}, continues from the end of the buffer, unless the search began there. \item[Key Binding] \T{M-\DOT} \end{commandentry} \item[tags-query-replace]\NEWLINE{} \begin{commandentry} \item[Action] Run a \EC{query-replace} on all files named in the \T{*TAGS*} buffer. Each \EC{query-replace} works only on the current buffer, so if you type a command to quit, or complete the substitutions in the remainder of the buffer, only the current file will have been processed. The original and replacement strings are remembered, so if you invoke this function again and respond to the prompt with a null string, \EC{query-replace} will continue in the next file found in the \T{*TAGS*} buffer. When there are no more files left, it will ring the bell and return. \item[Relations] \EC{query-replace}, \EC{tags-search} \item[Key Binding] None. \end{commandentry} \item[tags-search]\NEWLINE{} \begin{commandentry} \item[Action] Prompt for a search string and search for it through all the files in the tags file. The search string is remembered, so a null string entered on a second invocation will use the last string and continue the search, switching files if necessary. You can continue to use \EC{normal-search}, usually bound to \T{C-S}, in the current buffer. With an argument, use \EC{re-search} for a regular-expression search instead. \item[Relations] \EC{tags-query-replace} \item[Key Binding] \T{C-M-S} \end{commandentry} \end{commandtable}