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 +10 -0
- data/Manifest +5 -2
- data/README +3 -4
- data/examples/elisp_master/elisp_master.el +3 -4
- data/examples/elisp_master/ruby_slave +4 -1
- data/lib/relisp/elisp_functions.rb +38 -1
- data/lib/relisp/slaves.rb +74 -29
- data/lib/relisp/type_conversion/editing_types.rb +1178 -0
- data/lib/relisp/{programming_types.rb → type_conversion/programming_types.rb} +56 -11
- data/lib/relisp/type_conversion.rb +60 -0
- data/lib/relisp.rb +3 -4
- data/manual_test/tests.el +72 -0
- data/manual_test/tests.rb +66 -0
- data/src/relisp.el +91 -40
- data/src/relisp.elc +0 -0
- data/test/test_editing_types.rb +455 -14
- data/test/test_elisp_functions.rb +2 -0
- data/test/test_programming_types.rb +42 -20
- data/test/test_slaves.rb +7 -5
- metadata +7 -4
- data/lib/relisp/editing_types.rb +0 -295
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
|
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>
|
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
|
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-
|
13
|
+
(ruby-exec "sample_ruby_method3")
|
14
14
|
(member "ruby-created-buffer" (mapcar (lambda (a) (buffer-name a)) (buffer-list)))
|
15
15
|
|
16
|
-
(ruby-
|
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-
|
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 =
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
154
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =~
|
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 =~
|
385
|
+
puts "lisp> " + output unless output =~ TRANSMISSION_CODES_REGEXP
|
341
386
|
end
|
342
387
|
return output
|
343
388
|
end
|