Mercurial > hg > xemacs-beta
diff lisp/efs/efs-vos.el @ 22:8fc7fe29b841 r19-15b94
Import from CVS: tag r19-15b94
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:50:29 +0200 |
parents | |
children | 8b8b7f3559a2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/efs/efs-vos.el Mon Aug 13 08:50:29 2007 +0200 @@ -0,0 +1,285 @@ +;; -*-Emacs-Lisp-*- +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; File: efs-vos.el +;; Description: VOS support for efs +;; Release: $efs release: 1.15 $ +;; Version: $Revision: 1.1 $ +;; RCS: +;; Author: Sandy Rutherford <sandy@ibm550.sissa.it> +;; Created: Sat Apr 3 03:05:00 1993 by sandy on ibm550 +;; Modified: Sun Nov 27 18:45:24 1994 by sandy on gandalf +;; Language: Emacs-Lisp +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; This file is part of efs. See efs.el for copyright +;;; (it's copylefted) and warrranty (there isn't one) information. + +;;; The original ange-ftp VOS support was written by Joe Wells <jbw@cs.bu.edu> + +;;; Thank you to Jim Franklin <jimf%shared@uunet.uu.net> for providing +;;; information on the VOS operating system. + +(provide 'efs-vos) +(require 'efs) + +(defconst efs-vos-version + (concat (substring "$efs release: 1.15 $" 14 -2) + "/" + (substring "$Revision: 1.1 $" 11 -2))) + +;;;;--------------------------------------------------------------- +;;;; VOS support for efs +;;;;--------------------------------------------------------------- + +;;; A legal VOS pathname is of the form: +;;; %systemname#diskname>dirname>dirname>dir-or-filename +;;; +;;; Each of systemname, diskname, dirname, dir-or-filename can be +;;; at most 32 characters. +;;; Valid characters are all alpha, upper and lower case, all digits, +;;; plus: @[]\^`{|}~"$+,-./:_ +;;; restrictions: name cannot begin with hyphen (-) or period (.) +;;; name must not end with a period (.) +;;; name must not contain two adjacent periods (.) +;;; +;;; Invalid characters are: +;;; non-printing control characters +;;; SPACE and DEL +;;; !#%&'()*;<=>? +;;; all other ascii chars +;;; +;;; The full pathname must be less than or equal to 256 characters. +;;; VOS pathnames are CASE-SENSITIVE. +;;; The may be a directory depth limitation of 10 (newer versions may have +;;; eliminated this). + +;;; entry points + +(efs-defun efs-fix-path vos (path &optional reverse) + ;; Convert PATH from UNIX-ish to VOS. + ;; If REVERSE given then convert from VOS to UNIX-ish. + ;; Does crude checking for valid path syntax, but is by no means exhaustive. + (efs-save-match-data + (if reverse + (if (string-match "^\\(\\(%[^#>%]+\\)?#[^>#%]+\\)?>[^>#%]" path) + (let ((marker (1- (match-end 0))) + (result "/") + system drive) + (if (match-beginning 1) + (if (match-beginning 2) + (setq system (substring path 1 (match-end 2)) + drive (substring path (1+ (match-end 2)) + (match-end 1))) + (setq drive (substring 1 (match-end 1))))) + (while (string-match ">" path marker) + (setq result (concat result + (substring path marker + (match-beginning 0)) + "/") + marker (match-end 0))) + (if drive + (if system + (concat "/" system "/" drive result + (substring path marker)) + (concat "/" drive result (substring path marker))) + (concat result (substring path marker)))) + (error "Invalid VOS pathname %s" path)) + (if (string-match "^/\\([^/]+\\)/\\([^/]+\\)/[^/]" path) + (let ((marker (1- (match-end 0))) + (result (concat "%" + (substring path + (match-beginning 1) + (match-end 1)) + "#" + (substring path + (match-beginning 2) + (match-end 2)) + ">"))) + ;; I'm guessing that VOS doesn't have a directory syntax. + (setq path (efs-internal-directory-file-name path)) + (while (string-match "/" path marker) + (setq result + (concat result + (substring path marker + (match-beginning 0)) + ">") + marker (match-end 0))) + (concat result (substring path marker))) + (error "Cannot convert path %s to VOS." path))))) + +(efs-defun efs-fix-dir-path vos (dir-path) + ;; Convert path from UNIX-ish to VMS ready for a DIRectory listing. + (cond ((string-equal dir-path "/") + (error "Cannot gork VOS system names")) + ((string-match "^/[^/]/$" dir-path) + (error "Cannot grok VOS devices")) + ((efs-fix-path 'vos dir-path)))) + +(defconst efs-vos-date-and-time-regexp + (concat + "\\(^\\| \\)" ; For links, this must match at the beginning of the line. + "[678901][0-9]-[01][0-9]-[0-3][0-9] [012][0-9]:[0-6][0-9]:[0-6][0-9] ")) +;; Regexp to match a VOS file line. The end of the regexp must correspond +;; to the start of the filename. + +(defmacro efs-vos-parse-filename () + ;; Return the VOS filename on the current line of a listing. + ;; Assumes that the point is at the beginning of the line. + ;; Return nil if no filename is found. + (` (let ((eol (save-excursion (end-of-line) (point)))) + (and (re-search-forward efs-vos-date-and-time-regexp eol t) + (buffer-substring (point) eol))))) + +(efs-defun efs-parse-listing vos + (host user dir path &optional switches) + ;; Parse the current buffer which is assumed to be in MultiNet FTP dir + ;; format, and return a hashtable as the result. SWITCHES are never used, + ;; but they must be specified in the argument list for compatibility + ;; with the unix version of this function. + ;; HOST = remote host name + ;; USER = user name + ;; DIR = directory in as a full remote path + ;; PATH = directory in full efs path syntax + ;; SWITCHES = ls switches (not relevant here) + (goto-char (point-min)) + (efs-save-match-data + (let (tbl file) + ;; Look file files. + (if (search-forward "\nFiles: " nil t) + (progn + (setq tbl (efs-make-hashtable)) + (forward-line 1) + (skip-chars-forward "\n") + (while (setq file (efs-vos-parse-filename)) + (efs-put-hash-entry file '(nil) tbl) + (forward-line 1)))) + ;; Look for directories. + (if (search-forward "\nDirs: " nil t) + (progn + (or tbl (setq tbl (efs-make-hashtable))) + (forward-line 1) + (skip-chars-forward "\n") + (while (setq file (efs-vos-parse-filename)) + (efs-put-hash-entry file '(t) tbl) + (forward-line 1)))) + ;; Look for links + (if (search-forward "\nLinks: " nil t) + (let (link) + (or tbl (setq tbl (efs-make-hashtable))) + (forward-line 1) + (skip-chars-forward "\n") + (while (setq file (efs-vos-parse-filename)) + (if (string-match " -> \\([^ ]+\\)" file) + ;; VOS puts a trailing blank after the name of a symlink + ;; target. Go figure... + (setq link (substring file (match-beginning 1) (match-end 1)) + file (substring file 0 (match-beginning 0))) + (setq link "")) ; weird? + (efs-put-hash-entry file (list link) tbl) + (forward-line 1)))) + ;; This returns nil if no headings for files, dirs, or links + ;; are found. In this case, we're assuming that it isn't a valid + ;; listing. + (if tbl + (progn + (efs-put-hash-entry "." '(t) tbl) + (efs-put-hash-entry ".." '(t) tbl))) + tbl))) + +(efs-defun efs-allow-child-lookup vos (host user dir file) + ;; Returns t if FILE in directory DIR could possibly be a subdir + ;; according to its file-name syntax, and therefore a child listing should + ;; be attempted. + ;; Directoried don't have a size. + (string-match ": not a file\\.$" + (cdr (efs-send-size host user (concat dir file))))) + +;;; Tree Dired Support + +(defconst efs-dired-vos-re-exe + "^. +e ") + +(or (assq 'vos efs-dired-re-exe-alist) + (setq efs-dired-re-exe-alist + (cons (cons 'vos efs-dired-vos-re-exe) + efs-dired-re-exe-alist))) + +(defconst efs-dired-vos-re-dir + "^. +[nsm] +[0-9]+ +[678901][0-9]-") + +(or (assq 'vos efs-dired-re-dir-alist) + (setq efs-dired-re-dir-alist + (cons (cons 'vos efs-dired-vos-re-dir) + efs-dired-re-dir-alist))) + +(efs-defun efs-dired-manual-move-to-filename vos + (&optional raise-error bol eol) + ;; In dired, move to the first char of filename on this line, where + ;; line can be delimited by either \r or \n. + ;; Returns (point) or nil if raise-error is nil and there is no + ;; filename on this line. In the later case, leaves the point at the + ;; beginning of the line. + ;; This version is for VOS. + (or eol (setq eol (save-excursion (skip-chars-forward "^\r\n") (point)))) + (let (case-fold-search) + (if bol + (goto-char bol) + (skip-chars-backward "^\n\r")) + (if (re-search-forward efs-vos-date-and-time-regexp eol t) + (point) + (and raise-error (error "No file on this line"))))) + +(efs-defun efs-dired-manual-move-to-end-of-filename vos + (&optional no-error bol eol) + ;; Assumes point is at the beginning of filename. + ;; So, it should be called only after (dired-move-to-filename t) + ;; On failure signals an error, or returns nil. + ;; This is the VOS version. + (let ((opoint (point))) + (and selective-display + (null no-error) + (eq (char-after + (1- (or bol (save-excursion + (skip-chars-backward "^\r\n") + (point))))) + ?\r) + ;; File is hidden or omitted. + (cond + ((dired-subdir-hidden-p (dired-current-directory)) + (error + (substitute-command-keys + "File line is hidden. Type \\[dired-hide-subdir] to unhide."))) + ((error + (substitute-command-keys + "File line is omitted. Type \\[dired-omit-toggle] to un-omit." + ))))) + (skip-chars-forward "-a-zA-Z0-9@[]\\^`{|}~\"$+,./:_") + (if (or (= opoint (point)) (not (memq (following-char) '(?\n ?\r ?\ )))) + (if no-error + nil + (error "No file on this line")) + (point)))) + +(efs-defun efs-dired-fixup-listing vos (file path &optional switches wildcard) + ;; VOS listing contain some empty lines, which is inconvenient for dired. + (goto-char (point-min)) + (skip-chars-forward "\n") + (delete-region (point-min) (point)) + (while (search-forward "\n\n" nil t) + (forward-char -2) + (delete-char 1))) + +(efs-defun efs-dired-ls-trim vos () + ;; Trims VOS dir listings for single files, so that they are exactly one line + ;; long. + (goto-char (point-min)) + (let (case-fold-search) + (re-search-forward efs-vos-date-and-time-regexp)) + (beginning-of-line) + (delete-region (point-min) (point)) + (forward-line 1) + (delete-region (point) (point-max))) + +;;; end of efs-vos.el