comparison lisp/hyperbole/hpath.el @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents 1a767b41a199
children 4be1180a9e89
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
4 ;; SUMMARY: Hyperbole support routines for handling UNIX paths. 4 ;; SUMMARY: Hyperbole support routines for handling UNIX paths.
5 ;; USAGE: GNU Emacs Lisp Library 5 ;; USAGE: GNU Emacs Lisp Library
6 ;; KEYWORDS: comm, hypermedia, unix 6 ;; KEYWORDS: comm, hypermedia, unix
7 ;; 7 ;;
8 ;; AUTHOR: Bob Weiner 8 ;; AUTHOR: Bob Weiner
9 ;; ORG: InfoDock Associates 9 ;; ORG: Brown U.
10 ;; 10 ;;
11 ;; ORIG-DATE: 1-Nov-91 at 00:44:23 11 ;; ORIG-DATE: 1-Nov-91 at 00:44:23
12 ;; LAST-MOD: 20-Mar-97 at 11:52:51 by Bob Weiner 12 ;; LAST-MOD: 10-Oct-95 at 23:31:56 by Bob Weiner
13 ;;
14 ;; This file is part of Hyperbole.
15 ;; Available for use and distribution under the same terms as GNU Emacs.
16 ;;
17 ;; Copyright (C) 1991-1995, Free Software Foundation, Inc.
18 ;; Developed with support from Motorola Inc.
19 ;;
20 ;; DESCRIPTION:
21 ;; DESCRIP-END.
13 22
14 ;;; ************************************************************************ 23 ;;; ************************************************************************
15 ;;; Public variables 24 ;;; Public variables
16 ;;; ************************************************************************ 25 ;;; ************************************************************************
17 26
18 (defvar hpath:rfc "/anonymous@ds.internic.net:rfc/rfc%s.txt" 27 (defvar hpath:rfc "/anonymous@ds.internic.net:rfc/rfc%s.txt"
19 "*String to be used in the call: (hpath:rfc rfc-num) 28 "*String to be used in the call: (hpath:rfc rfc-num)
20 to create an path to the RFC document for `rfc-num'.") 29 to create an path to the RFC document for 'rfc-num'.")
21 30
22 (defvar hpath:suffixes '(".gz" ".Z") 31 (defvar hpath:suffixes '(".gz" ".Z")
23 "*List of filename suffixes to add or remove within (hpath:exists-p) calls.") 32 "*List of filename suffixes to add or remove within (hpath:exists-p) calls.")
24 33
25 (defvar hpath:tmp-prefix "/tmp/remote-" 34 (defvar hpath:tmp-prefix "/tmp/remote-"
28 ;;; ************************************************************************ 37 ;;; ************************************************************************
29 ;;; Public functions 38 ;;; Public functions
30 ;;; ************************************************************************ 39 ;;; ************************************************************************
31 40
32 (defun hpath:absolute-to (path &optional default-dirs) 41 (defun hpath:absolute-to (path &optional default-dirs)
33 "Returns PATH as an absolute path relative to one directory from optional DEFAULT-DIRS or `default-directory'. 42 "Returns PATH as an absolute path relative to one directory from optional DEFAULT-DIRS or 'default-directory'.
34 Returns PATH unchanged when it is not a valid path or when DEFAULT-DIRS 43 Returns PATH unchanged when it is not a valid path or when DEFAULT-DIRS
35 is invalid. DEFAULT-DIRS when non-nil may be a single directory or a list of 44 is invalid. DEFAULT-DIRS when non-nil may be a single directory or a list of
36 directories. The first one in which PATH is found is used." 45 directories. The first one in which PATH is found is used."
37 (if (not (and (stringp path) (hpath:is-p path nil t))) 46 (if (not (and (stringp path) (hpath:is-p path nil t)))
38 path 47 path
52 (or (file-exists-p rtn) (setq rtn nil))) 61 (or (file-exists-p rtn) (setq rtn nil)))
53 (or rtn path))))) 62 (or rtn path)))))
54 63
55 (defun hpath:ange-ftp-at-p () 64 (defun hpath:ange-ftp-at-p ()
56 "Returns an ange-ftp pathname that point is within or nil. 65 "Returns an ange-ftp pathname that point is within or nil.
57 See the `ange-ftp' or `efs' Elisp packages for pathname format details. 66 See the 'ange-ftp' or 'efs' Elisp packages for pathname format details.
58 Always returns nil if (hpath:ange-ftp-available-p) returns nil." 67 Always returns nil if (hpath:ange-ftp-available-p) returns nil."
59 (if (hpath:ange-ftp-available-p) 68 (if (hpath:ange-ftp-available-p)
60 (let ((user (hpath:ange-ftp-default-user)) 69 (let ((user (hpath:ange-ftp-default-user))
61 path) 70 path)
62 (setq path 71 (setq path
63 (save-excursion 72 (save-excursion
64 (skip-chars-backward "^[ \t\n\"`'\(\{<") 73 (skip-chars-backward "^[ \t\n\"`'\(\{<")
65 (cond 74 (cond
66 ((hpath:url-at-p) 75 ((hpath:url-at-p)
67 (if (string-equal 76 (if (string-equal
68 (buffer-substring (match-beginning 2) (match-end 2)) 77 (buffer-substring (match-beginning 1) (match-end 1))
69 "ftp") 78 "ftp")
70 (concat 79 (concat
71 "/" 80 "/"
72 ;; user 81 ;; user
73 (if (match-beginning 3) 82 (if (match-beginning 2)
74 (buffer-substring 83 (buffer-substring
75 (match-beginning 3) (match-end 3)) 84 (match-beginning 2) (match-end 2))
76 (concat user "@")) 85 (concat user "@"))
77 ;; domain 86 ;; domain
78 (hpath:delete-trailer 87 (hpath:delete-trailer
79 (buffer-substring (match-beginning 4) (match-end 4))) 88 (buffer-substring (match-beginning 3) (match-end 3)))
80 ":" 89 ":"
81 ;; path 90 ;; path
82 (if (match-beginning 6) 91 (if (match-beginning 5)
83 (buffer-substring (match-beginning 6) 92 (buffer-substring (match-beginning 5)
84 (match-end 6)))) 93 (match-end 5))))
85 ;; else ignore this other type of WWW path 94 ;; else ignore this other type of WWW path
86 )) 95 ))
87 ;; user, domain and path 96 ;; user, domain and path
88 ((looking-at "/?[^/:@ \t\n\^M\"`']+@[^/:@ \t\n\^M\"`']+:[^]@ \t\n\^M\"`'\)\}]*") 97 ((looking-at "/?[^/:@ \t\n\^M\"`']+@[^/:@ \t\n\^M\"`']+:[^]@ \t\n\^M\"`'\)\}]*")
89 (buffer-substring (match-beginning 0) (match-end 0))) 98 (buffer-substring (match-beginning 0) (match-end 0)))
109 ))) 118 )))
110 (hpath:delete-trailer path)))) 119 (hpath:delete-trailer path))))
111 120
112 (defun hpath:ange-ftp-p (path) 121 (defun hpath:ange-ftp-p (path)
113 "Returns non-nil iff PATH is an ange-ftp pathname. 122 "Returns non-nil iff PATH is an ange-ftp pathname.
114 See the `ange-ftp' or `efs' Elisp package for pathname format details. 123 See the 'ange-ftp' or 'efs' Elisp package for pathname format details.
115 Always returns nil if (hpath:ange-ftp-available-p) returns nil." 124 Always returns nil if (hpath:ange-ftp-available-p) returns nil."
116 (and (stringp path) 125 (and (stringp path)
117 (or (featurep 'ange-ftp) (featurep 'efs)) 126 (or (featurep 'ange-ftp) (featurep 'efs))
118 (let ((user (hpath:ange-ftp-default-user)) 127 (let ((user (hpath:ange-ftp-default-user))
119 result) 128 result)
120 (setq result 129 (setq result
121 (cond 130 (cond
122 ((hpath:url-p path) 131 ((hpath:url-p path)
123 (if (string-equal 132 (if (string-equal
124 (substring path (match-beginning 2) (match-end 2)) 133 (substring path (match-beginning 1) (match-end 1))
125 "ftp") 134 "ftp")
126 (concat 135 (concat
127 "/" 136 "/"
128 ;; user 137 ;; user
129 (if (match-beginning 3) 138 (if (match-beginning 2)
130 (substring path (match-beginning 3) (match-end 3)) 139 (substring path (match-beginning 2) (match-end 2))
131 (concat user "@")) 140 (concat user "@"))
132 ;; domain 141 ;; domain
133 (hpath:delete-trailer 142 (hpath:delete-trailer
134 (substring path (match-beginning 4) (match-end 4))) 143 (substring path (match-beginning 3) (match-end 3)))
135 ":" 144 ":"
136 ;; path 145 ;; path
137 (if (match-beginning 6) 146 (if (match-beginning 5)
138 (substring path (match-beginning 6) 147 (substring path (match-beginning 5)
139 (match-end 6)))) 148 (match-end 5))))
140 ;; else ignore this other type of WWW path 149 ;; else ignore this other type of WWW path
141 )) 150 ))
142 ;; user, domain and path 151 ;; user, domain and path
143 ((string-match "/?[^/:@ \t\n\^M\"`']+@[^/:@ \t\n\^M\"`']+:[^]@ \t\n\^M\"`'\)\}]*" 152 ((string-match "/?[^/:@ \t\n\^M\"`']+@[^/:@ \t\n\^M\"`']+:[^]@ \t\n\^M\"`'\)\}]*"
144 path) 153 path)
175 Delimiters may be: double quotes, open and close single quote, or 184 Delimiters may be: double quotes, open and close single quote, or
176 Texinfo file references. 185 Texinfo file references.
177 If optional TYPE is the symbol 'file or 'directory, then only that path type is 186 If optional TYPE is the symbol 'file or 'directory, then only that path type is
178 accepted as a match. Only locally reachable paths are checked for existence. 187 accepted as a match. Only locally reachable paths are checked for existence.
179 With optional NON-EXIST, nonexistent local paths are allowed. 188 With optional NON-EXIST, nonexistent local paths are allowed.
180 Absolute pathnames must begin with a `/' or `~'. Relative pathnames 189 Absolute pathnames must begin with a '/' or '~'. Relative pathnames
181 must begin with a `./' or `../' to be recognized." 190 must begin with a './' or '../' to be recognized."
182 (cond (;; Local file URLs 191 (cond (;; Local file URLs
183 (hpath:is-p (hargs:delimited 192 (hpath:is-p (hargs:delimited
184 "file://localhost" "[ \t\n\^M\"\'\}]" nil t))) 193 "file://localhost" "[ \t\n\^M\"\'\}]" nil t)))
185 ((hpath:ange-ftp-at-p)) 194 ((hpath:ange-ftp-at-p))
186 ((hpath:www-at-p) nil) 195 ((hpath:www-at-p) nil)
189 (hargs:delimited "\`" "\'") 198 (hargs:delimited "\`" "\'")
190 ;; Filenames in TexInfo docs 199 ;; Filenames in TexInfo docs
191 (hargs:delimited "@file{" "}")) 200 (hargs:delimited "@file{" "}"))
192 type non-exist)))) 201 type non-exist))))
193 202
194 (defun hpath:display-buffer (buffer &optional display-where) 203 (defun hpath:find (filename &optional other-window-p)
195 "Displays BUFFER at optional DISPLAY-WHERE location or at hpath:display-where. 204 "Edit file FILENAME using program from hpath:find-alist if available.
196 BUFFER may be a buffer or a buffer name. 205 Otherwise, switch to a buffer visiting file FILENAME, creating one if none
197 206 already exists.
198 See documentation of `hpath:display-buffer-alist' for valid values of DISPLAY-WHERE.
199 Returns non-nil iff buffer is actually displayed."
200 (interactive "bDisplay buffer: ")
201 (if (stringp buffer) (setq buffer (get-buffer buffer)))
202 (if (null buffer)
203 nil
204 (if (null display-where)
205 (setq display-where hpath:display-where))
206 (funcall (car (cdr (or (assq display-where
207 hpath:display-buffer-alist)
208 (assq 'other-window
209 hpath:display-buffer-alist))))
210 buffer)
211 t))
212
213 (defun hpath:display-buffer-other-frame (buffer)
214 "Displays BUFFER, in another frame.
215 May create a new frame, or reuse an existing one.
216 See documentation of `hpath:display-buffer' for details.
217 Returns the dispalyed buffer."
218 (interactive "bDisplay buffer in other frame: ")
219 (if (= (length (frame-list)) 1)
220 (select-frame (make-frame))
221 (other-frame 1))
222 (if (br-in-browser)
223 (br-to-view-window))
224 (switch-to-buffer buffer))
225
226 (defun hpath:find (filename &optional display-where)
227 "Edits file FILENAME using user customizable settings of display program and location.
228 207
229 FILENAME may start with a special prefix character which is 208 FILENAME may start with a special prefix character which is
230 handled as follows: 209 handled as follows:
231 !filename - execute as a non-windowed program within a shell; 210 !filename - execute as a non-windowed program within a shell;
232 &filename - execute as a windowed program; 211 &filename - execute as a windowed program;
233 -filename - load as an Emacs Lisp program. 212 -filename - load as an Emacs Lisp program.
234 213
235 Otherwise, if FILENAME matches a regular expression in the variable 214 Return non-nil iff file is displayed within a buffer (not with an external
236 `hpath:find-alist,' the associated external display program is invoked.
237 If not, `hpath:display-alist' is consulted for a specialized internal
238 display function to use. If no matches are found there,
239 `hpath:display-where-alist' is consulted using the optional argument,
240 DISPLAY-WHERE (a symbol) or if that is nil, the value of
241 `hpath:display-where', and the matching display function is used.
242 Returns non-nil iff file is displayed within a buffer (not with an external
243 program)." 215 program)."
244 (interactive "FFind file: ") 216 (interactive "FFind file: ")
245 (let (modifier) 217 (let (modifier)
246 (if (string-match hpath:prefix-regexp filename) 218 (if (string-match hpath:prefix-regexp filename)
247 (setq modifier (aref filename 0) 219 (setq modifier (aref filename 0)
258 (cond ((stringp find-program) 230 (cond ((stringp find-program)
259 (hact 'exec-window-cmd find-program) 231 (hact 'exec-window-cmd find-program)
260 nil) 232 nil)
261 ((hypb:functionp find-program) 233 ((hypb:functionp find-program)
262 (funcall find-program filename) 234 (funcall find-program filename)
263 t) 235 nil)
264 (t (setq filename (hpath:validate filename)) 236 (t (setq filename (hpath:validate filename))
265 (if (null display-where) 237 (funcall (if (and other-window-p
266 (setq display-where hpath:display-where)) 238 (not (br-in-browser)))
267 (funcall (car (cdr (or (assq display-where 239 'switch-to-buffer-other-window
268 hpath:display-where-alist) 240 'switch-to-buffer)
269 (assq 'other-window 241 (find-file-noselect filename))
270 hpath:display-where-alist))))
271 filename)
272 t))))))) 242 t)))))))
273 243
274 (defun hpath:find-line (filename line-num &optional display-where)
275 "Edits file FILENAME with point placed at LINE-NUM.
276
277 `hpath:display-where-alist' is consulted using the optional argument,
278 DISPLAY-WHERE (a symbol) or if that is nil, the value of
279 `hpath:display-where', and the matching display function is used to determine
280 where to display the file, e.g. in another frame.
281 Always returns t."
282 (interactive "FFind file: ")
283 ;; Just delete any special characters preceding the filename, ignoring them.
284 (if (string-match hpath:prefix-regexp filename)
285 (setq filename (substring filename (match-end 0))))
286 (setq filename (hpath:substitute-value filename)
287 filename (hpath:validate filename))
288 (if (null display-where)
289 (setq display-where hpath:display-where))
290 (funcall (car (cdr (or (assq display-where
291 hpath:display-where-alist)
292 (assq 'other-window
293 hpath:display-where-alist))))
294 filename)
295 (if (integerp line-num)
296 (progn (widen) (goto-line line-num)))
297 t)
298
299 (defun hpath:find-other-frame (filename)
300 "Edits file FILENAME, in another frame.
301 May create a new frame, or reuse an existing one.
302 See documentation of `hpath:find' for details.
303 Returns the buffer of displayed file."
304 (interactive "FFind file in other frame: ")
305 (if (= (length (frame-list)) 1)
306 (select-frame (make-frame))
307 (other-frame 1))
308 (if (br-in-browser)
309 (br-to-view-window))
310 (find-file filename))
311
312 (defun hpath:find-other-window (filename) 244 (defun hpath:find-other-window (filename)
313 "Edits file FILENAME, in another window or using an external program. 245 "Edit file FILENAME, in another window or using program from hpath:find-alist.
314 May create a new window, or reuse an existing one; see the function display-buffer. 246 May create a new window, or reuse an existing one; see the function display-buffer.
315 See documentation of `hpath:find' for details. 247
316 Returns non-nil iff file is displayed within a buffer." 248 Alternatively, FILENAME may start with a prefix character to indicate special
249 handling. See documentation of `hpath:find' for details.
250
251 Return non-nil iff file is displayed within a buffer."
317 (interactive "FFind file in other window: ") 252 (interactive "FFind file in other window: ")
318 (hpath:find filename 'other-window)) 253 (hpath:find filename t))
319 254
320 (defun hpath:is-p (path &optional type non-exist) 255 (defun hpath:is-p (path &optional type non-exist)
321 "Returns PATH if PATH is a Unix path, else nil. 256 "Returns PATH if PATH is a Unix path, else nil.
322 If optional TYPE is the symbol 'file or 'directory, then only that path type 257 If optional TYPE is the symbol 'file or 'directory, then only that path type
323 is accepted as a match. The existence of the path is checked only for 258 is accepted as a match. The existence of the path is checked only for
338 path (substring path 0 (match-beginning 0))) 273 path (substring path 0 (match-beginning 0)))
339 (setq rtn-path (concat rtn-path "%s"))) 274 (setq rtn-path (concat rtn-path "%s")))
340 (if (string-match hpath:prefix-regexp path) 275 (if (string-match hpath:prefix-regexp path)
341 (setq path (substring path (match-end 0))) 276 (setq path (substring path (match-end 0)))
342 t) 277 t)
343 (not (or (string-equal path "") 278 (not (or (string= path "")
344 (string-match "\\`\\s \\|\\s \\'" path))) 279 (string-match "\\`\\s \\|\\s \\'" path)))
345 ;; Convert tabs and newlines to space. 280 ;; Convert tabs and newlines to space.
346 (setq path (hbut:key-to-label (hbut:label-to-key path))) 281 (setq path (hbut:key-to-label (hbut:label-to-key path)))
347 (or (not (string-match "[()]" path)) 282 (or (not (string-match "[()]" path))
348 (string-match "\\`([^ \t\n\^M\)]+)[ *A-Za-z0-9]" path)) 283 (string-match "\\`([^ \t\n\^M\)]+)[ *A-Za-z0-9]" path))
373 (not (file-directory-p path))) 308 (not (file-directory-p path)))
374 ((eq type 'directory) 309 ((eq type 'directory)
375 (file-directory-p path)) 310 (file-directory-p path))
376 (t))) 311 (t)))
377 ) 312 )
378 (progn 313 ;; Return path if non-nil return value
379 ;; Quote any but last %s within rtn-path. 314 (if (stringp suffix) ;; suffix could = t, which we ignore
380 (setq rtn-path (hypb:replace-match-string "%s" rtn-path "%%s") 315 (if (string-match
381 rtn-path (hypb:replace-match-string "%%s\\'" rtn-path "%s")) 316 (concat (regexp-quote suffix) "%s") rtn-path)
382 ;; Return path if non-nil return value. 317 ;; remove suffix
383 (if (stringp suffix);; suffix could = t, which we ignore 318 (concat (substring rtn-path 0 (match-beginning 0))
384 (if (string-match 319 (substring rtn-path (match-end 0)))
385 (concat (regexp-quote suffix) "%s") rtn-path) 320 ;; add suffix
386 ;; remove suffix 321 (format rtn-path suffix))
387 (concat (substring rtn-path 0 (match-beginning 0)) 322 (format rtn-path "")))))))
388 (substring rtn-path (match-end 0)))
389 ;; add suffix
390 (format rtn-path suffix))
391 (format rtn-path ""))))))))
392 323
393 (defun hpath:relative-to (path &optional default-dir) 324 (defun hpath:relative-to (path &optional default-dir)
394 "Returns PATH relative to optional DEFAULT-DIR or `default-directory'. 325 "Returns PATH relative to optional DEFAULT-DIR or 'default-directory'.
395 Returns PATH unchanged when it is not a valid path." 326 Returns PATH unchanged when it is not a valid path."
396 (if (not (and (stringp path) (hpath:is-p path))) 327 (if (not (and (stringp path) (hpath:is-p path)))
397 path 328 path
398 (setq default-dir 329 (setq default-dir
399 (expand-file-name 330 (expand-file-name
416 (concat "../../" (substring path end-dir))) 347 (concat "../../" (substring path end-dir)))
417 (t path))))))) 348 (t path)))))))
418 349
419 (defun hpath:rfc (rfc-num) 350 (defun hpath:rfc (rfc-num)
420 "Return pathname to textual rfc document indexed by RFC-NUM. 351 "Return pathname to textual rfc document indexed by RFC-NUM.
421 See the documentation of the `hpath:rfc' variable." 352 See the documentation of the 'hpath:rfc' variable."
422 (format hpath:rfc rfc-num)) 353 (format hpath:rfc rfc-num))
423 354
424 (defun hpath:substitute-value (path) 355 (defun hpath:substitute-value (path)
425 "Substitutes matching value for Emacs Lisp variables and environment variables in PATH. 356 "Substitutes matching value for Emacs Lisp variables and environment variables in PATH.
426 Returns path with variable values substituted." 357 Returns path with variable values substituted."
441 (hpath:substitute-dir var-name rest-of-path)) 372 (hpath:substitute-dir var-name rest-of-path))
442 var-group)))) 373 var-group))))
443 t))) 374 t)))
444 375
445 (defun hpath:substitute-var (path) 376 (defun hpath:substitute-var (path)
446 "Replaces up to one match in PATH with first matching variable from `hpath:variables'." 377 "Replaces up to one match in PATH with first matching variable from 'hpath:variables'."
447 (if (not (and (stringp path) (string-match "/" path) (hpath:is-p path))) 378 (if (not (and (stringp path) (string-match "/" path) (hpath:is-p path)))
448 path 379 path
449 (setq path (hpath:symlink-referent path)) 380 (setq path (hpath:symlink-referent path))
450 (let ((new-path) 381 (let ((new-path)
451 (vars hpath:variables) 382 (vars hpath:variables)
463 (while (and val (null new-path)) 394 (while (and val (null new-path))
464 (if (setq result 395 (if (setq result
465 (hpath:substitute-var-name var (car val) path)) 396 (hpath:substitute-var-name var (car val) path))
466 (setq new-path result)) 397 (setq new-path result))
467 (setq val (cdr val)))) 398 (setq val (cdr val))))
468 (t (error "(hpath:substitute-var): `%s' has invalid value for hpath:variables" var)))))) 399 (t (error "(hpath:substitute-var): '%s' has invalid value for hpath:variables" var))))))
469 (or new-path path) 400 (or new-path path)
470 ))) 401 )))
471 402
472 ;; 403 ;;
473 ;; The following function recursively resolves all UNIX links to their 404 ;; The following function recursively resolves all UNIX links to their
474 ;; final referents. 405 ;; final referents.
475 ;; Works with Apollo's variant and other strange links like: 406 ;; Works with Apollo's variant and other strange links like:
476 ;; /usr/local -> $(SERVER_LOCAL)/usr/local, /usr/bin -> 407 ;; /usr/local -> $(SERVER_LOCAL)/usr/local, /usr/bin ->
477 ;; ../$(SYSTYPE)/usr/bin and /tmp -> `node_data/tmp. It also handles 408 ;; ../$(SYSTYPE)/usr/bin and /tmp -> `node_data/tmp. It also handles
478 ;; relative links properly as in /usr/local/emacs -> gnu/emacs which must 409 ;; relative links properly as in /usr/local/emacs -> gnu/emacs which must
479 ;; be resolved relative to the `/usr/local' directory. 410 ;; be resolved relative to the '/usr/local' directory.
480 ;; It will fail on Apollos if the `../' notation is used to move just 411 ;; It will fail on Apollos if the '../' notation is used to move just
481 ;; above the `/' directory level. This is fairly uncommon and so the 412 ;; above the '/' directory level. This is fairly uncommon and so the
482 ;; problem has not been fixed. 413 ;; problem has not been fixed.
483 ;; 414 ;;
484 (defun hpath:symlink-referent (linkname) 415 (defun hpath:symlink-referent (linkname)
485 "Returns expanded file or directory referent of LINKNAME. 416 "Returns expanded file or directory referent of LINKNAME.
486 LINKNAME should not end with a directory delimiter. 417 LINKNAME should not end with a directory delimiter.
545 476
546 (defun hpath:url-at-p () 477 (defun hpath:url-at-p ()
547 "Return world-wide-web universal resource locator (url) that point immediately precedes or nil. 478 "Return world-wide-web universal resource locator (url) that point immediately precedes or nil.
548 Use buffer-substring with match-beginning and match-end on the following 479 Use buffer-substring with match-beginning and match-end on the following
549 groupings: 480 groupings:
550 1 = optional `URL:' literal 481 1 = access protocol
551 2 = access protocol 482 2 = optional username
552 4 = optional username 483 3 = host and domain to connect to
553 4 = host and domain to connect to 484 4 = optional port number to use
554 5 = optional port number to use 485 5 = pathname to access."
555 6 = optional pathname to access." 486 ;; WWW URL format: <protocol>:/[<user>@]<domain>[:<port>]/<path>
556 ;; WWW URL format: [URL:]<protocol>:/[<user>@]<domain>[:<port>][/<path>] 487 ;; or <protocol>://[<user>@]<domain>[:<port>]<path>
557 ;; or [URL:]<protocol>://[<user>@]<domain>[:<port>][<path>]
558 ;; Avoid [a-z]:/path patterns since these may be disk paths on OS/2, DOS or 488 ;; Avoid [a-z]:/path patterns since these may be disk paths on OS/2, DOS or
559 ;; Windows. 489 ;; Windows.
560 (if (looking-at "\\(URL:\\)?\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?") 490 (if (looking-at "\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?")
561 (save-excursion 491 (save-excursion
562 (goto-char (match-end 0)) 492 (goto-char (match-end 0))
563 (skip-chars-backward ".,?#!*()") 493 (skip-chars-backward ".?#!*()")
564 (buffer-substring (match-beginning 2) (point))))) 494 (buffer-substring (match-beginning 0) (point)))))
565 495
566 (defun hpath:url-p (obj) 496 (defun hpath:url-p (obj)
567 "Return t if OBJ is a world-wide-web universal resource locator (url) string, else nil. 497 "Return t if OBJ is a world-wide-web universal resource locator (url) string, else nil.
568 Use string-match with match-beginning and match-end on the following groupings: 498 Use string-match with match-beginning and match-end on the following groupings:
569 1 = optional `URL:' literal 499 1 = access protocol
570 2 = access protocol 500 2 = optional username
571 3 = optional username 501 3 = host and domain to connect to
572 4 = host and domain to connect to 502 4 = optional port number to use
573 5 = optional port number to use 503 5 = pathname to access."
574 6 = optional pathname to access." 504 ;; WWW URL format: <protocol>:/[<user>@]<domain>[:<port>]/<path>
575 ;; WWW URL format: [URL:]<protocol>:/[<user>@]<domain>[:<port>][/<path>] 505 ;; or <protocol>://[<user>@]<domain>[:<port>]<path>
576 ;; or [URL:]<protocol>://[<user>@]<domain>[:<port>][<path>]
577 ;; Avoid [a-z]:/path patterns since these may be disk paths on OS/2, DOS or 506 ;; Avoid [a-z]:/path patterns since these may be disk paths on OS/2, DOS or
578 ;; Windows. 507 ;; Windows.
579 (and (stringp obj) 508 (and (stringp obj)
580 (string-match "\\`<?\\(URL:\\)?\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?>?\\'" 509 (string-match "\\`<?\\([a-zA-Z][a-zA-Z]+\\)://?\\([^@/: \t\n\^M]+@\\)?\\([^/:@ \t\n\^M\"`']+\\)\\(:[0-9]+\\)?\\([/~][^]@ \t\n\^M\"`'\)\}>]*\\)?>?\\'"
581 obj) 510 obj)
582 t)) 511 t))
583 512
584 (defun hpath:www-at-p (&optional include-start-and-end-p) 513 (defun hpath:www-at-p (&optional include-start-and-end-p)
585 "Returns a world-wide-web link reference that point is within or nil. 514 "Returns a world-wide-web link reference that point is within or nil.
588 (save-excursion 517 (save-excursion
589 (skip-chars-backward "^[ \t\n\"`'\(\{<") 518 (skip-chars-backward "^[ \t\n\"`'\(\{<")
590 (cond ((not include-start-and-end-p) 519 (cond ((not include-start-and-end-p)
591 (hpath:url-at-p)) 520 (hpath:url-at-p))
592 ((hpath:url-at-p) 521 ((hpath:url-at-p)
593 (list (buffer-substring (match-beginning 2) (match-end 0)) 522 (list (buffer-substring (match-beginning 0) (match-end 0))
594 (match-beginning 2) 523 (match-beginning 0)
595 (match-end 0)))))) 524 (match-end 0))))))
596 525
597 (defun hpath:www-p (path) 526 (defun hpath:www-p (path)
598 "Returns non-nil iff PATH is a world-wide-web link reference." 527 "Returns non-nil iff PATH is a world-wide-web link reference."
599 (and (stringp path) (hpath:url-p path) path)) 528 (and (stringp path) (hpath:url-p path) path))
603 ;;; ************************************************************************ 532 ;;; ************************************************************************
604 533
605 (defun hpath:ange-ftp-available-p () 534 (defun hpath:ange-ftp-available-p ()
606 "Return t if the ange-ftp or efs package is available, nil otherwise. 535 "Return t if the ange-ftp or efs package is available, nil otherwise.
607 Either the package must have been loaded already or under versions of Emacs 536 Either the package must have been loaded already or under versions of Emacs
608 19, it must be set for autoloading via `file-name-handler-alist'." 537 19, it must be set for autoloading via 'file-name-handler-alist'."
609 (or (featurep 'ange-ftp) (featurep 'efs) 538 (or (featurep 'ange-ftp) (featurep 'efs)
610 (and (boundp 'file-name-handler-alist) ; v19 539 (and (boundp 'file-name-handler-alist) ; v19
611 (or (rassq 'ange-ftp-hook-function file-name-handler-alist) 540 (or (rassq 'ange-ftp-hook-function file-name-handler-alist)
612 (rassq 'efs-file-handler-function file-name-handler-alist)) 541 (rassq 'efs-file-handler-function file-name-handler-alist))
613 t))) 542 t)))
664 return-path)))) 593 return-path))))
665 594
666 (defun hpath:find-program (filename) 595 (defun hpath:find-program (filename)
667 "Return shell or Lisp command to execute to display FILENAME or nil. 596 "Return shell or Lisp command to execute to display FILENAME or nil.
668 Return nil if FILENAME is a directory name. 597 Return nil if FILENAME is a directory name.
669 See also documentation for `hpath:find-alist' and `hpath:display-alist'." 598 See also documentation for 'hpath:find-alist' and 'hpath:display-alist'."
670 (let ((cmd)) 599 (let ((cmd))
671 (cond ((and (stringp filename) (file-directory-p filename)) 600 (cond ((and (stringp filename) (file-directory-p filename))
672 nil) 601 nil)
673 ((stringp (setq cmd (hpath:match filename hpath:find-alist))) 602 ((stringp (setq cmd (hpath:match filename hpath:find-alist)))
674 (let ((orig-path filename)) 603 (let ((orig-path filename))
708 VAR-NAME's value may be a directory or a list of directories. If it is a 637 VAR-NAME's value may be a directory or a list of directories. If it is a
709 list, the first directory prepended to REST-OF-PATH which produces a valid 638 list, the first directory prepended to REST-OF-PATH which produces a valid
710 local pathname is returned." 639 local pathname is returned."
711 (let (sym val) 640 (let (sym val)
712 (cond ((not (stringp var-name)) 641 (cond ((not (stringp var-name))
713 (error "(hpath:substitute-dir): VAR-NAME arg, `%s', must be a string" var-name)) 642 (error "(hpath:substitute-dir): VAR-NAME arg, '%s', must be a string" var-name))
714 ((not (and (setq sym (intern-soft var-name)) 643 ((not (and (setq sym (intern-soft var-name))
715 (boundp sym))) 644 (boundp sym)))
716 (error "(hpath:substitute-dir): VAR-NAME arg, \"%s\", is not a bound variable" 645 (error "(hpath:substitute-dir): VAR-NAME arg, \"%s\", is not a bound variable"
717 var-name)) 646 var-name))
718 ((stringp (setq val (symbol-value sym))) 647 ((stringp (setq val (symbol-value sym)))