Mercurial > hg > xemacs-beta
view lisp/efs/efs-ti-twenex.el @ 102:a145efe76779 r20-1b3
Import from CVS: tag r20-1b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:15:49 +0200 |
parents | 8fc7fe29b841 |
children | 8b8b7f3559a2 8619ce7e4c50 |
line wrap: on
line source
;; -*-Emacs-Lisp-*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; File: efs-ti-twenex.el ;; Release: $efs release: 1.15 $ ;; Version: $Revision: 1.1 $ ;; RCS: ;; Description: Support for a TI lisp machine in Twenex emulation mode. ;; Author: Jamie Zawinski <jwz@lucid.com> ;; Created: Thu Dec 17 15:04:14 1992 ;; Modified: Sun Nov 27 18:43:17 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. (provide 'efs-ti-twenex) (require 'efs) (defconst efs-ti-twenex-version (concat (substring "$efs release: 1.15 $" 14 -2) "/" (substring "$Revision: 1.1 $" 11 -2))) ;;;; ------------------------------------------------------------ ;;;; Twenex support. ;;;; ------------------------------------------------------------ ;;; Written for an explorer in ti-twenex mode. Twenex is supposed to be just ;;; MIT's name for tops-20, but an explorer emulating twenex is not the same ;;; thing. (defconst efs-ti-twenex-filename-regexp (let* ((excluded-chars ":;<>.#\n\r\ta-z") (token (concat "[^" excluded-chars "]+")) (token* (concat "[^" excluded-chars "]*"))) (concat "\\(" token ": *" "\\)?" ; optional device "<\\(" token "\\)?\\(\\." token "\\)*> *" ; directory "\\(" token* "." token* "\\|\\) *" ; name and extension "\\(\\. *-?\\([0-9]+\\|>\\)\\)?"))) ; version ;;; The above isn't entirely accurate, because "/" can quote any character ;;; anywhere in a pathname. (efs-defun efs-fix-path ti-twenex (path &optional reverse) ;; Convert PATH from UNIX-ish to Twenex. If REVERSE given then convert ;; from Twenex to UNIX-ish. (efs-save-match-data (if reverse (if (string-match "^\\([^:]+:\\)? *\\([^:]+:\\)? *<\\([^>]*\\)> *\\(.*\\)$" path) (let (dir file) ;; I don't understand how "devices" work, so I'm ignoring them. ;; (if (match-beginning 2) ;; (setq device (substring path ;; (match-beginning 2) ;; (1- (match-end 2))))) (if (match-beginning 3) (setq dir (substring path (match-beginning 3) (match-end 3)))) (if (match-beginning 4) (setq file (substring path (match-beginning 4) (match-end 4)))) (cond (dir (setq dir (apply (function concat) (mapcar (function (lambda (char) (if (= char ?.) (vector ?/) (vector char)))) dir))) (if (string-match "^/" dir) (setq dir (substring dir 1)) (setq dir (concat "/" dir))))) (concat ;; (and device ":") device (and device ":") dir (and dir "/") file)) (error "path %s didn't match ti-twenex syntax" path)) (let (dir file tmp) ;; (if (string-match "^/[^:]+:" path) ;; (setq device (substring path 1 ;; (1- (match-end 0))) ;; path (substring path (match-end 0)))) (cond ((setq tmp (file-name-directory path)) (setq dir (apply (function concat) (mapcar (function (lambda (char) (if (= char ?/) (vector ?.) (vector char)))) (substring tmp 0 -1)))) (if (string-match "^[.]" dir) (setq dir (substring dir 1)) (setq dir (concat "." dir))))) (setq file (file-name-nondirectory path)) (concat ;; (and device ":") device (and device ":") (and dir "<") dir (and dir ">") file))))) ;; (efs-fix-path-for-twenex "/PUBLIC/ZMACS/ZYMURG.LISP.1") ;; (efs-fix-path-for-twenex "<PUBLIC.ZMACS>ZYMURG.LISP.1" t) (efs-defun efs-fix-dir-path ti-twenex (dir-path) ;; Convert path from UNIX-ish to Explorer ready for a DIRectory listing. (cond ((string-equal dir-path "/") (efs-fix-path 'ti-twenex "/~/" nil)) ((string-match "^/[-A-Z0-9_$]+:/" dir-path) (error "Don't grok TWENEX \"devices\" yet.")) ((efs-fix-path 'ti-twenex dir-path nil)))) (defmacro efs-parse-ti-twenex-filename () ;; Extract the next filename from an Explorer dired-like listing. (` (if (re-search-forward efs-ti-twenex-filename-regexp nil t) (buffer-substring (match-beginning 0) (match-end 0))))) (efs-defun efs-parse-listing ti-twenex (host user dir path &optional switches) ;; Parse the current buffer which is assumed to be a TWENEX 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 (while (setq file (efs-parse-ti-twenex-filename)) ;; Explorer/Twenex listings might come out in absolute form. (if (string-match "^[^>]*> *" file) (setq file (substring file (match-end 0)))) (if (string-match "\\.\\(DIRECTORY\\|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) (if (string-match "\\.[0-9]+$" file) ; deal with extension ;; sans extension (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 ti-twenex (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 ti-twenex (path &optional dir-p) (let ((ignore-case (memq 'ti-twenex 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 versions with explicit version numbers. (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 ti-twenex (path dir-p size owner &optional modes nlinks mdtm) ;; The ti-twenex version of this function needs to keep track ;; of ti-twenex's file versions. (let ((ignore-case (memq 'ti-twenex 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 ti-twenex (name) (efs-save-match-data (if (string-match "\\.\\(DIRECTORY\\|directory\\)\\(\\.[0-9>]\\)?$" name) (setq name (substring name 0 (match-beginning 0)))) (let (file-name-handler-alist) (file-name-as-directory name)))) (efs-defun efs-allow-child-lookup ti-twenex (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. ;; Subdirs in TI-TWENEX can't have an extension (other than .DIRECTORY, ;; which we have truncated). (not (string-match "\\." file))) ;;; Tree Dired (defconst efs-dired-ti-twenex-re-dir "^. *[^>\n\r]+>[^>\n\r.]+\\.\\(DIRECTORY\\|directory\\)\\b" "Regular expression to use to search for TWENEX directories.") (or (assq 'ti-twenex efs-dired-re-dir-alist) (setq efs-dired-re-dir-alist (cons (cons 'ti-twenex efs-dired-ti-twenex-re-dir) efs-dired-re-dir-alist))) (efs-defun efs-dired-manual-move-to-filename ti-twenex (&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 Twenex 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-ti-twenex-filename-regexp eol t) (progn (goto-char (match-beginning 0)) ;; Twenex listings might come out in absolute form. (if (looking-at "[^>]*> *") (goto-char (match-end 0)) (point))) (and raise-error (error "No file on this line"))))) (efs-defun efs-dired-manual-move-to-end-of-filename ti-twenex (&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 Explorer version. (let (case-fold-search) (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." ))))) (if (looking-at efs-ti-twenex-filename-regexp) (goto-char (match-end 0)) (if no-error nil (error "No file on this line"))))) (efs-defun efs-internal-file-name-sans-versions ti-twenex (name &optional keep-backup-version) (efs-save-match-data (if (string-match "\\.[0-9]+$" name) (substring name 0 (match-beginning 0)) name))) ;;; ### still need to ape these from vms: ;;; efs-dired-vms-clean-directory ;;; efs-dired-vms-collect-file-versions ;;; efs-dired-vms-trample-file-versions ;;; efs-dired-vms-flag-backup-files ;;; efs-dired-vms-backup-diff ;;; end of efs-ti-twenex.el