el4r 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) hide show
  1. data/BUGS +2 -0
  2. data/Changes +2412 -0
  3. data/bin/el4r +26 -0
  4. data/bin/el4r-instance +1105 -0
  5. data/bin/el4r-rctool +279 -0
  6. data/bin/el4r-runtest +26 -0
  7. data/data/emacs/site-lisp/el4r.el +441 -0
  8. data/doc/classes/El4r.html +200 -0
  9. data/doc/classes/El4r.src/M000004.html +25 -0
  10. data/doc/classes/El4r.src/M000005.html +25 -0
  11. data/doc/classes/El4r.src/M000006.html +18 -0
  12. data/doc/classes/El4r.src/M000008.html +25 -0
  13. data/doc/classes/El4r.src/M000009.html +18 -0
  14. data/doc/classes/El4r/ELConsCell.html +145 -0
  15. data/doc/classes/El4r/ELConsCell.src/M000044.html +16 -0
  16. data/doc/classes/El4r/ELConsCell.src/M000046.html +16 -0
  17. data/doc/classes/El4r/ELConsCell.src/M000050.html +16 -0
  18. data/doc/classes/El4r/ELInstance.html +755 -0
  19. data/doc/classes/El4r/ELInstance.src/M000046.html +36 -0
  20. data/doc/classes/El4r/ELInstance.src/M000047.html +41 -0
  21. data/doc/classes/El4r/ELInstance.src/M000048.html +31 -0
  22. data/doc/classes/El4r/ELInstance.src/M000049.html +22 -0
  23. data/doc/classes/El4r/ELInstance.src/M000050.html +25 -0
  24. data/doc/classes/El4r/ELInstance.src/M000051.html +35 -0
  25. data/doc/classes/El4r/ELInstance.src/M000052.html +31 -0
  26. data/doc/classes/El4r/ELInstance.src/M000053.html +23 -0
  27. data/doc/classes/El4r/ELInstance.src/M000054.html +41 -0
  28. data/doc/classes/El4r/ELInstance.src/M000055.html +31 -0
  29. data/doc/classes/El4r/ELInstance.src/M000056.html +43 -0
  30. data/doc/classes/El4r/ELInstance.src/M000057.html +31 -0
  31. data/doc/classes/El4r/ELInstance.src/M000058.html +22 -0
  32. data/doc/classes/El4r/ELInstance.src/M000059.html +25 -0
  33. data/doc/classes/El4r/ELInstance.src/M000060.html +43 -0
  34. data/doc/classes/El4r/ELInstance.src/M000061.html +31 -0
  35. data/doc/classes/El4r/ELInstance.src/M000062.html +22 -0
  36. data/doc/classes/El4r/ELInstance.src/M000063.html +25 -0
  37. data/doc/classes/El4r/ELInstance.src/M000064.html +35 -0
  38. data/doc/classes/El4r/ELInstance.src/M000065.html +23 -0
  39. data/doc/classes/El4r/ELInstance.src/M000066.html +23 -0
  40. data/doc/classes/El4r/ELInstance.src/M000067.html +19 -0
  41. data/doc/classes/El4r/ELInstance.src/M000068.html +18 -0
  42. data/doc/classes/El4r/ELInstance.src/M000069.html +20 -0
  43. data/doc/classes/El4r/ELInstance.src/M000070.html +18 -0
  44. data/doc/classes/El4r/ELInstance.src/M000071.html +19 -0
  45. data/doc/classes/El4r/ELInstance.src/M000072.html +30 -0
  46. data/doc/classes/El4r/ELInstance.src/M000073.html +20 -0
  47. data/doc/classes/El4r/ELInstance.src/M000074.html +20 -0
  48. data/doc/classes/El4r/ELInstance.src/M000075.html +17 -0
  49. data/doc/classes/El4r/ELInstance.src/M000076.html +18 -0
  50. data/doc/classes/El4r/ELInstance.src/M000077.html +21 -0
  51. data/doc/classes/El4r/ELInstance.src/M000078.html +18 -0
  52. data/doc/classes/El4r/ELInstance.src/M000079.html +18 -0
  53. data/doc/classes/El4r/ELInstance.src/M000080.html +35 -0
  54. data/doc/classes/El4r/ELInstance.src/M000081.html +24 -0
  55. data/doc/classes/El4r/ELInstance.src/M000082.html +22 -0
  56. data/doc/classes/El4r/ELInstance.src/M000083.html +21 -0
  57. data/doc/classes/El4r/ELInstance.src/M000084.html +19 -0
  58. data/doc/classes/El4r/ELInstance.src/M000085.html +18 -0
  59. data/doc/classes/El4r/ELInstance.src/M000086.html +21 -0
  60. data/doc/classes/El4r/ELInstance.src/M000087.html +18 -0
  61. data/doc/classes/El4r/ELInstance.src/M000088.html +24 -0
  62. data/doc/classes/El4r/ELInstance.src/M000089.html +23 -0
  63. data/doc/classes/El4r/ELInstance.src/M000090.html +18 -0
  64. data/doc/classes/El4r/ELInstance.src/M000091.html +20 -0
  65. data/doc/classes/El4r/ELInstance.src/M000092.html +18 -0
  66. data/doc/classes/El4r/ELInstance.src/M000093.html +19 -0
  67. data/doc/classes/El4r/ELListCell.html +163 -0
  68. data/doc/classes/El4r/ELListCell.src/M000026.html +16 -0
  69. data/doc/classes/El4r/ELListCell.src/M000027.html +16 -0
  70. data/doc/classes/El4r/ELListCell.src/M000028.html +23 -0
  71. data/doc/classes/El4r/ELListCell.src/M000031.html +16 -0
  72. data/doc/classes/El4r/ELListCell.src/M000032.html +23 -0
  73. data/doc/classes/El4r/ELListCell.src/M000033.html +16 -0
  74. data/doc/classes/El4r/ELListCell.src/M000034.html +23 -0
  75. data/doc/classes/El4r/ELListCell.src/M000037.html +16 -0
  76. data/doc/classes/El4r/ELListCell.src/M000038.html +23 -0
  77. data/doc/classes/El4r/ELMethodsMixin.html +648 -0
  78. data/doc/classes/El4r/ELMethodsMixin.src/M000006.html +27 -0
  79. data/doc/classes/El4r/ELMethodsMixin.src/M000007.html +27 -0
  80. data/doc/classes/El4r/ELMethodsMixin.src/M000008.html +18 -0
  81. data/doc/classes/El4r/ELMethodsMixin.src/M000009.html +18 -0
  82. data/doc/classes/El4r/ELMethodsMixin.src/M000010.html +27 -0
  83. data/doc/classes/El4r/ELMethodsMixin.src/M000011.html +19 -0
  84. data/doc/classes/El4r/ELMethodsMixin.src/M000012.html +18 -0
  85. data/doc/classes/El4r/ELMethodsMixin.src/M000013.html +19 -0
  86. data/doc/classes/El4r/ELMethodsMixin.src/M000014.html +19 -0
  87. data/doc/classes/El4r/ELMethodsMixin.src/M000015.html +18 -0
  88. data/doc/classes/El4r/ELMethodsMixin.src/M000016.html +21 -0
  89. data/doc/classes/El4r/ELMethodsMixin.src/M000017.html +18 -0
  90. data/doc/classes/El4r/ELMethodsMixin.src/M000018.html +23 -0
  91. data/doc/classes/El4r/ELMethodsMixin.src/M000019.html +18 -0
  92. data/doc/classes/El4r/ELMethodsMixin.src/M000020.html +46 -0
  93. data/doc/classes/El4r/ELMethodsMixin.src/M000021.html +18 -0
  94. data/doc/classes/El4r/ELMethodsMixin.src/M000022.html +23 -0
  95. data/doc/classes/El4r/ELMethodsMixin.src/M000023.html +28 -0
  96. data/doc/classes/El4r/ELMethodsMixin.src/M000024.html +46 -0
  97. data/doc/classes/El4r/ELMethodsMixin.src/M000025.html +18 -0
  98. data/doc/classes/El4r/ELMethodsMixin.src/M000026.html +18 -0
  99. data/doc/classes/El4r/ELMethodsMixin.src/M000027.html +28 -0
  100. data/doc/classes/El4r/ELMethodsMixin.src/M000028.html +31 -0
  101. data/doc/classes/El4r/ELMethodsMixin.src/M000029.html +24 -0
  102. data/doc/classes/El4r/ELMethodsMixin.src/M000030.html +18 -0
  103. data/doc/classes/El4r/ELMethodsMixin.src/M000031.html +18 -0
  104. data/doc/classes/El4r/ELMethodsMixin.src/M000032.html +18 -0
  105. data/doc/classes/El4r/ELMethodsMixin.src/M000033.html +18 -0
  106. data/doc/classes/El4r/ELMethodsMixin.src/M000034.html +18 -0
  107. data/doc/classes/El4r/ELMethodsMixin.src/M000035.html +18 -0
  108. data/doc/classes/El4r/ELMethodsMixin.src/M000036.html +25 -0
  109. data/doc/classes/El4r/ELObject.html +235 -0
  110. data/doc/classes/El4r/ELObject.src/M000078.html +19 -0
  111. data/doc/classes/El4r/ELObject.src/M000079.html +18 -0
  112. data/doc/classes/El4r/ELObject.src/M000080.html +19 -0
  113. data/doc/classes/El4r/ELObject.src/M000081.html +18 -0
  114. data/doc/classes/El4r/ELObject.src/M000082.html +19 -0
  115. data/doc/classes/El4r/ELObject.src/M000083.html +18 -0
  116. data/doc/classes/El4r/ELObject.src/M000084.html +18 -0
  117. data/doc/classes/El4r/ELObject.src/M000085.html +18 -0
  118. data/doc/classes/El4r/ELObject.src/M000086.html +20 -0
  119. data/doc/classes/El4r/ELObject.src/M000087.html +19 -0
  120. data/doc/classes/El4r/ELObject.src/M000088.html +20 -0
  121. data/doc/classes/El4r/ELObject.src/M000090.html +19 -0
  122. data/doc/classes/El4r/ELObject.src/M000091.html +19 -0
  123. data/doc/classes/El4r/ELObject.src/M000092.html +18 -0
  124. data/doc/classes/El4r/ELObject.src/M000093.html +19 -0
  125. data/doc/classes/El4r/ELObject.src/M000094.html +18 -0
  126. data/doc/classes/El4r/ELObject.src/M000095.html +18 -0
  127. data/doc/classes/El4r/ELObject.src/M000096.html +18 -0
  128. data/doc/classes/El4r/ELObject.src/M000097.html +19 -0
  129. data/doc/classes/El4r/ELObject.src/M000098.html +18 -0
  130. data/doc/classes/El4r/ELObject.src/M000099.html +18 -0
  131. data/doc/classes/El4r/ELObject.src/M000100.html +18 -0
  132. data/doc/classes/El4r/ELObject.src/M000102.html +19 -0
  133. data/doc/classes/El4r/ELObject.src/M000103.html +20 -0
  134. data/doc/classes/El4r/ELRubyObjectStock.html +283 -0
  135. data/doc/classes/El4r/ELRubyObjectStock.src/M000030.html +21 -0
  136. data/doc/classes/El4r/ELRubyObjectStock.src/M000031.html +22 -0
  137. data/doc/classes/El4r/ELRubyObjectStock.src/M000032.html +22 -0
  138. data/doc/classes/El4r/ELRubyObjectStock.src/M000033.html +42 -0
  139. data/doc/classes/El4r/ELRubyObjectStock.src/M000034.html +19 -0
  140. data/doc/classes/El4r/ELRubyObjectStock.src/M000035.html +22 -0
  141. data/doc/classes/El4r/ELRubyObjectStock.src/M000036.html +22 -0
  142. data/doc/classes/El4r/ELRubyObjectStock.src/M000037.html +22 -0
  143. data/doc/classes/El4r/ELRubyObjectStock.src/M000038.html +22 -0
  144. data/doc/classes/El4r/ELRubyObjectStock.src/M000039.html +17 -0
  145. data/doc/classes/El4r/ELRubyObjectStock.src/M000040.html +17 -0
  146. data/doc/classes/El4r/ELRubyObjectStock.src/M000041.html +22 -0
  147. data/doc/classes/El4r/ELRubyObjectStock.src/M000042.html +22 -0
  148. data/doc/classes/El4r/ELRubyObjectStock.src/M000043.html +17 -0
  149. data/doc/classes/El4r/ELRubyObjectStock.src/M000044.html +17 -0
  150. data/doc/classes/El4r/ELRubyObjectStock.src/M000045.html +46 -0
  151. data/doc/classes/El4r/ELRubyObjectStock.src/M000046.html +19 -0
  152. data/doc/classes/El4r/ELRubyObjectStock.src/M000047.html +21 -0
  153. data/doc/classes/El4r/ELRubyObjectStock.src/M000048.html +19 -0
  154. data/doc/classes/El4r/ELRubyObjectStock.src/M000049.html +18 -0
  155. data/doc/classes/El4r/ELSequence.html +221 -0
  156. data/doc/classes/El4r/ELSequence.src/M000040.html +18 -0
  157. data/doc/classes/El4r/ELSequence.src/M000041.html +18 -0
  158. data/doc/classes/El4r/ELSequence.src/M000042.html +20 -0
  159. data/doc/classes/El4r/ELSequence.src/M000043.html +19 -0
  160. data/doc/classes/El4r/ELSequence.src/M000044.html +18 -0
  161. data/doc/classes/El4r/ELSequence.src/M000045.html +19 -0
  162. data/doc/classes/El4r/ELSequence.src/M000048.html +18 -0
  163. data/doc/classes/El4r/ELSequence.src/M000049.html +20 -0
  164. data/doc/classes/El4r/ELSequence.src/M000050.html +18 -0
  165. data/doc/classes/El4r/ELSequence.src/M000051.html +20 -0
  166. data/doc/classes/El4r/ELSequence.src/M000052.html +19 -0
  167. data/doc/classes/El4r/ELSequence.src/M000053.html +18 -0
  168. data/doc/classes/El4r/ELSequence.src/M000054.html +18 -0
  169. data/doc/classes/El4r/ELSequence.src/M000055.html +20 -0
  170. data/doc/classes/El4r/ELSequence.src/M000056.html +19 -0
  171. data/doc/classes/El4r/ELSequence.src/M000057.html +18 -0
  172. data/doc/classes/El4r/ELSequence.src/M000058.html +19 -0
  173. data/doc/classes/El4r/ELVariables.html +173 -0
  174. data/doc/classes/El4r/ELVariables.src/M000037.html +18 -0
  175. data/doc/classes/El4r/ELVariables.src/M000038.html +18 -0
  176. data/doc/classes/El4r/ELVariables.src/M000039.html +18 -0
  177. data/doc/classes/El4r/ELVariables.src/M000040.html +23 -0
  178. data/doc/classes/El4r/ELVariables.src/M000045.html +18 -0
  179. data/doc/classes/El4r/ELVariables.src/M000046.html +18 -0
  180. data/doc/classes/El4r/ELVariables.src/M000047.html +18 -0
  181. data/doc/classes/El4r/ELVariables.src/M000048.html +18 -0
  182. data/doc/classes/El4r/ELVariables.src/M000049.html +23 -0
  183. data/doc/classes/El4r/ELVariables.src/M000051.html +18 -0
  184. data/doc/classes/El4r/ELVariables.src/M000052.html +18 -0
  185. data/doc/classes/El4r/ELVariables.src/M000053.html +23 -0
  186. data/doc/classes/El4r/ELVector.html +160 -0
  187. data/doc/classes/El4r/ELVector.src/M000028.html +22 -0
  188. data/doc/classes/El4r/ELVector.src/M000029.html +22 -0
  189. data/doc/classes/El4r/ELVector.src/M000030.html +16 -0
  190. data/doc/classes/El4r/ELVector.src/M000033.html +22 -0
  191. data/doc/classes/El4r/ELVector.src/M000034.html +16 -0
  192. data/doc/classes/El4r/ELVector.src/M000035.html +22 -0
  193. data/doc/classes/El4r/ELVector.src/M000036.html +16 -0
  194. data/doc/classes/El4r/ELVector.src/M000039.html +22 -0
  195. data/doc/classes/El4r/ELVector.src/M000040.html +16 -0
  196. data/doc/classes/El4r/El4rOutput.html +175 -0
  197. data/doc/classes/El4r/El4rOutput.src/M000080.html +18 -0
  198. data/doc/classes/El4r/El4rOutput.src/M000081.html +21 -0
  199. data/doc/classes/El4r/El4rOutput.src/M000088.html +18 -0
  200. data/doc/classes/El4r/El4rOutput.src/M000089.html +21 -0
  201. data/doc/classes/El4r/El4rOutput.src/M000090.html +18 -0
  202. data/doc/classes/El4r/El4rOutput.src/M000091.html +21 -0
  203. data/doc/classes/El4r/El4rOutput.src/M000092.html +18 -0
  204. data/doc/classes/El4r/El4rOutput.src/M000094.html +18 -0
  205. data/doc/classes/El4r/El4rOutput.src/M000095.html +21 -0
  206. data/doc/classes/El4r/El4rOutput.src/M000096.html +18 -0
  207. data/doc/classes/El4rAccessor.html +134 -0
  208. data/doc/classes/El4rAccessor.src/M000005.html +18 -0
  209. data/doc/classes/ElApp.html +211 -0
  210. data/doc/classes/ElApp.src/M000001.html +21 -0
  211. data/doc/classes/ElApp.src/M000002.html +17 -0
  212. data/doc/classes/ElApp.src/M000003.html +18 -0
  213. data/doc/classes/ElApp.src/M000004.html +18 -0
  214. data/doc/classes/ElMixin.html +163 -0
  215. data/doc/classes/ElMixin.src/M000001.html +19 -0
  216. data/doc/classes/ElMixin.src/M000002.html +19 -0
  217. data/doc/classes/ElMixin.src/M000003.html +18 -0
  218. data/doc/classes/ElMixin.src/M000004.html +18 -0
  219. data/doc/classes/ElMixin.src/M000006.html +19 -0
  220. data/doc/classes/ElMixin.src/M000007.html +18 -0
  221. data/doc/created.rid +1 -0
  222. data/doc/files/bin/el4r-instance.html +119 -0
  223. data/doc/fr_class_index.html +40 -0
  224. data/doc/fr_file_index.html +27 -0
  225. data/doc/fr_method_index.html +129 -0
  226. data/doc/index.html +24 -0
  227. data/doc/rdoc-style.css +208 -0
  228. data/el4r.en.html +468 -0
  229. data/el4r.ja.html +640 -0
  230. data/files +29 -0
  231. data/lib/el4r/el4r-sub.rb +1023 -0
  232. data/lib/el4r/emacsruby/autoload/70el4r-mode.rb +9 -0
  233. data/lib/el4r/emacsruby/el4r-mode.rb +35 -0
  234. data/lib/el4r/emacsruby/stdlib.rb +37 -0
  235. data/lib/el4r/exec-el4r.rb +182 -0
  236. data/man/el4r.1 +125 -0
  237. data/setup.rb +1551 -0
  238. data/testing/alltest.rb +5 -0
  239. data/testing/badcase.rb +50 -0
  240. data/testing/el4r.e +262 -0
  241. data/testing/euc.txt +1 -0
  242. data/testing/jis.txt +1 -0
  243. data/testing/sjis.txt +1 -0
  244. data/testing/test-el4r.rb +1053 -0
  245. data/testing/test-gc.rb +81 -0
  246. data/testing/test.el +16 -0
  247. data/testing/test.rb +97 -0
  248. data/testing/utf8.txt +1 -0
  249. metadata +311 -0
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ # el4r - EmacsLisp for Ruby
3
+ # Copyright (C) 2005 rubikitch <rubikitch@ruby-lang.org>
4
+ # Version: $Id: el4r 852 2005-11-15 19:38:07Z rubikitch $
5
+
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+
20
+ require 'el4r/exec-el4r'
21
+ exec_el4r false
22
+
23
+
24
+ # Local Variables:
25
+ # modes: (ruby-mode emacs-lisp-mode)
26
+ # End:
@@ -0,0 +1,1105 @@
1
+ #!/usr/bin/env ruby
2
+ # el4r - EmacsLisp for Ruby
3
+ # Copyright (C) 2005 rubikitch <rubikitch@ruby-lang.org>
4
+ # Version: $Id: el4r-instance 1376 2006-09-21 05:50:24Z rubikitch $
5
+
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+
20
+ require 'forwardable'
21
+
22
+ if ENV["EL4R_RECORDIO"]
23
+ # Requires ucspi-tcp
24
+ exec("sh", "-c", '\
25
+ exec 2>"$EL4R_RECORDIO"
26
+ unset EL4R_RECORDIO
27
+ exec recordio "$@"', "--", $0, *ARGV)
28
+ end
29
+ # TODO: ENV['EL4R_RC']
30
+ load "~/.el4rrc.rb";
31
+ # The EmacsRuby engine
32
+ module El4r
33
+ ErrorUtils = Module.new
34
+ class << ErrorUtils
35
+ def error_description(exception = nil)
36
+ exception ||= $!
37
+ sprintf("%s (%s)", exception.to_s, exception.class)
38
+ end
39
+
40
+ def backtrace_message(backtrace = nil)
41
+ backtrace ||= caller(1)
42
+ lines = []
43
+ backtrace.each do |line|
44
+ lines << sprintf(" from %s", line)
45
+ end
46
+ lines.join("\n")
47
+ end
48
+
49
+ def stacktrace_message(exception = nil)
50
+ exception ||= $!
51
+ lines = []
52
+
53
+ lines << error_description(exception)
54
+ lines << backtrace_message(exception.backtrace)
55
+ lines.join("\n")
56
+ end
57
+ end #/<< ErrorUtils
58
+
59
+ El4rError = Class.new(StandardError)
60
+ ELError = Class.new(El4rError)
61
+
62
+ ELISP_INTEGER_RANGE = (-134217727..134217727)
63
+
64
+ class << self
65
+ def lisp_dump_string(string)
66
+ dumped = string.dup
67
+ # \ -> \\
68
+ dumped.gsub! %r"\\" do '\\\\' end
69
+ # " -> \"
70
+ dumped.gsub! %r'"' do '\\"' end
71
+ # (zero byte) -> \0
72
+ dumped.gsub! %r'\0' do "\\\0" end
73
+ %Q'"#{dumped}"'
74
+ end
75
+
76
+ def name_rb2el(rbname)
77
+ rbname.gsub(/_/, "-")
78
+ end
79
+ end #/<< self
80
+
81
+ ELExpression = Struct.new(:expression)
82
+
83
+ # Reference of an EmacsLisp object.
84
+ class ELObject < Struct.new(:instance, :object_id)
85
+ def initialize(*args)
86
+ ObjectSpace.define_finalizer(self, ELObject.finalizer_proc(*args))
87
+ super(*args)
88
+ end
89
+
90
+ def to_lisp
91
+ "(el4r-lisp-object-from-id #{object_id})"
92
+ end
93
+
94
+ def inspect
95
+ "#<#{self.class} id=#{object_id}>"
96
+ end
97
+
98
+ def to_s
99
+ instance.prin1_to_string(self)
100
+ end
101
+ alias :to_str :to_s
102
+
103
+ def ==(x)
104
+ ELObject === x or return false
105
+ object_id == x.object_id or instance.equal(self,x)
106
+ end
107
+
108
+ def self.finalizer_proc(instance, object_id)
109
+ proc {
110
+ instance.el4r_add_garbage_lispobj(object_id)
111
+ }
112
+ end
113
+ end #/ELObject
114
+
115
+ class ELSequence < ELObject
116
+ include Enumerable
117
+
118
+ def inspect
119
+ "#{self.class.to_s.split(/::/)[-1]}#{to_a.inspect}"
120
+ end
121
+
122
+ def check(x)
123
+ @length ||= to_a.length
124
+ Fixnum === x or raise TypeError, "must be Fixnum"
125
+ @length <= x and raise ArgumentError, "Args out of range #{inspect}[#{x}]"
126
+ end
127
+
128
+ def [](*args)
129
+ check args[0]
130
+ to_a[*args]
131
+ end
132
+
133
+ def each(&block)
134
+ to_a.each(&block)
135
+ end
136
+
137
+ def to_a
138
+ # subclass must define `to_a_func' method
139
+ @ary ||= instance.__send__(to_a_func, self)
140
+ end
141
+ alias :to_ary :to_a
142
+
143
+ end #/ELSequence
144
+
145
+ # An Array like object converted from a list object of EmacsLisp.
146
+ class ELListCell < ELSequence
147
+ def to_a_func () :el4r_list_to_rubyary end
148
+
149
+ # Convert alist -> Hash
150
+ def to_hash
151
+ hash = {}
152
+ each { |cell|
153
+ cell.kind_of?(ELListCell) or raise(TypeError, "Malformed assoc list.")
154
+ hash[instance.car(cell)] = instance.cdr(cell)
155
+ }
156
+ hash
157
+ end
158
+ end #/ELListCell
159
+
160
+ # An Array like object converted from a cons cell of EmacsLisp.
161
+ class ELConsCell < ELListCell
162
+ def to_a_func () :el4r_cons_to_rubyary end
163
+ end
164
+
165
+ # An Array like object converted from a vector object of EmacsLisp.
166
+ class ELVector < ELSequence
167
+ def []=(x,y)
168
+ check x
169
+ x < 0 and x = @length+x
170
+
171
+ @ary[x]=y
172
+ instance.aset(self, x, y)
173
+ end
174
+
175
+ def to_a_func () :el4r_vector_to_rubyary end
176
+ end #/ELVector
177
+
178
+
179
+ # EmacsLisp objects stock.
180
+ class ELRubyObjectStock
181
+ attr_accessor :gc_trigger_count, :gc_trigger_increment
182
+ def initialize(instance)
183
+ @instance = instance
184
+ conf = instance.conf
185
+ @oid_to_obj_hash = {}
186
+ @gc_trigger_count = conf.ruby_gc_trigger_count
187
+ @gc_trigger_increment = conf.ruby_gc_trigger_increment
188
+ end
189
+
190
+ def garbage_collect_if_required
191
+ if count_of_stocked_objects >= @gc_trigger_count
192
+ garbage_collect
193
+ @gc_trigger_count =
194
+ count_of_stocked_objects + @gc_trigger_increment
195
+ end
196
+ end
197
+
198
+ def pre_gc_hook
199
+ end
200
+
201
+ def post_gc_hook
202
+ end
203
+
204
+ def garbage_collect
205
+ pre_gc_hook
206
+ stock_ids = @oid_to_obj_hash.keys
207
+ stock_ids.sort!
208
+ @instance.el4r_debug { "(GC) 1" }
209
+ alive_ids = @instance.el4r_rubyobj_get_alive_ids.to_a # funcall
210
+ @instance.el4r_debug { "(GC) 2" }
211
+ alive_ids.collect! { |id| id.to_i; }
212
+ alive_ids.sort!
213
+
214
+ @instance.el4r_debug { "(GC) Stocked IDs: #{stock_ids.inspect}"; }
215
+ @instance.el4r_debug { "(GC) Alive IDs: #{alive_ids.inspect}"; }
216
+
217
+ freed_ids = []
218
+ while aid = alive_ids.pop
219
+ while true
220
+ sid = stock_ids.pop or raise(El4rError, "Can't happen!")
221
+ break if sid == aid
222
+ freed_ids << sid
223
+ end
224
+ end
225
+ freed_ids.concat(stock_ids)
226
+
227
+ @instance.el4r_debug { "(GC) IDs to free: #{freed_ids.inspect}"; }
228
+ freed_ids.each { |id|
229
+ @oid_to_obj_hash.delete(id)
230
+ }
231
+
232
+ @instance.el4r_debug { "(GC) Count of stocked object is reduced to #{count_of_stocked_objects}"; }
233
+ post_gc_hook
234
+ end
235
+
236
+ def obj2lisp(obj)
237
+ # NOTE: Ruby's object ID exceeds elisp's 28-bit integer limitation.
238
+ "(el4r-rubyobj-create \"#{obj2id(obj)}\")"
239
+ end
240
+
241
+ def obj2id(obj)
242
+ garbage_collect_if_required
243
+ oid = obj.__id__
244
+ @oid_to_obj_hash[oid] ||= obj
245
+ oid
246
+ end
247
+
248
+ def id2obj(oid)
249
+ @oid_to_obj_hash[oid] or
250
+ raise(El4rError, "No such object for ID: #{oid}")
251
+ end
252
+
253
+ def count_of_stocked_objects
254
+ @oid_to_obj_hash.size
255
+ end
256
+ end #/ELRubyObjectStock
257
+
258
+ # A Struct like object to handle EmacsLisp variables.
259
+ class ELVariables < Struct.new(:instance)
260
+ def [](name)
261
+ instance.getq(name)
262
+ end
263
+
264
+ def []=(name, value)
265
+ instance.setq(name, value)
266
+ end
267
+
268
+ def method_missing(name, value = nil)
269
+ name = name.to_s
270
+ if name[-1] == ?=
271
+ instance.setq(name[0..-2], value)
272
+ else
273
+ instance.getq(name)
274
+ end
275
+ end
276
+ end #/ELVariables
277
+
278
+ # EmacsLisp wrapper methods
279
+ module ELMethodsMixin
280
+ # Call an EmacsLisp function
281
+ def funcall(name_or_lambda, *args, &block)
282
+ func = case name_or_lambda
283
+ when Symbol, String
284
+ El4r.name_rb2el(name_or_lambda.to_s)
285
+ when ELObject, ELExpression
286
+ "funcall #{el4r_ruby2lisp(name_or_lambda)}"
287
+ else
288
+ raise(TypeError,
289
+ "Invalid 1st argument for funcall: #{name_or_lambda.inspect}")
290
+ end
291
+ funcall_internal(func, *args, &block)
292
+ end
293
+ alias method_missing funcall
294
+
295
+ def funcall_internal(funcexpr, *args, &block)
296
+ el4r_lisp_eval("(#{funcexpr} #{el4r_args_to_lispseq(*args, &block)})")
297
+ end
298
+
299
+ # Call (func FORMS...) type function
300
+ def with(name, *args, &block)
301
+ args << el("(funcall #{el4r_rubyproc_to_lambda(&block)})")
302
+ funcall(name, *args)
303
+ end
304
+
305
+ # EmacsLisp's defun.
306
+ #
307
+ # +attrs+ is a Hash.
308
+ # attrs[:interactive]:: If the function is interactive, set +true+ or String.
309
+ # attrs[:docstring]:: The docstring.
310
+ #
311
+ # The function arguments are block arguments.
312
+ def defun(name, attrs = nil, &block)
313
+ String === name and name = el("'#{name}")
314
+ funcall_internal("el4r-define-function", name, el_lambda(attrs, &block))
315
+ end
316
+
317
+ def defvar(name, value=nil, docstring="")
318
+ funcall_internal :defvar, el(name), value, docstring
319
+ end
320
+
321
+ # EmacsLisp's define-key.
322
+ #
323
+ # +map+ is a +Symbol+ or +ELObject+ refering to a keymap object.
324
+ # This method can be called with block.
325
+ def define_key(map, key, command = nil, &block)
326
+ map = el(map) unless map.kind_of?(ELObject)
327
+ key = el(%Q'"#{key}"') if key.kind_of?(String)
328
+ command = el_lambda(:interactive => true, &block) if block_given?
329
+ funcall_internal("define-key", map, key, command)
330
+ end
331
+
332
+ def symbol_value(name)
333
+ el4r_lisp_eval(El4r.name_rb2el(name.to_s))
334
+ end
335
+ alias getq symbol_value
336
+
337
+ def setq(name, value)
338
+ el4r_lisp_eval("(setq #{El4r.name_rb2el(name.to_s)} #{el4r_ruby2lisp(value)})")
339
+ end
340
+ alias set setq
341
+
342
+ def _init_eval_after_load
343
+ @eval_after_load_func = "el4r-eval-after-load-function-1"
344
+ end
345
+
346
+ # EmacsLisp's eval-after-load
347
+ def eval_after_load(lib, &block)
348
+ raise ArgumentError, "must have block" unless block
349
+ # el4r_lisp_eval "(eval-after-load #{el4r_ruby2lisp(lib)} '(funcall #{el4r_rubyproc_to_lambda(&block)}))" # '
350
+ defun(@eval_after_load_func, &block)
351
+ el4r_lisp_eval "(eval-after-load #{el4r_ruby2lisp(lib)} '(#{@eval_after_load_func}))" # '
352
+ @eval_after_load_func.succ!
353
+ nil
354
+ end
355
+
356
+ # EmacsLisp's let.
357
+ # +name_and_value_list+ is [variable_name, value, variable_name, value...].
358
+ # +name_and_value_list.length+ must be even.
359
+ # +variable_name+ is a Symbol.
360
+ def let(*name_and_value_list, &block)
361
+ (name_and_value_list.size % 2) == 0 or
362
+ raise(ArgumentError, "Invalid count of arguments.")
363
+
364
+ letexpr = "(let ("
365
+ until name_and_value_list.empty?
366
+ name = El4r.name_rb2el(name_and_value_list.shift.to_s)
367
+ value = el4r_ruby2lisp(name_and_value_list.shift)
368
+ letexpr << "(#{name} #{value}) "
369
+ end
370
+ letexpr << ") (funcall #{el4r_rubyproc_to_lambda(&block)}))"
371
+ el4r_lisp_eval(letexpr)
372
+ end
373
+
374
+ # Create a new buffer with some initialization.
375
+ # With block, newbuf execute it by the context of the generated buffer.
376
+ #
377
+ # A parameter is a Hash.
378
+ # :name :: buffer-name
379
+ # :file :: find-file-noselect / insert-file-contents [with :name]
380
+ # :contents :: buffer-string
381
+ # :line :: goto-line
382
+ # :point :: goto-char [default is (point-max)]
383
+ # :display :: :pop / :only / true
384
+ # :current :: set-buffer
385
+ # :read_only :: buffer-read-only
386
+ # :bury :: bury-buffer
387
+ def newbuf(x)
388
+ Hash === x or raise ArgumentError, "argument must be a hash!"
389
+ x[:name] || x[:file] or raise ArgumentError, "`:name' or `:file' key is mandatory!"
390
+ x[:name] and b = get_buffer_create(x[:name])
391
+ x[:file] && !x[:name] and b = find_file_noselect(x[:file])
392
+
393
+ check = lambda{|key, type| x[key] && (type===x[key] or raise ArgumentError) }
394
+ with(:with_current_buffer, b) {
395
+ elvar.buffer_read_only = nil
396
+ # TODO: coding-system
397
+ x[:name] and erase_buffer
398
+ x[:name] && x[:file] and insert_file_contents(x[:file])
399
+ x[:contents] and insert x[:contents].to_s
400
+ check[:line,Integer] and goto_line x[:line]
401
+ check[:point,Integer] and goto_char x[:point]
402
+ block_given? and yield
403
+ x[:read_only] and elvar.buffer_read_only = true
404
+ }
405
+
406
+ case x[:display]
407
+ when :pop; pop_to_buffer b
408
+ when :only; delete_other_windows; switch_to_buffer b
409
+ when true; display_buffer b
410
+ else
411
+ end
412
+
413
+ x[:bury] and bury_buffer b
414
+ x[:current] and set_buffer b
415
+
416
+ b
417
+ end
418
+
419
+ # Extended buffer-string.
420
+ # +buf+ is a buffer object.
421
+ def bufstr(buf=current_buffer)
422
+ with(:with_current_buffer, buf) { buffer_string }
423
+ end
424
+
425
+ def ad_do_it
426
+ el4r_lisp_eval("(funcall --defadvice-ad-do-it--)")
427
+ end
428
+
429
+ # EmacsLisp's defadvice.
430
+ # +func+ is Symbol or String refering to the function.
431
+ # +args+ is parameters to defadvice such as :before, :after, :around, :activate.
432
+ # In the block, you can call +ad_do_it+. [around advice]
433
+
434
+ def defadvice(func, *args, &block)
435
+ Hash === args[-1] and attrs = args.pop
436
+
437
+ param = args.map{|a| El4r.name_rb2el(a.to_s)}.join(' ')
438
+ forms = "#{El4r.name_rb2el(func.to_s)} (#{param})\n"
439
+
440
+ if attrs
441
+ _handle_attrs attrs, forms, false
442
+ end
443
+
444
+ forms << "(setq --defadvice-ad-do-it-- (lambda () ad-do-it))\n"
445
+ with(:defadvice, el(forms), &block)
446
+ end
447
+
448
+ def _handle_attrs(attrs, forms, quote)
449
+ docstring = attrs[:docstring]
450
+ forms << el4r_ruby2lisp(docstring) << "\n" if docstring
451
+ interactive = attrs[:interactive]
452
+ if interactive
453
+ forms << "'" if quote
454
+ case interactive
455
+ when Proc;
456
+ lmd = el4r_ruby2lisp(interactive)
457
+ el4r_lisp_eval %Q((el4r-register-lambda #{lmd}))
458
+ forms << "(interactive (eval (list #{lmd})))"
459
+ when true; forms << "(interactive)\n"
460
+ else; forms << "(interactive #{el4r_ruby2lisp(interactive)})\n"
461
+ end
462
+ end
463
+ end
464
+
465
+ # Call defun-type macro. `mode' is an EmacsLisp function to define.
466
+ # Most case the first argument is the function name.
467
+ #
468
+ # `define_derived_mode' and `define_minor_mode' are examples of this method's usage.
469
+ def with_preserved_block(funcexpr, mode, *args, &block)
470
+ mode = el(mode)
471
+ subfuncexpr = "#{mode.expression}--el4r-function"
472
+ block ||= lambda{}
473
+ defun(subfuncexpr, &block)
474
+ args << el("(#{subfuncexpr})")
475
+
476
+ funcall_internal(funcexpr, mode, *args)
477
+ end
478
+
479
+ # EmacsLisp's define-derived-mode.
480
+ def define_derived_mode(child, parent, name, docstring=nil, &block)
481
+ with_preserved_block "define-derived-mode", child, el(parent), name, docstring, &block
482
+ end
483
+
484
+ # EmacsLisp's define-minor-mode
485
+ def define_minor_mode(mode, doc, init_value=nil, lighter=nil, keymap=nil, &block)
486
+ with_preserved_block "define-minor-mode", mode, doc, init_value, lighter, keymap, &block
487
+ end
488
+
489
+ # Ruby's require.
490
+ def require(*args)
491
+ Kernel.require(*args)
492
+ end
493
+
494
+ # EmacsLisp's require.
495
+ def el_require(*args)
496
+ funcall_internal("require", *args)
497
+ end
498
+
499
+ # EmacsLisp's load.
500
+ def el_load(*args)
501
+ funcall_internal("load", *args)
502
+ end
503
+
504
+ # EmacsLisp's lambda.
505
+ def el_lambda(attr = nil, &block)
506
+ el(el4r_rubyproc_to_lambda(attr, &block))
507
+ end
508
+
509
+ # Bare EmacsLisp expression.
510
+ def el(expression)
511
+ case expression
512
+ when Symbol; ELExpression.new(El4r.name_rb2el(expression.to_s))
513
+ when String; ELExpression.new(expression)
514
+ when ELExpression; expression
515
+ else
516
+ raise(TypeError,
517
+ "Cannot treat as lisp expression: <#{expression.inspect}>")
518
+ end
519
+ end
520
+ end #/ELMethodsMixin
521
+
522
+ # Pseudo $stdout object for el4r.
523
+ # This object appends to *el4r output* buffer
524
+ class El4rOutput
525
+ def initialize(instance)
526
+ @instance = instance
527
+ end
528
+
529
+ def write(s)
530
+ @instance.instance_eval do
531
+ princ(s.to_s, get_buffer_create(conf.output_buffer))
532
+ end
533
+ nil
534
+ end
535
+
536
+ def flush
537
+ self
538
+ end
539
+ end
540
+
541
+ class ELInstance
542
+ include ELMethodsMixin
543
+ extend Forwardable
544
+
545
+ attr_accessor :outer # maybe thread-unsafe(no problem)
546
+ attr_reader :el4r_rubyobj_stock
547
+
548
+ # An Struct like object to handle EmacsLisp's variable.
549
+ attr_reader :elvar
550
+
551
+ # If +true+, verbose log output.
552
+ attr_accessor :el4r_is_debug
553
+
554
+ # el4r_load evals an EmacsRuby script from this directory.
555
+ attr_accessor :el4r_homedir
556
+
557
+ # settings by ~/.el4rrc.rb
558
+ attr_reader :conf
559
+
560
+ def_delegators :@conf, :el4r_load_path, :root_dir, :site_dir
561
+ def initialize(conf)
562
+ @conf = conf
563
+ @emacs_in = STDIN
564
+ @emacs_out = STDOUT
565
+ @call_level = 0
566
+ @last_error = nil
567
+ @el4r_is_debug = ENV["EL4R_DEBUG"]
568
+ @el4r_homedir = conf.home_dir
569
+ @elvar = ELVariables.new(self)
570
+ @el4r_rubyobj_stock = ELRubyObjectStock.new(self)
571
+ @el4r_garbage_elobj_ids = []
572
+
573
+ @el4r_output = El4rOutput.new self
574
+
575
+ log = ENV["EL4R_LOG"]
576
+ @log = case log
577
+ when "stderr"; STDERR
578
+ when /^\|/; File.popen($~.post_match, "w")
579
+ else; File.open(log || "/tmp/el4r-#{`whoami`.chomp}.#{Process.pid}.log", "w")
580
+ end
581
+
582
+ @el_backtrace_reset_threshold = 1 # very nasty hack!
583
+ @el_backtrace = []
584
+
585
+ _init_eval_after_load
586
+
587
+ $: << el4r_homedir
588
+ end
589
+
590
+ # --------------------------------
591
+ # Methods for user
592
+
593
+ # Load an EmacsRuby script.
594
+ #
595
+ # If +path_to_rb+'s dirname is omitted, searches a script from el4r_load_path.
596
+ # If +is_noerror+ is true and +path_to_rb+ is not found, returns false instead of raise LoadError.
597
+ # If success, returns true.
598
+ def el4r_load(path_to_rb, is_noerror = nil)
599
+ el4r_load_path.each do |dir|
600
+ full_path_to_rb = File.expand_path(path_to_rb, dir)
601
+ if File.exist?(full_path_to_rb)
602
+ source = el4r_readfile(full_path_to_rb)
603
+ instance_eval(source, full_path_to_rb)
604
+ return true
605
+ end
606
+ end
607
+
608
+ if is_noerror
609
+ false
610
+ else
611
+ raise LoadError, "el4r_load: cannot load #{path_to_rb}"
612
+ end
613
+ end
614
+
615
+ # Eval an EmacsLisp expression.
616
+ def el4r_lisp_eval(lispexpr)
617
+ el4r_interrupt if el4r_callback?
618
+ el4r_with_call {
619
+ el4r_send(lispexpr)
620
+ el4r_get
621
+ }
622
+ end
623
+
624
+ # Convert a Ruby Regexp into EmacsLisp.
625
+ def el4r_conv_regexp(re)
626
+ s = re.source.dup
627
+ s.gsub!(/[\|\(\)]/){'\\'+$&}
628
+ s.sub!(/\\A/){'\`'}
629
+ s.sub!(/\\Z/){'\\\''}
630
+ s.sub!(/\\w/, '[0-9A-Za-z_]')
631
+ s.sub!(/\\W/, '[^0-9A-Za-z_]')
632
+
633
+ s
634
+ end
635
+
636
+ # Convert a Ruby object into EmacsLisp.
637
+ def el4r_ruby2lisp(obj)
638
+ case obj
639
+ when nil, false; "nil"
640
+ when true; "t"
641
+ when String; El4r.lisp_dump_string(obj)
642
+ when Regexp; El4r.lisp_dump_string(el4r_conv_regexp(obj))
643
+ when Symbol; "'#{El4r.name_rb2el(obj.to_s)}"
644
+ when Proc; el4r_rubyproc_to_lambda(&obj)
645
+ when Integer
646
+ (ELISP_INTEGER_RANGE === obj) or
647
+ raise(RangeError,
648
+ "Integer #{obj} exceed elisp limitation (#{ELISP_INTEGER_RANGE})")
649
+ obj.to_s
650
+ when Numeric; obj.to_s
651
+ when Array; "(list #{el4r_args_to_lispseq(*obj)})"
652
+ when ELObject; obj.to_lisp
653
+ when ELExpression; obj.expression
654
+ else; el4r_rubyobj_stock.obj2lisp(obj)
655
+ end
656
+ end
657
+
658
+ # Convert a Ruby Proc into EmacsLisp
659
+ # +attrs+ is the same as that of +defun+.
660
+ def el4r_rubyproc_to_lambda(attrs = nil, &block)
661
+ forms =
662
+ ["el4r-lambda-for-rubyproc \"#{el4r_rubyobj_stock.obj2id(block)}\""]
663
+ if attrs
664
+ _handle_attrs attrs, forms, true
665
+ end
666
+ "(#{forms.join(' ')})"
667
+ end
668
+
669
+ def el4r_args_to_lispseq(*args, &block)
670
+ elargs = args
671
+ elargs << block if block_given?
672
+ elargs.collect! { |form|
673
+ el4r_ruby2lisp(form)
674
+ }
675
+ elargs.join(' ')
676
+ end
677
+
678
+ # Write a log message.
679
+ def el4r_log(msg)
680
+ @log.print(Time.now, ":")
681
+ @log.puts(msg); @log.flush
682
+ end
683
+
684
+ # String representation. obj.inspect and (prin1-to-string obj).
685
+ def el4r_prin1_to_string(obj)
686
+ "[ruby] #{obj.inspect} / [lisp] #{prin1_to_string(obj)}"
687
+ end
688
+
689
+ # Write string representation(both in Ruby and in EmacsLisp) of all the argument to the log.
690
+ def el4r_prin1(*objs)
691
+ objs.each { |obj|
692
+ el4r_log("el4r_prin1: #{el4r_prin1_to_string(obj)}")
693
+ }
694
+ end
695
+
696
+ # Write string representation(only in Ruby) of all the argument to the log.
697
+ def el4r_p(*objs)
698
+ el4r_log("el4r_p: #{objs.inspect}")
699
+ end
700
+
701
+ # Write a backtrace message to the log.
702
+ def el4r_backtrace(msg = nil)
703
+ msg ||= "*backtrace*"
704
+ el4r_log "#{msg}\n#{ErrorUtils.backtrace_message(caller(2))}"
705
+ end
706
+
707
+ # --------------------------------
708
+ # Methods for internal use
709
+
710
+ # Startup el4r without loading init.rb.
711
+ def el4r_boot__noinit
712
+ logbuf = get_buffer_create conf.log_buffer
713
+ elvar.el4r_log_path = el4r_log_io.path
714
+
715
+ el4r_lisp_eval('(defun el4r-show-log () (interactive)
716
+ (with-current-buffer (get-buffer-create el4r-log-buffer)
717
+ (setq buffer-read-only nil)
718
+ (erase-buffer)
719
+ (insert-file-contents el4r-log-path)
720
+ (setq buffer-read-only t)
721
+ (goto-char (point-max))
722
+ (pop-to-buffer (current-buffer))))')
723
+ el4r_install_builtin_functions
724
+ $> = @el4r_output
725
+ end
726
+
727
+ def el4r_process_autoloads(dir=conf.autoload_dir)
728
+ Dir["#{dir}/[0-9][0-9]*.rb"].sort.each do |rb|
729
+ el4r_load rb
730
+ end
731
+ end
732
+
733
+ # Startup el4r.
734
+ def el4r_boot
735
+ el4r_boot__noinit
736
+ el4r_process_autoloads
737
+ el4r_load(conf.init_script, true)
738
+ end
739
+
740
+ # Obsolete.
741
+ def el4r_shutdown
742
+ end
743
+
744
+ def el4r_add_garbage_lispobj(id)
745
+ @el4r_garbage_elobj_ids << id
746
+ end
747
+
748
+ def el4r_get_garbage_lispobj_ids
749
+ GC.start
750
+ ids = @el4r_garbage_elobj_ids
751
+ @el4r_garbage_elobj_ids = []
752
+ ids
753
+ end
754
+
755
+ def el4r_readfile(file)
756
+ File.open(file) { |io| io.read || ""; }
757
+ end
758
+
759
+ def el4r_wait_expr_loop
760
+ el4r_wait_expr until @emacs_in.eof?
761
+ end
762
+
763
+ def el4r_wait_expr
764
+ @last_error = nil
765
+ el4r_with_call {
766
+ lispexpr = nil
767
+ begin
768
+ result = el4r_get
769
+ el4r_debug { "Result: <#{result.inspect}>"; }
770
+ lispexpr = el4r_ruby2lisp(result)
771
+ rescue ELError
772
+ el4r_debug { "Passing lisp error: #{ErrorUtils.stacktrace_message($!)}"; }
773
+ lispexpr = "(el4r-signal-last-error)"
774
+ rescue StandardError, ScriptError
775
+ @last_error or
776
+ el4r_log("Error: #{ErrorUtils.stacktrace_message($!)}")
777
+ @last_error = $!
778
+ lispexpr = "(signal 'el4r-ruby-error nil)"
779
+ end
780
+ el4r_send(lispexpr)
781
+ }
782
+ end
783
+
784
+ def el4r_get
785
+ expr = el4r_recv
786
+ while expr.empty?
787
+ el4r_debug { "Received callback interrupt."; }
788
+ el4r_wait_expr
789
+ expr = el4r_recv
790
+ end
791
+ el4r_ruby_eval(expr)
792
+ end
793
+
794
+ def el4r_recv
795
+ el4r_debug { "Waiting for Ruby expression"; }
796
+ expr = @emacs_in.readline("\0\n")
797
+ expr.slice!(-2, 2)
798
+ el4r_debug { "Received Ruby expression: #{expr}"; }
799
+ expr
800
+ end
801
+
802
+ def el4r_send(lispexpr)
803
+ el4r_debug { "Sending Lisp expression: #{lispexpr}"; }
804
+ @emacs_out.print(lispexpr)
805
+ @emacs_out.print("\0")
806
+ @emacs_out.flush
807
+ end
808
+
809
+ def el4r_interrupt
810
+ el4r_debug { "Sending callback interrupt."; }
811
+ @emacs_out.print("\0")
812
+ end
813
+
814
+ # Create an ELObject.
815
+ def el4r_elobject_new(id, klass = nil)
816
+ (klass || ELObject).new(self, id)
817
+ end
818
+
819
+ # Write a log message if el4r is debug.
820
+ def el4r_debug(msg = nil, &block)
821
+ if @el4r_is_debug
822
+ msg ||= yield
823
+ el4r_log("[DEBUG] (#{@call_level}) #{msg}")
824
+ end
825
+ end
826
+
827
+ # Log IO object.
828
+ def el4r_log_io
829
+ @log
830
+ end
831
+
832
+ def el4r_with_call(&block)
833
+ @call_level += 1
834
+ begin
835
+ yield
836
+ ensure
837
+ @call_level -= 1
838
+ @call_level <= @el_backtrace_reset_threshold and @el_backtrace = []
839
+ end
840
+ end
841
+
842
+ # Eval +source.
843
+ # When an Exception is raised, write a stacktrace message to the log.
844
+ def el4r_ruby_eval(source)
845
+ begin
846
+ instance_eval(source)
847
+ rescue Exception
848
+ el4r_debug { "Error in evaluating '#{source}': #{ErrorUtils.stacktrace_message($!)}"; }
849
+ raise
850
+ end
851
+ end
852
+
853
+ def el4r_reraise_last_error
854
+ raise @last_error
855
+ end
856
+
857
+ def el4r_raise_lisp_error
858
+ msg = el4r_lisp_eval("(prin1-to-string el4r-last-error-desc)")
859
+ @el_backtrace << el4r_lisp_eval("(prin1-to-string el4r-error-lisp-expression)")
860
+ raise(ELError, "Error in lisp code.:#{msg}\n#{@el_backtrace.join("\n")}")
861
+ end
862
+
863
+ def el4r_callback?
864
+ @call_level != 0
865
+ end
866
+
867
+ # Treat EmacsLisp strings containing C-c, C-d, C-q, C-s, C-v, C-w, C-z
868
+ def el4r_treat_ctrl_codes(&block)
869
+ #File.unlink conf.temp_file if File.exist? conf.temp_file
870
+ let(:el4r_treat_ctrl_codes, true, &block)
871
+ end
872
+
873
+ private
874
+ # Install the built in functions.
875
+ def el4r_install_builtin_functions
876
+ el4r_load "stdlib.rb"
877
+ el4r_install_unittest_stuff
878
+ el4r_install_xemacs_workaround
879
+ end
880
+
881
+ def el4r_install_unittest_stuff
882
+ el4r_install_test_unit_testrunner
883
+ el4r_install_run_unittest
884
+ end
885
+
886
+ # Install el4r version of Test::Unit.
887
+ def el4r_install_test_unit_testrunner
888
+ require 'test/unit'
889
+ require 'test/unit/ui/console/testrunner'
890
+ require 'stringio'
891
+
892
+ eval <<-EOS
893
+ module ::Test
894
+ module Unit
895
+ module UI
896
+ module Console
897
+ class El4rTestRunner < TestRunner
898
+ OUTPUT = StringIO.new
899
+
900
+ def initialize(*args)
901
+ super
902
+ @io = OUTPUT
903
+ end
904
+ end
905
+ end
906
+ end
907
+
908
+ class TestCase
909
+ include ElMixin
910
+ extend ElMixin
911
+ end
912
+ end
913
+ end
914
+ EOS
915
+ end
916
+
917
+
918
+ # Install el4r-run-unittest.
919
+ def el4r_install_run_unittest
920
+ elvar.el4r_unittest_strip_instance_error = true
921
+ defun(:el4r_run_unittest, :interactive=>true) do
922
+ el4r_unittest_tweak_gc
923
+ save_some_buffers
924
+ load(elvar.el4r_unittest_file_name)
925
+ begin
926
+ runner_class = ::Test::Unit::UI::Console::El4rTestRunner
927
+ el4r_unittest_run_internal(runner_class)
928
+ ensure
929
+ out = runner_class::OUTPUT
930
+ display = el4r_make_unittest_output(out)
931
+ el4r_unittest_display_result(display)
932
+ @el_backtrace_reset_threshold = 2
933
+ out.string = ""
934
+ end
935
+ end #/defun
936
+ end
937
+
938
+ def el4r_unittest_tweak_gc
939
+ el4r_rubyobj_stock.gc_trigger_count = conf.unittest_ruby_gc_trigger_count
940
+ el4r_rubyobj_stock.gc_trigger_increment = conf.unittest_ruby_gc_trigger_increment
941
+ elvar.el4r_lisp_object_gc_trigger_count = conf.unittest_lisp_object_gc_trigger_count
942
+ elvar.el4r_lisp_object_gc_trigger_increment = conf.unittest_lisp_object_gc_trigger_increment
943
+ end
944
+
945
+ def el4r_unittest_run_internal(runner_class)
946
+ r = ::Test::Unit::AutoRunner.new(nil)
947
+ r.process_args(elvar.el4r_unittest_args.to_a)
948
+ r.runner = proc{|r| runner_class}
949
+ r.run
950
+ end
951
+
952
+ def el4r_make_unittest_output(out)
953
+ display = format("ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM)
954
+ display << "#{emacs_version}\n\n"
955
+ display << out.string
956
+ display.gsub!(/^ +.+el4r-instance:\d+.*\n/,'') if elvar.el4r_unittest_strip_instance_error
957
+ display
958
+ end
959
+
960
+ def el4r_unittest_display_result(display)
961
+ let(:ee_buffer_name, "*el4r:unittest*"){
962
+ if elvar.noninteractive
963
+ princ(display)
964
+ else
965
+ switch_to_buffer "*Result*"
966
+ unittest_mode
967
+ elvar.buffer_read_only = nil
968
+ erase_buffer
969
+ insert display
970
+ elvar.buffer_read_only = true
971
+ goto_char 1
972
+ fundamental_mode
973
+ delete_other_windows
974
+ end
975
+ }
976
+ end
977
+
978
+ # Install an xemacs workaround.
979
+ def el4r_install_xemacs_workaround
980
+ # delete-other-windows at xemacs workaround! very nasty hack!
981
+ if elvar.noninteractive and featurep(:xemacs)
982
+ defun(:delete_other_windows) do
983
+ windows = []
984
+ walk_windows{|w| windows << w}
985
+
986
+ curwin = selected_window
987
+ windows.each do |w|
988
+ delete_window w unless eq(w,curwin)
989
+ end
990
+ select_window curwin
991
+ nil
992
+ end #/defun
993
+ end #/if
994
+
995
+ end #/def
996
+
997
+ end #/ELInstance
998
+ end #/El4r
999
+
1000
+ module El4rAccessor
1001
+ # The el4r object.
1002
+ def el4r
1003
+ $el
1004
+ end
1005
+
1006
+ end
1007
+
1008
+ # A mix-in to add EmacsRuby features.
1009
+ module ElMixin
1010
+ include El4rAccessor
1011
+ # Eval the block in the el4r context.
1012
+ # +outer+ is the caller of this method.
1013
+ def elisp(&block)
1014
+ el4r.outer = self
1015
+ el4r.instance_eval(&block)
1016
+ end
1017
+
1018
+ def method_missing(func, *args, &block)
1019
+ el4r.__send__(func, *args, &block)
1020
+ end
1021
+
1022
+ end
1023
+
1024
+ # A class with EmacsRuby features.
1025
+ class ElApp
1026
+ include ElMixin
1027
+ extend El4rAccessor
1028
+ @@instances = {}
1029
+
1030
+ # Run the application.
1031
+ def self.run(params={})
1032
+ obj = new(params)
1033
+ (@@instances[self] ||= []) << obj # preserve from GC
1034
+ process_defun(obj)
1035
+ obj
1036
+ end
1037
+
1038
+ def self._change_receiver_of(orgblock, obj, name)
1039
+ ## HACK Yuck!
1040
+ defunmeth = "#{name}__defun__"
1041
+ define_method(defunmeth, orgblock)
1042
+ private defunmeth
1043
+
1044
+ obj.instance_eval{ lambda{|*args| __send__(defunmeth, *args)}}
1045
+ end
1046
+ private_class_method :_change_receiver_of
1047
+
1048
+ def self.process_defun(obj)
1049
+ (@defuns || []).each do |name, attrs, block|
1050
+ block = _change_receiver_of(block, obj, name)
1051
+ obj.defun(name, attrs, &block)
1052
+ end
1053
+ end
1054
+ private_class_method :process_defun
1055
+
1056
+ def initialize(params)
1057
+ end
1058
+
1059
+ # EmacsLisp's defun. See El4r::ELMethodsMixin#defun.
1060
+ #
1061
+ # It is a convenient defun. Note that +block+ is evaluated within a
1062
+ # context of INSTANCE.
1063
+ def self.defun(name, attrs=nil, &block)
1064
+ (@defuns ||= []) << [name, attrs, block]
1065
+ end
1066
+
1067
+ extend SingleForwardable
1068
+
1069
+ # Import EmacsLisp (and El4r::ELMethodsMixin) functions within class definition.
1070
+
1071
+ def self.import_function(*funcs)
1072
+ def_delegators :el4r, *funcs
1073
+ end
1074
+ import_function :defvar, :el4r_lisp_eval
1075
+
1076
+ end
1077
+
1078
+ if __FILE__ == $0
1079
+ el4r = El4r::ELInstance.new __conf__
1080
+ $el = el4r # backward compatibility
1081
+ STDERR.reopen(el4r.el4r_log_io)
1082
+
1083
+ finalizer = lambda {
1084
+ el4r.el4r_log "Caught SIGTERM, exiting."
1085
+ logfile = el4r.el4r_log_io.path
1086
+ File.unlink logfile if !ENV["EL4R_PRESERVE_LOG"] and logfile and File.exist? logfile
1087
+ exit 0
1088
+ }
1089
+ trap(:TERM, &finalizer)
1090
+ trap(:HUP, &finalizer) rescue nil # for windows
1091
+
1092
+ el4r.el4r_log "Starting, waiting for expression."
1093
+ begin
1094
+ el4r.el4r_wait_expr_loop
1095
+ rescue Exception
1096
+ el4r.el4r_log El4r::ErrorUtils.stacktrace_message($!)
1097
+ ensure
1098
+ el4r.el4r_log "Exiting."
1099
+ end
1100
+ end
1101
+
1102
+ # Local Variables:
1103
+ # mode: ruby
1104
+ # test-script: "../testing/test-el4r.rb"
1105
+ # End: