diff --git a/assets/index.css b/assets/index.css index 59152c4..69d6301 100644 --- a/assets/index.css +++ b/assets/index.css @@ -130,6 +130,14 @@ @apply bg-red-400 hover:bg-red-500 dark:bg-red-800 dark:hover:bg-red-700; } + .gutter.covered { + @apply bg-green-400 dark:bg-green-800 !important; + } + + .gutter.uncovered { + @apply bg-red-400 dark:bg-red-800 !important; + } + .page-footer { @apply text-sm font-bold pl-4 pt-4; } diff --git a/src/cli.rs b/src/cli.rs index c4b506b..589b500 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,12 +1,13 @@ //! Handling of command line arguments. use std::{ + fmt::{self, Display}, fs::OpenOptions, io::{self, BufWriter, Write}, }; use camino::{Utf8Path, Utf8PathBuf}; -use clap::{CommandFactory, Parser, Subcommand, ValueHint}; +use clap::{CommandFactory, Parser, Subcommand, ValueEnum, ValueHint}; use clap_complete::Shell; use color_eyre::eyre::{ensure, Result, WrapErr}; @@ -24,6 +25,9 @@ pub struct Cli { /// The highlighting theme to use, if not disabled. #[arg(long, default_value_t = Theme::OneHalf)] pub theme: Theme, + /// Where to place the coverage color marker. + #[arg(long, default_value_t = CoverageStyle::Line)] + pub coverage_style: CoverageStyle, /// Location of the project's Cargo.toml, in case the default detection isn't sufficient. #[arg(long)] pub manifest_path: Option, @@ -40,6 +44,24 @@ impl Cli { } } +/// The way in which to mark source code lines as covered or uncovered. +#[derive(Clone, Copy, Eq, PartialEq, ValueEnum)] +pub enum CoverageStyle { + /// Highlight the whole source line. + Line, + /// Only highlight the gutter (count column). + Gutter, +} + +impl Display for CoverageStyle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Self::Line => "line", + Self::Gutter => "gutter", + }) + } +} + #[derive(Subcommand)] pub enum Command { /// Generate auto-completions scripts for various shells. diff --git a/src/main.rs b/src/main.rs index 16438c1..c3413fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -115,6 +115,7 @@ fn main() -> Result<()> { base_dir: &"../".repeat(file.relative_path.ancestors().skip(2).count()), lines: &lines, info: &file, + coverage_style: cli.coverage_style, show_instantiations: cli.show_instantiations, } .render()? diff --git a/src/templates.rs b/src/templates.rs index 78577bb..293888f 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -6,7 +6,7 @@ use askama::Template; use camino::Utf8PathBuf; use time::OffsetDateTime; -use crate::schema; +use crate::{cli::CoverageStyle, schema}; /// Global constant instance with this project's info, so it doesn't have to be included as part of /// each template struct. @@ -62,6 +62,7 @@ pub struct Source<'a> { pub base_dir: &'a str, pub lines: &'a [String], pub info: &'a FileInfo, + pub coverage_style: CoverageStyle, pub show_instantiations: bool, } @@ -148,8 +149,7 @@ mod tests { use camino::Utf8PathBuf; use time::OffsetDateTime; - use super::FileInfo; - use crate::schema; + use super::{schema, CoverageStyle, FileInfo}; #[test] fn render_index() { @@ -187,6 +187,7 @@ mod tests { called: HashMap::default(), uncalled: HashMap::default(), }, + coverage_style: CoverageStyle::Line, show_instantiations: true, } .render() diff --git a/templates/source.html b/templates/source.html index 9b256e9..29bcad7 100644 --- a/templates/source.html +++ b/templates/source.html @@ -45,17 +45,9 @@ {{loop.index}} - - {% match self.get_coverage(loop.index) %} - {% when Coverage::Covered(count) %} - {{count}} - {% when Coverage::Uncovered(count) %} - {{count}} - {% when Coverage::Unknown %} - {% endmatch %} - + {% let coverage = self.get_coverage(loop.index) %} {% let class %} - {% match self.get_coverage(loop.index) %} + {% match coverage %} {% when Coverage::Covered(_) %} {% let class = "covered" %} {% when Coverage::Uncovered(_) %} @@ -63,7 +55,16 @@ {% when Coverage::Unknown %} {% let class = "" %} {% endmatch %} - + + {% match coverage %} + {% when Coverage::Covered(count) %} + {{count}} + {% when Coverage::Uncovered(count) %} + {{count}} + {% when Coverage::Unknown %} + {% endmatch %} + +
{{line|safe}}
{% if show_instantiations %} {% if let Some(functions) = self.info.uncalled.get(loop.index) %}