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,517 @@
|
|
1
|
+
require 'opal'
|
2
|
+
require 'opal-jquery'
|
3
|
+
require 'opal_irb_log_redirector'
|
4
|
+
require 'opal_irb'
|
5
|
+
require 'opal_irb/completion_engine'
|
6
|
+
require 'opal_irb/completion_formatter'
|
7
|
+
require 'jqconsole'
|
8
|
+
|
9
|
+
# top level methods for irb cmd line
|
10
|
+
def irb_link_for history_num=nil
|
11
|
+
OpalIrbJqconsole.console.irb_link_for history_num
|
12
|
+
end
|
13
|
+
|
14
|
+
class Timeout
|
15
|
+
def initialize(time=0, &block)
|
16
|
+
@timeout = `setTimeout(#{block}, time)`
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear
|
20
|
+
`clearTimeout(#{@timeout})`
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# module Kernel
|
25
|
+
# # just like osx's say command, only tested on desktop safari and chrome on osx
|
26
|
+
# def say msg
|
27
|
+
# %x|
|
28
|
+
# var msg = new SpeechSynthesisUtterance(#{msg});
|
29
|
+
# window.speechSynthesis.speak(msg);
|
30
|
+
# |
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
|
34
|
+
class OpalIrbJqconsole
|
35
|
+
def self.console
|
36
|
+
@console
|
37
|
+
end
|
38
|
+
|
39
|
+
# create on a pre existing div
|
40
|
+
def self.create(parent_element_id)
|
41
|
+
@console = OpalIrbJqconsole.new(parent_element_id)
|
42
|
+
end
|
43
|
+
|
44
|
+
BOTTOM_PANEL_ID = "opal-irb-console-bottom-panel"
|
45
|
+
# create a bottom panel
|
46
|
+
def self.create_bottom_panel(hidden = false)
|
47
|
+
parent_element_id="opal-irb-console"
|
48
|
+
style = hidden ? "style=\"display:none\"" : ""
|
49
|
+
# <a href="#" id="collapse-opal-irb-console" class=\"boxclose\"></a>
|
50
|
+
|
51
|
+
html = <<HTML
|
52
|
+
<div id="#{BOTTOM_PANEL_ID}" #{style}>
|
53
|
+
<div id="opal-irb-console-topbar">
|
54
|
+
<span id="collapse-opal-irb-console" class=\"boxclose\"></span>
|
55
|
+
</div>
|
56
|
+
<div id='#{parent_element_id}'>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
HTML
|
60
|
+
Element.find("body").append(html)
|
61
|
+
Element.id("collapse-opal-irb-console").on(:click) {
|
62
|
+
Element.id("#{BOTTOM_PANEL_ID}").hide;
|
63
|
+
}
|
64
|
+
create("##{parent_element_id}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.add_hot_key_panel_behavior(keys_hash)
|
68
|
+
Element.find("body").on(:keydown) { |evt|
|
69
|
+
if create_key_filter(keys_hash, evt)
|
70
|
+
if panel.visible?
|
71
|
+
hide_panel
|
72
|
+
else
|
73
|
+
show_panel
|
74
|
+
end
|
75
|
+
end
|
76
|
+
}
|
77
|
+
end
|
78
|
+
# set $DEBUG_KEY_FILTER = true somewhere in your app to see the keys for debugging
|
79
|
+
def self.create_key_filter(keys_hash, evt)
|
80
|
+
puts "evt.ctrl_key #{evt.ctrl_key} evt.meta_key #{evt.meta_key} evt.shift_key #{evt.shift_key} evt.key_code #{evt.key_code}_" if $DEBUG_KEY_FILTER
|
81
|
+
keys_hash[:modifiers].all? { |modifier| evt.send("#{modifier}_key") } && evt.key_code == keys_hash[:key].upcase.ord
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.add_open_panel_behavior(link_id)
|
85
|
+
Element.id(link_id).on(:click) {
|
86
|
+
if panel.visible?
|
87
|
+
alert "OpalIRB is already showing"
|
88
|
+
else
|
89
|
+
show_panel
|
90
|
+
end
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.panel
|
95
|
+
Element.id("#{BOTTOM_PANEL_ID}")
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.show_panel
|
99
|
+
panel.show
|
100
|
+
Timeout.new { console.focus}
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.hide_panel
|
104
|
+
panel.hide
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def focus
|
109
|
+
@jqconsole.Focus
|
110
|
+
end
|
111
|
+
|
112
|
+
attr_reader :irb
|
113
|
+
def initialize(parent_element_id)
|
114
|
+
@irb = OpalIrb.new
|
115
|
+
setup_cmd_line_methods
|
116
|
+
setup_jqconsole(parent_element_id)
|
117
|
+
create_multiline_editor
|
118
|
+
redirect_console_dot_log
|
119
|
+
handler()
|
120
|
+
setup_code_link_handling
|
121
|
+
end
|
122
|
+
|
123
|
+
# logs only to js console, not to irb, for things you want only for
|
124
|
+
# debug and not public viewing
|
125
|
+
def log thing
|
126
|
+
`console.orig_log(#{thing})`
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def setup_code_link_handling
|
131
|
+
@code_link_handler = CodeLinkHandler.new
|
132
|
+
link_code = @code_link_handler.grab_link_code
|
133
|
+
if link_code
|
134
|
+
# do this after everything initializes
|
135
|
+
Timeout.new {
|
136
|
+
print_and_process_code link_code
|
137
|
+
self.class.show_panel
|
138
|
+
}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def create_and_display_code_link code
|
143
|
+
code_link = @code_link_handler.create_link_for_code code
|
144
|
+
unescaped_write "<a href=#{code_link}>#{code_link}</a>\n" if code_link
|
145
|
+
end
|
146
|
+
|
147
|
+
class CodeLinkHandler
|
148
|
+
|
149
|
+
def initialize(location=`window.location`)
|
150
|
+
@location = Native(location) # inject this so we can test
|
151
|
+
end
|
152
|
+
|
153
|
+
def create_link_for_code code
|
154
|
+
if code
|
155
|
+
@location.origin + @location.pathname + "#code:" + `encodeURIComponent(#{code})`
|
156
|
+
else
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
end
|
160
|
+
# initialize irb w/link passed in code ala try opal
|
161
|
+
def grab_link_code
|
162
|
+
link_code = `decodeURIComponent(#{@location.hash})`
|
163
|
+
if link_code != ''
|
164
|
+
link_code[6..-1]
|
165
|
+
else
|
166
|
+
nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
def irb_link_for history_num
|
173
|
+
history_num = -1 unless history_num # pick last command before irb_link_for if nil
|
174
|
+
history_num -= 1 # offset off by 1
|
175
|
+
code = jqconsole.GetHistory[history_num] #
|
176
|
+
create_and_display_code_link code
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
def irb_link_for_current_line
|
181
|
+
current_code = jqconsole.GetPromptText
|
182
|
+
create_and_display_code_link current_code
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
def redirect_console_dot_log
|
187
|
+
OpalIrbLogRedirector.add_to_redirect(lambda {|args| OpalIrbJqconsole.write(args)})
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
def create_multiline_editor
|
192
|
+
editor = <<EDITOR
|
193
|
+
<div id="multiline-editor-dialog" class="dialog" style="display:none" >
|
194
|
+
<textarea name="multi_line_input" id="multi_line_input"></textarea>
|
195
|
+
</div>
|
196
|
+
EDITOR
|
197
|
+
myself = self # self is now the div and not self anymore
|
198
|
+
Element.find("body") << editor
|
199
|
+
%x|
|
200
|
+
$( ".dialog" ).dialog({
|
201
|
+
autoOpen: false,
|
202
|
+
show: "blind",
|
203
|
+
hide: "explode",
|
204
|
+
modal: true,
|
205
|
+
width: "500px",
|
206
|
+
title: "Multi Line Edit",
|
207
|
+
buttons: {
|
208
|
+
"Run it": function() {
|
209
|
+
$( this ).dialog( "close" );
|
210
|
+
#{myself}.$process_multiline();
|
211
|
+
},
|
212
|
+
"Cancel": function() {
|
213
|
+
$( this ).dialog( "close" );
|
214
|
+
},
|
215
|
+
}
|
216
|
+
});
|
217
|
+
|
|
218
|
+
|
219
|
+
@open_editor_dialog_function = %x|function() {
|
220
|
+
$( ".dialog" ).dialog( "open" );
|
221
|
+
setTimeout(function(){editor.refresh();}, 20);
|
222
|
+
}
|
223
|
+
|
|
224
|
+
# setup opal auto complete
|
225
|
+
OpalIrb::CompletionEngine.set_irb @irb
|
226
|
+
%x*
|
227
|
+
var WORD = /[\w$]+/, RANGE = 500;
|
228
|
+
CodeMirror.commands.autocomplete = function(cm) {
|
229
|
+
CodeMirror.showHint(cm, function(editor, options) {
|
230
|
+
var word = options && options.word || WORD;
|
231
|
+
var range = options && options.range || RANGE;
|
232
|
+
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
|
233
|
+
var end = cur.ch, start = end;
|
234
|
+
// debugger
|
235
|
+
while (start && word.test(curLine.charAt(start - 1))) --start;
|
236
|
+
var curWord = start != end && curLine.slice(start, end);
|
237
|
+
var token = editor.getTokenAt(editor.getCursor()).string;
|
238
|
+
console.orig_log('The receiver is');
|
239
|
+
|
240
|
+
if( token.string === '.') {
|
241
|
+
var receiver = editor.getTokenAt(CodeMirror.Pos(cur.line, start-1)).string;
|
242
|
+
console.orig_log(receiver);
|
243
|
+
// token = receiver + ".";
|
244
|
+
}
|
245
|
+
var anyList = CodeMirror.hint.anyword(editor, options);
|
246
|
+
var list = Opal.OpalIrb.CompletionEngine.$editor_complete(token);
|
247
|
+
list = list.concat(anyList.list);
|
248
|
+
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
|
249
|
+
}
|
250
|
+
);
|
251
|
+
};
|
252
|
+
*
|
253
|
+
@editor = %x|
|
254
|
+
editor = CodeMirror.fromTextArea(document.getElementById("multi_line_input"),
|
255
|
+
{ mode: "ruby",
|
256
|
+
lineNumbers: true,
|
257
|
+
matchBrackets: true,
|
258
|
+
extraKeys: {
|
259
|
+
"Ctrl-Space": "autocomplete",
|
260
|
+
"Ctrl-Enter": function(cm) { $(".ui-dialog-buttonset").find("button:eq(0)").trigger("click"); } // submit on ctrl-enter
|
261
|
+
},
|
262
|
+
keyMap: "emacs",
|
263
|
+
/* foldGutter: {
|
264
|
+
rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.brace, CodeMirror.fold.comment)
|
265
|
+
},
|
266
|
+
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], */
|
267
|
+
theme: "default"
|
268
|
+
});
|
269
|
+
|
270
|
+
|
|
271
|
+
@editor = Native(@editor) # seamless bridging removed
|
272
|
+
|
273
|
+
end
|
274
|
+
def open_multiline_dialog
|
275
|
+
@editor.setValue(@jqconsole.GetPromptText)
|
276
|
+
@open_editor_dialog_function.call
|
277
|
+
end
|
278
|
+
|
279
|
+
def print_and_process_code code
|
280
|
+
@jqconsole.SetPromptText code
|
281
|
+
@jqconsole._HandleEnter
|
282
|
+
end
|
283
|
+
|
284
|
+
def process_multiline
|
285
|
+
multi_line_value = @editor.getValue.sub(/(\n)+$/, "")
|
286
|
+
print_and_process_code multi_line_value
|
287
|
+
end
|
288
|
+
|
289
|
+
# show completions on hitting tab. This modeled after irb.
|
290
|
+
# * If there are completions it will print the prompt, show the
|
291
|
+
# completions and reprint the prompt line. Same as irb behavior,
|
292
|
+
# but these are the steps you need to take w/jq-console
|
293
|
+
# * If no completions it acts as jq-console tab
|
294
|
+
# @param text [String] text on the opal-irb command line
|
295
|
+
# @returns [Boolean] returns true if opal-irb is to actually tab - i.e. no completion found
|
296
|
+
# results.prompt_change(@jqconsole, 'jqconsole-old-prompt')
|
297
|
+
# results.write_results(@jqconsole)
|
298
|
+
# results.change_prompt(@jqconsole)
|
299
|
+
def tab_complete(text)
|
300
|
+
results = OpalIrb::CompletionEngine.complete(text, @irb)
|
301
|
+
# if results
|
302
|
+
# if results.size > 1
|
303
|
+
# @jqconsole.Write("#{CONSOLE_PROMPT}#{text}\n", "jqconsole-old-prompt")
|
304
|
+
# @jqconsole.Write(OpalIrb::CompletionFormatter.format(results))
|
305
|
+
# append_common_prefix_if_exists(text, results)
|
306
|
+
# else
|
307
|
+
# @jqconsole.SetPromptText(results.first)
|
308
|
+
# end
|
309
|
+
# false
|
310
|
+
# else
|
311
|
+
# true
|
312
|
+
# end
|
313
|
+
results.set_old_prompt(@jqconsole, CONSOLE_PROMPT, 'jqconsole-old-prompt')
|
314
|
+
results.display_matches(@jqconsole)
|
315
|
+
results.update_prompt(@jqconsole)
|
316
|
+
results.insert_tab?
|
317
|
+
end
|
318
|
+
|
319
|
+
|
320
|
+
CONSOLE_PROMPT = 'opal> '
|
321
|
+
attr_reader :jqconsole
|
322
|
+
def setup_jqconsole(parent_element_id)
|
323
|
+
Element.expose(:jqconsole)
|
324
|
+
|
325
|
+
@jqconsole = Native(Element.find(parent_element_id).jqconsole("Welcome to Opal #{Opal::VERSION}\ntype help for assistance\n", CONSOLE_PROMPT)) # seamless jquery plugin removed
|
326
|
+
@jqconsole.RegisterTabHandler(lambda { |text| tab_complete(text)})
|
327
|
+
@jqconsole.RegisterShortcut('M', lambda { open_multiline_dialog; handler})
|
328
|
+
@jqconsole.RegisterShortcut('C', lambda { @jqconsole.AbortPrompt(); handler})
|
329
|
+
|
330
|
+
# These are the ubiquitous emacs commands that I have to implement now, my other
|
331
|
+
# solution I got them all for free in OSX
|
332
|
+
@jqconsole.RegisterShortcut('A', lambda{ @jqconsole.MoveToStart(); handler})
|
333
|
+
@jqconsole.RegisterShortcut('E', lambda{ @jqconsole.MoveToEnd(); handler})
|
334
|
+
@jqconsole.RegisterShortcut('B', lambda{ @jqconsole._MoveLeft(); handler})
|
335
|
+
@jqconsole.RegisterShortcut('F', lambda{ @jqconsole._MoveRight(); handler})
|
336
|
+
@jqconsole.RegisterShortcut('N', lambda{ @jqconsole._HistoryNext(); handler})
|
337
|
+
@jqconsole.RegisterShortcut('P', lambda{ @jqconsole._HistoryPrevious(); handler})
|
338
|
+
@jqconsole.RegisterShortcut('D', lambda{ @jqconsole._Delete(); handler})
|
339
|
+
@jqconsole.RegisterShortcut('K', lambda{ @jqconsole.Kill; handler})
|
340
|
+
@jqconsole.RegisterShortcut('L', lambda{ irb_link_for_current_line})
|
341
|
+
|
342
|
+
@jqconsole.RegisterAltShortcut('B', lambda{ @jqconsole._MoveLeft(true); handler})
|
343
|
+
@jqconsole.RegisterAltShortcut('F', lambda{ @jqconsole._MoveRight(true); handler})
|
344
|
+
@jqconsole.RegisterAltShortcut('D', lambda{ @jqconsole._Delete(true); handler})
|
345
|
+
|
346
|
+
# to implement in jq-console emacs key bindings you get for free normally
|
347
|
+
# in all Cocoa text widgets
|
348
|
+
# alt-u upcase
|
349
|
+
# alt-l lowercase
|
350
|
+
# alt-c capitalize
|
351
|
+
# ctrl-t toggle character
|
352
|
+
# ctrl-y yanking the kill buffer - can I override the system here?
|
353
|
+
|
354
|
+
end
|
355
|
+
|
356
|
+
CMD_LINE_METHOD_DEFINITIONS = [
|
357
|
+
'def help
|
358
|
+
OpalIrbJqconsole.help
|
359
|
+
nil
|
360
|
+
end',
|
361
|
+
'def history
|
362
|
+
OpalIrbJqconsole.history
|
363
|
+
nil
|
364
|
+
end',
|
365
|
+
'def js_require(js_file)
|
366
|
+
s = DOM do
|
367
|
+
script({ src: js_file})
|
368
|
+
end
|
369
|
+
$document.body << s
|
370
|
+
end', # js_require "http://www.goodboydigital.com/runpixierun/js/pixi.js"
|
371
|
+
'def say msg
|
372
|
+
%x|
|
373
|
+
var msg = new SpeechSynthesisUtterance(#{msg});
|
374
|
+
window.speechSynthesis.speak(msg);
|
375
|
+
|
|
376
|
+
end'
|
377
|
+
|
378
|
+
]
|
379
|
+
def setup_cmd_line_methods
|
380
|
+
CMD_LINE_METHOD_DEFINITIONS.each {|method_definition|
|
381
|
+
compiled = @irb.parse method_definition
|
382
|
+
`eval(compiled)`
|
383
|
+
}
|
384
|
+
end
|
385
|
+
|
386
|
+
def self.history
|
387
|
+
history = @console.jqconsole.GetHistory
|
388
|
+
lines = []
|
389
|
+
history.each_with_index {|history_line, i|
|
390
|
+
lines << "#{i+1}: #{history_line}"
|
391
|
+
}
|
392
|
+
@console.jqconsole.Write("#{lines.join("\n")}\n")
|
393
|
+
|
394
|
+
end
|
395
|
+
|
396
|
+
|
397
|
+
def handler(cmd)
|
398
|
+
if cmd && `#{cmd } != undefined`
|
399
|
+
begin
|
400
|
+
@jqconsole.Write( " => #{process(cmd)} \n")
|
401
|
+
rescue Exception => e
|
402
|
+
@jqconsole.Write('Error: ' + e.message + "\n")
|
403
|
+
end
|
404
|
+
end
|
405
|
+
@jqconsole.Prompt(true, lambda {|c| handler(c) }, lambda {|c| check_is_incomplete(c)})
|
406
|
+
|
407
|
+
end
|
408
|
+
|
409
|
+
def check_is_incomplete(cmd)
|
410
|
+
begin
|
411
|
+
@irb.parse cmd
|
412
|
+
false
|
413
|
+
rescue Exception => e
|
414
|
+
# make this a global so we can inspect this
|
415
|
+
$check_error = e
|
416
|
+
# 1st attempt to return on bad code vs incomplete code
|
417
|
+
if parse_error? $check_error
|
418
|
+
# TODO when rescue is fixed to return last evaluated value remove returns
|
419
|
+
return 0
|
420
|
+
else
|
421
|
+
# see above to-do
|
422
|
+
return false
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
def parse_error? check_error
|
428
|
+
# for Chrome errors
|
429
|
+
check_error.backtrace.first =~ /unexpected 'false/ || check_error.backtrace[2] =~ /unexpected 'false/ ||
|
430
|
+
# safari error
|
431
|
+
check_error.message =~/error occurred while compiling/
|
432
|
+
end
|
433
|
+
|
434
|
+
|
435
|
+
def write *stuff
|
436
|
+
@jqconsole.Write *stuff
|
437
|
+
end
|
438
|
+
|
439
|
+
def unescaped_write str
|
440
|
+
# `#{@jqconsole}.Write(str, "unescaped", false)`
|
441
|
+
@jqconsole.Write(str, "unescaped", false)
|
442
|
+
end
|
443
|
+
|
444
|
+
def self.write *stuff
|
445
|
+
@console.write *stuff
|
446
|
+
end
|
447
|
+
|
448
|
+
def self.puts *stuff
|
449
|
+
@console.write *stuff
|
450
|
+
@console.write "\n"
|
451
|
+
end
|
452
|
+
|
453
|
+
def self.unescaped_write *stuff
|
454
|
+
@console.unescaped_write *stuff
|
455
|
+
|
456
|
+
end
|
457
|
+
|
458
|
+
def self.help
|
459
|
+
help = <<HELP
|
460
|
+
<b>help</b>: This text
|
461
|
+
<b>$_</b> last value returned is stored in this global
|
462
|
+
<b>history</b>: Shows history
|
463
|
+
<b>irb_link_for history_num</b>: Create a link for the code in the history
|
464
|
+
<b>ctrl-c</b>: Abort prompt
|
465
|
+
<b>ctrl-m</b>: Pop up multi-line editor
|
466
|
+
<b>ctrl-Enter</b>: Submit code in multi-line editor
|
467
|
+
<b>ctrl-l</b>: Creates a link with the code you have on the current line/lines
|
468
|
+
<hr/>
|
469
|
+
<b>EDITOR FUNCTIONALITY</b>
|
470
|
+
<b>Up/Down Arrow and ctrl-p/ctrl-n</b>: Navigate through history
|
471
|
+
<b>ctrl-a</b>: Beginning of line
|
472
|
+
<b>ctrl-e</b>: End of line
|
473
|
+
<b>ctrl-b</b>: Back 1 character
|
474
|
+
<b>ctrl-f</b>: Forward 1 character
|
475
|
+
<b>ctrl-d</b>: Delete 1 character
|
476
|
+
<b>ctrl-k</b>: Kill to the end of the line
|
477
|
+
<b>alt-b</b>: Back 1 word
|
478
|
+
<b>alt-f</b>: Forward 1 word
|
479
|
+
<b>alt-d</b>: Delete 1 word
|
480
|
+
HELP
|
481
|
+
unescaped_write help
|
482
|
+
end
|
483
|
+
|
484
|
+
|
485
|
+
def process(cmd)
|
486
|
+
begin
|
487
|
+
log "\n\n|#{cmd}|"
|
488
|
+
if cmd
|
489
|
+
$last_cmd = cmd
|
490
|
+
$irb_last_compiled = @irb.parse cmd
|
491
|
+
log $irb_last_compiled
|
492
|
+
value = `eval(#{$irb_last_compiled})`
|
493
|
+
$_ = value
|
494
|
+
Native($_).inspect # coz native JS objects don't support inspect
|
495
|
+
end
|
496
|
+
rescue Exception => e
|
497
|
+
$last_exception = e
|
498
|
+
# alert e.backtrace.join("\n")
|
499
|
+
if e.backtrace
|
500
|
+
output = "FOR:\n#{$irb_last_compiled}\n============\n" + "#{e.message}\n" + e.backtrace.join("\n")
|
501
|
+
# TODO remove return when bug is fixed in rescue block
|
502
|
+
return output
|
503
|
+
# FF doesn't have Error.toString() as the first line of Error.stack
|
504
|
+
# while Chrome does.
|
505
|
+
# if output.split("\n")[0] != `e.toString()`
|
506
|
+
# output = "#{`e.toString()`}\n#{`e.stack`}"
|
507
|
+
# end
|
508
|
+
else
|
509
|
+
output = `e.toString()`
|
510
|
+
log "\nReturning NO have backtrace |#{output}|"
|
511
|
+
# TODO remove return when bug is fixed in rescue block
|
512
|
+
return output
|
513
|
+
end
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
end
|