diff lisp/hyperbole/hpath.el @ 24:4103f0995bd7 r19-15b95

Import from CVS: tag r19-15b95
author cvs
date Mon, 13 Aug 2007 08:51:03 +0200
parents 376386a54a3c
children c53a95d3c46d
line wrap: on
line diff
--- a/lisp/hyperbole/hpath.el	Mon Aug 13 08:50:31 2007 +0200
+++ b/lisp/hyperbole/hpath.el	Mon Aug 13 08:51:03 2007 +0200
@@ -6,19 +6,10 @@
 ;; KEYWORDS:     comm, hypermedia, unix
 ;;
 ;; AUTHOR:       Bob Weiner
-;; ORG:          Brown U.
+;; ORG:          InfoDock Associates
 ;;
 ;; ORIG-DATE:     1-Nov-91 at 00:44:23
-;; LAST-MOD:     10-Oct-95 at 23:31:56 by Bob Weiner
-;;
-;; This file is part of Hyperbole.
-;; Available for use and distribution under the same terms as GNU Emacs.
-;;
-;; Copyright (C) 1991-1995, Free Software Foundation, Inc.
-;; Developed with support from Motorola Inc.
-;;
-;; DESCRIPTION:  
-;; DESCRIP-END.
+;; LAST-MOD:     16-Feb-97 at 02:34:35 by Bob Weiner
 
 ;;; ************************************************************************
 ;;; Public variables
@@ -26,7 +17,7 @@
 
 (defvar hpath:rfc "/anonymous@ds.internic.net:rfc/rfc%s.txt"
   "*String to be used in the call: (hpath:rfc rfc-num)
-to create an path to the RFC document for 'rfc-num'.")
+to create an path to the RFC document for `rfc-num'.")
 
 (defvar hpath:suffixes '(".gz" ".Z")
   "*List of filename suffixes to add or remove within (hpath:exists-p) calls.")
@@ -39,7 +30,7 @@
 ;;; ************************************************************************
 
 (defun hpath:absolute-to (path &optional default-dirs)
-  "Returns PATH as an absolute path relative to one directory from optional DEFAULT-DIRS or 'default-directory'.
+  "Returns PATH as an absolute path relative to one directory from optional DEFAULT-DIRS or `default-directory'.
 Returns PATH unchanged when it is not a valid path or when DEFAULT-DIRS
 is invalid.  DEFAULT-DIRS when non-nil may be a single directory or a list of
 directories.  The first one in which PATH is found is used."
@@ -63,7 +54,7 @@
 
 (defun hpath:ange-ftp-at-p ()
   "Returns an ange-ftp pathname that point is within or nil.
-See the 'ange-ftp' or 'efs' Elisp packages for pathname format details.
+See the `ange-ftp' or `efs' Elisp packages for pathname format details.
 Always returns nil if (hpath:ange-ftp-available-p) returns nil."
   (if (hpath:ange-ftp-available-p)
       (let ((user (hpath:ange-ftp-default-user))
@@ -74,23 +65,23 @@
 		(cond
 		  ((hpath:url-at-p)
 		   (if (string-equal
-			 (buffer-substring (match-beginning 1) (match-end 1))
+			 (buffer-substring (match-beginning 2) (match-end 2))
 			 "ftp")
 		       (concat
 			"/"
 			;; user
-			(if (match-beginning 2)
+			(if (match-beginning 3)
 			    (buffer-substring
-			     (match-beginning 2) (match-end 2))
+			     (match-beginning 3) (match-end 3))
 			  (concat user "@"))
 			;; domain
 			(hpath:delete-trailer
-			 (buffer-substring (match-beginning 3) (match-end 3)))
+			 (buffer-substring (match-beginning 4) (match-end 4)))
 			":"
 			;; path
-			(if (match-beginning 5)
-			    (buffer-substring (match-beginning 5)
-					      (match-end 5))))
+			(if (match-beginning 6)
+			    (buffer-substring (match-beginning 6)
+					      (match-end 6))))
 		     ;; else ignore this other type of WWW path
 		     ))
 		  ;; user, domain and path
@@ -120,7 +111,7 @@
 
 (defun hpath:ange-ftp-p (path)
   "Returns non-nil iff PATH is an ange-ftp pathname.
-See the 'ange-ftp' or 'efs' Elisp package for pathname format details.
+See the `ange-ftp' or `efs' Elisp package for pathname format details.
 Always returns nil if (hpath:ange-ftp-available-p) returns nil."
   (and (stringp path)
        (or (featurep 'ange-ftp) (featurep 'efs))
@@ -130,22 +121,22 @@
 	       (cond
 		 ((hpath:url-p path)
 		  (if (string-equal
-			(substring path (match-beginning 1) (match-end 1))
+			(substring path (match-beginning 2) (match-end 2))
 			"ftp")
 		      (concat
 			"/"
 			;; user
-			(if (match-beginning 2)
-			    (substring path (match-beginning 2) (match-end 2))
+			(if (match-beginning 3)
+			    (substring path (match-beginning 3) (match-end 3))
 			  (concat user "@"))
 			;; domain
 			(hpath:delete-trailer
-			 (substring path (match-beginning 3) (match-end 3)))
+			 (substring path (match-beginning 4) (match-end 4)))
 			":"
 			;; path
-			(if (match-beginning 5)
-			    (substring path (match-beginning 5)
-				       (match-end 5))))
+			(if (match-beginning 6)
+			    (substring path (match-beginning 6)
+				       (match-end 6))))
 		    ;; else ignore this other type of WWW path
 		    ))
 		 ;; user, domain and path
@@ -186,8 +177,8 @@
 If optional TYPE is the symbol 'file or 'directory, then only that path type is
 accepted as a match.  Only locally reachable paths are checked for existence.
 With optional NON-EXIST, nonexistent local paths are allowed.
-Absolute pathnames must begin with a '/' or '~'.  Relative pathnames
-must begin with a './' or '../' to be recognized."
+Absolute pathnames must begin with a `/' or `~'.  Relative pathnames
+must begin with a `./' or `../' to be recognized."
   (cond	(;; Local file URLs
 	 (hpath:is-p (hargs:delimited
 		      "file://localhost" "[ \t\n\^M\"\'\}]" nil t)))
@@ -200,10 +191,40 @@
 			 (hargs:delimited "@file{" "}"))
 		     type non-exist))))
 
-(defun hpath:find (filename &optional other-window-p)
-  "Edit file FILENAME using program from hpath:find-alist if available.
-Otherwise, switch to a buffer visiting file FILENAME, creating one if none
-already exists.
+(defun hpath:display-buffer (buffer &optional display-where)
+  "Displays BUFFER at optional DISPLAY-WHERE location or at hpath:display-where.
+BUFFER may be a buffer or a buffer name.
+
+See documentation of `hpath:display-buffer-alist' for valid values of DISPLAY-WHERE.
+Returns non-nil iff buffer is actually displayed."
+  (interactive "bDisplay buffer: ")
+  (if (stringp buffer) (setq buffer (get-buffer buffer)))
+  (if (null buffer)
+      nil
+    (if (null display-where)
+	(setq display-where hpath:display-where))
+    (funcall (car (cdr (or (assq display-where
+				 hpath:display-buffer-alist)
+			   (assq 'other-window
+				 hpath:display-buffer-alist))))
+	     buffer)
+    t))
+
+(defun hpath:display-buffer-other-frame (buffer)
+  "Displays BUFFER, in another frame.
+May create a new frame, or reuse an existing one.
+See documentation of `hpath:display-buffer' for details.
+Returns the dispalyed buffer."
+  (interactive "bDisplay buffer in other frame: ")
+  (if (= (length (frame-list)) 1)
+      (select-frame (make-frame))
+    (other-frame 1))
+  (if (br-in-browser)
+      (br-to-view-window))
+  (switch-to-buffer buffer))
+
+(defun hpath:find (filename &optional display-where)
+  "Edits file FILENAME using user customizable settings of display program and location.
 
 FILENAME may start with a special prefix character which is
 handled as follows:
@@ -211,7 +232,14 @@
   &filename  - execute as a windowed program;
   -filename  - load as an Emacs Lisp program.
 
-Return non-nil iff file is displayed within a buffer (not with an external
+Otherwise, if FILENAME matches a regular expression in the variable
+`hpath:find-alist,' the associated external display program is invoked.
+If not, `hpath:display-alist' is consulted for a specialized internal
+display function to use.  If no matches are found there,
+`hpath:display-where-alist' is consulted using the optional argument,
+DISPLAY-WHERE (a symbol) or if that is nil, the value of
+`hpath:display-where', and the matching display function is used.
+Returns non-nil iff file is displayed within a buffer (not with an external
 program)."
   (interactive "FFind file: ")
   (let (modifier)
@@ -232,25 +260,62 @@
 		      nil)
 		     ((hypb:functionp find-program)
 		      (funcall find-program filename)
-		      nil)
+		      t)
 		     (t (setq filename (hpath:validate filename))
-			(funcall (if (and other-window-p
-					  (not (br-in-browser)))
-				     'switch-to-buffer-other-window
-				   'switch-to-buffer)
-				 (find-file-noselect filename))
+			(if (null display-where)
+			    (setq display-where hpath:display-where))
+			(funcall (car (cdr (or (assq display-where
+						     hpath:display-where-alist)
+					       (assq 'other-window
+						     hpath:display-where-alist))))
+				 filename)
 			t)))))))
 
+(defun hpath:find-line (filename line-num &optional display-where)
+  "Edits file FILENAME with point placed at LINE-NUM.
+
+`hpath:display-where-alist' is consulted using the optional argument,
+DISPLAY-WHERE (a symbol) or if that is nil, the value of
+`hpath:display-where', and the matching display function is used to determine
+where to display the file, e.g. in another frame.
+Always returns t."
+  (interactive "FFind file: ")
+  ;; Just delete any special characters preceding the filename, ignoring them.
+  (if (string-match hpath:prefix-regexp filename)
+      (setq filename (substring filename (match-end 0))))
+  (setq filename (hpath:substitute-value filename)
+	filename (hpath:validate filename))
+  (if (null display-where)
+      (setq display-where hpath:display-where))
+  (funcall (car (cdr (or (assq display-where
+			       hpath:display-where-alist)
+			 (assq 'other-window
+			       hpath:display-where-alist))))
+	   filename)
+  (if (integerp line-num)
+      (progn (widen) (goto-line line-num)))
+  t)
+
+(defun hpath:find-other-frame (filename)
+  "Edits file FILENAME, in another frame.
+May create a new frame, or reuse an existing one.
+See documentation of `hpath:find' for details.
+Returns the buffer of displayed file."
+  (interactive "FFind file in other frame: ")
+  (if (= (length (frame-list)) 1)
+      (select-frame (make-frame))
+    (other-frame 1))
+  (if (br-in-browser)
+      (br-to-view-window))
+  (find-file filename))
+
 (defun hpath:find-other-window (filename)
-  "Edit file FILENAME, in another window or using program from hpath:find-alist.
+  "Edits file FILENAME, in another window or using an external program.
 May create a new window, or reuse an existing one; see the function display-buffer.
-
-Alternatively, FILENAME may start with a prefix character to indicate special
-handling.  See documentation of `hpath:find' for details.
-
-Return non-nil iff file is displayed within a buffer."
+See documentation of `hpath:find' for details.
+Returns non-nil iff file is displayed within a buffer."
   (interactive "FFind file in other window: ")
-  (hpath:find filename t))
+  (hpath:find filename 'other-window))
 
 (defun hpath:is-p (path &optional type non-exist)
   "Returns PATH if PATH is a Unix path, else nil.
@@ -275,7 +340,7 @@
 	 (if (string-match hpath:prefix-regexp path)
 	     (setq path (substring path (match-end 0)))
 	   t)
-	 (not (or (string= path "")
+	 (not (or (string-equal path "")
 		  (string-match "\\`\\s \\|\\s \\'" path)))
 	 ;; Convert tabs and newlines to space.
 	 (setq path (hbut:key-to-label (hbut:label-to-key path)))
@@ -310,19 +375,23 @@
 			     (file-directory-p path))
 			    (t)))
 		     )
-	       ;; Return path if non-nil return value
-	       (if (stringp suffix) ;; suffix could = t, which we ignore
-		   (if (string-match
-			(concat (regexp-quote suffix) "%s") rtn-path)
-		       ;; remove suffix
-		       (concat (substring rtn-path 0 (match-beginning 0))
-			       (substring rtn-path (match-end 0)))
-		     ;; add suffix
-		     (format rtn-path suffix))
-		 (format rtn-path "")))))))
+	       (progn
+		 ;; Quote any but last %s within rtn-path.
+		 (setq rtn-path (hypb:replace-match-string "%s" rtn-path "%%s")
+		       rtn-path (hypb:replace-match-string "%%s\\'" rtn-path "%s"))
+		 ;; Return path if non-nil return value.
+		 (if (stringp suffix);; suffix could = t, which we ignore
+		     (if (string-match
+			  (concat (regexp-quote suffix) "%s") rtn-path)
+			 ;; remove suffix
+			 (concat (substring rtn-path 0 (match-beginning 0))
+				 (substring rtn-path (match-end 0)))
+		       ;; add suffix
+		       (format rtn-path suffix))
+		   (format rtn-path ""))))))))
 
 (defun hpath:relative-to (path &optional default-dir)
-  "Returns PATH relative to optional DEFAULT-DIR or 'default-directory'.
+  "Returns PATH relative to optional DEFAULT-DIR or `default-directory'.
 Returns PATH unchanged when it is not a valid path."
   (if (not (and (stringp path) (hpath:is-p path)))
       path
@@ -349,7 +418,7 @@
 
 (defun hpath:rfc (rfc-num)
   "Return pathname to textual rfc document indexed by RFC-NUM.
-See the documentation of the 'hpath:rfc' variable."
+See the documentation of the `hpath:rfc' variable."
   (format hpath:rfc rfc-num))
 
 (defun hpath:substitute-value (path)
@@ -374,7 +443,7 @@
       t)))
 
 (defun hpath:substitute-var (path)
-  "Replaces up to one match in PATH with first matching variable from 'hpath:variables'."
+  "Replaces up to one match in PATH with first matching variable from `hpath:variables'."
   (if (not (and (stringp path) (string-match "/" path) (hpath:is-p path)))
       path
     (setq path (hpath:symlink-referent path))
@@ -396,7 +465,7 @@
 				    (hpath:substitute-var-name var (car val) path))
 				(setq new-path result))
 			    (setq val (cdr val))))
-			 (t (error "(hpath:substitute-var): '%s' has invalid value for hpath:variables" var))))))
+			 (t (error "(hpath:substitute-var): `%s' has invalid value for hpath:variables" var))))))
       (or new-path path)
       )))
 
@@ -407,9 +476,9 @@
 ;; /usr/local -> $(SERVER_LOCAL)/usr/local, /usr/bin ->
 ;; ../$(SYSTYPE)/usr/bin and /tmp -> `node_data/tmp.  It also handles
 ;; relative links properly as in /usr/local/emacs -> gnu/emacs which must
-;; be resolved relative to the '/usr/local' directory.
-;; It will fail on Apollos if the '../' notation is used to move just
-;; above the '/' directory level.  This is fairly uncommon and so the
+;; be resolved relative to the `/usr/local' directory.
+;; It will fail on Apollos if the `../' notation is used to move just
+;; above the `/' directory level.  This is fairly uncommon and so the
 ;; problem has not been fixed.
 ;;
 (defun hpath:symlink-referent (linkname)
@@ -478,35 +547,37 @@
   "Return world-wide-web universal resource locator (url) that point immediately precedes or nil.
 Use buffer-substring with match-beginning and match-end on the following
 groupings:
-  1 = access protocol
-  2 = optional username
-  3 = host and domain to connect to
-  4 = optional port number to use
-  5 = pathname to access."
-  ;; WWW URL format:  <protocol>:/[<user>@]<domain>[:<port>]/<path>
-  ;;             or   <protocol>://[<user>@]<domain>[:<port>]<path>
+  1 = optional `URL:' literal
+  2 = access protocol
+  4 = optional username
+  4 = host and domain to connect to
+  5 = optional port number to use
+  6 = pathname to access."
+  ;; WWW URL format:  [URL:]<protocol>:/[<user>@]<domain>[:<port>]/<path>
+  ;;             or   [URL:]<protocol>://[<user>@]<domain>[:<port>]<path>
   ;; Avoid [a-z]:/path patterns since these may be disk paths on OS/2, DOS or
   ;; Windows.
-  (if (looking-at "\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?")
+  (if (looking-at "\\(URL:\\)?\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?")
       (save-excursion
-	(goto-char (match-end 0))
+	(goto-char (match-end 6))
 	(skip-chars-backward ".?#!*()")
-	(buffer-substring (match-beginning 0) (point)))))
+	(buffer-substring (match-beginning 2) (point)))))
 
 (defun hpath:url-p (obj)
   "Return t if OBJ is a world-wide-web universal resource locator (url) string, else nil.
 Use string-match with match-beginning and match-end on the following groupings:
-  1 = access protocol
-  2 = optional username
-  3 = host and domain to connect to
-  4 = optional port number to use
-  5 = pathname to access."
-  ;; WWW URL format:  <protocol>:/[<user>@]<domain>[:<port>]/<path>
-  ;;             or   <protocol>://[<user>@]<domain>[:<port>]<path>
+  1 = optional `URL:' literal
+  2 = access protocol
+  3 = optional username
+  4 = host and domain to connect to
+  5 = optional port number to use
+  6 = pathname to access."
+  ;; WWW URL format:  [URL:]<protocol>:/[<user>@]<domain>[:<port>]/<path>
+  ;;             or   [URL:]<protocol>://[<user>@]<domain>[:<port>]<path>
   ;; Avoid [a-z]:/path patterns since these may be disk paths on OS/2, DOS or
   ;; Windows.
   (and (stringp obj)
-       (string-match "\\`<?\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?>?\\'"
+       (string-match "\\`<?\\(URL:\\)?\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?>?\\'"
 		     obj)
        t))
 
@@ -519,9 +590,9 @@
     (cond ((not include-start-and-end-p)
 	   (hpath:url-at-p))
 	  ((hpath:url-at-p)
-	   (list (buffer-substring (match-beginning 0) (match-end 0))
-		 (match-beginning 0)
-		 (match-end 0))))))
+	   (list (buffer-substring (match-beginning 2) (match-end 6))
+		 (match-beginning 2)
+		 (match-end 6))))))
 
 (defun hpath:www-p (path)
   "Returns non-nil iff PATH is a world-wide-web link reference."
@@ -534,7 +605,7 @@
 (defun hpath:ange-ftp-available-p ()
   "Return t if the ange-ftp or efs package is available, nil otherwise.
 Either the package must have been loaded already or under versions of Emacs
-19, it must be set for autoloading via 'file-name-handler-alist'."
+19, it must be set for autoloading via `file-name-handler-alist'."
   (or (featurep 'ange-ftp) (featurep 'efs)
       (and (boundp 'file-name-handler-alist) ; v19
 	   (or (rassq 'ange-ftp-hook-function file-name-handler-alist)
@@ -595,7 +666,7 @@
 (defun hpath:find-program (filename)
   "Return shell or Lisp command to execute to display FILENAME or nil.
 Return nil if FILENAME is a directory name.
-See also documentation for 'hpath:find-alist' and 'hpath:display-alist'."
+See also documentation for `hpath:find-alist' and `hpath:display-alist'."
   (let ((cmd))
     (cond ((and (stringp filename) (file-directory-p filename))
 	   nil)
@@ -639,7 +710,7 @@
 local pathname is returned."
   (let (sym val)
     (cond ((not (stringp var-name))
-	   (error "(hpath:substitute-dir): VAR-NAME arg, '%s', must be a string" var-name))
+	   (error "(hpath:substitute-dir): VAR-NAME arg, `%s', must be a string" var-name))
 	  ((not (and (setq sym (intern-soft var-name))
 		     (boundp sym)))
 	   (error "(hpath:substitute-dir): VAR-NAME arg, \"%s\", is not a bound variable"