summaryrefslogtreecommitdiffstats
path: root/emacs.d/lisp/rudel/rudel-operations.el
blob: 3637303ddbded631e11c3900b7f4b988ae2bd81a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
;;; rudel-operations.el --- Rudel domain operations
;;
;; Copyright (C) 2009 Jan Moringen
;;
;; Author: Jan Moringen <scymtym@users.sourceforge.net>
;; Keywords: Rudel, operations
;; X-RCS: $Id:$
;;
;; This file is part of Rudel.
;;
;; Rudel is free software: you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; Rudel is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with Rudel. If not, see <http://www.gnu.org/licenses>.


;;; Commentary:
;;
;; This file contains classes representing operations like insertions
;; and deletions, that are import for Rudel's domain of collaborative
;; editing.


;;; History:
;;
;; 0.1 - Initial revision


;;; Code:
;;

(require 'eieio)


;;; Class rudel-operation
;;

(defclass rudel-operation ()
  ()
  "Abstract base class for operations."
  :abstract t)

(defgeneric rudel-apply ((this rudel-operation) object)
  "Apply the change represented by THIS to OBJECT.")


;;; Class rudel-insert-op
;;

;; TODO should be rudel-insert but there is a method of the same name
(defclass rudel-insert-op (rudel-operation)
  ((from :initarg :from
	 :type    (or null (integer 0))
	 :documentation
	 "Start of the region affected by this operation or
nil. nil means end of buffer")
   (data :initarg :data
	 :type    string
	 :documentation
	 "The inserted string."))
  "Objects of this class represent insertion operations.")

(defmethod rudel-apply ((this rudel-insert-op) object)
  "Apply THIS to OBJECT by inserting the associated data."
  (with-slots (from data) this
    (rudel-insert object from data)))

(defmethod slot-missing ((this rudel-insert-op)
			 slot-name operation &optional new-value)
  "Simulate read-only slots :length and :to."
  (cond
   ;; Slot :length
   ((and (or (eq slot-name :length)
	     (eq slot-name 'length))
	 (eq operation 'oref))
    (with-slots (data) this
      (length data)))
   ;; Slot :to
   ((and (or (eq slot-name :to)
	     (eq slot-name 'to))
	 (eq operation 'oref))
    (with-slots (from length) this
      (+ from length)))
   ;; Call next method
   (t (call-next-method)))
  )


;;; Class rudel-delete-op
;;

;; TODO should be rudel-delete but there is a method of the same name
(defclass rudel-delete-op (rudel-operation)
  ((from :initarg :from
	 :type    (integer 0)
	 :documentation
	 "Start of the region affected by this operation.")
   (to   :initarg :to
	 :type    (integer 0)
	 :documentation
	 "End of the region affected by this operation."))
  "Objects of this class represent deletion operations.")

(defmethod rudel-apply ((this rudel-delete-op) object)
  "Apply THIS to OBJECT by deleting the associated region."
  (with-slots (from length) this
    (rudel-delete object from length)))

(defmethod slot-missing ((this rudel-delete-op)
			 slot-name operation &optional new-value)
  "Simulate slot :length"
  (cond
   ;; Slot :length
   ((or (eq slot-name :length)
	(eq slot-name 'length))
    (with-slots (from to) this
      (if (eq operation 'oref)
	  (- to from)
	(setq to (+ from new-value)))))
   ;; Call next method
   (t (call-next-method)))
  )

(provide 'rudel-operations)
;;; rudel-operations.el ends here