relisp 1.0.1 → 1.1.0
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.
- data/CHANGELOG +14 -0
- data/README +22 -22
- data/Rakefile +4 -3
- data/examples/elisp_master/elisp_master.el +70 -34
- data/examples/elisp_master/ruby_slave.rb +37 -0
- data/examples/elisp_master/ruby_slave2.rb +33 -0
- data/examples/ruby_master/basic.rb +20 -0
- data/examples/ruby_master/debugging.rb +32 -0
- data/examples/ruby_master/elisp_data_types.rb +26 -0
- data/examples/ruby_master/method_missing.rb +24 -0
- data/examples/ruby_master/recursive_calling.rb +11 -0
- data/lib/relisp/elisp_functions.rb +30 -13
- data/lib/relisp/slaves.rb +39 -35
- data/lib/relisp/type_conversion/editing_types.rb +677 -643
- data/lib/relisp/type_conversion/programming_types.rb +70 -117
- data/lib/relisp/type_conversion.rb +43 -2
- data/lib/relisp.rb +5 -2
- data/manual_test/tests.el +0 -2
- data/manual_test/tests.rb +0 -29
- data/src/relisp.el +223 -220
- data/test/test_editing_types.rb +4 -3
- data/test/test_elisp_functions.rb +0 -1
- data/test/test_programming_types.rb +5 -4
- data/test/test_slaves.rb +2 -1
- metadata +15 -10
- data/examples/elisp_master/ruby_slave +0 -26
- data/examples/ruby_master/ruby_master_example +0 -27
- data/setup.rb +0 -1598
data/lib/relisp/slaves.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (C) 2009
|
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 =
|
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
|
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
|
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(
|
151
|
+
def to_ruby(result)
|
151
152
|
|
152
|
-
# The
|
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).
|
160
|
-
|
161
|
-
|
162
|
-
|
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 =
|
169
|
-
object_string =
|
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 = (
|
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
|
-
|
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
|
235
|
-
#
|
236
|
-
#
|
237
|
-
#
|
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
|
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
|