relisp 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/relisp/slaves.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (C) 2009 <don@ohspite.net>
2
+ # Copyright (C) 2009, 2010 Don March
3
3
  #
4
4
  # This file is part of Relisp.
5
5
  #
@@ -18,6 +18,7 @@
18
18
  # <http://www.gnu.org/licenses/>.
19
19
  #++
20
20
  #
21
+
21
22
  # TODO: maybe catch Errno::EPIPE to see if slave died
22
23
 
23
24
  module Relisp
@@ -53,6 +54,7 @@ module Relisp
53
54
  CONSTANTS << BEGIN_ANSWER_CODE = '___WHATIS___'
54
55
  CONSTANTS << ANSWER_CODE = '___FORTYTWO___'
55
56
  CONSTANTS << ERROR_CODE = '___NO_THATSNOTTRUE_THATSIMPOSSIBLE___'
57
+ CONSTANTS << BEGIN_SLAVE_CODE = '___LETSDOTHISLIKEBRUTUS___'
56
58
  TRANSMISSION_CODES_REGEXP = Regexp.new(CONSTANTS.join('|'))
57
59
 
58
60
  # Every time ruby asks elisp to evaluate an expression, the result
@@ -67,7 +69,7 @@ module Relisp
67
69
  # elisp it is in a context where any new variables set will drop
68
70
  # out of scope immediately. The @local_binding is a way of
69
71
  # allowing these variables to persist through multiple calls.
70
- @local_binding = nil
72
+ @local_binding = binding
71
73
  @current_elisp_variable_num = '0'
72
74
  @debug = nil
73
75
  Relisp.default_slave = self
@@ -93,7 +95,7 @@ module Relisp
93
95
  # Run _code_ in the elisp process.
94
96
  #
95
97
  def elisp_exec(code)
96
- code = code.to_s # maybe code is a symbol or something
98
+ code = code.to_s # maybe code is nil or something
97
99
  write_to_emacs code
98
100
  write_to_emacs COMMAND_CODE
99
101
  receive_answer
@@ -125,7 +127,6 @@ module Relisp
125
127
  output = ''
126
128
  elsif output_line.strip == COMMAND_CODE
127
129
  eval output, @local_binding
128
- # write_to_emacs ""
129
130
  write_to_emacs ANSWER_CODE
130
131
  output = ''
131
132
  elsif output_line.strip == ERROR_CODE
@@ -141,32 +142,29 @@ module Relisp
141
142
  end
142
143
 
143
144
  # Pass an elisp evaluation result to the appropriate Relisp class
144
- # for translation. The first line of _result_string_ is the
145
+ # for translation. The first line of _result_ is the
145
146
  # 'type-of' the elisp object. The line(s) after that are the text
146
147
  # version of the object. In case the string representation isn't
147
148
  # enough information to translate the object, the result needs to
148
149
  # be kept (in emacs) in the variable +PREVIOUS_ELISP_RESULT+.
149
150
  #
150
- def to_ruby(result_string)
151
+ def to_ruby(result)
151
152
 
152
- # The result_string might have junk at the begining caused by
153
+ # The result might have junk at the beginning caused by
153
154
  # whatever emacs sends to the echo area while evaluating ruby's
154
155
  # instructions (it doesn't seem possible to get around this
155
156
  # using with-output-to-string because the output from
156
157
  # save-buffer and other functions is 'message'd). It is also
157
158
  # not possible to just pull off the last two elements, because
158
159
  # 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
-
164
- result_string = result_string.split("\n")
165
- start_index = result_string.index(BEGIN_ANSWER_CODE) + 1
166
- result_string = result_string[start_index..(result_string.size-1)]
160
+ # in it (Buffer#to_s, for example).
161
+
162
+ result = result.split("\n")
163
+ start_index = result.index(BEGIN_ANSWER_CODE) + 1
164
+ result = result[start_index..(result.size-1)]
167
165
 
168
- elisp_type = result_string.reverse!.pop
169
- object_string = result_string.reverse!.join("\n")
166
+ elisp_type = result.shift
167
+ object_string = result.join("\n")
170
168
 
171
169
  object_info = {
172
170
  :string => object_string,
@@ -177,10 +175,11 @@ module Relisp
177
175
  # Just one more reason to love Ruby. Call the Relisp class
178
176
  # formed by rubyizing the 'type-of' the result (i.e., hash-table
179
177
  # becomes HashTable).
180
- ruby_type = (eval elisp_type.split("-").map { |a| a.capitalize }.join)
178
+ ruby_type = Relisp.const_get(elisp_type.split("-").map { |a| a.capitalize }.join)
181
179
  unless ruby_type.kind_of? Class
182
180
  raise "#{ruby_type} not implemented"
183
181
  end
182
+
184
183
  ruby_type.from_elisp(object_info)
185
184
  end
186
185
 
@@ -189,8 +188,9 @@ module Relisp
189
188
  def send_constants
190
189
  CONSTANTS.each do |constant|
191
190
  read_from_emacs
192
- write_to_emacs constant
191
+ write_to_emacs constant.to_s + "\n"
193
192
  end
193
+ read_from_emacs
194
194
  end
195
195
 
196
196
  public
@@ -214,7 +214,7 @@ module Relisp
214
214
  # emacs.elisp_eval('(ruby-eval "number")') # => 5
215
215
  #
216
216
  def provide(symbol, binding)
217
- eval "@__#{symbol.to_s}__binding = binding"
217
+ instance_variable_set "@__#{symbol.to_s}__binding".to_sym, binding
218
218
 
219
219
  instance_eval <<-endstr
220
220
  def #{symbol.to_s}
@@ -230,12 +230,17 @@ module Relisp
230
230
  #
231
231
  class RubySlave < Slave
232
232
 
233
+ # Creates a new RubySlave and immediately starts it.
234
+ #
235
+ def self.start
236
+ self.new.start
237
+ end
238
+
233
239
  # Can be provided with a block, in which case the block is run in
234
- # the context of the slave and then the slave is automatically
235
- # started. This makes slave methods available to the block
236
- # without specifying an explicit receiver, and variables and
237
- # functions defined in the block are in scope when requests from
238
- # elisp are evaluated.
240
+ # the context of the slave. This makes slave methods available to
241
+ # the block without specifying an explicit receiver, and variables
242
+ # and functions defined in the block are in scope when requests
243
+ # from elisp are later evaluated.
239
244
  #
240
245
  def initialize
241
246
  super
@@ -243,17 +248,17 @@ module Relisp
243
248
 
244
249
  if block_given?
245
250
  yield self
246
- start
251
+ # start
247
252
  end
248
-
249
253
  end
250
254
 
251
255
  # Begin the main listening loop.
252
256
  #
253
257
  def start
258
+ write_to_emacs BEGIN_SLAVE_CODE
259
+ write_to_emacs ANSWER_CODE
260
+
254
261
  begin
255
- @local_binding = binding
256
-
257
262
  loop do
258
263
  code = ''
259
264
  input = read_from_emacs
@@ -275,7 +280,7 @@ module Relisp
275
280
  dag_yo.backtrace.each do |b|
276
281
  msg << " " + b + "\n"
277
282
  end
278
- write_to_emacs(msg)
283
+ write_to_emacs msg.chomp
279
284
  #write_to_emacs(dag_yo.message)
280
285
  write_to_emacs ERROR_CODE
281
286
  retry
@@ -288,7 +293,8 @@ module Relisp
288
293
  # the ruby process.
289
294
  #
290
295
  def write_to_emacs(code)
291
- puts code
296
+ # puts code
297
+ print code
292
298
  end
293
299
 
294
300
  # Messages appear on ruby's stdin after emacs sends them to ruby
@@ -298,7 +304,7 @@ module Relisp
298
304
  gets
299
305
  end
300
306
  end
301
-
307
+
302
308
  # Provides an interface to an instance of emacs started as an IO
303
309
  # object. See Relisp::Slave.
304
310
  #
@@ -313,11 +319,9 @@ module Relisp
313
319
  #
314
320
  def initialize(cli_options = "--no-site-file --no-init-file", load_files = [])
315
321
  super()
316
- # load relisp.elc if available
322
+ # leave off '.el' to load relisp.elc if available
317
323
  elisp_path = File.expand_path(File.join(File.dirname(__FILE__), '../../src/relisp'))
318
324
 
319
- @local_binding = binding
320
-
321
325
  emacs_command = if RUBY_PLATFORM.downcase.include?('mswin')
322
326
  "start emacs --batch "
323
327
  else