Skip to content

Commit 73027f0

Browse files
committed
HTML report hotkeys work differently if the current chunk is off-screen. A chunk on-screen will be selected next.
1 parent f1cca3a commit 73027f0

File tree

3 files changed

+167
-12
lines changed

3 files changed

+167
-12
lines changed

CHANGES.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
Change history for Coverage.py
33
------------------------------
44

5+
Version 3.5b2
6+
-------------
7+
8+
- The HTML report hotkeys now behave slightly differently when the current
9+
chunk isn't visible at all: a chunk on the screen will be selected,
10+
instead of the old behavior of jumping to the literal next chunk.
11+
The hotkeys now work in Google Chrome. Thanks, Guido van Rossum.
12+
513

614
Version 3.5b1 --- 5 June 2011
715
-----------------------------

coverage/htmlfiles/coverage_html.js

Lines changed: 116 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ coverage.pyfile_ready = function ($) {
116116
}
117117

118118
$(document)
119-
.bind('keydown', 'j', coverage.to_next_chunk)
120-
.bind('keydown', 'k', coverage.to_prev_chunk)
119+
.bind('keydown', 'j', coverage.to_next_chunk_nicely)
120+
.bind('keydown', 'k', coverage.to_prev_chunk_nicely)
121121
.bind('keydown', '0', coverage.to_top)
122122
.bind('keydown', '1', coverage.to_first_chunk)
123123
;
@@ -139,12 +139,12 @@ coverage.toggle_lines = function (btn, cls) {
139139
}
140140
};
141141

142-
// Return the nth line.
142+
// Return the nth line div.
143143
coverage.line_elt = function (n) {
144144
return $("#t" + n);
145145
};
146146

147-
// Return the nth line number.
147+
// Return the nth line number div.
148148
coverage.num_elt = function (n) {
149149
return $("#n" + n);
150150
};
@@ -154,6 +154,7 @@ coverage.code_container = function () {
154154
return $(".linenos");
155155
};
156156

157+
// Set the selection. b and e are line numbers.
157158
coverage.set_sel = function (b, e) {
158159
// The first line selected.
159160
coverage.sel_begin = b;
@@ -163,7 +164,7 @@ coverage.set_sel = function (b, e) {
163164

164165
coverage.to_top = function () {
165166
coverage.set_sel(0, 1);
166-
$("html,body").animate({scrollTop: 0}, 200);
167+
coverage.scroll_window(0);
167168
};
168169

169170
coverage.to_first_chunk = function () {
@@ -240,6 +241,104 @@ coverage.to_prev_chunk = function () {
240241
c.show_selection();
241242
};
242243

244+
// Return the line number of the line nearest pixel position pos
245+
coverage.line_at_pos = function (pos) {
246+
var l1 = coverage.line_elt(1),
247+
l2 = coverage.line_elt(2),
248+
result;
249+
if (l1.length && l2.length) {
250+
var l1_top = l1.offset().top,
251+
line_height = l2.offset().top - l1_top,
252+
nlines = (pos - l1_top) / line_height;
253+
if (nlines < 1) {
254+
result = 1;
255+
}
256+
else {
257+
result = Math.ceil(nlines);
258+
}
259+
}
260+
else {
261+
result = 1;
262+
}
263+
return result;
264+
};
265+
266+
// Returns 0, 1, or 2: how many of the two ends of the selection are on
267+
// the screen right now?
268+
coverage.selection_ends_on_screen = function () {
269+
if (coverage.sel_begin === 0) {
270+
return 0;
271+
}
272+
273+
var top = coverage.line_elt(coverage.sel_begin);
274+
var next = coverage.line_elt(coverage.sel_end-1);
275+
276+
return (
277+
(top.isOnScreen() ? 1 : 0) +
278+
(next.isOnScreen() ? 1 : 0)
279+
);
280+
};
281+
282+
coverage.to_next_chunk_nicely = function () {
283+
coverage.finish_scrolling();
284+
if (coverage.selection_ends_on_screen() === 0) {
285+
// The selection is entirely off the screen: select the top line on
286+
// the screen.
287+
var win = $(window);
288+
coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop()));
289+
}
290+
coverage.to_next_chunk();
291+
};
292+
293+
coverage.to_prev_chunk_nicely = function () {
294+
coverage.finish_scrolling();
295+
if (coverage.selection_ends_on_screen() === 0) {
296+
var win = $(window);
297+
coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win.height()));
298+
}
299+
coverage.to_prev_chunk();
300+
};
301+
302+
// Select line number lineno, or if it is in a colored chunk, select the
303+
// entire chunk
304+
coverage.select_line_or_chunk = function (lineno) {
305+
var c = coverage;
306+
var probe_line = c.line_elt(lineno);
307+
if (probe_line.length === 0) {
308+
return;
309+
}
310+
var the_color = probe_line.css("background-color");
311+
if (!c.is_transparent(the_color)) {
312+
// The line is in a highlighted chunk.
313+
// Search backward for the first line.
314+
var probe = lineno;
315+
var color = the_color;
316+
while (probe > 0 && color === the_color) {
317+
probe--;
318+
probe_line = c.line_elt(probe);
319+
if (probe_line.length === 0) {
320+
break;
321+
}
322+
color = probe_line.css("background-color");
323+
}
324+
var begin = probe + 1;
325+
326+
// Search forward for the last line.
327+
probe = lineno;
328+
color = the_color;
329+
while (color === the_color) {
330+
probe++;
331+
probe_line = c.line_elt(probe);
332+
color = probe_line.css("background-color");
333+
}
334+
335+
coverage.set_sel(begin, probe);
336+
}
337+
else {
338+
coverage.set_sel(lineno);
339+
}
340+
};
341+
243342
coverage.show_selection = function () {
244343
var c = coverage;
245344

@@ -254,13 +353,20 @@ coverage.show_selection = function () {
254353

255354
coverage.scroll_to_selection = function () {
256355
// Scroll the page if the chunk isn't fully visible.
257-
var top = coverage.line_elt(coverage.sel_begin);
258-
var next = coverage.line_elt(coverage.sel_end);
259-
260-
if (!top.isOnScreen() || !next.isOnScreen()) {
356+
if (coverage.selection_ends_on_screen() < 2) {
261357
// Need to move the page. The html,body trick makes it scroll in all
262358
// browsers, got it from http://stackoverflow.com/questions/3042651
359+
var top = coverage.line_elt(coverage.sel_begin);
263360
var top_pos = parseInt(top.offset().top, 10);
264-
$("html,body").animate({scrollTop: top_pos-30}, 300);
361+
coverage.scroll_window(top_pos - 30);
265362
}
266363
};
364+
365+
coverage.scroll_window = function (to_pos) {
366+
$("html,body").animate({scrollTop: to_pos}, 200);
367+
};
368+
369+
coverage.finish_scrolling = function () {
370+
$("html,body").stop(true, true);
371+
};
372+

test/js/tests.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
// Tests of coverage.py HTML report chunk navigation.
2-
/* global: coverage, test, module, equals, jQuery, $ */
2+
/*global coverage, test, module, equals, jQuery, $ */
33

44
// Test helpers
55

66
function selection_is(sel) {
7+
raw_selection_is(sel, true);
8+
}
9+
10+
function raw_selection_is(sel, check_highlight) {
711
var beg = sel[0], end = sel[1];
812
equals(coverage.sel_begin, beg);
913
equals(coverage.sel_end, end);
10-
equals(coverage.code_container().find(".highlight").length, end-beg);
14+
if (check_highlight) {
15+
equals(coverage.code_container().find(".highlight").length, end-beg);
16+
}
1117
}
1218

1319
function build_fixture(spec) {
@@ -161,3 +167,38 @@ test("Jump from a line selected", function () {
161167
coverage.to_next_chunk();
162168
selection_is([5,7]);
163169
});
170+
171+
// Tests of select_line_or_chunk.
172+
173+
$.each([
174+
// The data for each test: a spec for the fixture to build, and an array
175+
// of the selection that will be selected by select_line_or_chunk for
176+
// each line in the fixture.
177+
['rrwwrr', [[1,3], [1,3], [3,4], [4,5], [5,7], [5,7]]],
178+
['rb', [[1,2], [2,3]]],
179+
['r', [[1,2]]],
180+
['w', [[1,2]]],
181+
['www', [[1,2], [2,3], [3,4]]],
182+
['wwwrrr', [[1,2], [2,3], [3,4], [4,7], [4,7], [4,7]]],
183+
['rrrwww', [[1,4], [1,4], [1,4], [4,5], [5,6], [6,7]]],
184+
['rrrbbb', [[1,4], [1,4], [1,4], [4,7], [4,7], [4,7]]]
185+
], function (i, params) {
186+
187+
// Each of these tests uses a fixture with two highlighted chunks.
188+
var id = params[0];
189+
var sels = params[1];
190+
191+
module("Select line or chunk - " + id, {
192+
setup: function () {
193+
build_fixture(id);
194+
}
195+
});
196+
197+
$.each(sels, function (i, sel) {
198+
i++;
199+
test("Select line " + i, function () {
200+
coverage.select_line_or_chunk(i);
201+
raw_selection_is(sel);
202+
});
203+
});
204+
});

0 commit comments

Comments
 (0)