opal-irb 0.7.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/.gitignore +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +113 -0
- data/Guardfile +5 -0
- data/LICENSE +21 -0
- data/README.md +175 -0
- data/Rakefile +65 -0
- data/Roadmap.org +17 -0
- data/app/assets/stylesheets/opal-irb/jqconsole.css +263 -0
- data/compiled/app-embeddable.js +39765 -0
- data/compiled/app-jqconsole.js +39767 -0
- data/compiled/application.js +27399 -0
- data/css/ansi.css +172 -0
- data/css/opal_irb_jqconsole.css +79 -0
- data/css/show-hint.css +38 -0
- data/doc/presentations/opal_irb_overview.html +678 -0
- data/doc/presentations/opal_irb_overview.org +448 -0
- data/examples/app-embeddable.rb +8 -0
- data/examples/app-jqconsole.rb +10 -0
- data/examples/application.rb +8 -0
- data/index-embeddable.html +29 -0
- data/index-homebrew.html +115 -0
- data/index-jq.html +80 -0
- data/js/anyword-hint.js +44 -0
- data/js/jqconsole.js +1583 -0
- data/js/nodeutil.js +546 -0
- data/js/ruby.js +285 -0
- data/js/show-hint.js +383 -0
- data/lib/opal-irb/rails_engine.rb +3 -0
- data/lib/opal-irb/version.rb +3 -0
- data/lib/opal-irb-rails.rb +2 -0
- data/lib/opal-irb.rb +44 -0
- data/opal/object_extensions.rb +20 -0
- data/opal/opal_irb/completion_engine.rb +202 -0
- data/opal/opal_irb/completion_formatter.rb +49 -0
- data/opal/opal_irb/completion_results.rb +88 -0
- data/opal/opal_irb.rb +88 -0
- data/opal/opal_irb_homebrew_console.rb +398 -0
- data/opal/opal_irb_jqconsole.rb +517 -0
- data/opal/opal_irb_jqconsole_css.rb +259 -0
- data/opal/opal_irb_log_redirector.rb +32 -0
- data/opal/opal_phantomjs.rb +49 -0
- data/opal-irb.gemspec +20 -0
- data/spec/code_link_handler_spec.rb +30 -0
- data/spec/jquery.js +5 -0
- data/spec/object_extensions_spec.rb +32 -0
- data/spec/opal_irb/completion_engine_spec.rb +204 -0
- data/spec/opal_irb/completion_results_spec.rb +32 -0
- data/spec/opal_irb_log_director_spec.rb +19 -0
- data/spec/opal_irb_spec.rb +19 -0
- data/spec/spec_helper.rb +1 -0
- metadata +151 -0
@@ -0,0 +1,398 @@
|
|
1
|
+
require 'opal'
|
2
|
+
require "opal-jquery"
|
3
|
+
require "opal_irb"
|
4
|
+
|
5
|
+
class OpalIRBHomebrewConsole
|
6
|
+
|
7
|
+
def reset_settings
|
8
|
+
`localStorage.clear()`
|
9
|
+
end
|
10
|
+
|
11
|
+
def save_settings
|
12
|
+
`localStorage.settings = JSON.stringify( #{@settings.map})`
|
13
|
+
end
|
14
|
+
|
15
|
+
def resize_input(e)
|
16
|
+
width = @inputdiv.width() - @inputl.width()
|
17
|
+
content = @input.value()
|
18
|
+
# content.gsub /\n/, '<br/>'
|
19
|
+
@inputcopy.html content
|
20
|
+
|
21
|
+
@inputcopy.width width
|
22
|
+
@input.width width
|
23
|
+
@input.height @inputcopy.height() + 2
|
24
|
+
end
|
25
|
+
|
26
|
+
def scroll_to_bottom
|
27
|
+
`window.scrollTo( 0, #@prompt[0].offsetTop)`
|
28
|
+
end
|
29
|
+
|
30
|
+
DEFAULT_SETTINGS = {
|
31
|
+
# last_variable: '$_',
|
32
|
+
max_lines: 500,
|
33
|
+
max_depth: 2,
|
34
|
+
show_hidden: false,
|
35
|
+
colorize: true,
|
36
|
+
}
|
37
|
+
|
38
|
+
def escape_html(s)
|
39
|
+
s.gsub(/&/,'&').gsub(/</,'<').gsub(/>/,'>');
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :settings
|
43
|
+
|
44
|
+
def initialize (output, input, prompt, inputdiv, inputl, inputr, inputcopy, settings={})
|
45
|
+
@output, @input, @prompt, @inputdiv, @inputl, @inputr, @inputcopy =
|
46
|
+
output, input, prompt, inputdiv, inputl, inputr, inputcopy
|
47
|
+
@history = []
|
48
|
+
@historyi = -1
|
49
|
+
@saved = ''
|
50
|
+
@multiline = false
|
51
|
+
@settings = DEFAULT_SETTINGS.clone
|
52
|
+
|
53
|
+
@irb = OpalIrb.new
|
54
|
+
|
55
|
+
# if localStorage and localStorage.settings
|
56
|
+
# for k, v of JSON.parse(localStorage.settings)
|
57
|
+
# @settings[k] = v
|
58
|
+
# end
|
59
|
+
# for k, v of settings
|
60
|
+
# @settings[k] = v
|
61
|
+
# end
|
62
|
+
myself = self
|
63
|
+
@input.on :keydown do |evt|
|
64
|
+
myself.handle_keypress(evt)
|
65
|
+
end
|
66
|
+
|
67
|
+
initialize_window
|
68
|
+
print_header
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def print(args)
|
74
|
+
s = args
|
75
|
+
o = @output.html + s + "\n"
|
76
|
+
# @output[0].innerHTML = o.split("\n")[-@settings.max_lines...].join("\n")
|
77
|
+
# @output.html = o.split("\n")[-@settings[:max_lines]].join("\n")
|
78
|
+
@output.html = o
|
79
|
+
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s
|
84
|
+
{
|
85
|
+
history: @history,
|
86
|
+
multiline: @multiline,
|
87
|
+
settings: @settings
|
88
|
+
}.inspect
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def add_to_history(s)
|
93
|
+
@history.unshift s
|
94
|
+
@historyi = -1
|
95
|
+
end
|
96
|
+
|
97
|
+
def add_to_saved(s)
|
98
|
+
@saved += s[0...-1] == '\\' ? s[0...-1] : s
|
99
|
+
@saved += "\n"
|
100
|
+
add_to_history s
|
101
|
+
end
|
102
|
+
|
103
|
+
def clear
|
104
|
+
@output.html = ""
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def process_saved
|
109
|
+
begin
|
110
|
+
compiled = @irb.parse @saved
|
111
|
+
# doesn't work w/th opal 0.3.27 compiled = compiled[14..-7] # strip off anonymous function so variables will persist
|
112
|
+
# compiled = compiled.split("\n")[2..-2].join("\n")
|
113
|
+
# compiled = compiled.gsub("return", "")
|
114
|
+
# value = eval.call window, compiled
|
115
|
+
log compiled
|
116
|
+
value = `eval(compiled)`
|
117
|
+
# window[@settings.last_variable] = value
|
118
|
+
$_ = value
|
119
|
+
output = `nodeutil.inspect( value, #{@settings[:show_hidden]}, #{@settings[:max_depth]}, #{@settings[:colorize]})`
|
120
|
+
# output = value
|
121
|
+
rescue Exception => e
|
122
|
+
if e.backtrace
|
123
|
+
output = "FOR:\n#{compiled}\n============\n" + e.backtrace.join("\n")
|
124
|
+
|
125
|
+
# FF doesn't have Error.toString() as the first line of Error.stack
|
126
|
+
# while Chrome does.
|
127
|
+
# if output.split("\n")[0] != `e.toString()`
|
128
|
+
# output = "#{`e.toString()`}\n#{`e.stack`}"
|
129
|
+
# end
|
130
|
+
else
|
131
|
+
output = `e.toString()`
|
132
|
+
end
|
133
|
+
end
|
134
|
+
@saved = ''
|
135
|
+
print output
|
136
|
+
end
|
137
|
+
|
138
|
+
# help
|
139
|
+
def help
|
140
|
+
text = [
|
141
|
+
" ",
|
142
|
+
"<strong>Features</strong>",
|
143
|
+
"<strong>========</strong>",
|
144
|
+
"+ <strong>Esc</strong> enters multiline mode.",
|
145
|
+
"+ <strong>Up/Down arrow and ctrl-p/ctrl-n</strong> flips through line history.",
|
146
|
+
# "+ <strong>#{@settings[:last_variable]}</strong> stores the last returned value.",
|
147
|
+
"+ Access the internals of this console through <strong>$irb</strong>.",
|
148
|
+
"+ <strong>clear</strong> clears this console.",
|
149
|
+
"+ <strong>history</strong> shows line history.",
|
150
|
+
" ",
|
151
|
+
"<strong>@Settings</strong>",
|
152
|
+
"<strong>========</strong>",
|
153
|
+
"You can modify the behavior of this IRB by altering <strong>$irb.@settings</strong>:",
|
154
|
+
" ",
|
155
|
+
# "+ <strong>last_variable</strong> (#{@settings[:last_variable]}): variable name in which last returned value is stored",
|
156
|
+
"+ <strong>max_lines</strong> (#{@settings[:max_lines]}): max line count of this console",
|
157
|
+
"+ <strong>max_depth</strong> (#{@settings[:max_depth]}): max_depth in which to inspect outputted object",
|
158
|
+
"+ <strong>show_hidden</strong> (#{@settings[:show_hidden]}): flag to output hidden (not enumerable) properties of objects",
|
159
|
+
"+ <strong>colorize</strong> (#{@settings[:colorize]}): flag to colorize output (set to false if IRB is slow)",
|
160
|
+
" ",
|
161
|
+
# "<strong>$irb.save_settings()</strong> will save settings to localStorage.",
|
162
|
+
# "<strong>$irb.reset_settings()</strong> will reset settings to default.",
|
163
|
+
" "
|
164
|
+
].join("\n")
|
165
|
+
print text
|
166
|
+
end
|
167
|
+
|
168
|
+
# only outputs to console log, use for debugging
|
169
|
+
def log thing
|
170
|
+
`console.orig_log(#{thing})`
|
171
|
+
end
|
172
|
+
|
173
|
+
def history
|
174
|
+
@history.reverse.each_with_index {|line, i|
|
175
|
+
print "#{i}: #{line}"
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
def handle_keypress(e)
|
180
|
+
# log e.which
|
181
|
+
|
182
|
+
case e.which
|
183
|
+
when 13 # return
|
184
|
+
e.prevent_default()
|
185
|
+
input = @input.value()
|
186
|
+
@input.value = ''
|
187
|
+
|
188
|
+
print @prompt.html + escape_html(input)
|
189
|
+
|
190
|
+
if input
|
191
|
+
add_to_saved input
|
192
|
+
if input[0...-1] != '\\' and not @multiline
|
193
|
+
process_saved()
|
194
|
+
end
|
195
|
+
end
|
196
|
+
when 27 # escape
|
197
|
+
e.prevent_default
|
198
|
+
open_multiline_dialog
|
199
|
+
when 38 # up arrow
|
200
|
+
e.prevent_default
|
201
|
+
show_previous_history
|
202
|
+
when 40 # down arrow
|
203
|
+
e.prevent_default
|
204
|
+
show_next_history
|
205
|
+
when 80 # p
|
206
|
+
if e.ctrl_key
|
207
|
+
e.prevent_default
|
208
|
+
show_previous_history
|
209
|
+
end
|
210
|
+
when 78 # n
|
211
|
+
if e.ctrl_key
|
212
|
+
e.prevent_default
|
213
|
+
show_next_history
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
def show_previous_history
|
221
|
+
if @historyi < @history.length-1
|
222
|
+
@historyi += 1
|
223
|
+
@input.value = @history[@historyi]
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
def show_next_history
|
229
|
+
if @historyi > 0
|
230
|
+
@historyi += -1
|
231
|
+
@input.value = @history[@historyi]
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def initialize_window
|
236
|
+
resize_input()
|
237
|
+
@input.focus()
|
238
|
+
end
|
239
|
+
|
240
|
+
CMD_LINE_METHOD_DEFINITIONS = [
|
241
|
+
'def help
|
242
|
+
$irb.help
|
243
|
+
nil
|
244
|
+
end',
|
245
|
+
|
246
|
+
'def clear
|
247
|
+
$irb.clear
|
248
|
+
nil
|
249
|
+
end',
|
250
|
+
|
251
|
+
'def history
|
252
|
+
$irb.history
|
253
|
+
nil
|
254
|
+
end'
|
255
|
+
]
|
256
|
+
def setup_cmd_line_methods
|
257
|
+
CMD_LINE_METHOD_DEFINITIONS.each {|method_defn|
|
258
|
+
compiled = @irb.parse method_defn
|
259
|
+
`eval(compiled)`
|
260
|
+
}
|
261
|
+
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
def print_header
|
266
|
+
print [
|
267
|
+
"# Opal v#{Opal::VERSION} IRB", #"# Opal v#{OPAL_VERSION} IRB",
|
268
|
+
"# <a href=\"https://github.com/fkchang/opal-irb\" target=\"_blank\">https://github.com/fkchang/opal-irb</a>",
|
269
|
+
"# inspired by <a href=\"https://github.com/larryng/coffeescript-repl\" target=\"_blank\">https://github.com/larryng/coffeescript-repl</a>",
|
270
|
+
"#",
|
271
|
+
"# <strong>help</strong> for features and tips.",
|
272
|
+
" "
|
273
|
+
].join("\n")
|
274
|
+
end
|
275
|
+
|
276
|
+
def self.create_html(parent_container_id)
|
277
|
+
parent = Element.find(parent_container_id)
|
278
|
+
parent.html = ' <div id="outputdiv">
|
279
|
+
<pre id="output"></pre>
|
280
|
+
</div>
|
281
|
+
<div id="inputdiv">
|
282
|
+
<div id="inputl">
|
283
|
+
<pre id="prompt">opal> </pre>
|
284
|
+
</div>
|
285
|
+
<div id="inputr">
|
286
|
+
<textarea id="input" spellcheck="false"></textarea>
|
287
|
+
<div id="inputcopy"></div>
|
288
|
+
</div>
|
289
|
+
'
|
290
|
+
# puts parent.html
|
291
|
+
|
292
|
+
end
|
293
|
+
|
294
|
+
def self.create(container_id)
|
295
|
+
create_html(container_id)
|
296
|
+
output = Element.find('#output')
|
297
|
+
input = Element.find('#input')
|
298
|
+
prompt = Element.find('#prompt')
|
299
|
+
inputdiv = Element.find('#inputdiv')
|
300
|
+
inputl = Element.find('#inputl')
|
301
|
+
inputr = Element.find('#inputr')
|
302
|
+
inputcopy = Element.find('#inputcopy')
|
303
|
+
|
304
|
+
# instantiate our IRB and expose irb as $irb
|
305
|
+
irb = OpalIRBHomebrewConsole.new( output, input, prompt, inputdiv, inputl, inputr,
|
306
|
+
inputcopy)
|
307
|
+
irb.setup_cmd_line_methods
|
308
|
+
# bind other handlers
|
309
|
+
input.on :keydown do
|
310
|
+
irb.scroll_to_bottom
|
311
|
+
end
|
312
|
+
Element.find(`window`).on :resize do |e|
|
313
|
+
irb.resize_input e
|
314
|
+
end
|
315
|
+
|
316
|
+
input.on :keyup do |e|
|
317
|
+
irb.resize_input e
|
318
|
+
end
|
319
|
+
input.on :change do |e|
|
320
|
+
irb.resize_input e
|
321
|
+
end
|
322
|
+
|
323
|
+
Element.find('html').on :click do |e|
|
324
|
+
# if e.clientY > input[0].offsetTop
|
325
|
+
input.focus()
|
326
|
+
# end
|
327
|
+
end
|
328
|
+
|
329
|
+
%x|
|
330
|
+
console.orig_log = console.log
|
331
|
+
console.log = function() {
|
332
|
+
var args;
|
333
|
+
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
334
|
+
console.orig_log(args);
|
335
|
+
Opal.gvars["irb"].$print(args);
|
336
|
+
};
|
337
|
+
|
|
338
|
+
$irb = irb
|
339
|
+
|
340
|
+
irb.setup_multi_line
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
def setup_multi_line
|
345
|
+
myself = self # hate that I have to do this, didn't have to do it before
|
346
|
+
%x|
|
347
|
+
$( ".dialog" ).dialog({
|
348
|
+
autoOpen: false,
|
349
|
+
show: "blind",
|
350
|
+
hide: "explode",
|
351
|
+
modal: true,
|
352
|
+
width: "500px",
|
353
|
+
title: "Multi Line Edit",
|
354
|
+
buttons: {
|
355
|
+
"Run it": function() {
|
356
|
+
$( this ).dialog( "close" );
|
357
|
+
#{myself}.$process_multiline();
|
358
|
+
},
|
359
|
+
"Cancel": function() {
|
360
|
+
$( this ).dialog( "close" );
|
361
|
+
},
|
362
|
+
}
|
363
|
+
});
|
364
|
+
|
|
365
|
+
|
366
|
+
@open_editor_dialog_function = %x|function() {
|
367
|
+
$( ".dialog" ).dialog( "open" );
|
368
|
+
setTimeout(function(){editor.refresh();}, 20);
|
369
|
+
}
|
370
|
+
|
|
371
|
+
@editor = %x|
|
372
|
+
editor = CodeMirror.fromTextArea(document.getElementById("multi_line_input"),
|
373
|
+
{mode: "ruby",
|
374
|
+
lineNumbers: true,
|
375
|
+
matchBrackets: true,
|
376
|
+
keyMap: "emacs",
|
377
|
+
theme: "default"
|
378
|
+
});
|
379
|
+
|
380
|
+
|
|
381
|
+
|
382
|
+
end
|
383
|
+
|
384
|
+
def open_multiline_dialog
|
385
|
+
@editor.setValue(@input.value)
|
386
|
+
@open_editor_dialog_function.call
|
387
|
+
end
|
388
|
+
|
389
|
+
|
390
|
+
def process_multiline
|
391
|
+
multi_line_value = @editor.getValue.sub(/(\n)+$/, "")
|
392
|
+
add_to_saved multi_line_value
|
393
|
+
print multi_line_value
|
394
|
+
process_saved
|
395
|
+
@input.value = ""
|
396
|
+
end
|
397
|
+
|
398
|
+
end
|