summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Power <Aaronepower@users.noreply.github.com>2015-10-11 21:50:55 +0100
committerAaron Power <Aaronepower@users.noreply.github.com>2015-10-11 21:50:55 +0100
commitc06871b56faa0c3cb4d515dce979b455b256b3ea (patch)
treea42ab4855f42fd32b37e65dc57f42144b2b82813
parent1481e27bd2cfda165be3f1c1f6c4c7252ec00327 (diff)
parentee4712be1d9a201eb88d5bc9100e0130cb85cbe4 (diff)
Merge pull request #17 from Aaronepower/RefCell1.2.0
Added support for multiple file extensions
-rw-r--r--src/language.rs201
-rw-r--r--src/main.rs464
2 files changed, 381 insertions, 284 deletions
diff --git a/src/language.rs b/src/language.rs
index 70b3441..9c3fedb 100644
--- a/src/language.rs
+++ b/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)
+ }
}
diff --git a/src/main.rs b/src/main.rs
index 9f71121..1ddd852 100644
--- a/src/main.rs
+++ b/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 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", "#"));
-
- if matches.is_present("languages") {
- for (ext, language) in languages {
- println!("{:<25} ({})", language.name, ext);
- }
- return;
- }
-
-
- 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 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);
+ let yaml = load_yaml!("../cli.yml");
+ let matches = App::from_yaml(yaml).get_matches();
+
+ 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", "#")));
+
+ 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;
+ }
+ }
+
+
+ if is_in_comments {
+ if line.contains(language.borrow().multi_line_end) {
+ is_in_comments = false;
+ }
+
+ 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();
+
+ 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, &&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!(),
+ };
+
+ for (_, language) in unsorted_vec {
+
+ if !language.borrow().is_empty() && language.borrow().printed {
+ language.borrow_mut().printed = false;
+ println!("{}", *language.borrow());
+ }
+ }
+ }
+
+ println!("{}", ROW);
+ println!("{}", total);
+ println!("{}", ROW);
}