relisp 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ == 0.9.2 / 2009-03-09
2
+
3
+ * 3 minor enhancements
4
+ * Added a 'ruby-exec' lisp function that executes ruby code taking
5
+ the time to translate the result.
6
+ * Improved the 'elisp_exec' ruby function.
7
+ * Wrote test cases that cover a good chunk of a Relisp::Proxy
8
+ classes.
9
+ * Fixed whatever bugs that were found by writing the tests.
10
+
1
11
  == 0.9.1 / 2009-01-28
2
12
 
3
13
  * 2 major enhancements
data/Manifest CHANGED
@@ -7,10 +7,13 @@ examples/elisp_master/elisp_master.el
7
7
  examples/elisp_master/ruby_slave
8
8
  examples/ruby_master/ruby_master_example
9
9
  lib/relisp.rb
10
- lib/relisp/editing_types.rb
11
10
  lib/relisp/elisp_functions.rb
12
- lib/relisp/programming_types.rb
13
11
  lib/relisp/slaves.rb
12
+ lib/relisp/type_conversion.rb
13
+ lib/relisp/type_conversion/editing_types.rb
14
+ lib/relisp/type_conversion/programming_types.rb
15
+ manual_test/tests.el
16
+ manual_test/tests.rb
14
17
  setup.rb
15
18
  src/relisp.el
16
19
  src/relisp.elc
data/README CHANGED
@@ -13,7 +13,7 @@ Emacs is great. So is Ruby. This purpose of this library is to:
13
13
 
14
14
  == Install
15
15
 
16
- [sudo] gem install sundae
16
+ [sudo] gem install relisp
17
17
 
18
18
  Then the library is installed, and you can call elisp from ruby. But
19
19
  if you want to call ruby from emacs (and you do, right?) you need to
@@ -110,7 +110,7 @@ The Emacs process is managed by <tt>Relisp::ElispSlave</tt>.
110
110
  require 'relisp'
111
111
  emacs = Relisp::ElispSlave.new
112
112
 
113
- Calls are made calling <tt>elisp_eval</tt> and <tt>elisp_execute</tt>
113
+ Calls are made calling <tt>elisp_eval</tt> and <tt>elisp_exec</tt>
114
114
  on the ElispSlave object.
115
115
 
116
116
  emacs.elisp_eval "(+ 1 2)"
@@ -128,7 +128,7 @@ functions:
128
128
  emacs.*(5,2) # (* 5 2)
129
129
  emacs.create_file_buffer("blah.txt") # (create-file-buffer "blah.txt")
130
130
 
131
- Emacs editing types have (or will have) proxy classes:
131
+ Emacs editing types have proxy classes with extensive functionality:
132
132
 
133
133
  buffer = Relisp::Buffer.new("ruby-created-buffer")
134
134
  => #<Relisp::Buffer:0xb7c4784c>
@@ -144,7 +144,6 @@ use the <tt>ElispSlave#debugging</tt> method:
144
144
 
145
145
  == To Do
146
146
 
147
- * finish implementing emacs editting types (buffers, frames, etc.)
148
147
  * fix Windows bug(s)
149
148
 
150
149
  == Author
@@ -10,10 +10,10 @@
10
10
  (ruby-eval "sample_ruby_method2")
11
11
 
12
12
  (member "ruby-created-buffer" (mapcar (lambda (a) (buffer-name a)) (buffer-list)))
13
- (ruby-eval "sample_ruby_method3")
13
+ (ruby-exec "sample_ruby_method3")
14
14
  (member "ruby-created-buffer" (mapcar (lambda (a) (buffer-name a)) (buffer-list)))
15
15
 
16
- (ruby-eval "sample_ruby_method4")
16
+ (ruby-exec "sample_ruby_method4")
17
17
 
18
18
  ;; How to start the ruby slave without a file. The rest of the
19
19
  ;; commands will work fine with a slave started either way.
@@ -48,9 +48,8 @@
48
48
  (ruby-eval "elisp_eval('(ruby-eval \"1 + 2\")')")
49
49
 
50
50
  ;; Variable persistence between calls:
51
- (ruby-eval "a = 5")
51
+ (ruby-exec "a = 5")
52
52
  (ruby-eval "a + 1")
53
53
 
54
54
 
55
55
 
56
-
@@ -17,7 +17,10 @@ def sample_ruby_method3
17
17
  end
18
18
 
19
19
  def sample_ruby_method4
20
- Relisp::Frame.new({:width => 80, :height => 20, :name => "ruby frame"})
20
+ frame= Relisp::Frame.new({:width => 80, :height => 20, :name => "ruby frame"})
21
+ frame.height
22
+ frame.height=60
23
+ frame.height
21
24
  end
22
25
 
23
26
  slave.start
@@ -28,13 +28,14 @@ module Relisp
28
28
  #
29
29
  # This does not simply call the <tt>save-excursion</tt> function
30
30
  # in elisp, it is a rewrite to accept a ruby block.
31
+ #
31
32
  def save_excursion
32
33
  raise ArgumentError unless block_given?
33
34
  begin
34
35
  start_point = point()
35
36
  start_mark = mark()
36
37
  start_buffer = current_buffer()
37
- start_active = elisp_execute( "mark-active" )
38
+ start_active = elisp_eval( "mark-active" )
38
39
  yield
39
40
  ensure
40
41
  set_buffer(start_buffer)
@@ -44,6 +45,42 @@ module Relisp
44
45
  end
45
46
  end
46
47
 
48
+ # Save the current buffer; execute a block of code;
49
+ # restore the current buffer.
50
+ #
51
+ # This does not simply call the <tt>with-current-buffer</tt>
52
+ # function in elisp, it is a rewrite to accept a ruby block.
53
+ #
54
+ def with_current_buffer
55
+ raise ArgumentError unless block_given?
56
+ begin
57
+ start_buffer = current_buffer()
58
+ yield
59
+ ensure
60
+ set_buffer(start_buffer)
61
+ end
62
+ end
63
+
64
+ # Create a temporary buffer, and evaluate a block of code there.
65
+ #
66
+ # This does not simply call the <tt>with-temp-buffer</tt> function
67
+ # in elisp, it is a rewrite to accept a ruby block.
68
+ #
69
+ def with_temp_buffer
70
+ raise ArgumentError unless block_given?
71
+ begin
72
+ start_buffer = current_buffer()
73
+ temp_buffer = Relisp::Buffer.new("*temp--relisp--buffer*", self)
74
+ yield
75
+ ensure
76
+ set_buffer(start_buffer)
77
+ temp_buffer.kill
78
+ end
79
+ end
80
+
81
+ # TODO: save_selected_window
82
+ # TODO: with_selected_window
83
+
47
84
  private
48
85
 
49
86
  # Forward any missing method to elisp, writing the function and
data/lib/relisp/slaves.rb CHANGED
@@ -44,14 +44,21 @@ module Relisp
44
44
  # each other. This ruby library and the elisp code are tied to
45
45
  # one another so closely that I don't know if it matters, but it
46
46
  # still seemed like a bad idea to hard code the constants in both
47
- # places.
48
- ANSWER_CODE = '___FORTYTWO___'
49
- QUESTION_CODE = '___TOBEORNOTTOBE___'
50
- ERROR_CODE = '___NO_THATSNOTTRUE_THATSIMPOSSIBLE___'
51
- ENDOFMESSAGE_REGEXP = Regexp.new(ANSWER_CODE + '|' + QUESTION_CODE + '|' + ERROR_CODE)
47
+ # places. Just make sure that the order in the elisp function
48
+ # <tt>relisp-get-constants</tt> matches the ruby method
49
+ # <tt>send_constants</tt>.
50
+ CONSTANTS = Array.new
51
+ CONSTANTS << QUESTION_CODE = '___TOBEORNOTTOBE___'
52
+ CONSTANTS << COMMAND_CODE = '___THOUSHALT___'
53
+ CONSTANTS << BEGIN_ANSWER_CODE = '___WHATIS___'
54
+ CONSTANTS << ANSWER_CODE = '___FORTYTWO___'
55
+ CONSTANTS << ERROR_CODE = '___NO_THATSNOTTRUE_THATSIMPOSSIBLE___'
56
+ TRANSMISSION_CODES_REGEXP = Regexp.new(CONSTANTS.join('|'))
57
+
52
58
  # Every time ruby asks elisp to evaluate an expression, the result
53
59
  # is saved in this variable so ruby can access it if necessary.
54
- PREVIOUS_ELISP_RESULT = :"--relisp--previous--result"
60
+ PREVIOUS_ELISP_RESULT = :"--relisp--previous--result"
61
+ CONSTANTS << PREVIOUS_ELISP_RESULT
55
62
  # A prefix for elisp variables created by ruby.
56
63
  VARIABLE_PREFIX = '--relisp--variable--'
57
64
 
@@ -79,17 +86,36 @@ module Relisp
79
86
  #
80
87
  def get_permanent_variable(old_variable)
81
88
  permanent_variable = new_elisp_variable
82
- elisp_execute( "(setq #{permanent_variable} #{old_variable})" )
89
+ elisp_exec( "(setq #{permanent_variable} #{old_variable})" )
83
90
  return permanent_variable
84
91
  end
85
92
 
86
93
  # Run _code_ in the elisp process.
87
94
  #
88
- def elisp_execute(code)
95
+ def elisp_exec(code)
96
+ code = code.to_s # maybe code is a symbol or something
97
+ write_to_emacs code
98
+ write_to_emacs COMMAND_CODE
99
+ receive_answer
100
+ end
101
+
102
+ # Run _code_ in the elisp process and return the result as the
103
+ # corresponding ruby object. If the ruby object is not going to
104
+ # be used, use elisp_exec instead.
105
+ #
106
+ def elisp_eval(code)
89
107
  code = code.to_s # maybe code is a symbol or something
90
108
  write_to_emacs code
91
109
  write_to_emacs QUESTION_CODE
110
+ to_ruby(receive_answer)
111
+ end
112
+
113
+ private
92
114
 
115
+ # Handle messages from emacs after <tt>elisp_exec</tt> or
116
+ # <tt>elisp_eval</tt> are called.
117
+ #
118
+ def receive_answer
93
119
  output = ''
94
120
  output_line = read_from_emacs
95
121
  until output_line.strip == ANSWER_CODE
@@ -97,6 +123,11 @@ module Relisp
97
123
  write_to_emacs((eval(output, @local_binding)).to_elisp)
98
124
  write_to_emacs ANSWER_CODE
99
125
  output = ''
126
+ elsif output_line.strip == COMMAND_CODE
127
+ eval output, @local_binding
128
+ # write_to_emacs ""
129
+ write_to_emacs ANSWER_CODE
130
+ output = ''
100
131
  elsif output_line.strip == ERROR_CODE
101
132
  raise Relisp::ElispError, (eval output)
102
133
  else
@@ -108,17 +139,6 @@ module Relisp
108
139
  output.gsub!(/\n\z/, '')
109
140
  return output
110
141
  end
111
-
112
- # Run _code_ in the elisp process and return the result as the
113
- # corresponding ruby object. If the ruby object is not going to
114
- # be used, use elisp_execute instead.
115
- #
116
- def elisp_eval(code)
117
- result_string = elisp_execute(code)
118
- to_ruby(result_string)
119
- end
120
-
121
- private
122
142
 
123
143
  # Pass an elisp evaluation result to the appropriate Relisp class
124
144
  # for translation. The first line of _result_string_ is the
@@ -128,8 +148,24 @@ module Relisp
128
148
  # be kept (in emacs) in the variable +PREVIOUS_ELISP_RESULT+.
129
149
  #
130
150
  def to_ruby(result_string)
151
+
152
+ # The result_string might have junk at the begining caused by
153
+ # whatever emacs sends to the echo area while evaluating ruby's
154
+ # instructions (it doesn't seem possible to get around this
155
+ # using with-output-to-string because the output from
156
+ # save-buffer and other functions is 'message'd). It is also
157
+ # not possible to just pull off the last two elements, because
158
+ # sometimes the string representation of the result has newlines
159
+ # in it (Buffer#to_s, for example). Otherwise, you could just
160
+ # do:
161
+ # object_string = result_string.pop
162
+ # elisp_type = result_string.pop
163
+
131
164
  result_string = result_string.split("\n")
132
- elisp_type = result_string.reverse!.pop
165
+ start_index = result_string.index(BEGIN_ANSWER_CODE) + 1
166
+ result_string = result_string[start_index..(result_string.size-1)]
167
+
168
+ elisp_type = result_string.reverse!.pop
133
169
  object_string = result_string.reverse!.join("\n")
134
170
 
135
171
  object_info = {
@@ -150,8 +186,8 @@ module Relisp
150
186
 
151
187
  # Send the constants that ruby and elisp need to share.
152
188
  #
153
- def pass_constants
154
- [ANSWER_CODE, QUESTION_CODE, ERROR_CODE, PREVIOUS_ELISP_RESULT].each do |constant|
189
+ def send_constants
190
+ CONSTANTS.each do |constant|
155
191
  read_from_emacs
156
192
  write_to_emacs constant
157
193
  end
@@ -203,7 +239,7 @@ module Relisp
203
239
  #
204
240
  def initialize
205
241
  super
206
- pass_constants
242
+ send_constants
207
243
 
208
244
  if block_given?
209
245
  yield self
@@ -221,17 +257,26 @@ module Relisp
221
257
  loop do
222
258
  code = ''
223
259
  input = read_from_emacs
224
- until input.strip == QUESTION_CODE
260
+ until input.strip == QUESTION_CODE || input.strip == COMMAND_CODE
225
261
  code << input
226
262
  input = read_from_emacs
227
263
  end
228
264
  code.gsub!(/\n\z/, '')
229
265
 
230
- write_to_emacs((eval code, @local_binding).to_elisp)
266
+ if input.strip == QUESTION_CODE
267
+ write_to_emacs((eval code, @local_binding).to_elisp)
268
+ else
269
+ eval(code, @local_binding)
270
+ end
231
271
  write_to_emacs ANSWER_CODE
232
272
  end
233
273
  rescue => dag_yo
234
- write_to_emacs dag_yo
274
+ msg = dag_yo.message + "\n"
275
+ dag_yo.backtrace.each do |b|
276
+ msg << " " + b + "\n"
277
+ end
278
+ write_to_emacs(msg)
279
+ #write_to_emacs(dag_yo.message)
235
280
  write_to_emacs ERROR_CODE
236
281
  retry
237
282
  end
@@ -291,7 +336,7 @@ module Relisp
291
336
 
292
337
  # gobble whatever output until emacs reports for duty
293
338
  until read_from_emacs.strip == "SEND CONSTANTS"; end
294
- pass_constants
339
+ send_constants
295
340
  end
296
341
 
297
342
  attr_accessor :debug
@@ -325,7 +370,7 @@ module Relisp
325
370
  #
326
371
  def write_to_emacs(code)
327
372
  if @debug
328
- puts "ruby> " + code.to_s unless code =~ ENDOFMESSAGE_REGEXP
373
+ puts "ruby> " + code.to_s unless code =~ TRANSMISSION_CODES_REGEXP
329
374
  end
330
375
  @emacs_pipe.puts code
331
376
  end
@@ -337,7 +382,7 @@ module Relisp
337
382
  def read_from_emacs
338
383
  output = @emacs_pipe.gets
339
384
  if @debug
340
- puts "lisp> " + output unless output =~ ENDOFMESSAGE_REGEXP
385
+ puts "lisp> " + output unless output =~ TRANSMISSION_CODES_REGEXP
341
386
  end
342
387
  return output
343
388
  end