mirror of
https://github.com/XAMPPRocky/tokei
synced 2024-09-13 21:11:29 +00:00
Merge pull request #17 from Aaronepower/RefCell
Added support for multiple file extensions
This commit is contained in:
commit
c06871b56f
201
src/language.rs
201
src/language.rs
|
@ -4,118 +4,119 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Language<'a> {
|
||||
pub name: &'a str,
|
||||
pub line_comment: &'a str,
|
||||
pub multi_line: &'a str,
|
||||
pub multi_line_end: &'a str,
|
||||
pub files: Vec<String>,
|
||||
pub code: usize,
|
||||
pub comments: usize,
|
||||
pub blanks: usize,
|
||||
pub lines: usize,
|
||||
pub total: usize,
|
||||
pub size: usize,
|
||||
pub name: &'a str,
|
||||
pub line_comment: &'a str,
|
||||
pub multi_line: &'a str,
|
||||
pub multi_line_end: &'a str,
|
||||
pub files: Vec<String>,
|
||||
pub code: usize,
|
||||
pub comments: usize,
|
||||
pub blanks: usize,
|
||||
pub lines: usize,
|
||||
pub total: usize,
|
||||
pub printed: bool,
|
||||
}
|
||||
|
||||
|
||||
impl<'a> Language<'a> {
|
||||
pub fn new<'b>(name: &'a str,
|
||||
line_comment: &'a str,
|
||||
multi_line: &'a str,
|
||||
multi_line_end: &'a str) -> Language<'a> {
|
||||
pub fn new<'b>(name: &'a str,
|
||||
line_comment: &'a str,
|
||||
multi_line: &'a str,
|
||||
multi_line_end: &'a str) -> Language<'a> {
|
||||
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: line_comment,
|
||||
multi_line: multi_line,
|
||||
multi_line_end: multi_line_end,
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: line_comment,
|
||||
multi_line: multi_line,
|
||||
multi_line_end: multi_line_end,
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
printed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_c(name: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: "//",
|
||||
multi_line: "/*",
|
||||
multi_line_end: "*/",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
pub fn new_c(name: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: "//",
|
||||
multi_line: "/*",
|
||||
multi_line_end: "*/",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
printed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_html(name: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: "<!--",
|
||||
multi_line: "<!--",
|
||||
multi_line_end: "-->",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
pub fn new_html(name: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: "<!--",
|
||||
multi_line: "<!--",
|
||||
multi_line_end: "-->",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
printed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_blank(name: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: "",
|
||||
multi_line: "",
|
||||
multi_line_end: "",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
pub fn new_blank(name: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: "",
|
||||
multi_line: "",
|
||||
multi_line_end: "",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
printed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_single(name: &'a str, line_comment: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: line_comment,
|
||||
multi_line: "",
|
||||
multi_line_end: "",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
pub fn new_single(name: &'a str, line_comment: &'a str) -> Language<'a> {
|
||||
Language {
|
||||
name: name,
|
||||
line_comment: line_comment,
|
||||
multi_line: "",
|
||||
multi_line_end: "",
|
||||
files: Vec::new(),
|
||||
code: 0,
|
||||
comments: 0,
|
||||
blanks: 0,
|
||||
lines: 0,
|
||||
total: 0,
|
||||
printed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.code == 0 && self.comments == 0 && self.blanks == 0 && self.lines == 0
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.code == 0 && self.comments == 0 && self.blanks == 0 && self.lines == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Language<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let total = if self.total == 0 {
|
||||
self.files.len()
|
||||
} else {
|
||||
self.total
|
||||
};
|
||||
write!(f," {: <15} {: >15} {:>15} {:>15} {:>15} {:>15}", self.name, total, self.lines, self.blanks, self.comments, self.code)
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let total = if self.total == 0 {
|
||||
self.files.len()
|
||||
} else {
|
||||
self.total
|
||||
};
|
||||
write!(f," {: <15} {: >15} {:>15} {:>15} {:>15} {:>15}", self.name, total, self.lines, self.blanks, self.comments, self.code)
|
||||
}
|
||||
}
|
||||
|
|
444
src/main.rs
444
src/main.rs
|
@ -10,6 +10,8 @@ pub mod macros;
|
|||
pub mod language;
|
||||
pub mod fsutil;
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
|
@ -23,188 +25,282 @@ use fsutil::{get_all_files, contains_comments};
|
|||
static ROW: &'static str = "--------------------------------------------------------------------------------------------------";
|
||||
|
||||
fn main() {
|
||||
let yaml = load_yaml!("../cli.yml");
|
||||
let matches = App::from_yaml(yaml).get_matches();
|
||||
let yaml = load_yaml!("../cli.yml");
|
||||
let matches = App::from_yaml(yaml).get_matches();
|
||||
|
||||
let mut languages: BTreeMap<&str, Language> = BTreeMap::new();
|
||||
languages.insert("as" , Language::new_c("ActionScript"));
|
||||
languages.insert("c" , Language::new_c("C"));
|
||||
languages.insert("cs" , Language::new_c("C#"));
|
||||
languages.insert("clj" , Language::new_single("Clojure", ";,#,#_"));
|
||||
languages.insert("coffee" , Language::new("CoffeeScript", "#", "###", "###"));
|
||||
languages.insert("cfm" , Language::new("ColdFusion", "<!---", "<!---", "--->"));
|
||||
languages.insert("cfc" , Language::new_c("ColdFusion CFScript"));
|
||||
languages.insert("cpp" , Language::new_c("C++"));
|
||||
languages.insert("css" , Language::new_c("CSS"));
|
||||
languages.insert("d" , Language::new_c("D"));
|
||||
languages.insert("dart" , Language::new_c("Dart"));
|
||||
languages.insert("el" , Language::new("LISP", ";", "#|", "|#"));
|
||||
languages.insert("f" , Language::new_single("FORTRAN Legacy", "c,C,!,*"));
|
||||
languages.insert("f90" , Language::new_single("FORTRAN Modern", "!"));
|
||||
languages.insert("go" , Language::new_c("Go"));
|
||||
languages.insert("h" , Language::new_c("C Header"));
|
||||
languages.insert("hs" , Language::new_single("Haskell", "--"));
|
||||
languages.insert("hpp" , Language::new_c("C++ Header"));
|
||||
languages.insert("html" , Language::new_html("HTML"));
|
||||
languages.insert("java" , Language::new_c("Java"));
|
||||
languages.insert("js" , Language::new_c("JavaScript"));
|
||||
languages.insert("jl" , Language::new("Julia", "#", "#=", "=#"));
|
||||
languages.insert("json" , Language::new_blank("JSON"));
|
||||
languages.insert("jsx" , Language::new_c("JSX"));
|
||||
languages.insert("less" , Language::new_c("LESS"));
|
||||
languages.insert("m" , Language::new_c("Objective-C"));
|
||||
languages.insert("md" , Language::new_blank("Markdown"));
|
||||
languages.insert("mm" , Language::new_c("Objective-C++"));
|
||||
languages.insert("php" , Language::new("PHP", "#,//","/*","*/"));
|
||||
languages.insert("pas" , Language::new("Pascal", "//,(*","{","}"));
|
||||
languages.insert("pl" , Language::new("Perl", "#","=","=cut"));
|
||||
languages.insert("py" , Language::new("Python", "#","'''","'''"));
|
||||
languages.insert("rs" , Language::new("Rust", "//,///,//!", "/*", "*/"));
|
||||
languages.insert("r" , Language::new("R", "#","",""));
|
||||
languages.insert("rb" , Language::new("Ruby", "#","=begin","=end"));
|
||||
languages.insert("rhtml" , Language::new_html("Ruby HTML"));
|
||||
languages.insert("sass" , Language::new_c("Sass"));
|
||||
languages.insert("sh" , Language::new_single("BASH", "#"));
|
||||
languages.insert("sql" , Language::new("SQL", "--", "/*", "*/"));
|
||||
languages.insert("swift" , Language::new_c("Swift"));
|
||||
languages.insert("toml" , Language::new_single("TOML", "#"));
|
||||
languages.insert("ts" , Language::new_c("TypeScript"));
|
||||
languages.insert("xml" , Language::new_html("XML"));
|
||||
languages.insert("yml" , Language::new_single("YAML", "#"));
|
||||
let action_script = Rc::new(RefCell::new(Language::new_c("ActionScript")));
|
||||
let bash = Rc::new(RefCell::new(Language::new_single("BASH", "#")));
|
||||
let batch = Rc::new(RefCell::new(Language::new_single("Batch", "REM")));
|
||||
let c = Rc::new(RefCell::new(Language::new_c("C")));
|
||||
let c_header = Rc::new(RefCell::new(Language::new_c("C Header")));
|
||||
let c_sharp = Rc::new(RefCell::new(Language::new_c("C#")));
|
||||
let clojure = Rc::new(RefCell::new(Language::new_single("Clojure", ";,#,#_")));
|
||||
let coffee_script = Rc::new(RefCell::new(Language::new("CoffeeScript", "#", "###", "###")));
|
||||
let cold_fusion = Rc::new(RefCell::new(Language::new("ColdFusion", "<!---", "<!---", "--->")));
|
||||
let cf_script = Rc::new(RefCell::new(Language::new_c("ColdFusion CFScript")));
|
||||
let cpp = Rc::new(RefCell::new(Language::new_c("C++")));
|
||||
let cpp_header = Rc::new(RefCell::new(Language::new_c("C++ Header")));
|
||||
let css = Rc::new(RefCell::new(Language::new_c("CSS")));
|
||||
let d = Rc::new(RefCell::new(Language::new_c("D")));
|
||||
let dart = Rc::new(RefCell::new(Language::new_c("Dart")));
|
||||
let lisp = Rc::new(RefCell::new(Language::new("LISP", ";", "#|", "|#")));
|
||||
let fortran_legacy = Rc::new(RefCell::new(Language::new_single("FORTRAN Legacy", "c,C,!,*")));
|
||||
let fortran_modern = Rc::new(RefCell::new(Language::new_single("FORTRAN Modern", "!")));
|
||||
let go = Rc::new(RefCell::new(Language::new_c("Go")));
|
||||
let haskell = Rc::new(RefCell::new(Language::new_single("Haskell", "--")));
|
||||
let html = Rc::new(RefCell::new(Language::new_html("HTML")));
|
||||
let java = Rc::new(RefCell::new(Language::new_c("Java")));
|
||||
let java_script = Rc::new(RefCell::new(Language::new_c("JavaScript")));
|
||||
let julia = Rc::new(RefCell::new(Language::new("Julia", "#", "#=", "=#")));
|
||||
let json = Rc::new(RefCell::new(Language::new_blank("JSON")));
|
||||
let jsx = Rc::new(RefCell::new(Language::new_c("JSX")));
|
||||
let less = Rc::new(RefCell::new(Language::new_c("LESS")));
|
||||
let markdown = Rc::new(RefCell::new(Language::new_blank("Markdown")));
|
||||
let objective_c = Rc::new(RefCell::new(Language::new_c("Objective-C")));
|
||||
let objective_cpp = Rc::new(RefCell::new(Language::new_c("Objective-C++")));
|
||||
let php = Rc::new(RefCell::new(Language::new("PHP", "#,//","/*","*/")));
|
||||
let pascal = Rc::new(RefCell::new(Language::new("Pascal", "//,(*","{","}")));
|
||||
let perl = Rc::new(RefCell::new(Language::new("Perl", "#","=","=cut")));
|
||||
let python = Rc::new(RefCell::new(Language::new("Python", "#","'''","'''")));
|
||||
let r = Rc::new(RefCell::new(Language::new("R", "#","","")));
|
||||
let ruby = Rc::new(RefCell::new(Language::new("Ruby", "#","=begin","=end")));
|
||||
let ruby_html = Rc::new(RefCell::new(Language::new_html("Ruby HTML")));
|
||||
let rust = Rc::new(RefCell::new(Language::new("Rust", "//,///,//!", "/*", "*/")));
|
||||
let sass = Rc::new(RefCell::new(Language::new_c("Sass")));
|
||||
let sql = Rc::new(RefCell::new(Language::new("SQL", "--", "/*", "*/")));
|
||||
let swift = Rc::new(RefCell::new(Language::new_c("Swift")));
|
||||
let toml = Rc::new(RefCell::new(Language::new_single("TOML", "#")));
|
||||
let type_script = Rc::new(RefCell::new(Language::new_c("TypeScript")));
|
||||
let xml = Rc::new(RefCell::new(Language::new_html("XML")));
|
||||
let yaml = Rc::new(RefCell::new(Language::new_single("YAML", "#")));
|
||||
|
||||
if matches.is_present("languages") {
|
||||
for (ext, language) in languages {
|
||||
println!("{:<25} ({})", language.name, ext);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let mut languages: BTreeMap<&str, &Rc<RefCell<Language>>> = BTreeMap::new();
|
||||
languages.insert("as" , &action_script);
|
||||
languages.insert("bat" , &batch);
|
||||
languages.insert("btm" , &batch);
|
||||
languages.insert("cmd" , &batch);
|
||||
languages.insert("bash" , &bash);
|
||||
languages.insert("sh" , &bash);
|
||||
languages.insert("c" , &c);
|
||||
languages.insert("ec" , &c);
|
||||
languages.insert("pgc" , &c);
|
||||
languages.insert("cs" , &c_sharp);
|
||||
languages.insert("clj" , &clojure);
|
||||
languages.insert("coffee" , &coffee_script);
|
||||
languages.insert("cfm" , &cold_fusion);
|
||||
languages.insert("cfc" , &cf_script);
|
||||
languages.insert("cc" , &cpp);
|
||||
languages.insert("cpp" , &cpp);
|
||||
languages.insert("cxx" , &cpp);
|
||||
languages.insert("pcc" , &cpp);
|
||||
languages.insert("c++" , &cpp);
|
||||
languages.insert("css" , &css);
|
||||
languages.insert("d" , &d);
|
||||
languages.insert("dart" , &dart);
|
||||
languages.insert("el" , &lisp);
|
||||
languages.insert("lisp" , &lisp);
|
||||
languages.insert("lsp" , &lisp);
|
||||
languages.insert("sc" , &lisp);
|
||||
languages.insert("f" , &fortran_legacy);
|
||||
languages.insert("f77" , &fortran_legacy);
|
||||
languages.insert("for" , &fortran_legacy);
|
||||
languages.insert("ftn" , &fortran_legacy);
|
||||
languages.insert("pfo" , &fortran_legacy);
|
||||
languages.insert("f90" , &fortran_modern);
|
||||
languages.insert("f95" , &fortran_modern);
|
||||
languages.insert("go" , &go);
|
||||
languages.insert("h" , &c_header);
|
||||
languages.insert("hs" , &haskell);
|
||||
languages.insert("hpp" , &cpp_header);
|
||||
languages.insert("hh" , &cpp_header);
|
||||
languages.insert("html" , &html);
|
||||
languages.insert("java" , &java);
|
||||
languages.insert("js" , &java_script);
|
||||
languages.insert("jl" , &julia);
|
||||
languages.insert("json" , &json);
|
||||
languages.insert("jsx" , &jsx);
|
||||
languages.insert("less" , &less);
|
||||
languages.insert("m" , &objective_c);
|
||||
languages.insert("md" , &markdown);
|
||||
languages.insert("mm" , &objective_cpp);
|
||||
languages.insert("php" , &php);
|
||||
languages.insert("pas" , &pascal);
|
||||
languages.insert("pl" , &perl);
|
||||
languages.insert("py" , &python);
|
||||
languages.insert("r" , &r);
|
||||
languages.insert("rake" , &ruby);
|
||||
languages.insert("rb" , &ruby);
|
||||
languages.insert("rhtml" , &ruby_html);
|
||||
languages.insert("rs" , &rust);
|
||||
languages.insert("sass" , &sass);
|
||||
languages.insert("scss" , &sass);
|
||||
languages.insert("sql" , &sql);
|
||||
languages.insert("swift" , &swift);
|
||||
languages.insert("toml" , &toml);
|
||||
languages.insert("ts" , &type_script);
|
||||
languages.insert("xml" , &xml);
|
||||
languages.insert("yaml" , &yaml);
|
||||
languages.insert("yml" , &yaml);
|
||||
|
||||
if matches.is_present("languages") {
|
||||
for (_, language) in languages.iter() {
|
||||
let ref language = language.borrow();
|
||||
println!("{:<25}", language.name);
|
||||
}
|
||||
}
|
||||
|
||||
let paths = matches.values_of("input").unwrap();
|
||||
|
||||
let mut ignored_directories: Vec<String> = Vec::new();
|
||||
|
||||
if let Some(user_ignored) = matches.value_of("exclude") {
|
||||
for ignored in user_ignored.split(",") {
|
||||
ignored_directories.push(ignored.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let mut sort = String::new();
|
||||
if let Some(sort_by) = matches.value_of("sort") {
|
||||
match &*sort_by.to_lowercase() {
|
||||
"files" | "total" | "blanks" | "comments" | "code" => sort.push_str(&*sort_by.to_lowercase()),
|
||||
_ => println!("--sort must be any of the following files, total, blanks, comments, code"),
|
||||
}
|
||||
}
|
||||
let sort_empty = sort.is_empty();
|
||||
|
||||
println!("{}", ROW);
|
||||
println!(" {:<15} {:>15} {:>15} {:>15} {:>15} {:>15}",
|
||||
"Language", "Files", "Total", "Blanks", "Comments", "Code");
|
||||
println!("{}", ROW);
|
||||
for path in paths {
|
||||
let files = get_all_files(path.to_owned(), &ignored_directories);
|
||||
for file in files {
|
||||
let extension = unwrap_opt_cont!(unwrap_opt_cont!(Path::new(&file).extension()).to_str());
|
||||
let lowercase: &str = &extension.to_lowercase();
|
||||
let language = unwrap_opt_cont!(languages.get_mut(lowercase));
|
||||
language.borrow_mut().files.push(file.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let mut total = Language::new_blank("Total");
|
||||
for (_, language) in &mut languages {
|
||||
if language.borrow().printed {
|
||||
continue;
|
||||
}
|
||||
let files = language.borrow_mut().files.clone();
|
||||
for file in files {
|
||||
|
||||
let mut contents = String::new();
|
||||
let is_fortran = language.borrow().name.contains("FORTRAN");
|
||||
let _ = unwrap_rs_cont!(unwrap_rs_cont!(File::open(&file)).read_to_string(&mut contents));
|
||||
|
||||
let mut is_in_comments = false;
|
||||
let lines = contents.lines();
|
||||
|
||||
'line: for line in lines {
|
||||
let line = if is_fortran {line} else {line.trim()};
|
||||
language.borrow_mut().lines += 1;
|
||||
|
||||
if line.trim().is_empty() {
|
||||
language.borrow_mut().blanks += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if !language.borrow().multi_line.is_empty() {
|
||||
let multi_line = language.borrow().multi_line;
|
||||
if line.starts_with(multi_line) {
|
||||
is_in_comments = true;
|
||||
} else if contains_comments(line, multi_line) {
|
||||
language.borrow_mut().code += 1;
|
||||
is_in_comments = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let paths = matches.values_of("input").unwrap();
|
||||
if is_in_comments {
|
||||
if line.contains(language.borrow().multi_line_end) {
|
||||
is_in_comments = false;
|
||||
}
|
||||
|
||||
let mut ignored_directories: Vec<String> = Vec::new();
|
||||
language.borrow_mut().comments += 1;
|
||||
continue;
|
||||
}
|
||||
let single_comments = language.borrow().line_comment.split(",");
|
||||
for single in single_comments {
|
||||
if line.starts_with(single) {
|
||||
language.borrow_mut().comments += 1;
|
||||
continue 'line;
|
||||
}
|
||||
}
|
||||
language.borrow_mut().code += 1;
|
||||
}
|
||||
}
|
||||
if !language.borrow().is_empty() {
|
||||
language.borrow_mut().printed = true;
|
||||
if sort_empty {
|
||||
println!("{}", *language.borrow());
|
||||
}
|
||||
}
|
||||
let language = language.borrow();
|
||||
|
||||
if let Some(user_ignored) = matches.value_of("exclude") {
|
||||
for ignored in user_ignored.split(",") {
|
||||
ignored_directories.push(ignored.to_owned());
|
||||
}
|
||||
}
|
||||
total.total += language.files.len();
|
||||
total.lines += language.lines;
|
||||
total.comments += language.comments;
|
||||
total.blanks += language.blanks;
|
||||
total.code += language.code;
|
||||
}
|
||||
|
||||
let mut sort = String::new();
|
||||
if let Some(sort_by) = matches.value_of("sort") {
|
||||
match &*sort_by.to_lowercase() {
|
||||
"files" | "total" | "blanks" | "comments" | "code" => sort.push_str(&*sort_by.to_lowercase()),
|
||||
_ => println!("--sort must be any of the following files, total, blanks, comments, code"),
|
||||
}
|
||||
}
|
||||
let sort_empty = sort.is_empty();
|
||||
if !sort_empty {
|
||||
let mut unsorted_vec:Vec<(&&str, &&Rc<RefCell<Language>>)> = languages.iter().collect();
|
||||
match &*sort {
|
||||
"files" => {
|
||||
unsorted_vec.sort_by(|a, b| {
|
||||
let ref a = *a.1.borrow();
|
||||
let ref b = *b.1.borrow();
|
||||
b.files.len().cmp(&a.files.len())
|
||||
})
|
||||
},
|
||||
"total" => {
|
||||
unsorted_vec.sort_by(|a, b| {
|
||||
let ref a = *a.1.borrow();
|
||||
let ref b = *b.1.borrow();
|
||||
b.lines.cmp(&a.lines)
|
||||
})
|
||||
},
|
||||
"blanks" => {
|
||||
unsorted_vec.sort_by(|a, b| {
|
||||
let ref a = *a.1.borrow();
|
||||
let ref b = *b.1.borrow();
|
||||
b.blanks.cmp(&a.blanks)
|
||||
})
|
||||
},
|
||||
"comments" => {
|
||||
unsorted_vec.sort_by(|a, b| {
|
||||
let ref a = *a.1.borrow();
|
||||
let ref b = *b.1.borrow();
|
||||
b.comments.cmp(&a.comments)
|
||||
})
|
||||
},
|
||||
"code" => {
|
||||
unsorted_vec.sort_by(|a, b| {
|
||||
let ref a = *a.1.borrow();
|
||||
let ref b = *b.1.borrow();
|
||||
b.code.cmp(&a.code)
|
||||
})
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
println!("{}", ROW);
|
||||
println!(" {:<15} {:>15} {:>15} {:>15} {:>15} {:>15}",
|
||||
"Language", "Files", "Total", "Blanks", "Comments", "Code");
|
||||
println!("{}", ROW);
|
||||
for path in paths {
|
||||
let files = get_all_files(path.to_owned(), &ignored_directories);
|
||||
for (_, language) in unsorted_vec {
|
||||
|
||||
for file in files {
|
||||
let extension = unwrap_opt_cont!(unwrap_opt_cont!(Path::new(&file).extension()).to_str());
|
||||
if !language.borrow().is_empty() && language.borrow().printed {
|
||||
language.borrow_mut().printed = false;
|
||||
println!("{}", *language.borrow());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let lowercase: &str = &extension.to_lowercase();
|
||||
|
||||
let mut language = unwrap_opt_cont!(languages.get_mut(lowercase));
|
||||
language.files.push(file.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let mut total = Language::new_blank("Total");
|
||||
|
||||
for (_, language) in &mut languages {
|
||||
|
||||
for file in language.files.iter() {
|
||||
|
||||
let mut contents = String::new();
|
||||
let is_fortran = language.name.contains("FORTRAN");
|
||||
let _ = unwrap_rs_cont!(unwrap_rs_cont!(File::open(&file)).read_to_string(&mut contents));
|
||||
|
||||
let mut is_in_comments = false;
|
||||
'line: for line in contents.lines() {
|
||||
let line = if is_fortran {line} else {line.trim()};
|
||||
language.lines += 1;
|
||||
|
||||
if line.trim().is_empty() {
|
||||
language.blanks += 1;
|
||||
continue;
|
||||
}
|
||||
if !language.multi_line.is_empty() {
|
||||
if line.starts_with(language.multi_line) {
|
||||
is_in_comments = true;
|
||||
} else if contains_comments(line, language.multi_line) {
|
||||
language.code += 1;
|
||||
is_in_comments = true;
|
||||
}
|
||||
}
|
||||
|
||||
if is_in_comments {
|
||||
if line.contains(language.multi_line_end) {
|
||||
is_in_comments = false;
|
||||
}
|
||||
language.comments += 1;
|
||||
continue;
|
||||
}
|
||||
if !language.line_comment.is_empty() {
|
||||
let single_comments = language.line_comment.split(",");
|
||||
for single in single_comments {
|
||||
if line.starts_with(single) {
|
||||
language.comments += 1;
|
||||
continue 'line;
|
||||
}
|
||||
}
|
||||
}
|
||||
language.code += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if !language.is_empty() && sort_empty {
|
||||
println!("{}", language);
|
||||
}
|
||||
|
||||
total.total += language.files.len();
|
||||
total.lines += language.lines;
|
||||
total.comments += language.comments;
|
||||
total.blanks += language.blanks;
|
||||
total.code += language.code;
|
||||
}
|
||||
|
||||
if !sort_empty {
|
||||
let mut unsorted_vec:Vec<(&&str, &Language)> = languages.iter().collect();
|
||||
match &*sort {
|
||||
"files" => {
|
||||
unsorted_vec.sort_by(|a, b| b.1.files.len().cmp(&a.1.files.len()))
|
||||
},
|
||||
"total" => {
|
||||
unsorted_vec.sort_by(|a, b| b.1.lines.cmp(&a.1.lines))
|
||||
},
|
||||
"blanks" => {
|
||||
unsorted_vec.sort_by(|a, b| b.1.blanks.cmp(&a.1.blanks))
|
||||
},
|
||||
"comments" => {
|
||||
unsorted_vec.sort_by(|a, b| b.1.comments.cmp(&a.1.comments))
|
||||
},
|
||||
"code" => {
|
||||
unsorted_vec.sort_by(|a, b| b.1.code.cmp(&a.1.code))
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
for (_, language) in unsorted_vec {
|
||||
if !language.is_empty() {
|
||||
println!("{}", language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("{}", ROW);
|
||||
println!("{}", total);
|
||||
println!("{}", ROW);
|
||||
println!("{}", ROW);
|
||||
println!("{}", total);
|
||||
println!("{}", ROW);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue