diff --git a/lib/better_errors/code_formatter.rb b/lib/better_errors/code_formatter.rb
index 4c6824d1..fea2643f 100644
--- a/lib/better_errors/code_formatter.rb
+++ b/lib/better_errors/code_formatter.rb
@@ -12,12 +12,16 @@ class CodeFormatter
".haml" => :haml
}
- attr_reader :filename, :line, :context
+ attr_reader :filename, :line, :uperlines, :lowerlines
- def initialize(filename, line, context = 5)
- @filename = filename
- @line = line
- @context = context
+ def initialize(filename, line, uperlines = nil, lowerlines = nil)
+ @filename = filename
+ @line = line
+ @uperlines = uperlines || line - 5
+ @lowerlines = lowerlines || line + 5
+
+ @uperlines = 1 if begin_of_file_reached?
+ @lowerlines = source_lines.count if end_of_file_reached?
end
def output
@@ -55,9 +59,15 @@ def source_lines
end
def line_range
- min = [line - context, 1].max
- max = [line + context, source_lines.count].min
- min..max
+ uperlines..lowerlines
+ end
+
+ def begin_of_file_reached?
+ uperlines <= 1
+ end
+
+ def end_of_file_reached?
+ lowerlines >= source_lines.count
end
end
end
diff --git a/lib/better_errors/code_formatter/html.rb b/lib/better_errors/code_formatter/html.rb
index ec96a214..4a116b59 100644
--- a/lib/better_errors/code_formatter/html.rb
+++ b/lib/better_errors/code_formatter/html.rb
@@ -19,8 +19,40 @@ def formatted_nums
}
end
+ def diff_expander_icon
+ ''
+ end
+
def formatted_code
- %{
#{formatted_nums.join}
#{super}
}
+ code = ''
+
+ if true
+ code << '' \
+ "" \
+ "#{diff_expander_icon}" \
+ "" \
+ ''
+ end
+
+ code << "#{formatted_nums.join}
"
+ code << "#{super}
"
+
+ if true
+ code << '' \
+ "" \
+ "#{diff_expander_icon}" \
+ "" \
+ ''
+ end
+
+ code
end
end
end
diff --git a/lib/better_errors/error_page.rb b/lib/better_errors/error_page.rb
index 40cccb1c..0102199e 100644
--- a/lib/better_errors/error_page.rb
+++ b/lib/better_errors/error_page.rb
@@ -31,8 +31,7 @@ def render(template_name = "main")
end
def do_variables(opts)
- index = opts["index"].to_i
- @frame = backtrace_frames[index]
+ load_frame_from(opts)
@var_start_time = Time.now.to_f
{ html: render("variable_info") }
end
@@ -50,6 +49,16 @@ def do_eval(opts)
eval_and_respond(index, code)
end
+ def do_diffexpand(opts)
+ load_frame_from(opts)
+
+ @frame.uperlines -= 5 if opts['direction'] == 'up'
+ @frame.lowerlines += 5 if opts['direction'] == 'down'
+
+ @var_start_time = Time.now.to_f
+ { html: render("trace_info") }
+ end
+
def backtrace_frames
exception.backtrace
end
@@ -92,7 +101,8 @@ def request_path
end
def html_formatted_code_block(frame)
- CodeFormatter::HTML.new(frame.filename, frame.line).output
+ CodeFormatter::HTML.new(frame.filename, frame.line, frame.uperlines,
+ frame.lowerlines).output
end
def text_formatted_code_block(frame)
@@ -138,5 +148,10 @@ def eval_and_respond(index, code)
result: result
}
end
+
+ def load_frame_from(opts)
+ index = opts["index"].to_i
+ @frame = backtrace_frames[index]
+ end
end
end
diff --git a/lib/better_errors/stack_frame.rb b/lib/better_errors/stack_frame.rb
index 46518031..56c78d6c 100644
--- a/lib/better_errors/stack_frame.rb
+++ b/lib/better_errors/stack_frame.rb
@@ -8,12 +8,15 @@ def self.from_exception(exception)
end
attr_reader :filename, :line, :name, :frame_binding
+ attr_accessor :uperlines, :lowerlines
- def initialize(filename, line, name, frame_binding = nil)
+ def initialize(filename, line, name, frame_binding = nil, uperlines = nil, lowerlines = nil)
@filename = filename
@line = line
@name = name
@frame_binding = frame_binding
+ @uperlines = uperlines || line - 5
+ @lowerlines = lowerlines || line + 5
set_pretty_method_name if frame_binding
end
diff --git a/lib/better_errors/templates/main.erb b/lib/better_errors/templates/main.erb
index 81487982..3e3a8160 100644
--- a/lib/better_errors/templates/main.erb
+++ b/lib/better_errors/templates/main.erb
@@ -474,11 +474,23 @@
float:left;
}
+ .code_block span.diff-expander {
+ display: block;
+ padding: 0 12px;
+ height: 23px;
+ }
+
.code_linenums span{
display:block;
padding:0 12px;
}
+ .code_block span.diff-expander a {
+ position: relative;
+ top: 3px;
+ margin-bottom: 2px;
+ }
+
.code {
margin-bottom: -1px;
border-top-left-radius:2px;
@@ -929,6 +941,33 @@
if (replInput) replInput.focus();
}
+ function connectDiffExpanders() {
+ var allDiffExpanders = document.querySelectorAll(".diff-expander a");
+ var selectedFrame = document.querySelector("ul.frames li.selected");
+
+ for(var i = 0; i < allDiffExpanders.length; i++) {
+ (function(i, el) {
+ var el = allDiffExpanders[i];
+ el.onclick = function() {
+ var direction = el.getAttribute("data-direction");
+ var index = selectedFrame.getAttribute("data-index");
+ apiCall("diffexpand", { "direction": direction, "index": index }, function(response) {
+ if(response.error) {
+ el.innerHTML = "" + escapeHTML(response.error) + "
";
+ if(response.explanation) {
+ el.innerHTML += "" + escapeHTML(response.explanation) + "
";
+ }
+ el.innerHTML += "More about Better Errors
";
+ } else {
+ document.querySelector(".code_block").innerHTML = response.html;
+ connectDiffExpanders();
+ }
+ });
+ }
+ })(i);
+ }
+ }
+
function selectFrameInfo(index) {
var el = allFrameInfos[index];
if(el) {
@@ -947,6 +986,8 @@
} else {
el.innerHTML = response.html;
+ connectDiffExpanders();
+
var repl = el.querySelector(".be-repl .be-console");
if(repl) {
new REPL(index).install(repl);
diff --git a/lib/better_errors/templates/trace_info.erb b/lib/better_errors/templates/trace_info.erb
new file mode 100644
index 00000000..bc16e370
--- /dev/null
+++ b/lib/better_errors/templates/trace_info.erb
@@ -0,0 +1 @@
+<%== html_formatted_code_block @frame %>