Mercurial > hg > xemacs-beta
view lisp/efs/efs-tops-20.el @ 100:4be1180a9e89 r20-1b2
Import from CVS: tag r20-1b2
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:15:11 +0200 |
parents | 8fc7fe29b841 |
children | 8b8b7f3559a2 8619ce7e4c50 |
line wrap: on
line source
;; -*-Emacs-Lisp-*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; File: efs-tops-20.el ;; Release: $efs release: 1.15 $ ;; Version: $Revision: 1.1 $ ;; RCS: ;; Description: TOPS-20 support for efs ;; Author: Sandy Rutherford <sandy@math.ubc.ca, sandy@itp.ethz.ch> ;; Created: Fri Oct 23 08:52:00 1992 ;; Modified: Sun Nov 27 18:43:45 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. (require 'efs) (provide 'efs-tops-20) (defconst efs-tops-20-version (concat (substring "$efs release: 1.15 $" 14 -2) "/" (substring "$Revision: 1.1 $" 11 -2))) ;;;; ------------------------------------------------------------ ;;;; TOPS-20 support ;;;; ------------------------------------------------------------ (efs-defun efs-send-pwd tops-20 (host user &optional xpwd) ;; pwd doesn't work for tops-20. Need to get the cwd from a dir listing ;; this function returns the cwd in tops-20 syntax (let* ((temp (efs-make-tmp-name host nil)) (cmd (concat "dir * " (cdr temp))) dir u-dir full-dir result) (unwind-protect (if (null (and (car (setq result (efs-raw-send-cmd (efs-get-process host user) cmd "Getting TOPS-20 PWD"))) (progn (condition-case () (delete-file (car temp)) (error nil)) (car (setq result (efs-raw-send-cmd (efs-get-process host user) cmd "Trying to get TOPS-20 PWD, again.")))))) (save-excursion (set-buffer (get-buffer-create efs-data-buffer-name)) (erase-buffer) (if (or (file-readable-p (car temp)) (sleep-for efs-retry-time) (file-readable-p (car temp))) ;; Try again. (insert-file-contents (car temp)) (efs-error host user (format "list data file %s not readable" (car temp)))) ;; get the cwd (goto-char (point-min)) (efs-save-match-data (if (looking-at "[^ /:]+:<[^<>/ ]+>") (progn (setq dir (buffer-substring (match-beginning 0) (match-end 0)) u-dir (efs-internal-directory-file-name (efs-fix-path 'tops-20 dir t)) full-dir (format efs-path-format-string user host u-dir)) ;; cache the files too (efs-set-files full-dir (efs-parse-listing 'tops-20 host user u-dir full-dir)) (efs-add-to-ls-cache full-dir nil (buffer-string) t)))))) (efs-del-tmp-name (car temp))) (cons dir (nth 1 result)))) (efs-defun efs-fix-path tops-20 (path &optional reverse) ;; Convert PATH from UNIX-ish to tops-20. If REVERSE given, then ;; do just that. (efs-save-match-data (if reverse (if (string-match "^\\([^:]+:\\)?<\\([^>.][^>]*\\)>.*$" path) (let ((device (and (match-beginning 1) (substring path (match-beginning 1) (match-end 1)))) (dir (substring path (match-beginning 2) (match-end 2))) (file (substring path (1+ (match-end 2))))) (while (string-match "\\." dir) (setq dir (concat (substring dir 0 (match-beginning 0)) "/" (substring dir (match-end 0))))) (if device (setq dir (concat "/" device "/" dir))) (concat dir file)) (error "path %s didn't match tops-20 syntax" path)) (if (string-match "^\\(/[^:/]+:/\\)?\\([^./]+/\\)*\\([^/]*\\)$" path) (let ((device (and (match-beginning 1) (substring path 1 (1- (match-end 1))))) (dir (and (match-beginning 2) (substring path (match-beginning 2) (1- (match-end 2))))) (file (substring path (match-beginning 3) (match-end 3)))) (if dir (progn (while (string-match "/" dir) (setq dir (concat (substring dir 0 (match-beginning 0)) "." (substring dir (match-end 0))))) (if device (concat device "<" dir ">" file) (concat "<" dir ">" file))) (if device (error "%s is invalid relative syntax for tops-20" path) file))) (error "path %s is invalid syntax for tops-20" path))))) (efs-defun efs-fix-dir-path tops-20 (dir-path) ;; Convert a path from UNIX-ish to Tops-20 fir a dir listing. (cond ((string-equal "/" dir-path) (error "Can't list tops-20 devices")) ((string-match "/[^:/]+:/$" dir-path) (error "Can't list all root directories on a tops-20 device")) ((efs-fix-path 'tops-20 dir-path nil)))) ;; In tops-20 listings, the filename starts immediatley after the date regexp. (defconst efs-tops-20-date-regexp (concat " [1-3]?[0-9]-\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct" "\\|Nov\\|Dec\\)-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ")) (efs-defun efs-parse-listing tops-20 (host user dir path &optional switches) ;; Parse the current buffer which is assumed to be a TOPS-20 directory ;; listing, and return a hashtable as the result. ;; 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) (let ((tbl (efs-make-hashtable)) file) (goto-char (point-min)) (efs-save-match-data (if (looking-at " *[^/:]+:<\\([^/.<>]+\\.\\)+> *$") ;; looking at the directory name (forward-line 1)) (while (re-search-forward efs-tops-20-date-regexp nil t) (setq file (buffer-substring (point) (progn (end-of-line) (point)))) (if (string-match "\\.DIRECTORY\\.[0-9]+$" file) ;; deal with directories (efs-put-hash-entry (substring file 0 (match-beginning 0)) '(t) tbl) (efs-put-hash-entry file '(nil) tbl) ;; sans extension (if (string-match "\\.[0-9]+$" file) (efs-put-hash-entry (substring file 0 (match-beginning 0)) '(nil) tbl))) (forward-line 1)) (efs-put-hash-entry "." '(t) tbl) (efs-put-hash-entry ".." '(t) tbl)) tbl)) (efs-defun efs-really-file-p tops-20 (file ent) ;; Eliminates the version entries (or (car ent) ; file-directory-p (efs-save-match-data (string-match "\\.[0-9]+$" file)))) (efs-defun efs-delete-file-entry tops-20 (path &optional dir-p) (let ((ignore-case (memq 'tops-20 efs-case-insensitive-host-types))) (if dir-p (let ((path (file-name-as-directory path)) files) (efs-del-hash-entry path efs-files-hashtable ignore-case) (setq path (directory-file-name path) files (efs-get-hash-entry (file-name-directory path) efs-files-hashtable ignore-case)) (if files (efs-del-hash-entry (efs-get-file-part path) files ignore-case))) (efs-save-match-data (let ((file (efs-get-file-part path))) (if (string-match "\\.[0-9]+$" file) ;; Only delete explicit versions (let ((files (efs-get-hash-entry (file-name-directory path) efs-files-hashtable ignore-case))) (if files (let ((root (substring file 0 (match-beginning 0))) (completion-ignore-case ignore-case) (len (match-beginning 0))) (efs-del-hash-entry file files ignore-case) ;; Now we need to check if there are any ;; versions left. If not, then delete the ;; root entry. (or (all-completions root files (function (lambda (sym) (string-match "\\.[0-9]+$" (symbol-name sym) len)))) (efs-del-hash-entry root files ignore-case))))))))) (efs-del-from-ls-cache path t ignore-case))) (efs-defun efs-add-file-entry tops-20 (path dir-p size owner &optional modes nlinks mdtm) ;; The tops-20 version of this function needs to keep track ;; of tops-20's file versions. (let ((ignore-case (memq 'tops-20 efs-case-insensitive-host-types)) (ent (let ((dir-p (null (null dir-p)))) (if mdtm (list dir-p size owner nil nil mdtm) (list dir-p size owner))))) (if dir-p (let* ((path (directory-file-name path)) (files (efs-get-hash-entry (file-name-directory path) efs-files-hashtable ignore-case))) (if files (efs-put-hash-entry (efs-get-file-part path) ent files ignore-case))) (let ((files (efs-get-hash-entry (file-name-directory path) efs-files-hashtable ignore-case))) (if files (let ((file (efs-get-file-part path))) (efs-save-match-data (if (string-match "\\.[0-9]+$" file) (efs-put-hash-entry (substring file 0 (match-beginning 0)) ent files ignore-case) ;; Need to figure out what version of the file ;; is being added. (let* ((completion-ignore-case ignore-case) (len (length file)) (versions (all-completions file files (function (lambda (sym) (string-match "\\.[0-9]+$" (symbol-name sym) len))))) (N (1+ len)) (max (apply 'max (cons 0 (mapcar (function (lambda (x) (string-to-int (substring x N)))) versions))))) ;; No need to worry about case here. (efs-put-hash-entry (concat file "." (int-to-string (1+ max))) ent files)))) (efs-put-hash-entry file ent files ignore-case))))) (efs-del-from-ls-cache path t ignore-case))) (efs-defun efs-internal-file-name-as-directory tops-20 (name) (efs-save-match-data (if (string-match "\\.DIRECTORY\\(\\.[0-9>]\\)?$" name) (setq name (substring name 0 (match-beginning 0)))) (let (file-name-handler-alist) (file-name-as-directory name)))) ;;; Tree Dired (defconst efs-dired-tops-20-re-dir "^[^\n]+\\.DIRECTORY\\(\\.[0-9]+\\)?$") (or (assq 'tops-20 efs-dired-re-dir-alist) (setq efs-dired-re-dir-alist (cons (cons 'tops-20 efs-dired-tops-20-re-dir) efs-dired-re-dir-alist))) (efs-defun efs-dired-manual-move-to-filename tops-20 (&optional raise-error bol eol) ;; In dired, move to first char of filename on this line. ;; Returns position (point) or nil if no filename on this line. ;; This is the Tops-20 version. (or eol (setq eol (save-excursion (skip-chars-forward "^\n\r") (point)))) (let (case-fold-search) (if bol (goto-char bol) (skip-chars-backward "^\n\r")) (if (re-search-forward efs-tops-20-date-regexp eol t) (point) (and raise-error (error "No file on this line"))))) (efs-defun efs-dired-manual-move-to-end-of-filename tops-20 (&optional no-error bol eol) ;; Assumes point is at 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 Tops-20 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." ))))) ;; Is this the right character set? (skip-chars-forward "-_A-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-internal--file-name-sans-versions tops-20 (name &optional keep-backup-version) (efs-save-match-data (if (string-match "\\.[0-9]+$" name) (substring name 0 (match-beginning 0)) name))) (efs-defun efs-dired-insert-headerline tops-20 (dir) ;; TOPS-20 inserts a headerline. I would prefer the headerline ;; to be in efs format. This version tries to ;; be careful, because we can't count on a headerline ;; over ftp, and we wouldn't want to delete anything ;; important. (save-excursion (if (looking-at "^ wildcard ") (forward-line 1)) (if (looking-at "^[ \n\t]*[^:/<>]+:<[^<>/]+> *\n") (delete-region (point) (match-end 0))) (insert " " (directory-file-name dir) ":\n\n"))) ;;; end of efs-tops-20.el