maglev-webtools 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +25 -0
- data/README.rdoc +121 -0
- data/bin/webtools +15 -0
- data/lib/web_tools/#debugger.rb# +212 -0
- data/lib/web_tools/browser.rb +45 -0
- data/lib/web_tools/debugger.rb +219 -0
- data/lib/web_tools/info.rb +29 -0
- data/lib/web_tools/middleware/debugger.rb +118 -0
- data/lib/web_tools/support/app_model.rb +117 -0
- data/lib/web_tools/support/code_browser.rb +109 -0
- data/lib/web_tools/support/ruby.rb +132 -0
- data/lib/web_tools/support/service_helper.rb +22 -0
- data/lib/web_tools/support/smalltalk_extensions.rb +65 -0
- data/lib/web_tools/support/smalltalk_tools.rb +16 -0
- data/lib/web_tools/ui.rb +67 -0
- data/lib/web_tools.rb +10 -0
- data/public/images/favicon.ico +0 -0
- data/public/javascript/CodeMirror/LICENSE +23 -0
- data/public/javascript/CodeMirror/css/Smalltalk.css +34 -0
- data/public/javascript/CodeMirror/js/codemirror.js +582 -0
- data/public/javascript/CodeMirror/js/editor.js +1671 -0
- data/public/javascript/CodeMirror/js/highlight.js +68 -0
- data/public/javascript/CodeMirror/js/parseSmalltalk.js +126 -0
- data/public/javascript/CodeMirror/js/parsedummy.js +32 -0
- data/public/javascript/CodeMirror/js/select.js +699 -0
- data/public/javascript/CodeMirror/js/stringstream.js +159 -0
- data/public/javascript/CodeMirror/js/tokenize.js +57 -0
- data/public/javascript/CodeMirror/js/undo.js +413 -0
- data/public/javascript/CodeMirror/js/util.js +133 -0
- data/public/javascript/CodeMirror/testSmalltalkParser.html +116 -0
- data/public/javascript/ace/ace-uncompressed.js +17299 -0
- data/public/javascript/ace/ace.js +1 -0
- data/public/javascript/ace/keybinding-emacs.js +1 -0
- data/public/javascript/ace/keybinding-vim.js +1 -0
- data/public/javascript/ace/mode-c_cpp.js +1 -0
- data/public/javascript/ace/mode-clojure.js +1 -0
- data/public/javascript/ace/mode-coffee.js +1 -0
- data/public/javascript/ace/mode-csharp.js +1 -0
- data/public/javascript/ace/mode-css.js +1 -0
- data/public/javascript/ace/mode-groovy.js +1 -0
- data/public/javascript/ace/mode-html.js +1 -0
- data/public/javascript/ace/mode-java.js +1 -0
- data/public/javascript/ace/mode-javascript.js +1 -0
- data/public/javascript/ace/mode-json.js +1 -0
- data/public/javascript/ace/mode-lua.js +1 -0
- data/public/javascript/ace/mode-markdown.js +1 -0
- data/public/javascript/ace/mode-ocaml.js +1 -0
- data/public/javascript/ace/mode-perl.js +1 -0
- data/public/javascript/ace/mode-php.js +1 -0
- data/public/javascript/ace/mode-python.js +1 -0
- data/public/javascript/ace/mode-ruby.js +1 -0
- data/public/javascript/ace/mode-scad.js +1 -0
- data/public/javascript/ace/mode-scala.js +1 -0
- data/public/javascript/ace/mode-scss.js +1 -0
- data/public/javascript/ace/mode-svg.js +1 -0
- data/public/javascript/ace/mode-textile.js +1 -0
- data/public/javascript/ace/mode-xml.js +1 -0
- data/public/javascript/ace/theme-clouds.js +1 -0
- data/public/javascript/ace/theme-clouds_midnight.js +1 -0
- data/public/javascript/ace/theme-cobalt.js +1 -0
- data/public/javascript/ace/theme-crimson_editor.js +1 -0
- data/public/javascript/ace/theme-dawn.js +1 -0
- data/public/javascript/ace/theme-eclipse.js +1 -0
- data/public/javascript/ace/theme-idle_fingers.js +1 -0
- data/public/javascript/ace/theme-kr_theme.js +1 -0
- data/public/javascript/ace/theme-merbivore.js +1 -0
- data/public/javascript/ace/theme-merbivore_soft.js +1 -0
- data/public/javascript/ace/theme-mono_industrial.js +1 -0
- data/public/javascript/ace/theme-monokai.js +1 -0
- data/public/javascript/ace/theme-pastel_on_dark.js +1 -0
- data/public/javascript/ace/theme-solarized_dark.js +1 -0
- data/public/javascript/ace/theme-solarized_light.js +1 -0
- data/public/javascript/ace/theme-textmate.js +1 -0
- data/public/javascript/ace/theme-twilight.js +1 -0
- data/public/javascript/ace/theme-vibrant_ink.js +1 -0
- data/public/javascript/ace/worker-coffee.js +1 -0
- data/public/javascript/ace/worker-css.js +1 -0
- data/public/javascript/ace/worker-javascript.js +1 -0
- data/public/javascript/webtools/#debugger.coffee# +253 -0
- data/public/javascript/webtools/browser.js +260 -0
- data/public/javascript/webtools/debugger.coffee +286 -0
- data/public/javascript/webtools/debugger.js +366 -0
- data/public/javascript/webtools/sessions.coffee +17 -0
- data/public/javascript/webtools/sessions.js +27 -0
- data/public/javascript/webtools/version.coffee +14 -0
- data/public/javascript/webtools/version.js +20 -0
- data/public/stylesheets/base/images/ui-anim_basic_16x16.gif +0 -0
- data/public/stylesheets/base/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/public/stylesheets/base/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/public/stylesheets/base/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/public/stylesheets/base/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/public/stylesheets/base/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/public/stylesheets/base/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/public/stylesheets/base/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/public/stylesheets/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/public/stylesheets/base/images/ui-icons_222222_256x240.png +0 -0
- data/public/stylesheets/base/images/ui-icons_2e83ff_256x240.png +0 -0
- data/public/stylesheets/base/images/ui-icons_454545_256x240.png +0 -0
- data/public/stylesheets/base/images/ui-icons_888888_256x240.png +0 -0
- data/public/stylesheets/base/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/public/stylesheets/base/jquery.ui.accordion.css +12 -0
- data/public/stylesheets/base/jquery.ui.all.css +2 -0
- data/public/stylesheets/base/jquery.ui.autocomplete.css +39 -0
- data/public/stylesheets/base/jquery.ui.base.css +11 -0
- data/public/stylesheets/base/jquery.ui.button.css +35 -0
- data/public/stylesheets/base/jquery.ui.core.css +37 -0
- data/public/stylesheets/base/jquery.ui.datepicker.css +61 -0
- data/public/stylesheets/base/jquery.ui.dialog.css +13 -0
- data/public/stylesheets/base/jquery.ui.progressbar.css +4 -0
- data/public/stylesheets/base/jquery.ui.resizable.css +13 -0
- data/public/stylesheets/base/jquery.ui.selectable.css +3 -0
- data/public/stylesheets/base/jquery.ui.slider.css +17 -0
- data/public/stylesheets/base/jquery.ui.tabs.css +11 -0
- data/public/stylesheets/base/jquery.ui.theme.css +247 -0
- data/public/stylesheets/jquery.contextMenu.css +62 -0
- data/public/stylesheets/reset.css +18 -0
- data/public/stylesheets/webtools.css +53 -0
- data/public/test.html +47 -0
- data/views/browser.rhtml +63 -0
- data/views/debugger.rhtml +59 -0
- data/views/index.rhtml +8 -0
- data/views/layout.rhtml +24 -0
- data/views/sessions.rhtml +12 -0
- data/views/version.rhtml +10 -0
- metadata +316 -0
@@ -0,0 +1,286 @@
|
|
1
|
+
window.escapeHTML = (str) ->
|
2
|
+
str = "" unless str?
|
3
|
+
str += str unless typeof str == "string"
|
4
|
+
$("<i></i>").text(str).html()
|
5
|
+
|
6
|
+
class Frame
|
7
|
+
constructor: (@server, @pid, @frame_idx, @container) ->
|
8
|
+
|
9
|
+
update_detail_view: (objectInfo) ->
|
10
|
+
@inspector.hide()
|
11
|
+
@inspector.find('.objInfoClass').text(objectInfo['class'])
|
12
|
+
@inspector.find('.objInfoValue').text(objectInfo['inspect'])
|
13
|
+
this.renderTableData @inspector.children('.objInstVars'),
|
14
|
+
objectInfo.instance_variables,
|
15
|
+
(idx, data) ->
|
16
|
+
$("<tr><td>#{idx}</td><td>#{data}</td></tr>")
|
17
|
+
@inspector.show()
|
18
|
+
|
19
|
+
renderTableData: (table, object, formatFn) ->
|
20
|
+
ui = table.children('tbody')
|
21
|
+
ui.empty()
|
22
|
+
$.each object, (key, value) ->
|
23
|
+
if key.indexOf("@") == 0
|
24
|
+
ui.append(formatFn(key, value))
|
25
|
+
|
26
|
+
create_detail_view: ->
|
27
|
+
@inspector = $('#objectInspector').clone()
|
28
|
+
@inspector.removeAttr('id')
|
29
|
+
@inspector.removeClass('hidden')
|
30
|
+
@container.append(@inspector)
|
31
|
+
|
32
|
+
create_source_code_holder: () ->
|
33
|
+
@container.prepend(window.editorDiv)
|
34
|
+
window.editor.save_url = "#{@server}/process/#{@pid}/frames/#{@frame_idx}"
|
35
|
+
window.editorDiv.show()
|
36
|
+
|
37
|
+
create_inspector: (object, index, path) ->
|
38
|
+
index = 0 unless index?
|
39
|
+
path = "#{@server}/process/#{@pid}/frames/#{@frame_idx}" unless path?
|
40
|
+
options = $([])
|
41
|
+
if object.instance_variables?
|
42
|
+
$.each object.instance_variables, (key, value) ->
|
43
|
+
options.push("#{key}")
|
44
|
+
else
|
45
|
+
$.each object, (key, value) ->
|
46
|
+
options.push("#{key}")
|
47
|
+
if not @inspector_div?
|
48
|
+
@inspector_div = $(document.createElement("div"))
|
49
|
+
@inspector_div.addClass("inspectors")
|
50
|
+
@container.prepend(@inspector_div)
|
51
|
+
if @inspectors[index]?
|
52
|
+
inspector = @inspectors[index]
|
53
|
+
else
|
54
|
+
@inspectors[index] = (inspector = $(document.createElement("select")))
|
55
|
+
@inspector_div.append(inspector)
|
56
|
+
inspector.attr
|
57
|
+
multiple: true
|
58
|
+
class: 'inspector'
|
59
|
+
inspector.html("")
|
60
|
+
$(options).each (idx, o) =>
|
61
|
+
inspector.append("<option value=#{idx}>#{escapeHTML(o)}</option>")
|
62
|
+
this.create_evaluator(path)
|
63
|
+
inspector.bind "change", =>
|
64
|
+
value = options[inspector.val()]
|
65
|
+
url = "#{path}/objects/#{value}"
|
66
|
+
for i in @inspectors.slice(index + 1)
|
67
|
+
i.html("")
|
68
|
+
$.get url, (object) =>
|
69
|
+
this.create_inspector(object.instance_variables, index + 1, url)
|
70
|
+
this.update_detail_view(object)
|
71
|
+
, 'json'
|
72
|
+
|
73
|
+
create_evaluator: (path) ->
|
74
|
+
unless @evaluator?
|
75
|
+
@evaluator = $(document.createElement("input"))
|
76
|
+
@evaluator.attr
|
77
|
+
type: "text"
|
78
|
+
name: "#{@frame_idx}_evaluator"
|
79
|
+
id: "#{@frame_idx}_evaluator"
|
80
|
+
class: "ui-widget-content ui-corner-all"
|
81
|
+
style: 'width: 100%;'
|
82
|
+
@container.prepend(@evaluator)
|
83
|
+
@evaluator.bind "focus", =>
|
84
|
+
|
85
|
+
@evaluator.unbind("keypress")
|
86
|
+
@evaluator.bind "keypress", (e) =>
|
87
|
+
code = e.keyCode if e.keyCode?
|
88
|
+
code = e.which unless code
|
89
|
+
if code == 13 # RETURN
|
90
|
+
$.ajax
|
91
|
+
url: path
|
92
|
+
data:
|
93
|
+
"do-it": @evaluator.val()
|
94
|
+
success: (data) =>
|
95
|
+
result = data["do-it-result"]
|
96
|
+
@evaluator.val("#{@evaluator.val()} => #{result['inspect']}")
|
97
|
+
this.update_detail_view(result)
|
98
|
+
@evaluator.select()
|
99
|
+
dataType: 'json'
|
100
|
+
type: 'PUT'
|
101
|
+
|
102
|
+
render: ->
|
103
|
+
@container.html("")
|
104
|
+
@inspectors = []
|
105
|
+
this.create_source_code_holder()
|
106
|
+
$.get "#{@server}/process/#{@pid}/frames/#{@frame_idx}", (frame) =>
|
107
|
+
editor.getSession().setValue(frame.debug_info.source)
|
108
|
+
this.create_inspector(frame.debug_info.context)
|
109
|
+
this.create_detail_view()
|
110
|
+
, 'json'
|
111
|
+
|
112
|
+
class Process
|
113
|
+
constructor: (@server, @pid, @tab) ->
|
114
|
+
@info_div = $("##{@tab} .info-bar")
|
115
|
+
@stack_div = $("##{@tab} .frame-list")
|
116
|
+
|
117
|
+
render: ->
|
118
|
+
this.render_info()
|
119
|
+
this.render_stack()
|
120
|
+
|
121
|
+
render_info: ->
|
122
|
+
request = $.get "#{@server}/process/#{@pid}", (data) =>
|
123
|
+
@info_div.text("#{data.label} (#{data.timestamp})")
|
124
|
+
, 'json'
|
125
|
+
|
126
|
+
render_stack: ->
|
127
|
+
@stack_div.html("")
|
128
|
+
request = $.get "#{@server}/process/#{@pid}/frames", (framelist) =>
|
129
|
+
$(framelist).each (idx, f) =>
|
130
|
+
header = $(document.createElement("h3"))
|
131
|
+
link = $(document.createElement("a"))
|
132
|
+
link.attr
|
133
|
+
href: '#'
|
134
|
+
data_idx: idx
|
135
|
+
link.text("#{f.class}##{f.method_name}")
|
136
|
+
link.append("<small>#{escapeHTML(f.source_location)}</small>")
|
137
|
+
header.append(link)
|
138
|
+
restartLink = $('<a href="#">Restart frame</a>')
|
139
|
+
restartLink.bind "click", (e) =>
|
140
|
+
$.ajax
|
141
|
+
url: "#{@server}/process/#{@pid}/frames/#{idx}",
|
142
|
+
type: 'DELETE'
|
143
|
+
success: =>
|
144
|
+
this.render()
|
145
|
+
e.preventDefault()
|
146
|
+
header.append(restartLink)
|
147
|
+
div = document.createElement("div")
|
148
|
+
$(div).text("Waiting for data...")
|
149
|
+
@stack_div.append(header)
|
150
|
+
@stack_div.append(div)
|
151
|
+
if idx == 0
|
152
|
+
@selected_frame = new Frame(@server, @pid, 0, $(div))
|
153
|
+
@selected_frame.render()
|
154
|
+
@stack_div.accordion( "destroy" )
|
155
|
+
@stack_div.accordion
|
156
|
+
clearStyle: true
|
157
|
+
collapsible: true
|
158
|
+
changestart: (event, ui) =>
|
159
|
+
frame_idx = ui.newHeader.children("a").attr("data_idx")
|
160
|
+
if frame_idx?
|
161
|
+
@selected_frame = new Frame(@server, @pid, frame_idx, ui.newContent)
|
162
|
+
@selected_frame.render()
|
163
|
+
, 'json'
|
164
|
+
|
165
|
+
class Debugger
|
166
|
+
constructor: (@server) ->
|
167
|
+
@tab_content_template = $("#tab_content_template")
|
168
|
+
|
169
|
+
toString: ->
|
170
|
+
"Debugger on #{server}"
|
171
|
+
|
172
|
+
server_alive: () ->
|
173
|
+
request = $.ajax
|
174
|
+
url: "#{@server}/process"
|
175
|
+
async: false
|
176
|
+
request.status == 200
|
177
|
+
|
178
|
+
clone_template: () ->
|
179
|
+
@content = @tab_content_template.clone()
|
180
|
+
@content.show()
|
181
|
+
@content.removeAttr("id")
|
182
|
+
|
183
|
+
fill_process_selector: () ->
|
184
|
+
@process_box = @content.children("select[name='process-select-box']")
|
185
|
+
$.getJSON "#{@server}/process", (errors) =>
|
186
|
+
$(errors).each (idx, e) =>
|
187
|
+
@process_box.append("<option value='#{e.process_id}'>#{e.process_id}: #{escapeHTML(e.label)}</option>")
|
188
|
+
@process_box.bind "change", =>
|
189
|
+
@process = new Process(@server, @process_box.val(), @tab)
|
190
|
+
@process.render()
|
191
|
+
refreshButton = @content.children(".reload-button")
|
192
|
+
refreshButton.bind "click", (e) =>
|
193
|
+
e.preventDefault()
|
194
|
+
@process = new Process(@server, @process_box.val(), @tab)
|
195
|
+
@process.render()
|
196
|
+
|
197
|
+
content_for: (ui_panel) ->
|
198
|
+
if not @content?
|
199
|
+
@tab = $(ui_panel).attr("id")
|
200
|
+
return "<p>The URL " + url + " could not be reached</p>" unless this.server_alive()
|
201
|
+
this.clone_template()
|
202
|
+
this.fill_process_selector()
|
203
|
+
ui_panel.append(@content)
|
204
|
+
@content
|
205
|
+
|
206
|
+
DebuggerApp =
|
207
|
+
setup: ->
|
208
|
+
debuggers = []
|
209
|
+
tab_server_input = $("#tab_server")
|
210
|
+
tab_counter = 2
|
211
|
+
|
212
|
+
# actual addTab function: adds new tab using the title input
|
213
|
+
# from the form above
|
214
|
+
add_tab = ->
|
215
|
+
tab_server = tab_server_input.val()
|
216
|
+
tabs.tabs("add", "#tabs-#{tab_counter}", tab_server)
|
217
|
+
tab_counter++
|
218
|
+
|
219
|
+
# tabs init with a custom tab template and an "add" callback
|
220
|
+
# filling in the content
|
221
|
+
tabs = $("#tabs").tabs
|
222
|
+
tabTemplate: '<li><a href=\'#{href}\'>#{label}</a>' +
|
223
|
+
"<span class='ui-icon ui-icon-close'>Remove Tab</span></li>"
|
224
|
+
add: (event, ui) ->
|
225
|
+
new_debugger = new Debugger(tab_server_input.val())
|
226
|
+
debuggers.push(new_debugger)
|
227
|
+
new_debugger.content_for($(ui.panel))
|
228
|
+
|
229
|
+
# modal dialog init: custom buttons and a "close" callback
|
230
|
+
# reseting the form inside
|
231
|
+
dialog = $("#dialog").dialog
|
232
|
+
autoOpen: false
|
233
|
+
modal: true
|
234
|
+
buttons:
|
235
|
+
Add: ->
|
236
|
+
add_tab()
|
237
|
+
dialog.dialog("close")
|
238
|
+
Cancel: ->
|
239
|
+
dialog.dialog("close")
|
240
|
+
open: ->
|
241
|
+
tab_server_input.focus()
|
242
|
+
close: ->
|
243
|
+
form[0].reset()
|
244
|
+
|
245
|
+
# addTab form: calls addTab function on submit and closes the
|
246
|
+
# dialog
|
247
|
+
form = $("form", this.dialog).submit ->
|
248
|
+
add_tab()
|
249
|
+
dialog.dialog("close")
|
250
|
+
false
|
251
|
+
|
252
|
+
# addTab button: just opens the dialog
|
253
|
+
$("#add_tab").button().click ->
|
254
|
+
dialog.dialog("open");
|
255
|
+
|
256
|
+
# close icon: removing the tab on click
|
257
|
+
$("#tabs span.ui-icon-close").live "click", ->
|
258
|
+
index = $("li", tabs).index($(this).parent())
|
259
|
+
tabs.tabs("remove", index);
|
260
|
+
|
261
|
+
$(document).ready ->
|
262
|
+
DebuggerApp.setup()
|
263
|
+
window.RubyMode = require("ace/mode/ruby").Mode
|
264
|
+
window.canon = require('pilot/canon')
|
265
|
+
window.editorDiv = $("#editor")
|
266
|
+
window.editor = ace.edit('editor')
|
267
|
+
window.editor.getSession().setUseSoftTabs(true)
|
268
|
+
window.editor.getSession().setMode(new RubyMode())
|
269
|
+
canon.addCommand
|
270
|
+
name: "save",
|
271
|
+
bindKey:
|
272
|
+
win: "Ctrl-S",
|
273
|
+
mac: "Command-S",
|
274
|
+
sender: "editor"
|
275
|
+
exec: ->
|
276
|
+
$.ajax
|
277
|
+
url: window.editor.save_url
|
278
|
+
type: 'PUT'
|
279
|
+
data:
|
280
|
+
debug_info:
|
281
|
+
source: window.editor.getSession().getValue()
|
282
|
+
success: ->
|
283
|
+
alert('Save successful. The stack has been reset to the new method.')
|
284
|
+
$("#tabs").select(".reload-button").filter(':visible').click()
|
285
|
+
|
286
|
+
|
@@ -0,0 +1,366 @@
|
|
1
|
+
var Debugger, DebuggerApp, Frame, Process;
|
2
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
3
|
+
window.escapeHTML = function(str) {
|
4
|
+
if (str == null) {
|
5
|
+
str = "";
|
6
|
+
}
|
7
|
+
if (typeof str !== "string") {
|
8
|
+
str += str;
|
9
|
+
}
|
10
|
+
return $("<i></i>").text(str).html();
|
11
|
+
};
|
12
|
+
Frame = (function() {
|
13
|
+
function Frame(server, pid, frame_idx, container) {
|
14
|
+
this.server = server;
|
15
|
+
this.pid = pid;
|
16
|
+
this.frame_idx = frame_idx;
|
17
|
+
this.container = container;
|
18
|
+
}
|
19
|
+
Frame.prototype.update_detail_view = function(objectInfo) {
|
20
|
+
this.inspector.hide();
|
21
|
+
this.inspector.find('.objInfoClass').text(objectInfo['class']);
|
22
|
+
this.inspector.find('.objInfoValue').text(objectInfo['inspect']);
|
23
|
+
this.renderTableData(this.inspector.children('.objInstVars'), objectInfo.instance_variables, function(idx, data) {
|
24
|
+
return $("<tr><td>" + idx + "</td><td>" + data + "</td></tr>");
|
25
|
+
});
|
26
|
+
return this.inspector.show();
|
27
|
+
};
|
28
|
+
Frame.prototype.renderTableData = function(table, object, formatFn) {
|
29
|
+
var ui;
|
30
|
+
ui = table.children('tbody');
|
31
|
+
ui.empty();
|
32
|
+
return $.each(object, function(key, value) {
|
33
|
+
if (key.indexOf("@") === 0) {
|
34
|
+
return ui.append(formatFn(key, value));
|
35
|
+
}
|
36
|
+
});
|
37
|
+
};
|
38
|
+
Frame.prototype.create_detail_view = function() {
|
39
|
+
this.inspector = $('#objectInspector').clone();
|
40
|
+
this.inspector.removeAttr('id');
|
41
|
+
this.inspector.removeClass('hidden');
|
42
|
+
return this.container.append(this.inspector);
|
43
|
+
};
|
44
|
+
Frame.prototype.create_source_code_holder = function() {
|
45
|
+
this.container.prepend(window.editorDiv);
|
46
|
+
window.editor.save_url = "" + this.server + "/process/" + this.pid + "/frames/" + this.frame_idx;
|
47
|
+
return window.editorDiv.show();
|
48
|
+
};
|
49
|
+
Frame.prototype.create_inspector = function(object, index, path) {
|
50
|
+
var inspector, options;
|
51
|
+
if (index == null) {
|
52
|
+
index = 0;
|
53
|
+
}
|
54
|
+
if (path == null) {
|
55
|
+
path = "" + this.server + "/process/" + this.pid + "/frames/" + this.frame_idx;
|
56
|
+
}
|
57
|
+
options = $([]);
|
58
|
+
if (object.instance_variables != null) {
|
59
|
+
$.each(object.instance_variables, function(key, value) {
|
60
|
+
return options.push("" + key);
|
61
|
+
});
|
62
|
+
} else {
|
63
|
+
$.each(object, function(key, value) {
|
64
|
+
return options.push("" + key);
|
65
|
+
});
|
66
|
+
}
|
67
|
+
if (!(this.inspector_div != null)) {
|
68
|
+
this.inspector_div = $(document.createElement("div"));
|
69
|
+
this.inspector_div.addClass("inspectors");
|
70
|
+
this.container.prepend(this.inspector_div);
|
71
|
+
}
|
72
|
+
if (this.inspectors[index] != null) {
|
73
|
+
inspector = this.inspectors[index];
|
74
|
+
} else {
|
75
|
+
this.inspectors[index] = (inspector = $(document.createElement("select")));
|
76
|
+
this.inspector_div.append(inspector);
|
77
|
+
inspector.attr({
|
78
|
+
multiple: true,
|
79
|
+
"class": 'inspector'
|
80
|
+
});
|
81
|
+
}
|
82
|
+
inspector.html("");
|
83
|
+
$(options).each(__bind(function(idx, o) {
|
84
|
+
return inspector.append("<option value=" + idx + ">" + (escapeHTML(o)) + "</option>");
|
85
|
+
}, this));
|
86
|
+
this.create_evaluator(path);
|
87
|
+
return inspector.bind("change", __bind(function() {
|
88
|
+
var i, url, value, _i, _len, _ref;
|
89
|
+
value = options[inspector.val()];
|
90
|
+
url = "" + path + "/objects/" + value;
|
91
|
+
_ref = this.inspectors.slice(index + 1);
|
92
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
93
|
+
i = _ref[_i];
|
94
|
+
i.html("");
|
95
|
+
}
|
96
|
+
return $.get(url, __bind(function(object) {
|
97
|
+
this.create_inspector(object.instance_variables, index + 1, url);
|
98
|
+
return this.update_detail_view(object);
|
99
|
+
}, this), 'json');
|
100
|
+
}, this));
|
101
|
+
};
|
102
|
+
Frame.prototype.create_evaluator = function(path) {
|
103
|
+
if (this.evaluator == null) {
|
104
|
+
this.evaluator = $(document.createElement("input"));
|
105
|
+
this.evaluator.attr({
|
106
|
+
type: "text",
|
107
|
+
name: "" + this.frame_idx + "_evaluator",
|
108
|
+
id: "" + this.frame_idx + "_evaluator",
|
109
|
+
"class": "ui-widget-content ui-corner-all",
|
110
|
+
style: 'width: 100%;'
|
111
|
+
});
|
112
|
+
this.container.prepend(this.evaluator);
|
113
|
+
}
|
114
|
+
this.evaluator.bind("focus", __bind(function() {}, this));
|
115
|
+
this.evaluator.unbind("keypress");
|
116
|
+
return this.evaluator.bind("keypress", __bind(function(e) {
|
117
|
+
var code;
|
118
|
+
if (e.keyCode != null) {
|
119
|
+
code = e.keyCode;
|
120
|
+
}
|
121
|
+
if (!code) {
|
122
|
+
code = e.which;
|
123
|
+
}
|
124
|
+
if (code === 13) {
|
125
|
+
return $.ajax({
|
126
|
+
url: path,
|
127
|
+
data: {
|
128
|
+
"do-it": this.evaluator.val()
|
129
|
+
},
|
130
|
+
success: __bind(function(data) {
|
131
|
+
var result;
|
132
|
+
result = data["do-it-result"];
|
133
|
+
this.evaluator.val("" + (this.evaluator.val()) + " => " + result['inspect']);
|
134
|
+
this.update_detail_view(result);
|
135
|
+
return this.evaluator.select();
|
136
|
+
}, this),
|
137
|
+
dataType: 'json',
|
138
|
+
type: 'PUT'
|
139
|
+
});
|
140
|
+
}
|
141
|
+
}, this));
|
142
|
+
};
|
143
|
+
Frame.prototype.render = function() {
|
144
|
+
this.container.html("");
|
145
|
+
this.inspectors = [];
|
146
|
+
this.create_source_code_holder();
|
147
|
+
return $.get("" + this.server + "/process/" + this.pid + "/frames/" + this.frame_idx, __bind(function(frame) {
|
148
|
+
editor.getSession().setValue(frame.debug_info.source);
|
149
|
+
this.create_inspector(frame.debug_info.context);
|
150
|
+
return this.create_detail_view();
|
151
|
+
}, this), 'json');
|
152
|
+
};
|
153
|
+
return Frame;
|
154
|
+
})();
|
155
|
+
Process = (function() {
|
156
|
+
function Process(server, pid, tab) {
|
157
|
+
this.server = server;
|
158
|
+
this.pid = pid;
|
159
|
+
this.tab = tab;
|
160
|
+
this.info_div = $("#" + this.tab + " .info-bar");
|
161
|
+
this.stack_div = $("#" + this.tab + " .frame-list");
|
162
|
+
}
|
163
|
+
Process.prototype.render = function() {
|
164
|
+
this.render_info();
|
165
|
+
return this.render_stack();
|
166
|
+
};
|
167
|
+
Process.prototype.render_info = function() {
|
168
|
+
var request;
|
169
|
+
return request = $.get("" + this.server + "/process/" + this.pid, __bind(function(data) {
|
170
|
+
return this.info_div.text("" + data.label + " (" + data.timestamp + ")");
|
171
|
+
}, this), 'json');
|
172
|
+
};
|
173
|
+
Process.prototype.render_stack = function() {
|
174
|
+
var request;
|
175
|
+
this.stack_div.html("");
|
176
|
+
return request = $.get("" + this.server + "/process/" + this.pid + "/frames", __bind(function(framelist) {
|
177
|
+
$(framelist).each(__bind(function(idx, f) {
|
178
|
+
var div, header, link, restartLink;
|
179
|
+
header = $(document.createElement("h3"));
|
180
|
+
link = $(document.createElement("a"));
|
181
|
+
link.attr({
|
182
|
+
href: '#',
|
183
|
+
data_idx: idx
|
184
|
+
});
|
185
|
+
link.text("" + f["class"] + "#" + f.method_name);
|
186
|
+
link.append("<small>" + (escapeHTML(f.source_location)) + "</small>");
|
187
|
+
header.append(link);
|
188
|
+
restartLink = $('<a href="#">Restart frame</a>');
|
189
|
+
restartLink.bind("click", __bind(function(e) {
|
190
|
+
$.ajax({
|
191
|
+
url: "" + this.server + "/process/" + this.pid + "/frames/" + idx,
|
192
|
+
type: 'DELETE',
|
193
|
+
success: __bind(function() {
|
194
|
+
return this.render();
|
195
|
+
}, this)
|
196
|
+
});
|
197
|
+
return e.preventDefault();
|
198
|
+
}, this));
|
199
|
+
header.append(restartLink);
|
200
|
+
div = document.createElement("div");
|
201
|
+
$(div).text("Waiting for data...");
|
202
|
+
this.stack_div.append(header);
|
203
|
+
this.stack_div.append(div);
|
204
|
+
if (idx === 0) {
|
205
|
+
this.selected_frame = new Frame(this.server, this.pid, 0, $(div));
|
206
|
+
return this.selected_frame.render();
|
207
|
+
}
|
208
|
+
}, this));
|
209
|
+
this.stack_div.accordion("destroy");
|
210
|
+
return this.stack_div.accordion({
|
211
|
+
clearStyle: true,
|
212
|
+
collapsible: true,
|
213
|
+
changestart: __bind(function(event, ui) {
|
214
|
+
var frame_idx;
|
215
|
+
frame_idx = ui.newHeader.children("a").attr("data_idx");
|
216
|
+
if (frame_idx != null) {
|
217
|
+
this.selected_frame = new Frame(this.server, this.pid, frame_idx, ui.newContent);
|
218
|
+
return this.selected_frame.render();
|
219
|
+
}
|
220
|
+
}, this)
|
221
|
+
});
|
222
|
+
}, this), 'json');
|
223
|
+
};
|
224
|
+
return Process;
|
225
|
+
})();
|
226
|
+
Debugger = (function() {
|
227
|
+
function Debugger(server) {
|
228
|
+
this.server = server;
|
229
|
+
this.tab_content_template = $("#tab_content_template");
|
230
|
+
}
|
231
|
+
Debugger.prototype.toString = function() {
|
232
|
+
return "Debugger on " + server;
|
233
|
+
};
|
234
|
+
Debugger.prototype.server_alive = function() {
|
235
|
+
var request;
|
236
|
+
request = $.ajax({
|
237
|
+
url: "" + this.server + "/process",
|
238
|
+
async: false
|
239
|
+
});
|
240
|
+
return request.status === 200;
|
241
|
+
};
|
242
|
+
Debugger.prototype.clone_template = function() {
|
243
|
+
this.content = this.tab_content_template.clone();
|
244
|
+
this.content.show();
|
245
|
+
return this.content.removeAttr("id");
|
246
|
+
};
|
247
|
+
Debugger.prototype.fill_process_selector = function() {
|
248
|
+
var refreshButton;
|
249
|
+
this.process_box = this.content.children("select[name='process-select-box']");
|
250
|
+
$.getJSON("" + this.server + "/process", __bind(function(errors) {
|
251
|
+
return $(errors).each(__bind(function(idx, e) {
|
252
|
+
return this.process_box.append("<option value='" + e.process_id + "'>" + e.process_id + ": " + (escapeHTML(e.label)) + "</option>");
|
253
|
+
}, this));
|
254
|
+
}, this));
|
255
|
+
this.process_box.bind("change", __bind(function() {
|
256
|
+
this.process = new Process(this.server, this.process_box.val(), this.tab);
|
257
|
+
return this.process.render();
|
258
|
+
}, this));
|
259
|
+
refreshButton = this.content.children(".reload-button");
|
260
|
+
return refreshButton.bind("click", __bind(function(e) {
|
261
|
+
e.preventDefault();
|
262
|
+
this.process = new Process(this.server, this.process_box.val(), this.tab);
|
263
|
+
return this.process.render();
|
264
|
+
}, this));
|
265
|
+
};
|
266
|
+
Debugger.prototype.content_for = function(ui_panel) {
|
267
|
+
if (!(this.content != null)) {
|
268
|
+
this.tab = $(ui_panel).attr("id");
|
269
|
+
if (!this.server_alive()) {
|
270
|
+
return "<p>The URL " + url + " could not be reached</p>";
|
271
|
+
}
|
272
|
+
this.clone_template();
|
273
|
+
this.fill_process_selector();
|
274
|
+
ui_panel.append(this.content);
|
275
|
+
}
|
276
|
+
return this.content;
|
277
|
+
};
|
278
|
+
return Debugger;
|
279
|
+
})();
|
280
|
+
DebuggerApp = {
|
281
|
+
setup: function() {
|
282
|
+
var add_tab, debuggers, dialog, form, tab_counter, tab_server_input, tabs;
|
283
|
+
debuggers = [];
|
284
|
+
tab_server_input = $("#tab_server");
|
285
|
+
tab_counter = 2;
|
286
|
+
add_tab = function() {
|
287
|
+
var tab_server;
|
288
|
+
tab_server = tab_server_input.val();
|
289
|
+
tabs.tabs("add", "#tabs-" + tab_counter, tab_server);
|
290
|
+
return tab_counter++;
|
291
|
+
};
|
292
|
+
tabs = $("#tabs").tabs({
|
293
|
+
tabTemplate: '<li><a href=\'#{href}\'>#{label}</a>' + "<span class='ui-icon ui-icon-close'>Remove Tab</span></li>",
|
294
|
+
add: function(event, ui) {
|
295
|
+
var new_debugger;
|
296
|
+
new_debugger = new Debugger(tab_server_input.val());
|
297
|
+
debuggers.push(new_debugger);
|
298
|
+
return new_debugger.content_for($(ui.panel));
|
299
|
+
}
|
300
|
+
});
|
301
|
+
dialog = $("#dialog").dialog({
|
302
|
+
autoOpen: false,
|
303
|
+
modal: true,
|
304
|
+
buttons: {
|
305
|
+
Add: function() {
|
306
|
+
add_tab();
|
307
|
+
return dialog.dialog("close");
|
308
|
+
},
|
309
|
+
Cancel: function() {
|
310
|
+
return dialog.dialog("close");
|
311
|
+
}
|
312
|
+
},
|
313
|
+
open: function() {
|
314
|
+
return tab_server_input.focus();
|
315
|
+
},
|
316
|
+
close: function() {
|
317
|
+
return form[0].reset();
|
318
|
+
}
|
319
|
+
});
|
320
|
+
form = $("form", this.dialog).submit(function() {
|
321
|
+
add_tab();
|
322
|
+
dialog.dialog("close");
|
323
|
+
return false;
|
324
|
+
});
|
325
|
+
$("#add_tab").button().click(function() {
|
326
|
+
return dialog.dialog("open");
|
327
|
+
});
|
328
|
+
return $("#tabs span.ui-icon-close").live("click", function() {
|
329
|
+
var index;
|
330
|
+
index = $("li", tabs).index($(this).parent());
|
331
|
+
return tabs.tabs("remove", index);
|
332
|
+
});
|
333
|
+
}
|
334
|
+
};
|
335
|
+
$(document).ready(function() {
|
336
|
+
DebuggerApp.setup();
|
337
|
+
window.RubyMode = require("ace/mode/ruby").Mode;
|
338
|
+
window.canon = require('pilot/canon');
|
339
|
+
window.editorDiv = $("#editor");
|
340
|
+
window.editor = ace.edit('editor');
|
341
|
+
window.editor.getSession().setUseSoftTabs(true);
|
342
|
+
window.editor.getSession().setMode(new RubyMode());
|
343
|
+
return canon.addCommand({
|
344
|
+
name: "save",
|
345
|
+
bindKey: {
|
346
|
+
win: "Ctrl-S",
|
347
|
+
mac: "Command-S",
|
348
|
+
sender: "editor"
|
349
|
+
},
|
350
|
+
exec: function() {
|
351
|
+
return $.ajax({
|
352
|
+
url: window.editor.save_url,
|
353
|
+
type: 'PUT',
|
354
|
+
data: {
|
355
|
+
debug_info: {
|
356
|
+
source: window.editor.getSession().getValue()
|
357
|
+
}
|
358
|
+
},
|
359
|
+
success: function() {
|
360
|
+
alert('Save successful. The stack has been reset to the new method.');
|
361
|
+
return $("#tabs").select(".reload-button").filter(':visible').click();
|
362
|
+
}
|
363
|
+
});
|
364
|
+
}
|
365
|
+
});
|
366
|
+
});
|
@@ -0,0 +1,17 @@
|
|
1
|
+
$(document).ready ->
|
2
|
+
$.getJSON "#{WebTools.location}/sessions", (data) ->
|
3
|
+
error = data['_error']
|
4
|
+
if error?
|
5
|
+
console.log(data)
|
6
|
+
alert(error + ' (see console log for stack)')
|
7
|
+
else
|
8
|
+
thead = $('#sessionHeaders').children("tr")
|
9
|
+
$(data.headers).each (idx, element) ->
|
10
|
+
thead.append("<th title='#{element[1]}'>#{element[0]}</th>")
|
11
|
+
tbody = $('#sessionTable')
|
12
|
+
for session in data.report
|
13
|
+
row = $('<tr>')
|
14
|
+
for field in session
|
15
|
+
row.append("<td>#{field}</td>")
|
16
|
+
tbody.append(row)
|
17
|
+
$('.timestamp').html("Report generated #{data.timestamp}")
|
@@ -0,0 +1,27 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
return $.getJSON("" + WebTools.location + "/sessions", function(data) {
|
3
|
+
var error, field, row, session, tbody, thead, _i, _j, _len, _len2, _ref;
|
4
|
+
error = data['_error'];
|
5
|
+
if (error != null) {
|
6
|
+
console.log(data);
|
7
|
+
return alert(error + ' (see console log for stack)');
|
8
|
+
} else {
|
9
|
+
thead = $('#sessionHeaders').children("tr");
|
10
|
+
$(data.headers).each(function(idx, element) {
|
11
|
+
return thead.append("<th title='" + element[1] + "'>" + element[0] + "</th>");
|
12
|
+
});
|
13
|
+
tbody = $('#sessionTable');
|
14
|
+
_ref = data.report;
|
15
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
16
|
+
session = _ref[_i];
|
17
|
+
row = $('<tr>');
|
18
|
+
for (_j = 0, _len2 = session.length; _j < _len2; _j++) {
|
19
|
+
field = session[_j];
|
20
|
+
row.append("<td>" + field + "</td>");
|
21
|
+
}
|
22
|
+
tbody.append(row);
|
23
|
+
}
|
24
|
+
return $('.timestamp').html("Report generated " + data.timestamp);
|
25
|
+
}
|
26
|
+
});
|
27
|
+
});
|