Update of /project/climacs/cvsroot/climacs In directory common-lisp.net:/tmp/cvs-serv22428
Modified Files: TODO base-test.lisp base.lisp buffer-test.lisp cl-syntax.lisp climacs.asd html-syntax.lisp packages.lisp pane.lisp text-syntax.lisp Log Message: Line-oriented persistent buffer (binseq2). Warning: Need to fix minor bugs (related to number-of-lines-in-region, I believe).
base.lisp: Added faster methods on previous-line, next-line, buffer-number-of-lines-in-region.
pane.lisp, cl-syntax.lisp, html-syntax.lisp, text-syntax.lisp: Replaced some calls to make-instance to calls to clone-mark and (setf offset), in order to avoid passing climacs-buffer to marks. This also made possible to get rid of delegating methods on syntax.
climacs.asd: Added Persistent/binseq2.
packages.lisp: Added binseq2-related symbols.
Persistent/binseq.lisp, Persistent/obinseq.lisp: Cleanup.
Persistent/persistent-buffer.lisp: Added code for binseq2-buffer and related marks. Also some minor fixes.
Date: Sun Mar 13 21:51:48 2005 Author: abakic
Index: climacs/TODO diff -u climacs/TODO:1.5 climacs/TODO:1.6 --- climacs/TODO:1.5 Sun Feb 20 06:39:15 2005 +++ climacs/TODO Sun Mar 13 21:51:48 2005 @@ -1,8 +1,6 @@ - modify standard-buffer to use obinseq with leafs containing flexichain-based lines
-- implement a persistent buffer as a binseq of obinseqs (or similar, - one sequence type for lines, the other for line contents), then - upgrade it to an undoable buffer +- upgrade persistent buffer based on binseq2 to an undoable buffer
- replace the use of the scroller pane by custom pane
Index: climacs/base-test.lisp diff -u climacs/base-test.lisp:1.12 climacs/base-test.lisp:1.13 --- climacs/base-test.lisp:1.12 Sun Feb 27 19:52:00 2005 +++ climacs/base-test.lisp Sun Mar 13 21:51:48 2005 @@ -350,16 +350,18 @@ (let ((buffer (make-instance %%buffer))) (insert-buffer-sequence buffer 0 "climacs climacs") + (print (climacs-buffer::buffer-line-number buffer 15)) (values (climacs-base::buffer-number-of-lines-in-region buffer 0 6) (climacs-base::buffer-number-of-lines-in-region buffer 0 7) + (climacs-base::buffer-number-of-lines-in-region buffer 0 8) (climacs-base::buffer-number-of-lines-in-region buffer 0 10) (climacs-base::buffer-number-of-lines-in-region buffer 0 13) (climacs-base::buffer-number-of-lines-in-region buffer 0 14) (climacs-base::buffer-number-of-lines-in-region buffer 7 10) (climacs-base::buffer-number-of-lines-in-region buffer 8 13) (climacs-base::buffer-number-of-lines-in-region buffer 8 14))) - 0 0 1 1 1 1 0 0) + 0 0 1 1 1 1 1 0 0)
(defmultitest buffer-display-column.test-1 (let ((buffer (make-instance %%buffer)))
Index: climacs/base.lisp diff -u climacs/base.lisp:1.37 climacs/base.lisp:1.38 --- climacs/base.lisp:1.37 Sat Feb 19 07:19:06 2005 +++ climacs/base.lisp Sun Mar 13 21:51:48 2005 @@ -36,13 +36,13 @@ &body body) "Iterate over the elements of the region delimited by offset1 and offset2. The body is executed for each element, with object being the current object -(setf-able), and offset being its offset." +(setf-able), and offset being its offset." `(symbol-macrolet ((,object (buffer-object ,buffer ,offset))) (loop for ,offset from ,offset1 below ,offset2 do ,@body)))
-(defun previous-line (mark &optional column (count 1)) - "Move a mark up one line conserving horizontal position." +(defmethod previous-line (mark &optional column (count 1)) + "Move a mark up COUNT lines conserving horizontal position." (unless column (setf column (column-number mark))) (loop repeat count @@ -54,8 +54,17 @@ (beginning-of-line mark) (incf (offset mark) column)))
-(defun next-line (mark &optional column (count 1)) - "Move a mark down one line conserving horizontal position." +(defmethod previous-line ((mark p-line-mark-mixin) &optional column (count 1)) + "Move a mark up COUNT lines conserving horizontal position." + (unless column + (setf column (column-number mark))) + (let* ((line (line-number mark)) + (goto-line (max 0 (- line count)))) + (setf (offset mark) + (+ column (buffer-line-offset (buffer mark) goto-line))))) + +(defmethod next-line (mark &optional column (count 1)) + "Move a mark down COUNT lines conserving horizontal position." (unless column (setf column (column-number mark))) (loop repeat count @@ -67,16 +76,26 @@ (beginning-of-line mark) (incf (offset mark) column)))
+(defmethod next-line ((mark p-line-mark-mixin) &optional column (count 1)) + "Move a mark down COUNT lines conserving horizontal position." + (unless column + (setf column (column-number mark))) + (let* ((line (line-number mark)) + (goto-line (min (number-of-lines (buffer mark)) + (+ line count)))) + (setf (offset mark) + (+ column (buffer-line-offset (buffer mark) goto-line))))) + (defmethod open-line ((mark left-sticky-mark) &optional (count 1)) "Create a new line in a buffer after the mark." (loop repeat count - do (insert-object mark #\Newline))) + do (insert-object mark #\Newline)))
(defmethod open-line ((mark right-sticky-mark) &optional (count 1)) "Create a new line in a buffer after the mark." (loop repeat count - do (insert-object mark #\Newline) - (decf (offset mark)))) + do (insert-object mark #\Newline) + (decf (offset mark))))
(defun kill-line (mark) "Remove a line from a buffer." @@ -105,13 +124,19 @@ (incf (offset mark2)) finally (return indentation))))
-(defun buffer-number-of-lines-in-region (buffer offset1 offset2) - "Helper function for number-of-lines-in-region. Count newline -characters in the region between offset1 and offset2" +(defmethod buffer-number-of-lines-in-region (buffer offset1 offset2) + "Helper method for number-of-lines-in-region. Count newline +characters in the region between offset1 and offset2." (loop while (< offset1 offset2) count (eql (buffer-object buffer offset1) #\Newline) do (incf offset1)))
+(defmethod buffer-number-of-lines-in-region + ((buffer binseq2-buffer) offset1 offset2) + "Helper method for NUMBER-OF-LINES-IN-REGION." + (- (buffer-line-number buffer offset2) + (buffer-line-number buffer offset1))) + (defun buffer-display-column (buffer offset tab-width) (let ((line-start-offset (- offset (buffer-column-number buffer offset)))) (loop with column = 0 @@ -578,7 +603,7 @@ (loop for i downfrom (- offset (length vector)) to 0 when (buffer-looking-at buffer i vector :test test) return i - finally (return nil))) + finally (return nil)))
(defun search-forward (mark vector &key (test #'eql)) "move MARK forward after the first occurence of VECTOR after MARK"
Index: climacs/buffer-test.lisp diff -u climacs/buffer-test.lisp:1.18 climacs/buffer-test.lisp:1.19 --- climacs/buffer-test.lisp:1.18 Sun Feb 27 19:52:01 2005 +++ climacs/buffer-test.lisp Sun Mar 13 21:51:48 2005 @@ -48,6 +48,13 @@ ''persistent-right-sticky-mark (intern (concatenate 'string "OBINSEQ-BUFFER-" name-string)) form + results) + ,(%deftest-wrapper + ''binseq2-buffer + ''persistent-left-sticky-line-mark + ''persistent-right-sticky-line-mark + (intern (concatenate 'string "BINSEQ2-BUFFER-" name-string)) + form results)))))
(defmultitest buffer-make-instance.test-1 @@ -966,3 +973,76 @@ do (insert-buffer-sequence b (floor (size b) 2) "abcdefghij") finally (return (size b)))) 1000000) + +(defmultitest performance.test-4 + (time + (let ((b (make-instance %%buffer))) + (insert-buffer-sequence b 0 (make-array '(100000) :initial-element #\a)) + (let ((m (clone-mark (low-mark b)))) + (loop + for i from 0 below 1000 + for f = t then (not b) + do (if f + (end-of-line m) + (beginning-of-line m)))))) + nil) + +(defmultitest performance.test-4b + (time + (let ((b (make-instance %%buffer))) + (insert-buffer-object b 0 #\Newline) + (insert-buffer-sequence b 0 (make-array '(100000) :initial-element #\a)) + (insert-buffer-object b 0 #\Newline) + (let ((m (clone-mark (low-mark b)))) + (loop + for i from 0 below 1000 + for f = t then (not b) + do (if f + (end-of-line m) + (beginning-of-line m)))))) + nil) + +(defmultitest performance.test-4c + (time + (let ((b (make-instance %%buffer))) + (insert-buffer-object b 0 #\Newline) + (insert-buffer-sequence b 0 (make-array '(100000) :initial-element #\a)) + (insert-buffer-object b 0 #\Newline) + (let ((m (clone-mark (low-mark b)))) + (incf (offset m)) + (loop + for i from 0 below 1000 + for f = t then (not b) + do (if f + (end-of-line m) + (beginning-of-line m)))))) + nil) + +(defmultitest performance.test-4d + (time + (let ((b (make-instance %%buffer))) + (insert-buffer-object b 0 #\Newline) + (insert-buffer-sequence b 0 (make-array '(100000) :initial-element #\a)) + (insert-buffer-object b 0 #\Newline) + (let ((m (clone-mark (low-mark b)))) + (setf (offset m) (floor (size b) 2)) + (loop + for i from 0 below 10 + collect (list (line-number m) (column-number m)))))) + ((1 50000) (1 50000) (1 50000) (1 50000) (1 50000) (1 50000) + (1 50000) (1 50000) (1 50000) (1 50000))) + +(defmultitest performance.test-4e + (time + (let ((b (make-instance %%buffer))) + (insert-buffer-sequence + b 0 (make-array '(100000) :initial-element #\Newline)) + (let ((m (clone-mark (low-mark b)))) + (loop + for i from 0 below 1000 + for f = t then (not b) + do (if f + (next-line m 0 100000) + (previous-line m 0 100000)) + finally (return (number-of-lines b)))))) + 100000) \ No newline at end of file
Index: climacs/cl-syntax.lisp diff -u climacs/cl-syntax.lisp:1.5 climacs/cl-syntax.lisp:1.6 --- climacs/cl-syntax.lisp:1.5 Wed Mar 2 04:59:03 2005 +++ climacs/cl-syntax.lisp Sun Mar 13 21:51:48 2005 @@ -166,9 +166,8 @@ (defmethod initialize-instance :after ((syntax cl-syntax) &rest args) (declare (ignore args)) (with-slots (buffer elements) syntax - (let ((mark (make-instance 'standard-left-sticky-mark - :buffer buffer - :offset 0))) + (let ((mark (clone-mark (low-mark buffer) :left))) + (setf (offset mark) 0) (insert* elements 0 (make-instance 'start-entry :start-mark mark :size 0)))))
@@ -257,11 +256,12 @@ (loop until (or (= guess-pos (nb-elements elements)) (mark> (start-mark (element* elements guess-pos)) high-mark)) do (delete* elements guess-pos)) - (setf scan (make-instance 'standard-left-sticky-mark - :buffer buffer - :offset (if (zerop guess-pos) - 0 - (end-offset (element* elements (1- guess-pos)))))) + (let ((m (clone-mark (low-mark buffer) :left))) + (setf (offset m) + (if (zerop guess-pos) + 0 + (end-offset (element* elements (1- guess-pos))))) + (setf scan m)) ;; scan (loop with start-mark = nil do (loop until (end-of-buffer-p scan)
Index: climacs/climacs.asd diff -u climacs/climacs.asd:1.23 climacs/climacs.asd:1.24 --- climacs/climacs.asd:1.23 Fri Mar 11 11:23:33 2005 +++ climacs/climacs.asd Sun Mar 13 21:51:48 2005 @@ -46,6 +46,7 @@ "Persistent/binseq-package" "Persistent/binseq" "Persistent/obinseq" + "Persistent/binseq2" "translate" "packages" "buffer"
Index: climacs/html-syntax.lisp diff -u climacs/html-syntax.lisp:1.11 climacs/html-syntax.lisp:1.12 --- climacs/html-syntax.lisp:1.11 Sun Mar 13 07:55:27 2005 +++ climacs/html-syntax.lisp Sun Mar 13 21:51:48 2005 @@ -276,12 +276,12 @@ (setf parser (make-instance 'parser :grammar *html-grammar* :target 'html)) - (insert* lexemes 0 (make-instance 'start-element - :start-mark (make-instance 'standard-left-sticky-mark - :buffer buffer - :offset 0) - :size 0 - :state (initial-state parser))))) + (let ((m (clone-mark (low-mark buffer) :left))) + (setf (offset m) 0) + (insert* lexemes 0 (make-instance 'start-element + :start-mark m + :size 0 + :state (initial-state parser))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; @@ -325,9 +325,10 @@ do (forward-object scan)))
(defun update-lex (lexemes start-pos end) - (let ((scan (make-instance 'standard-left-sticky-mark - :buffer (buffer end) ; FIXME, eventually use the buffer of the lexer - :offset (end-offset (element* lexemes (1- start-pos)))))) + (let ((scan (clone-mark (low-mark (buffer end)) :left))) + ;; FIXME, eventually use the buffer of the lexer + (setf (offset scan) + (end-offset (element* lexemes (1- start-pos)))) (loop do (skip-inter-lexeme-objects lexemes scan) until (if (end-of-buffer-p end) (end-of-buffer-p scan)
Index: climacs/packages.lisp diff -u climacs/packages.lisp:1.55 climacs/packages.lisp:1.56 --- climacs/packages.lisp:1.55 Thu Mar 10 07:37:40 2005 +++ climacs/packages.lisp Sun Mar 13 21:51:48 2005 @@ -47,8 +47,10 @@ #:object-before #:object-after #:region-to-sequence #:low-mark #:high-mark #:modified-p #:clear-modify
- #:binseq-buffer #:obinseq-buffer + #:binseq-buffer #:obinseq-buffer #:binseq2-buffer #:persistent-left-sticky-mark #:persistent-right-sticky-mark + #:persistent-left-sticky-line-mark #:persistent-right-sticky-line-mark + #:p-line-mark-mixin #:buffer-line-offset
#:delegating-buffer #:implementation))
Index: climacs/pane.lisp diff -u climacs/pane.lisp:1.20 climacs/pane.lisp:1.21 --- climacs/pane.lisp:1.20 Sat Mar 5 08:03:53 2005 +++ climacs/pane.lisp Sun Mar 13 21:51:48 2005 @@ -182,20 +182,10 @@
;(defgeneric indent-tabs-mode (climacs-buffer))
-;;; syntax delegation - -(defmethod update-syntax ((buffer delegating-buffer) syntax) - (update-syntax (implementation buffer) syntax)) - -(defmethod update-syntax-for-redisplay ((buffer delegating-buffer) syntax from to) - (update-syntax-for-redisplay (implementation buffer) syntax from to)) - -;;; buffers - (defclass extended-standard-buffer (standard-buffer undo-mixin abbrev-mixin) () (:documentation "Extensions accessible via marks."))
-(defclass extended-obinseq-buffer (obinseq-buffer undo-mixin abbrev-mixin) () +(defclass extended-binseq2-buffer (binseq2-buffer undo-mixin abbrev-mixin) () (:documentation "Extensions accessible via marks."))
(defclass climacs-buffer (delegating-buffer filename-mixin name-mixin)
Index: climacs/text-syntax.lisp diff -u climacs/text-syntax.lisp:1.5 climacs/text-syntax.lisp:1.6 --- climacs/text-syntax.lisp:1.5 Tue Jan 18 00:10:24 2005 +++ climacs/text-syntax.lisp Sun Mar 13 21:51:48 2005 @@ -80,9 +80,9 @@ (and (eql (buffer-object buffer (1- offset)) #\Newline) (or (= offset 1) (eql (buffer-object buffer (- offset 2)) #\Newline))))) - (insert* paragraphs pos1 - (make-instance 'standard-left-sticky-mark - :buffer buffer :offset offset)) + (let ((m (clone-mark (low-mark buffer) :left))) + (setf (offset m) offset) + (insert* paragraphs pos1 m)) (incf pos1)) ((and (plusp offset) (not (eql (buffer-object buffer (1- offset)) #\Newline)) @@ -90,9 +90,9 @@ (and (eql (buffer-object buffer offset) #\Newline) (or (= offset (1- buffer-size)) (eql (buffer-object buffer (1+ offset)) #\Newline))))) - (insert* paragraphs pos1 - (make-instance 'standard-right-sticky-mark - :buffer buffer :offset offset)) + (let ((m (clone-mark (low-mark buffer) :right))) + (setf (offset m) offset) + (insert* paragraphs pos1 m)) (incf pos1)) (t nil)))))))