Skip to content

Commit

Permalink
Allows expanding the visible lines of code (Fixes BetterErrors#370)
Browse files Browse the repository at this point in the history
  • Loading branch information
zedtux committed Nov 24, 2017
1 parent 946281d commit 5323aa3
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 13 deletions.
32 changes: 24 additions & 8 deletions lib/better_errors/code_formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ class CodeFormatter
".haml" => :haml
}

attr_reader :filename, :line, :context
attr_reader :filename, :line, :upperlines, :lowerlines

def initialize(filename, line, context = 5)
@filename = filename
@line = line
@context = context
def initialize(filename, line, upperlines = nil, lowerlines = nil)
@filename = filename
@line = line
@upperlines = upperlines || line - 5
@lowerlines = lowerlines || line + 5

@upperlines = 1 if begin_of_file_reached?
@lowerlines = source_lines_count if end_of_file_reached?
end

def output
Expand Down Expand Up @@ -55,9 +59,21 @@ def source_lines
end

def line_range
min = [line - context, 1].max
max = [line + context, source_lines.count].min
min..max
upperlines..lowerlines
end

def begin_of_file_reached?
upperlines <= 1
end

def source_lines_count
@source_lines_count ||= source_lines.count
rescue Errno::ENOENT
0
end

def end_of_file_reached?
lowerlines >= source_lines_count
end
end
end
36 changes: 35 additions & 1 deletion lib/better_errors/code_formatter/html.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,42 @@ def formatted_nums
}
end

def expander_icon
<<-HEREDOC
<svg aria-hidden="true" class="octicon octicon-unfold"
height="16" version="1.1" viewBox="0 0 14 16" width="14">
<path fill-rule="evenodd" d="M11.5 7.5L14 10c0 .55-.45 1-1
1H9v-1h3.5l-2-2h-7l-2 2H5v1H1c-.55 0-1-.45-1-1l2.5-2.5L0
5c0-.55.45-1 1-1h4v1H1.5l2 2h7l2-2H9V4h4c.55 0 1 .45 1
1l-2.5 2.5zM6 6h2V3h2L7 0 4 3h2v3zm2 3H6v3H4l3 3 3-3H8V9z">
</path>
</svg>
HEREDOC
end

def formatted_code
%{<div class="code_linenums">#{formatted_nums.join}</div><div class="code">#{super}</div>}
code = ''

unless begin_of_file_reached?
code << '<span class="expander">' \
"<a href='#' data-direction='up' title='Expand'>" \
"#{expander_icon}" \
"</a>" \
'</span>'
end

code << "<div class='code_linenums'>#{formatted_nums.join}</div>"
code << "<div class='code'>#{super}</div>"

unless end_of_file_reached?
code << '<span class="expander">' \
"<a href='#' data-direction='down' title='Expand'>" \
"#{expander_icon}" \
"</a>" \
'</span>'
end

code
end
end
end
21 changes: 18 additions & 3 deletions lib/better_errors/error_page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -50,6 +49,16 @@ def do_eval(opts)
eval_and_respond(index, code)
end

def do_expand(opts)
load_frame_from(opts)

@frame.upperlines -= 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
Expand Down Expand Up @@ -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.upperlines,
frame.lowerlines).output
end

def text_formatted_code_block(frame)
Expand Down Expand Up @@ -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
5 changes: 4 additions & 1 deletion lib/better_errors/stack_frame.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ def self.from_exception(exception)
end

attr_reader :filename, :line, :name, :frame_binding
attr_accessor :upperlines, :lowerlines

def initialize(filename, line, name, frame_binding = nil)
def initialize(filename, line, name, frame_binding = nil, upperlines = nil, lowerlines = nil)
@filename = filename
@line = line
@name = name
@frame_binding = frame_binding
@upperlines = upperlines || line - 5
@lowerlines = lowerlines || line + 5

set_pretty_method_name if frame_binding
end
Expand Down
41 changes: 41 additions & 0 deletions lib/better_errors/templates/main.erb
Original file line number Diff line number Diff line change
Expand Up @@ -474,11 +474,23 @@
float:left;
}

.code_block span.expander {
display: block;
padding: 0 12px;
height: 23px;
}

.code_linenums span{
display:block;
padding:0 12px;
}

.code_block span.expander a {
position: relative;
top: 3px;
margin-bottom: 2px;
}

.code {
margin-bottom: -1px;
border-top-left-radius:2px;
Expand Down Expand Up @@ -929,6 +941,33 @@
if (replInput) replInput.focus();
}

function connectExpanders() {
var allExpanders = document.querySelectorAll(".expander a");
var selectedFrame = document.querySelector("ul.frames li.selected");

for(var i = 0; i < allExpanders.length; i++) {
(function(i, el) {
var el = allExpanders[i];
el.onclick = function() {
var direction = el.getAttribute("data-direction");
var index = selectedFrame.getAttribute("data-index");
apiCall("expand", { "direction": direction, "index": index }, function(response) {
if(response.error) {
el.innerHTML = "<h2 class='error'>" + escapeHTML(response.error) + "</h2>";
if(response.explanation) {
el.innerHTML += "<p class='explanation'>" + escapeHTML(response.explanation) + "</p>";
}
el.innerHTML += "<p><a target='_new' href='https://github.com/charliesome/better_errors'>More about Better Errors</a></p>";
} else {
document.querySelector(".code_block").innerHTML = response.html;
connectExpanders();
}
});
}
})(i);
}
}

function selectFrameInfo(index) {
var el = allFrameInfos[index];
if(el) {
Expand All @@ -947,6 +986,8 @@
} else {
el.innerHTML = response.html;

connectExpanders();

var repl = el.querySelector(".be-repl .be-console");
if(repl) {
new REPL(index).install(repl);
Expand Down
1 change: 1 addition & 0 deletions lib/better_errors/templates/trace_info.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%== html_formatted_code_block @frame %>
29 changes: 29 additions & 0 deletions spec/better_errors/error_page_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,5 +223,34 @@ def initialize(message = nil)
end
end
end

describe 'do_expand' do
context 'requesting more lines of code in the upper direction' do
subject(:do_expand) { error_page.do_expand('index' => 0, 'direction' => 'up') }
it 'should' do
html = do_expand[:html]
expect(html).to include("<span class=\"\"> 1</span>")
expect(html).to include("<span class=\"\"> 10</span>")
expect(html).to_not include("<span class=\"\"> 15</span>")
end
end
context 'requesting one time more lines of code in the lower direction' do
it 'should returns the codes from line 1 until line 15' do
html = error_page.do_expand('index' => 0, 'direction' => 'down')[:html]
expect(html).to include("<span class=\"\"> 1</span>")
expect(html).to include("<span class=\"\"> 15</span>")
expect(html).to_not include("<span class=\"\"> 16</span>")
end
end
context 'requesting two times more lines of code in the lower direction' do
it 'should returns the codes from line 1 until line 20' do
error_page.do_expand('index' => 0, 'direction' => 'down')
html = error_page.do_expand('index' => 0, 'direction' => 'down')[:html]
expect(html).to include("<span class=\"\"> 1</span>")
expect(html).to include("<span class=\"\"> 20</span>")
expect(html).to_not include("<span class=\"\"> 21</span>")
end
end
end
end
end

0 comments on commit 5323aa3

Please sign in to comment.