Skip to content

Commit

Permalink
add html reporter
Browse files Browse the repository at this point in the history
  • Loading branch information
aslilac committed May 12, 2024
1 parent b7e7c5c commit 6da27e3
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 21 deletions.
10 changes: 10 additions & 0 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ pub struct Color {
}

impl Color {
pub fn hex(&self) -> String {
format!("#{:02x}{:02x}{:02x}", self.r, self.g, self.b)
}

pub fn color<T>(&self, t: T) -> String
where
T: Colorize,
Expand Down Expand Up @@ -59,4 +63,10 @@ mod tests {
}
);
}

#[test]
fn hex() {
assert_eq!(Color::from([0, 0, 0]).hex(), "#000000");
assert_eq!(Color::from(0xbeeeef).hex(), "#beeeef");
}
}
4 changes: 4 additions & 0 deletions src/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ usage: kc [options] [directory]
include hidden files and directories
-A
include ignored files and directories
--blame
list all of the files for each language
-t, --top [number]
only show the top few languages
-x, --exclude [name | extension]
exclude a language based on name or file extension
-o, --only [name | extension]
only include the languages specified
-l, --lines
only report the total number of lines in all files
--reporter [name]
Expand Down
11 changes: 1 addition & 10 deletions src/langs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,7 @@ impl Language {
impl Display for Language {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let info = LanguageInfo::from(self);

write!(
f,
"{} {}",
info
.color
.map(|color| color.color("●"))
.unwrap_or_else(|| "●".to_string()),
&info.name
)
write!(f, "{}", &info.name)
}
}

Expand Down
16 changes: 12 additions & 4 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ where
println!("{}", include_str!("./help.txt"));
exit(0);
}
"-reporter" | "--reporter" => {
"-O" | "-reporter" | "--reporter" => {
options.reporter = args
.next()
.expect(&format!("expected a reporter to follow {} flag", arg))
Expand Down Expand Up @@ -105,7 +105,7 @@ where
.expect(&format!("unable to parse \"{}\" as a number", arg))
.into();
}
"-x" | "-exclude" | "--exclude" => {
"-x" | "-exclude" | "--exclude" | "-ignore" | "--ignore" => {
let exclusions = args.next();
let list = exclusions
.as_ref()
Expand Down Expand Up @@ -140,14 +140,14 @@ where
options.reporter = TotalLines;
}
_ => {
println!("unrecognized option: {}", arg);
eprintln!("unrecognized option: {}", arg);
exit(1);
}
}
}

if !options.only_include.is_empty() && !options.excluded.is_empty() {
println!("warning: both --only and --exclude have been set, which doesn't really make sense")
eprintln!("warning: both --only and --exclude have been set, which doesn't really make sense")
}

options
Expand Down Expand Up @@ -254,5 +254,13 @@ mod tests {
..Default::default()
},
);

assert_eq!(
["-O", "html"].into_iter().collect::<Options>(),
Options {
reporter: Reporter::Html,
..Default::default()
},
);
}
}
5 changes: 4 additions & 1 deletion src/reporters.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::str::FromStr;

pub mod html;
pub mod terminal;
pub mod total_lines;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Reporter {
Html,
Terminal,
TotalLines,
}
Expand All @@ -14,6 +16,7 @@ impl FromStr for Reporter {

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_ref() {
"html" => Ok(Self::Html),
"terminal" => Ok(Self::Terminal),
"total" | "total_lines" | "total-lines" | "totalLines" => Ok(Self::TotalLines),
_ => Err(()),
Expand All @@ -23,6 +26,6 @@ impl FromStr for Reporter {

impl Reporter {
pub fn help() -> &'static str {
"\"terminal\", \"total-lines\""
"\"html\", \"terminal\", \"total-lines\""
}
}
86 changes: 86 additions & 0 deletions src/reporters/html.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use crate::color::Color;
use crate::langs::Language;
use crate::langs::LanguageInfo;
use crate::langs::LanguageSummary;
use crate::options::Options;

pub struct HtmlReporter;

const ROW_STYLES: &str = include_str!("./html_reporter.css");

impl HtmlReporter {
pub fn report(
summaries: Vec<(Language, LanguageSummary)>,
options: Options,
) -> anyhow::Result<()> {
print!("<!doctype html>\n");
print!(
"<html>\n<head>\n<title>kc — {}</title>\n<style>\n{}</style>\n</head>\n",
options.root_dir.display(),
ROW_STYLES
);
print!("<body>\n\n");

// The bar
let total_lines = summaries
.iter()
.map(|(_, summary)| summary.lines)
.sum::<usize>();
let mut remaining_lines = total_lines;
let total_lines = total_lines as f32;

println!("<div aria-hidden class=\"bar\">");
{
for (_, stat) in summaries.iter() {
// If there are 0 total lines, then just say everything is 0%.
let percent = stat.lines as f32 / total_lines;
if percent.is_nan() || percent < 0.02 {
break;
}

remaining_lines -= stat.lines;

let lang = LanguageInfo::from(&stat.language);
let color = lang
.color
.as_ref()
.map(Color::hex)
.unwrap_or("gray".to_string());

println!(
"\t<div aria-hidden title=\"{}\" style=\"background-color: {}; flex-grow: {}\"></div>",
lang.name, color, stat.lines,
);
}

println!(
"\t<div aria-hidden style=\"background-color: gray; flex-grow: {}\"></div>",
remaining_lines,
);
}
print!("</div>\n\n");

print!(
"<table>\n\
<colgroup><col /><col width=\"15%\" /><col width=\"15%\" /></colgroup>\n\
<th>Language</th><th>Lines</th><th>Blank</th>\n"
);

for (_, stat) in summaries.iter() {
let lang = LanguageInfo::from(&stat.language);
let color = lang
.color
.as_ref()
.map(Color::hex)
.unwrap_or("gray".to_string());
println!(
"\t<tr><td><span style=\"color: {}\">●</span>&nbsp;{}</td><td>{}</td><td>{}</td></tr>",
color, stat.language, stat.lines, stat.blank_lines
);
}
print!("</table>\n\n");

print!("</body>\n</html>\n");
Ok(())
}
}
46 changes: 46 additions & 0 deletions src/reporters/html_reporter.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
:root {
font-family: Avenir, Montserrat, Corbel, "URW Gothic", source-sans-pro, sans-serif;
font-weight: normal;
}

body {
margin: 0 auto;
padding: 48px 24px 24px;
max-width: 968px;
}

.bar {
display: flex;
gap: 2px;
border-radius: 10px;
height: 10px;
overflow: hidden;
margin-bottom: 32px;
}

.bar > * {
flex-basis: 0;
}

table {
width: 100%;
}

th {
font-size: 1.2em;
}

th:first-of-type,
td:first-of-type {
text-align: left;
}

th,
td {
text-align: right;
}

td {
border-bottom: 1px dotted black;
padding: 0.2em 0;
}
25 changes: 19 additions & 6 deletions src/reporters/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ impl TerminalReporter {
)
}

let total_lines = summaries
.iter()
.map(|(_, summary)| summary.lines)
.reduce(|acc, lines| acc + lines)
.ok_or_else(|| anyhow!("no code found in \"{}\"", dir_path.display()))?;
let total_lines = summaries.iter().map(|(_, summary)| summary.lines).sum();

if total_lines == 0 {
println!(" no code found in {}", dir_path.display());
return Ok(());
}

let mut filled = 0;

Expand Down Expand Up @@ -102,7 +103,19 @@ impl<'a, 'b> Display for TerminalLanguageSummary<'a, 'b> {
let inlay = format!("{:.>width$}", "", width = width)
.bright_black()
.to_string();
write!(f, "{} {} {}", summary.language, inlay, right_side)?;

let info = LanguageInfo::from(&summary.language);
write!(
f,
"{} {} {} {}",
info
.color
.map(|color| color.color("●"))
.unwrap_or_else(|| "●".to_string()),
info.name,
inlay,
right_side
)?;

if options.blame {
let mut files = summary.files.iter().peekable();
Expand Down
2 changes: 2 additions & 0 deletions src/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::fc::FileContent;
use crate::langs::Language;
use crate::langs::LanguageSummary;
use crate::options::Options;
use crate::reporters::html::HtmlReporter;
use crate::reporters::terminal::TerminalReporter;
use crate::reporters::total_lines::TotalLinesReporter;
use crate::reporters::Reporter::*;
Expand Down Expand Up @@ -77,6 +78,7 @@ pub fn scan(options: Options) -> anyhow::Result<()> {
}

match options.reporter {
Html => HtmlReporter::report(summaries, options),
Terminal => TerminalReporter::report(summaries, options),
TotalLines => TotalLinesReporter::report(summaries, options),
}
Expand Down

0 comments on commit 6da27e3

Please sign in to comment.