relisp 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,7 +43,7 @@
43
43
  # Macro Type:: A method of expanding an expression into another
44
44
  # expression, more fundamental but less pretty.
45
45
  #
46
- # And then these elisp types are ignored completely.
46
+ # And then these elisp types are ignored completely, at least for now.
47
47
  #
48
48
  # Char-Table Type:: One-dimensional sparse arrays indexed by characters.
49
49
  # Bool-Vector Type:: One-dimensional arrays of `t' or `nil'.
@@ -182,26 +182,69 @@ module Relisp
182
182
  #
183
183
  class Cons < Proxy
184
184
 
185
- # _args_ must be of the form (_symbol_, <em>slave =
186
- # Relisp.default_slave</em>)
185
+ # _args_ can be any of these forms:
186
+ # * (_symbol_, <em>slave = Relisp.default_slave</em>)
187
+ # * (_car, _cdr_, <em>slave = Relisp.default_slave</em>)
187
188
  #
188
- # The _symbol_ argument is considered to be the name of a
189
- # pre-existing window in the _slave_ process.
189
+ # When a _symbol_ is given it is considered to be the name of a
190
+ # pre-existing cons in the _slave_ process. Otherwise a new cons
191
+ # is created with the given _car_ and _cdr
192
+ # (<tt>cons</tt>).
190
193
  #
191
194
  def initialize(*args)
192
- super do
193
- raise ArgumentError, "Cannot create Cons using 'new' method."
195
+ super do |car, cdr|
196
+ @slave.elisp_exec( "(setq #{@elisp_variable} (cons #{car.to_elisp} #{cdr.to_elisp}))")
194
197
  end
195
198
  end
196
199
 
200
+ # Set the +car+ of Cons to be _newcar_ (+setcar+).
201
+ #
202
+ def car=(newcar)
203
+ @slave.setcar(@elisp_variable.value, newcar)
204
+ end
205
+
206
+ # Set the +cdr+ of Cons to be _newcdr_. (+setcdr+).
207
+ #
208
+ def cdr=(newcdr)
209
+ @slave.setcdr(@elisp_variable.value, newcdr)
210
+ end
211
+
212
+ # Return the +car+ of the Cons. (+car+).
213
+ #
197
214
  def car
198
215
  @slave.car(@elisp_variable.value)
199
216
  end
200
217
 
218
+ # Return the +cdr+ of the Cons. (+cdr+).
219
+ #
201
220
  def cdr
202
221
  @slave.cdr(@elisp_variable.value)
203
222
  end
204
223
 
224
+ # Return the +car+ of the +car+ of the Cons. (+caar+)
225
+ #
226
+ def caar
227
+ @slave.caar(@elisp_variable.value)
228
+ end
229
+
230
+ # Return the +car+ of the +cdr+ of the Cons. (+cadr+)
231
+ #
232
+ def cadr
233
+ @slave.cadr(@elisp_variable.value)
234
+ end
235
+
236
+ # Return the +cdr+ of the +car+ of the Cons. (+cdar+)
237
+ #
238
+ def cdar
239
+ @slave.cadr(@elisp_variable.value)
240
+ end
241
+
242
+ # Return the +cdr+ of the +cdr+ of the Cons. (+cddr+)
243
+ #
244
+ def cddr
245
+ @slave.cadr(@elisp_variable.value)
246
+ end
247
+
205
248
  # This function will NOT return true whenever the elisp function
206
249
  # <tt>listp</tt> is true. The elisp function is true whenever the
207
250
  # object is a cons cell, but this method is true only when the
@@ -240,6 +283,8 @@ module Relisp
240
283
  end
241
284
  end
242
285
 
286
+ alias to_a to_list
287
+
243
288
  end
244
289
 
245
290
 
@@ -296,9 +341,9 @@ module Relisp
296
341
  end
297
342
  keys_var = slave.new_elisp_variable
298
343
  vals_var = slave.new_elisp_variable
299
- slave.elisp_execute( "(setq #{keys_var} nil)" )
300
- slave.elisp_execute( "(setq #{vals_var} nil)" )
301
- slave.elisp_execute( "(maphash (lambda (key val)
344
+ slave.elisp_exec( "(setq #{keys_var} nil)" )
345
+ slave.elisp_exec( "(setq #{vals_var} nil)" )
346
+ slave.elisp_exec( "(maphash (lambda (key val)
302
347
  (setq #{keys_var} (append #{keys_var} (list key)))
303
348
  (setq #{vals_var} (append #{vals_var} (list val)))) #{object_variable})" )
304
349
  keys = slave.elisp_eval( keys_var )
@@ -388,7 +433,7 @@ class Array
388
433
  object_array << object[:slave].elisp_eval( "(elt #{object_variable} #{i.to_elisp})" )
389
434
  end
390
435
 
391
- object[:slave].elisp_execute( "(makunbound #{object_variable.to_elisp})" )
436
+ object[:slave].elisp_exec( "(makunbound #{object_variable.to_elisp})" )
392
437
  return object_array
393
438
  end
394
439
 
@@ -0,0 +1,60 @@
1
+ module Relisp
2
+
3
+ # Proxy contains the code that creates a wrapper around a variable
4
+ # in emacs.
5
+ #
6
+ class Proxy
7
+ def self.from_elisp(object)
8
+ new(object[:variable], object[:slave])
9
+ end
10
+
11
+ # If the last argument is a Relisp::Slave, it gets pulled off and
12
+ # used as the slave; otherwise Relisp.default_slave is used. If
13
+ # the first argument is a Symbol, it is assumed to be the name of
14
+ # an elisp variable which needs a proxy. If the first argument
15
+ # isn't a Symbol, all of the arguments (except the last, if it was
16
+ # a Slave) are send off to the child to handle.
17
+ #
18
+ def initialize(*args)
19
+ @slave = if args.last.kind_of?(Relisp::Slave)
20
+ args.pop
21
+ else
22
+ Relisp.default_slave
23
+ end
24
+
25
+ if args[0].kind_of?(Symbol) && args[1].nil?
26
+ @elisp_variable = @slave.get_permanent_variable(args[0])
27
+ elisp_type= ""
28
+ self.class.to_s.split("::").last.split(//).each_with_index do |char, index|
29
+ unless index==0 || char == char.downcase
30
+ elisp_type << "-"
31
+ end
32
+ elisp_type << char.downcase
33
+ end
34
+
35
+ unless @slave.elisp_eval("(type-of #{@elisp_variable})") == elisp_type.to_sym
36
+ raise ArgumentError, "#{@elisp_variable} isn't a #{elisp_type}"
37
+ end
38
+ else
39
+ @elisp_variable = @slave.new_elisp_variable
40
+ yield args
41
+ end
42
+ end
43
+
44
+ attr_reader :slave, :elisp_variable
45
+
46
+ def to_elisp
47
+ @elisp_variable
48
+ end
49
+
50
+ private
51
+
52
+ def call_on_self(function, *args)
53
+ @slave.send(function, @elisp_variable.value, *args)
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ require 'relisp/type_conversion/editing_types'
60
+ require 'relisp/type_conversion/programming_types'
data/lib/relisp.rb CHANGED
@@ -19,12 +19,11 @@
19
19
  #++
20
20
 
21
21
  module Relisp
22
- VERSION = '0.9.1'
22
+ VERSION = '0.9.2'
23
23
 
24
24
  class ElispError < RuntimeError; end
25
25
  end
26
26
 
27
- require 'relisp/editing_types'
28
- require 'relisp/elisp_functions.rb'
29
- require 'relisp/programming_types'
27
+ require 'relisp/type_conversion'
28
+ require 'relisp/elisp_functions'
30
29
  require 'relisp/slaves'
@@ -0,0 +1,72 @@
1
+ (progn
2
+ (relisp-stop-slave)
3
+ (setq relisp-ruby-slave-path "tests.rb")
4
+ (relisp-start-slave))
5
+
6
+ ;; bury current buffer
7
+ (ruby-eval "buffer_bury")
8
+
9
+ ;; split this window vertically and set bottow window to
10
+ ;; 'other-buffer'
11
+ (ruby-eval "buffer_window_equals")
12
+
13
+ ;; split this window vertically then horizontally
14
+ (ruby-eval "window_split")
15
+
16
+ ;; should move text up and return nil
17
+ (ruby-eval "window_scroll_up")
18
+
19
+ ;; should move text down and return t
20
+ (ruby-eval "window_scroll_down")
21
+
22
+ ;; create some windows and move them horizontally and vertically
23
+ (ruby-eval "window_shrink")
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
+
@@ -0,0 +1,66 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "../lib")
2
+
3
+ require 'relisp'
4
+
5
+ slave = Relisp::RubySlave.new
6
+
7
+ def buffer_bury
8
+ b = current_buffer
9
+ b.bury
10
+ end
11
+
12
+ def buffer_window_equals
13
+ w = split_window_vertically
14
+ b = other_buffer
15
+ b.window = w
16
+ end
17
+
18
+ def window_split
19
+ w = selected_window
20
+ new_window = w.split_vertically
21
+ new_window.split_horizontally
22
+ end
23
+
24
+ def window_scroll_up
25
+ selected_window.scroll_up(1)
26
+ selected_window.visible?(1)
27
+ end
28
+
29
+ def window_scroll_down
30
+ selected_window.scroll_down(1)
31
+ selected_window.visible?(1)
32
+ end
33
+
34
+
35
+ def window_shrink
36
+ w = selected_window
37
+ w2 = w.split_vertically
38
+ w3 = w2.split_horizontally
39
+ 10.times do
40
+ w.shrink(1)
41
+ redisplay
42
+ sleep 0.01
43
+ end
44
+ 10.times do
45
+ w.enlarge(1)
46
+ redisplay
47
+ sleep 0.01
48
+ end
49
+ 10.times do
50
+ w2.shrink(0,1)
51
+ redisplay
52
+ sleep 0.01
53
+ end
54
+ 10.times do
55
+ w2.enlarge(0,1)
56
+ redisplay
57
+ sleep 0.01
58
+ end
59
+
60
+ w2.delete
61
+ w3.delete
62
+ end
63
+
64
+
65
+ slave.start
66
+
data/src/relisp.el CHANGED
@@ -61,8 +61,10 @@
61
61
  (defvar relisp-emacs-master-p t)
62
62
  (defvar relisp-slave-process)
63
63
  (defvar relisp-ruby-output)
64
- (defvar relisp-question-code)
64
+ (defvar relisp-begin-answer-code)
65
65
  (defvar relisp-answer-code)
66
+ (defvar relisp-question-code)
67
+ (defvar relisp-command-code)
66
68
  (defvar relisp-error-code)
67
69
  (defvar relisp-ruby-return)
68
70
  (defvar relisp-previous-result)
@@ -111,26 +113,55 @@
111
113
  (defun relisp-endofmessage-regexp nil
112
114
  "Return a regexp that matches codes indicating a message termination."
113
115
  (concat "\\(" relisp-question-code
116
+ "\\|" relisp-command-code
114
117
  "\\|" relisp-answer-code
115
118
  "\\|" relisp-error-code
116
119
  "\\)"
117
120
  "[[:space:]]*"))
118
121
 
122
+ (defun relisp-receive-answer nil
123
+ "Handle messages from emacs after ruby-eval or ruby-exec are called."
124
+ (let ((message (relisp-read-from-ruby)))
125
+ (while (or (string-match relisp-question-code message)
126
+ (string-match relisp-command-code message))
127
+ (if (string-match relisp-question-code message)
128
+ (relisp-answer-ruby message)
129
+ (relisp-obey-ruby message))
130
+ (setq message (relisp-read-from-ruby)))
131
+ message))
132
+
133
+ (defun ruby-exec (ruby-code)
134
+ "Have ruby evaluate RUBY-CODE without returning the result.
135
+ Reads input from the minibuffer unless an argument is
136
+ given."
137
+ (interactive "ruby> ")
138
+ (let (message result)
139
+ (if (and relisp-emacs-master-p (not (relisp-slave-alive-p)))
140
+ (relisp-start-slave))
141
+ (relisp-log (concat "lisp!> " ruby-code))
142
+ (relisp-write-to-ruby (relisp-form-command ruby-code))
143
+ (setq message (relisp-receive-answer))
144
+ (setq relisp-ruby-return (relisp-strip (car (split-string message relisp-answer-code))))
145
+ (relisp-log "")
146
+ (setq result (if (string-match (concat "\n?" relisp-error-code "[[:space:]]*") relisp-ruby-return)
147
+ (concat "RUBY ERROR: " (replace-match "" nil t relisp-ruby-return))
148
+ nil))
149
+ (if (and (interactive-p) (not (null result)))
150
+ (message (prin1-to-string result)))
151
+ result))
152
+
119
153
  (defun ruby-eval (ruby-code)
120
154
  "Have ruby evaluate RUBY-CODE and return the result.
121
155
  The result is an elisp object equivalent to the ruby result of
122
156
  RUBY-CODE. Reads input from the minibuffer unless an argument is
123
157
  given."
124
- (interactive "sruby> ")
158
+ (interactive "ruby> ")
125
159
  (let (message result)
126
160
  (if (and relisp-emacs-master-p (not (relisp-slave-alive-p)))
127
161
  (relisp-start-slave))
128
162
  (relisp-log (concat "lisp?> " ruby-code))
129
163
  (relisp-write-to-ruby (relisp-form-question ruby-code))
130
- (setq message (relisp-read-from-ruby))
131
- (while (string-match relisp-question-code message)
132
- (relisp-answer-ruby message)
133
- (setq message (relisp-read-from-ruby)))
164
+ (setq message (relisp-receive-answer))
134
165
  (setq relisp-ruby-return (relisp-strip (car (split-string message relisp-answer-code))))
135
166
  (relisp-log (concat "ruby=> " relisp-ruby-return "\n"))
136
167
  (setq result (if (string-match (concat "\n?" relisp-error-code "[[:space:]]*") relisp-ruby-return)
@@ -149,15 +180,35 @@ given."
149
180
  (progn
150
181
  (set relisp-previous-result (eval question))
151
182
  (relisp-log (concat "lisp=> " (prin1-to-string (type-of (eval relisp-previous-result)))))
152
- (relisp-log (concat " ... " (prin1-to-string (eval relisp-previous-result))))
183
+ (relisp-log (concat " => " (prin1-to-string (eval relisp-previous-result))))
184
+ (relisp-write-to-ruby relisp-begin-answer-code)
153
185
  (relisp-write-to-ruby (prin1-to-string (type-of (eval relisp-previous-result))))
154
186
  (relisp-write-to-ruby (relisp-form-answer (eval relisp-previous-result))))
155
187
  (error (relisp-write-to-ruby
156
188
  (relisp-form-error
157
189
  (error-message-string error-description))))))
158
190
 
159
- (defun relisp-form-question (code)
191
+ (defun relisp-obey-ruby (command)
192
+ "Evaluate the COMMAND from ruby."
193
+ (setq command (relisp-strip (car (split-string command relisp-command-code))))
194
+ (relisp-log (concat "ruby!> " command))
195
+ (setq command (read command))
196
+ (condition-case error-description
197
+ (progn
198
+ (set relisp-previous-result (eval command))
199
+ (relisp-write-to-ruby relisp-answer-code))
200
+ (error (relisp-write-to-ruby
201
+ (relisp-form-error
202
+ (error-message-string error-description))))))
203
+
204
+ (defun relisp-form-command (code)
160
205
  "Return a string that tells ruby to evaluate CODE."
206
+ (unless (stringp code)
207
+ (setq code (prin1-to-string code)))
208
+ (concat code "\n" relisp-command-code))
209
+
210
+ (defun relisp-form-question (code)
211
+ "Return a string that tells ruby to evaluate CODE and return the result."
161
212
  (unless (stringp code)
162
213
  (setq code (prin1-to-string code)))
163
214
  (concat code "\n" relisp-question-code))
@@ -178,6 +229,31 @@ given."
178
229
  (set var object)
179
230
  (concat "elisp_eval('" (prin1-to-string var) "')")))
180
231
 
232
+ (defun relisp-get-constant nil
233
+ "Return the next constant passed from ruby.
234
+ Intended to be called from relisp-get-constants."
235
+ (if relisp-emacs-master-p
236
+ (progn
237
+ (relisp-write-to-ruby "(prompt)")
238
+ (while (null (string-match "\n" relisp-ruby-output))
239
+ (accept-process-output))
240
+ (let ((result (relisp-strip relisp-ruby-output)))
241
+ (setq relisp-ruby-output "")
242
+ result))
243
+ (message "(prompt)")
244
+ (read-from-minibuffer "")))
245
+
246
+ (defun relisp-get-constants nil
247
+ "Sets all relisp constants shared between ruby and emacs.
248
+ Intended to be called from relisp-start-slave and
249
+ relisp-become-slave."
250
+ (setq relisp-question-code (relisp-get-constant))
251
+ (setq relisp-command-code (relisp-get-constant))
252
+ (setq relisp-begin-answer-code (relisp-get-constant))
253
+ (setq relisp-answer-code (relisp-get-constant))
254
+ (setq relisp-error-code (relisp-get-constant))
255
+ (setq relisp-previous-result (read (relisp-get-constant))))
256
+
181
257
  (defun relisp-start-slave nil
182
258
  "Start a ruby slave process to do emacs's bidding.
183
259
  If `relisp-ruby-slave-path' is bound, then that file is read and
@@ -200,26 +276,7 @@ emacs starts a ruby process and starts a RubySlave on its own."
200
276
  "Relisp::RubySlave.new.start\n"
201
277
  "__END__\n")))
202
278
  (set-process-filter relisp-slave-process 'relisp-slave-output-filter)
203
- (relisp-write-to-ruby "")
204
- (while (null (string-match "\n" relisp-ruby-output))
205
- (accept-process-output))
206
- (setq relisp-answer-code (relisp-strip relisp-ruby-output))
207
- (setq relisp-ruby-output "")
208
- (relisp-write-to-ruby "")
209
- (while (null (string-match "\n" relisp-ruby-output))
210
- (accept-process-output))
211
- (setq relisp-question-code (relisp-strip relisp-ruby-output))
212
- (setq relisp-ruby-output "")
213
- (relisp-write-to-ruby "")
214
- (while (null (string-match "\n" relisp-ruby-output))
215
- (accept-process-output))
216
- (setq relisp-error-code (relisp-strip relisp-ruby-output))
217
- (setq relisp-ruby-output "")
218
- (relisp-write-to-ruby "")
219
- (while (null (string-match "\n" relisp-ruby-output))
220
- (accept-process-output))
221
- (setq relisp-previous-result (read (relisp-strip relisp-ruby-output)))
222
- (setq relisp-ruby-output "")
279
+ (relisp-get-constants)
223
280
  relisp-slave-process)
224
281
 
225
282
  (defun relisp-become-slave nil
@@ -227,23 +284,18 @@ emacs starts a ruby process and starts a RubySlave on its own."
227
284
  (setq relisp-emacs-master-p nil)
228
285
  ;; get constants
229
286
  (message "SEND CONSTANTS")
230
- (message "(prompt for answer code)")
231
- (setq relisp-answer-code (read-from-minibuffer ""))
232
- (message "(prompt for question code)")
233
- (setq relisp-question-code (read-from-minibuffer ""))
234
- (message "(prompt for error code)")
235
- (setq relisp-error-code (read-from-minibuffer ""))
236
- (message "(prompt for previous result variable)")
237
- (setq relisp-previous-result (read (read-from-minibuffer "")))
287
+ (relisp-get-constants)
238
288
  (let (input input-line)
239
289
  (while t ;; loop is only a CL function, I guess
240
290
  (setq input "")
241
291
  (setq input-line "")
242
- (while (null (string-match relisp-question-code (relisp-strip input-line)))
292
+ (while (and (null (string-match relisp-question-code (relisp-strip input-line)))
293
+ (null (string-match relisp-command-code (relisp-strip input-line))))
243
294
  (setq input-line (read-from-minibuffer ""))
244
295
  (setq input (concat input input-line)))
245
- (relisp-answer-ruby input))))
246
-
296
+ (if (string-match relisp-question-code (relisp-strip input-line))
297
+ (relisp-answer-ruby input)
298
+ (relisp-obey-ruby input)))))
247
299
 
248
300
  (defun relisp-slave-output-filter (process output-line)
249
301
  "Listen to PROCESS and add each OUTPUT-LINE to `relisp-ruby-output'."
@@ -259,7 +311,6 @@ emacs starts a ruby process and starts a RubySlave on its own."
259
311
  (and (boundp 'relisp-slave-process)
260
312
  (equal (process-status relisp-slave-process) 'run)
261
313
  (boundp 'relisp-question-code)
262
- (boundp 'relisp-answer-code)
263
314
  (boundp 'relisp-error-code)))
264
315
 
265
316
  (provide 'relisp)
data/src/relisp.elc CHANGED
Binary file