Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stats reporting for directories #1055

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ src/test
results.csv
node_modules
*.code-workspace
/.idea
11 changes: 11 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub struct Cli {
pub columns: Option<usize>,
pub files: bool,
pub hidden: bool,
pub include_dirs: bool,
pub no_ignore: bool,
pub no_ignore_parent: bool,
pub no_ignore_dot: bool,
Expand Down Expand Up @@ -103,6 +104,14 @@ impl Cli {
.long("hidden")
.help("Count hidden files."),
)
.arg(
Arg::new("include_dirs")
.long("include-dirs")
.conflicts_with("streaming")
.help(
"Include directories in the final report.",
),
)
.arg(
Arg::new("input")
.min_values(1)
Expand Down Expand Up @@ -220,6 +229,7 @@ impl Cli {
let columns = matches.value_of("columns").map(parse_or_exit::<usize>);
let files = matches.is_present("files");
let hidden = matches.is_present("hidden");
let include_dirs = matches.is_present("include_dirs");
let no_ignore = matches.is_present("no_ignore");
let no_ignore_parent = matches.is_present("no_ignore_parent");
let no_ignore_dot = matches.is_present("no_ignore_dot");
Expand Down Expand Up @@ -270,6 +280,7 @@ impl Cli {
columns,
files,
hidden,
include_dirs,
no_ignore,
no_ignore_parent,
no_ignore_dot,
Expand Down
2 changes: 1 addition & 1 deletion src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ mod tests {
// Get language results from sample dir
let data_dir = Path::new("tests").join("data");
let mut langs = Languages::new();
langs.get_statistics(&[data_dir], &[], &Config::default());
langs.get_statistics(&[data_dir], &[], &Config::default(), false);

// Check that the value matches after serializing and deserializing
for variant in Format::iter() {
Expand Down
11 changes: 9 additions & 2 deletions src/language/languages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl Languages {
/// use tokei::{Config, Languages};
///
/// let mut languages = Languages::new();
/// languages.get_statistics(&["."], &[".git", "target"], &Config::default());
/// languages.get_statistics(&["."], &[".git", "target"], &Config::default(), false);
/// ```
///
/// [`Language`]: struct.Language.html
Expand All @@ -81,9 +81,16 @@ impl Languages {
paths: &[A],
ignored: &[&str],
config: &Config,
include_dirs: bool,
) {
utils::fs::get_all_files(paths, ignored, &mut self.inner, config);
self.inner.par_iter_mut().for_each(|(_, l)| l.total());
self.inner.par_iter_mut().for_each(|(_, l)| {
l.total();

if include_dirs {
l.dirs();
}
});
}

/// Constructs a new, Languages struct. Languages is always empty and does
Expand Down
54 changes: 53 additions & 1 deletion src/language/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub mod language_type;
pub mod languages;
mod syntax;

use std::{collections::BTreeMap, mem, ops::AddAssign};
use std::{collections::BTreeMap, collections::HashMap, mem, ops::AddAssign, path::Path};

pub use self::{language_type::*, languages::Languages};

Expand Down Expand Up @@ -83,6 +83,58 @@ impl Language {
summary
}

/// Generates stats for directories and their child directories.
///
/// ```no_run
/// use tokei::Language;
///
/// let mut language = Language::new();
///
/// // Add stats, assuming 10 directories are on the path afterward...
///
/// // Compute totals.
/// language.total();
///
/// let reports = language.reports.len();
///
/// language.dirs();
///
/// assert_eq!(reports + 10, language.reports.len());
/// ```
pub fn dirs(&mut self) {
let empty = Path::new("");

let reports: Vec<Report> = {
let mut dir_reports = HashMap::new();

for child_report in &self.reports {
let mut path = child_report.name.as_path();
while let Some(dir) = path.parent() {
path = dir;
if path == empty {
continue;
}

let dir_report = dir_reports
.entry(path)
.or_insert_with(|| {
let mut report = Report::default();
report.name = path.to_path_buf();
report
});

dir_report.stats.comments += child_report.stats.comments;
dir_report.stats.code += child_report.stats.code;
dir_report.stats.blanks += child_report.stats.blanks;
}
}

dir_reports.into_values().collect()
};

self.reports.extend(reports);
}

/// Totals up the statistics of the `Stat` structs currently contained in
/// the language.
///
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
//! let config = Config::default();
//!
//! let mut languages = Languages::new();
//! languages.get_statistics(paths, excluded, &config);
//! languages.get_statistics(paths, excluded, &config, false);
//! let rust = &languages[&LanguageType::Rust];
//!
//! println!("Lines of code: {}", rust.code);
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fn main() -> Result<(), Box<dyn Error>> {
);
}

languages.get_statistics(&input, &cli.ignored_directories(), &config);
languages.get_statistics(&input, &cli.ignored_directories(), &config, cli.include_dirs);
if config.for_each_fn.is_some() {
process::exit(0);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/accuracy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ mod config {
..Config::default()
};

languages.get_statistics(&["tests/data/python.py"], &[], &config);
languages.get_statistics(&["tests/data/python.py"], &[], &config, false);

if languages.len() != 1 {
panic!(
Expand Down