[climacs-cvs] CVS climacs

dmurray dmurray at common-lisp.net
Sat May 6 06:27:14 UTC 2006


Update of /project/climacs/cvsroot/climacs
In directory clnet:/tmp/cvs-serv6143

Modified Files:
	pane.lisp packages.lisp file-commands.lisp 
Log Message:
Changed backup behaviour. Now makes emacs-style versioned backups
(foo.lisp~42~) once per session. Also checks to see if the file
has changed on disk when saving and reverting.


--- /project/climacs/cvsroot/climacs/pane.lisp	2006/04/23 19:37:58	1.37
+++ /project/climacs/cvsroot/climacs/pane.lisp	2006/05/06 06:27:14	1.38
@@ -227,8 +227,10 @@
 
 (defparameter +climacs-textual-view+ (make-instance 'climacs-textual-view))
 
-(defclass filepath-mixin ()
-  ((filepath :initform nil :accessor filepath)))
+(defclass file-mixin ()
+  ((filepath :initform nil :accessor filepath)
+   (file-saved-p :initform nil :accessor file-saved-p)
+   (file-write-time :initform nil :accessor file-write-time)))
 
 ;(defgeneric indent-tabs-mode (climacs-buffer))
 
@@ -238,7 +240,7 @@
 (defclass extended-binseq2-buffer (read-only-mixin binseq2-buffer p-undo-mixin abbrev-mixin) ()
   (:documentation "Extensions accessible via marks."))
 
-(defclass climacs-buffer (delegating-buffer filepath-mixin name-mixin)
+(defclass climacs-buffer (delegating-buffer file-mixin name-mixin)
   ((needs-saving :initform nil :accessor needs-saving)
    (syntax :accessor syntax)
    (point :initform nil :initarg :point :accessor point)
--- /project/climacs/cvsroot/climacs/packages.lisp	2006/05/01 18:36:41	1.91
+++ /project/climacs/cvsroot/climacs/packages.lisp	2006/05/06 06:27:14	1.92
@@ -145,7 +145,8 @@
 (defpackage :climacs-pane
   (:use :clim-lisp :clim :climacs-buffer :climacs-base :climacs-abbrev
 	:climacs-syntax :flexichain :undo)
-  (:export #:climacs-buffer #:needs-saving #:filepath
+  (:export #:climacs-buffer #:needs-saving
+	   #:filepath #:file-saved-p #:file-write-time
 	   #:read-only-p #:buffer-read-only
 	   #:climacs-pane #:point #:mark
            #:clear-cache
--- /project/climacs/cvsroot/climacs/file-commands.lisp	2006/05/04 18:53:52	1.10
+++ /project/climacs/cvsroot/climacs/file-commands.lisp	2006/05/06 06:27:14	1.11
@@ -212,7 +212,7 @@
 	       (switch-to-buffer existing-buffer)
 	       (let ((buffer (make-buffer))
 		     (pane (current-window)))
-                 ;; Clear the panes cache; otherwise residue from the
+                 ;; Clear the pane's cache; otherwise residue from the
                  ;; previously displayed buffer may under certain
                  ;; circumstances be displayed.
                  (clear-cache pane)
@@ -223,6 +223,7 @@
 		 (when (probe-file filepath)
 		   (with-open-file (stream filepath :direction :input)
 		     (input-from-stream stream buffer 0))
+		   (setf (file-write-time buffer) (file-write-date filepath))
                    ;; A file! That means we may have a local options
                    ;; line to parse.
                    (evaluate-local-options-line buffer))
@@ -242,7 +243,7 @@
 
 (defun directory-of-buffer (buffer)
   "Extract the directory part of the filepath to the file in BUFFER.
-   If BUFFER does not have a filepath, the path to the users home 
+   If BUFFER does not have a filepath, the path to the user's home 
    directory will be returned."
   (make-pathname
    :directory
@@ -324,6 +325,8 @@
 
 (defun set-visited-file-name (filename buffer)
   (setf (filepath buffer) filename
+	(file-saved-p buffer) nil
+	(file-write-time buffer) nil
 	(name buffer) (filepath-filename filename)
 	(needs-saving buffer) t))
 
@@ -371,15 +374,51 @@
 	   (display-message "~A is a directory name." filepath)
 	   (beep))
 	  ((probe-file filepath)
+	   (unless (check-file-times buffer filepath "Revert" "reverted")
+	     (return-from com-revert-buffer))
 	   (erase-buffer buffer)
 	   (with-open-file (stream filepath :direction :input)
 	     (input-from-stream stream buffer 0))
-	   (setf (offset (point pane))
-		 (min (size buffer) save)))
+	   (setf (offset (point pane)) (min (size buffer) save)
+		 (file-saved-p buffer) nil))
 	  (t
 	   (display-message "No file ~A" filepath)
 	   (beep))))))
 
+(defun extract-version-number (pathname)
+  "Extracts the emacs-style version-number from a pathname."
+  (let* ((type (pathname-type pathname))
+	 (length (length type)))
+    (when (and (> length 2) (char= (char type (1- length)) #\~))
+      (let ((tilde (position #\~ type :from-end t :end (- length 2))))
+	(when tilde
+	  (parse-integer type :start (1+ tilde) :junk-allowed t))))))
+
+(defun version-number (pathname)
+  "Return the number of the highest versioned backup of PATHNAME
+or 0 if there is no versioned backup. Looks for name.type~X~,
+returns highest X."
+  (let* ((wildpath (merge-pathnames (make-pathname :type :wild) pathname))
+	 (possibilities (directory wildpath)))
+    (loop for possibility in possibilities
+	  for version = (extract-version-number possibility) 
+	  if (numberp version)
+	    maximize version into max
+	  finally (return max))))
+
+(defun check-file-times (buffer filepath question answer)
+  "Return NIL if filepath newer than buffer and user doesn't want to overwrite"
+  (let ((f-w-d (file-write-date filepath))
+	(f-w-t (file-write-time buffer)))
+    (if (and f-w-d f-w-t (> f-w-d f-w-t))
+	(if (accept 'boolean
+		    :prompt (format nil "File has changed on disk. ~a anyway?"
+				    question))
+	    t
+	    (progn (display-message "~a not ~a" filepath answer)
+		   nil))
+	t)))
+
 (defun save-buffer (buffer)
   (let ((filepath (or (filepath buffer)
 		      (accept 'pathname :prompt "Save Buffer to File"))))
@@ -388,16 +427,22 @@
        (display-message "~A is a directory." filepath)
        (beep))
       (t
-       (when (probe-file filepath)
+       (unless (check-file-times buffer filepath "Overwrite" "written")
+	 (return-from save-buffer))
+       (when  (and (probe-file filepath) (not (file-saved-p buffer)))
 	 (let ((backup-name (pathname-name filepath))
-	       (backup-type (concatenate 'string (pathname-type filepath) "~")))
+	       (backup-type (format nil "~A~~~D~~"
+				    (pathname-type filepath)
+				    (1+ (version-number filepath)))))
 	   (rename-file filepath (make-pathname :name backup-name
-						:type backup-type))))
+						:type backup-type)))
+	 (setf (file-saved-p buffer) t))
        (with-open-file (stream filepath :direction :output :if-exists :supersede)
 	 (output-to-stream stream buffer 0 (size buffer)))
        (setf (filepath buffer) filepath
+	     (file-write-time buffer) (file-write-date filepath)
 	     (name buffer) (filepath-filename filepath))
-       (display-message "Wrote: ~a" (filepath buffer))
+       (display-message "Wrote: ~a" filepath)
        (setf (needs-saving buffer) nil)))))
 
 (define-command (com-save-buffer :name t :command-table buffer-table) ()




More information about the Climacs-cvs mailing list