home *** CD-ROM | disk | FTP | other *** search
- ;;; goto-file.el
-
- ;;; By binding goto-file to a key or mouse stroke, you can essentially
- ;;; make filenames "hot"; it will attempt to find that file in the
- ;;; current buffer's default directory. If no such file exists, then
- ;;; it checks the current tags-table, gambling that it is one of your
- ;;; source files and will be tagged.
- ;;;
- ;;; Furthermore, it will try to go to the right location in the file.
- ;;; If there is an adjacent line number, then it will go to that line.
- ;;; Or if there is an adjacent grep pattern, then it will find that pattern.
- ;;;
- ;;; For instance, if you are in a shell and do an "ls", you can then click on
- ;;; any file name to open the file. If you do a "make", you can click on any
- ;;; error msg to take you to the line of the error. If you are in dbx, and it
- ;;; outputs a break or an assert outputs file/line, then you can simply click
- ;;; on the filename to take you to the line. If you do a "grep", then you
- ;;; can simply click on the filename of the match that you want to go to.
- ;;; IMO, this is preferable to M-x compile or grep, because there is no need
- ;;; to proceed in order. It also works everywhere: in source files, in
- ;;; shells, in night build logs, in mail buffers, etc.
-
- ;;; Copyright (C) 1993, Intellection Inc.
- ;;;
- ;;; Author: Brian M Kennedy (kennedy@intellection.com)
- ;;;
- ;;; This program is free software; you can redistribute it and/or modify
- ;;; it under the terms of the GNU General Public License as published by
- ;;; the Free Software Foundation; either version 1, or (at your option)
- ;;; any later version.
- ;;;
- ;;; This program is distributed in the hope that it will be useful,
- ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;;; GNU General Public License for more details.
- ;;;
- ;;; A copy of the GNU General Public License can be obtained from the
- ;;; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ;;; 92/07/23 Brian M Kennedy Original
-
- (provide 'goto-file)
-
- (require 'tags)
-
-
- (defvar goto-file-chars "-A-Za-z./_=+~#0-9"
- "Characters that goto-file considers part of a filename.
- Intentionally does not include (by default) ,:<> and quotes because
- these are more often delimiters than part of the filename.")
-
- (defvar goto-file-other-window-p t
- "When non-nil, goto new file in other window.")
-
- (defun goto-file (&optional dont-use-tags-p)
- "Attempts to identify a filename at or around point. If it finds one,
- then it attempts to find a line number of the form 'line nn' on the
- same line as the filename. If there is no line number, then it checks
- if the filename was followed by a colon. If so, it assumes it is a
- grep-style pattern that was matched in the file.
- It then tries to find a file by that filename in the current-dirctory.
- If there is none and the optional argument is nil, then it attempts to
- identify a file that has been tagged with the same name in order to get a
- full pathname.
- If it finds a file (either way), then it opens it in another window.
- If there was line number information, then it will goto that line.
- If not, and there was a grep-style pattern, then it searches for that
- pattern in the file (and sets it up so that you can search for additional
- matches via incremental search)."
- (interactive "P")
- (let ((filename nil)
- (basename nil)
- (file nil)
- (line nil)
- (pattern nil))
- (save-excursion
- ;; Get filename
- (skip-chars-backward goto-file-chars)
- (let (start-point base-point end-point)
- (setq start-point (point))
- (skip-chars-forward "./~") ;; strip leading context info for tagfile lookup
- (setq base-point (point))
- (skip-chars-forward goto-file-chars)
- (setq end-point (point))
- (setq filename (buffer-substring start-point end-point))
- (setq basename (buffer-substring base-point end-point)) )
- ;; Get pattern
- (if (looking-at ":")
- (progn (forward-char 1)
- (setq pattern (buffer-substring (point)
- (progn (end-of-line) (point)))) ))
- ;; Get line
- (cond ((looking-at "([0-9]+")
- (forward-char 1)
- (setq line (string-to-int
- (buffer-substring (point)
- (progn (skip-chars-forward "0-9")
- (point) )))) )
- ((looking-at ".*line [0-9]")
- (re-search-forward ".*line ")
- (setq line (string-to-int
- (buffer-substring (point)
- (progn (skip-chars-forward "0-9")
- (point) )))) )
- ((re-search-backward "line [0-9]"
- (save-excursion (beginning-of-line) (point))
- t)
- (forward-char 5)
- (setq line (string-to-int
- (buffer-substring (point)
- (progn (skip-chars-forward "0-9")
- (point) )))) )
- ))
- ;; Goto the file
- (if filename
- (let ((fullname (expand-file-name filename)))
- (if (and (not dont-use-tags-p)
- (not (and fullname (file-exists-p fullname))))
- (setq fullname (expand-tagged-file-name basename)))
- (if (and fullname (file-exists-p fullname))
- (progn
- (if goto-file-other-window-p
- (find-file-other-window fullname)
- (find-file fullname))
- (cond (line (goto-line line))
- (pattern (setq search-last-string pattern)
- (goto-char (point-min))
- (search-forward pattern nil t) )
- ))
- (if dont-use-tags-p
- (error "No file named %s is in current directory." filename)
- (error "No file named %s is in current or tagged directories." filename)
- ) ))
- (error "No filename found at point.") )))
-
-
-
- (defun expand-tagged-file-name (filename)
- "Find a tagged file with a name that includes 'filename' in it.
- If one is found, return that file's expanded filename.
- Otherwise, return nil."
- ;; Find the tagged file
- (save-excursion
- (visit-tags-table-buffer)
- (beginning-of-buffer)
- (if (re-search-forward (concat "\f\n\\(.*/\\)?" filename ",") nil t)
- (expand-file-name (file-of-tag) (file-name-directory tags-file-name)) )))
-