forked from kmroz/rmoo
-
Notifications
You must be signed in to change notification settings - Fork 5
/
rmoo-objects.el
317 lines (280 loc) · 9.19 KB
/
rmoo-objects.el
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
;;rmoo-objects
;;
;; This file implements a way of keeping track of rmoo-specific
;; `hot' objects.
;;
;; This file gives MOO worlds new properties:
;;
;; objects - an obarray
;; objects-file - a file in which to save hot objects
;;
;;
;; objects are symbols, here are some of their properties:
;;
;; objnum - a string, the object number
;; parent - a string, the parent of the object
;; verbs - a list, ((short-name owner perms full-name) ...)
;; properties - a list, ((name owner perms) ...)
;;
;;
;; This function defines the format of moo object symbol names
;; mo-<moo world name><objnum>
;;
;; Original Author: Ron Tapia <tapia@nmia.com>
;; Revised by: mattcamp
(require 'rmoo)
(require 'rmoo-mcp)
(provide 'rmoo-objects)
(defun mo-symbol-name (world objnum)
(concat "mo-" (symbol-name world) objnum))
(defun mo-intern (objnum world)
(intern (mo-symbol-name world objnum) (get world 'objects)))
(defun mo-intern-soft (objnum world)
(intern-soft (mo-symbol-name world objnum) (get world 'objects)))
(defun mo-symname-to-objnum (world symname)
(string-match (concat "mo-" (symbol-name world) "\\(.*$\\)")
symname)
(substring symname (match-beginning 1)))
(defun mo-symname-to-objnum-here (symname)
(mo-symname-to-objnum rmoo-world-here symname))
(defun mo-object-name (world object)
(mo-symname-to-objnum world (symbol-name object)))
(defvar rmoo-objects-max-objects 200 "The maximum number of objects per MOO.")
;;
;; For minibuffer completion, we need some way of knowing what
;; MOO's objects we need to look at.
;;
(defvar rmoo-objects-current-moo nil "A silly, but necessay kludge.")
;;
;;
;; This needs to be rewritten...but it works for now.
;; In particular, I'm just ignoring predicate for now.
;;
;;
;;
(defun rmoo-objects-verb-completion-function (string predicate flag)
(rmoo-objects-completion-function ":" ":" 'verbs string predicate flag))
(defun rmoo-objects-property-completion-function (string predicate flag)
(rmoo-objects-completion-function "." "\\." 'properties string predicate flag))
(defun rmoo-objects-completion-function (delim delimregexp prop string predicate flag)
(let ((index (string-match delimregexp string))
objstring verbstring objcomp verbcomp
obj comp comps c-func oc-func)
(if flag
(setq c-func 'all-completions)
(setq c-func 'try-completion))
(if (eq index nil)
(progn (setq objstring string)
(setq verbstring "")
(setq oc-func c-func))
(setq objstring (substring string 0 index))
(setq verbstring (substring string (+ index 1)))
(setq oc-func 'try-completion))
(setq objcomp (funcall oc-func (mo-symbol-name rmoo-objects-current-moo
objstring)
(get rmoo-objects-current-moo 'objects)))
(cond ((eq nil objcomp)
nil)
((stringp objcomp)
(mo-symname-to-objnum rmoo-objects-current-moo objcomp))
((listp objcomp)
(setq rmoo-world-here rmoo-objects-current-moo)
(setq objcomp (mapcar 'mo-symname-to-objnum-here objcomp))
objcomp)
(t
(setq obj (mo-intern objstring rmoo-objects-current-moo))
(setq verbcomp (funcall c-func verbstring
(get obj prop)))
(cond ((eq verbcomp t)
t)
((eq verbcomp nil)
nil)
(t
(if (eq nil flag)
(concat objstring delim verbcomp)
(setq comps nil)
(while verbcomp
(setq comps (cons (concat objstring
delim
(car verbcomp))
comps))
(setq verbcomp (cdr verbcomp)))
comps)))))))
;;
;; Whenever we connect to a moo, set up the appropriate hot objects.
;;
(defun rmoo-objects-initialize ()
(let* ((world rmoo-world-here)
(objects (get world 'objects))
(objects-file (get world 'objects-file)))
(if (not objects)
(put world 'objects (make-vector rmoo-objects-max-objects 0)))
(if objects-file
(load-file (expand-file-name objects-file)))))
;;
;; Interface to moo.el (rmoo-worlds)
;;
(add-hook 'rmoo-interactive-mode-hooks 'rmoo-objects-initialize)
(setq rmoo-worlds-properties-to-save
(append rmoo-worlds-properties-to-save '(objects-file)))
;;
;; Interface to MCP - Request that the MOO send us info about objects.
;;
(defvar rmoo-objects-download-object-command
"@mcp-download-object")
(defun rmoo-objects-download-object (object)
"Download an object from rmoo-world-here for use in completions, etc."
(interactive "sObject: ")
(rmoo-send-here (concat rmoo-objects-download-object-command
" "
object
"\n")))
(rmoo-mcp-register "cache-verb"
'(("object" . 'required)
("verb" . 'required)
("owner" . 'required)
("perms" . 'required)
("full-name" . 'required))
'rmoo-objects-cache-verb
"1.0"
"1.0"
nil)
(rmoo-mcp-register "cache-property"
'(("object" . 'required)
("property" . 'required)
("owner" . 'required)
("perms" . 'required))
'rmoo-objects-cache-property
"1.0"
"1.0"
nil)
(rmoo-mcp-register "cache-parent"
'(("object" . 'required)
("parent" . 'required))
'rmoo-objects-cache-parent
"1.0"
"1.0"
nil)
(rmoo-mcp-register "cache-object"
'(("object" . 'required)
("objnum" . 'required))
'rmoo-objects-cache-object
"1.0"
"1.0"
nil)
(defun rmoo-objects-cache-object (objname objnum)
(let ((object (mo-intern objname rmoo-world-here)))
(put object 'properties nil)
(put object 'verbs nil)
(put object 'objnum objnum)
(message (concat "Caching " objname)))
'rmoo-objects-nill-function)
(defun rmoo-objects-cache-verb (objname verb owner perms full-name)
(let* ((object (mo-intern objname rmoo-world-here))
(verbs (get object 'verbs)))
(put object 'verbs (cons (list verb owner perms full-name)
verbs))
(message (concat "Caching " objname ":" verb))
'rmoo-objects-niil-function))
(defun rmoo-objects-cache-property (objname property owner perms)
(let* ((object (mo-intern objname rmoo-world-here))
(properties (get object 'properties)))
(put object 'properties (cons (list property owner perms)
properties))
(message (concat "Caching " objname "." property))
'rmoo-objects-niil-function))
(defun rmoo-objects-cache-parent (object parent)
(let* ((object (mo-intern object rmoo-world-here))
(parent (mo-intern parent rmoo-world-here)))
(put object 'parent parent)
'rmoo-objects-nil-function))
;;
;; A function for adding an object and some properties
;;
(defun rmoo-objects-add (object-name plist)
(let ((object (mo-intern object-name rmoo-world-here)))
(setplist object plist)))
;;
;; A function for saving hot objects to a file
;;
(defun rmoo-objects-insert (object)
(let (s)
(setq s (concat "(rmoo-objects-add "
(prin1-to-string (mo-object-name rmoo-world-here object))
" '"
(prin1-to-string (symbol-plist object))
")\n"))
(insert-before-markers s)))
(defun rmoo-objects-write-objects-file (file)
"Write the current set of cached objects to a rmoo-world-here's objects-file if it's defined. Otherwise prompt for a file name and write to it."
(interactive (list (or (get rmoo-world-here 'objects-file)
(read-file-name "Objects file: "))))
(save-excursion
(let ((objects (get rmoo-world-here 'objects))
(buf (get-buffer-create
(generate-new-buffer-name (concat "* mo-save-"
(symbol-name rmoo-world-here)
"*"))))
(world rmoo-world-here))
(set-buffer buf)
(setq rmoo-world-here world)
(mapatoms 'rmoo-objects-insert objects)
(write-file file)
(kill-buffer nil))))
;;
;; Objects map
;;
(defvar rmoo-objects-map (make-sparse-keymap) "MOO objects keymap")
(define-key rmoo-interactive-mode-map "\C-c\C-o" rmoo-objects-map)
(define-key rmoo-objects-map "\C-o"
'rmoo-objects-download-object)
(define-key rmoo-objects-map "\C-s"
'rmoo-objects-write-objects-file)
(define-key rmoo-objects-map "\C-d"
'rmoo-objects-delete-object-here)
;;
;; Utilities
;;
(defun rmoo-objects-delete-object (world object)
(let* ((objects (get world 'objects))
(i (- (length objects) 1))
elt)
(while (>= i 0)
(setq elt (elt objects i))
(if (and (symbolp elt) elt (string= object (mo-symname-to-objnum world (symbol-name elt))))
(progn
(aset objects i 0)))
(setq i (- i 1)))
(put world 'objects objects)))
(defun rmoo-objects-delete-object-here (object)
(interactive (list (rmoo-objects-read-object-here)))
(rmoo-objects-delete-object rmoo-world-here object))
(defun rmoo-objects-read-object-here ()
(setq rmoo-objects-current-moo rmoo-world-here)
(completing-read "Object: "
'rmoo-objects-object-completion-function
nil
t
nil
nil))
(defun rmoo-objects-object-completion-function (string predicate flag)
(let* ((world rmoo-objects-current-moo)
(newstring (mo-symbol-name world string))
comp)
(setq rmoo-world-here world)
(cond ((eq nil flag)
(setq comp (try-completion newstring
(get world 'objects)
predicate))
(if (eq nil comp)
nil
(or (eq t comp) (mo-symname-to-objnum-here comp))))
((eq t flag)
(setq comp (all-completions newstring
(get world 'objects)
predicate))
(mapcar 'mo-symname-to-objnum-here comp))
((eq 'lambda flag)
(if ((intern-soft newstring (get world 'objects)))
t
nil)))))