diff options
author | J. M. F. Tsang <j.m.f.tsang@cantab.net> | 2022-04-22 00:32:11 +0100 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2022-05-19 12:40:23 -0400 |
commit | 5b2e525e4cf635db5c8149850fbd0732236b9711 (patch) | |
tree | d74de8eb15e256629d68883fca1fd59f9825afa1 /coverage/html.py | |
parent | 114b7625a1a90d669141bdf50825071a5500db38 (diff) | |
download | python-coveragepy-git-5b2e525e4cf635db5c8149850fbd0732236b9711.tar.gz |
feat: more html keyboard shortcuts
On each page the shortcuts '[' and ']' will take you to the previous and
next files respectively. On the index page they take you to the final
and first files respectively.
Pressing 'u' while on a file will now take you back to index.html, like
on Gerrit.
'?' opens and closes the help panel.
Test cases:
$ pytest --cov-report html --cov=. tests.py
in a directory with just tests.py, then with one, two or three .py
files.
Tested on Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:99.0) Gecko/20100101 Firefox/99.0
Diffstat (limited to 'coverage/html.py')
-rw-r--r-- | coverage/html.py | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/coverage/html.py b/coverage/html.py index e18a30a1..953b2db3 100644 --- a/coverage/html.py +++ b/coverage/html.py @@ -165,6 +165,8 @@ class HtmlReporter: self.datagen = HtmlDataGeneration(self.coverage) self.totals = Numbers(precision=self.config.precision) self.directory_was_empty = False + self.first_fr = None + self.final_fr = None self.template_globals = { # Functions available in the templates. @@ -204,9 +206,29 @@ class HtmlReporter: self.incr.read() self.incr.check_global_data(self.config, self.pyfile_html_source) - # Process all the files. - for fr, analysis in get_analysis_to_report(self.coverage, morfs): - self.html_file(fr, analysis) + # Process all the files. For each page we need to supply a link + # to the next page. Therefore in each iteration of the loop we + # work on the fr and analysis from the previous iteration. We + # also need a link to the preceding page (i.e. 2 before the + # current iteration). + analysis_to_report = get_analysis_to_report(self.coverage, morfs) + pluprev_fr, prev_fr = None, None + prev_analysis = None + + for fr, analysis in analysis_to_report: + if prev_fr is not None: + self.html_file(prev_fr, prev_analysis, pluprev_fr, fr) + else: + # This is the first file processed + self.first_fr = fr + pluprev_fr, prev_fr, prev_analysis = prev_fr, fr, analysis + + # One more iteration for the final file. (Or not, if there are + # no files at all.) + if prev_fr is not None: + self.html_file(prev_fr, prev_analysis, pluprev_fr, None) + # This is the last file processed + self.final_fr = prev_fr if not self.all_files_nums: raise NoDataError("No data to report.") @@ -236,10 +258,21 @@ class HtmlReporter: if self.extra_css: shutil.copyfile(self.config.extra_css, os.path.join(self.directory, self.extra_css)) - def html_file(self, fr, analysis): - """Generate an HTML file for one source file.""" + def html_file(self, fr, analysis, prev_fr=None, next_fr=None): + """Generate an HTML file for one source file, with links to the + previous and the next file, or to the index.""" rootname = flat_rootname(fr.relative_filename()) html_filename = rootname + ".html" + if prev_fr is not None: + prev_html = flat_rootname(prev_fr.relative_filename()) + ".html" + else: + prev_html = "index.html" + + if next_fr is not None: + next_html = flat_rootname(next_fr.relative_filename()) + ".html" + else: + next_html = "index.html" + ensure_dir(self.directory) if not os.listdir(self.directory): self.directory_was_empty = True @@ -316,7 +349,11 @@ class HtmlReporter: css_classes.append(self.template_globals['category'][ldata.category]) ldata.css_class = ' '.join(css_classes) or "pln" - html = self.source_tmpl.render(file_data.__dict__) + html = self.source_tmpl.render({ + **file_data.__dict__, + 'prev_html': prev_html, + 'next_html': next_html, + }) write_html(html_path, html) # Save this file's information for the index file. @@ -340,11 +377,23 @@ class HtmlReporter: n = self.skipped_empty_count skipped_empty_msg = f"{n} empty file{plural(n)} skipped." + if self.first_fr is not None: + first_html = flat_rootname(self.first_fr.relative_filename()) + ".html" + else: + first_html = "index.html" + + if self.final_fr is not None: + final_html = flat_rootname(self.final_fr.relative_filename()) + ".html" + else: + final_html = "index.html" + html = index_tmpl.render({ 'files': self.file_summaries, 'totals': self.totals, 'skipped_covered_msg': skipped_covered_msg, 'skipped_empty_msg': skipped_empty_msg, + 'first_html': first_html, + 'final_html': final_html, }) index_file = os.path.join(self.directory, "index.html") |