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.
- 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
|