diff --git a/Cargo.lock b/Cargo.lock index c597c84..b3abb07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,8 +2,9 @@ name = "tokei" version = "1.3.1" dependencies = [ - "clap 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -13,19 +14,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "1.5.5" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -33,6 +34,11 @@ name = "glob" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "maplit" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.4.0" @@ -45,6 +51,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "yaml-rust" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index bd1332e..bc71d32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,5 +18,6 @@ debug = true opt-level = 3 [dependencies] -clap = {version = "1.5.5", features = ["yaml"]} -glob = "0.2.10" +clap = {version = "2.0.1", features = ["yaml"]} +maplit = "*" +glob = "0.2.10" \ No newline at end of file diff --git a/README.md b/README.md index 95eb162..53e7d58 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Tokei +# Tokei [時計](https://en.wiktionary.org/wiki/%E6%99%82%E8%A8%88) [![GitHub License](https://img.shields.io/github/license/Aaronepower/tokei.svg)](http://github.com/Aaronepower/tokei/blob/master/LICENSE) [![](https://img.shields.io/github/release/Aaronepower/tokei.svg)](https://github.com/Aaronepower/tokei/releases/tag/1.1.1/) diff --git a/src/language.rs b/src/language.rs index d1ff232..9bf9cc4 100644 --- a/src/language.rs +++ b/src/language.rs @@ -3,6 +3,7 @@ // found in the LICENSE file. use std::fmt; +use std::cell::RefCell; #[derive(Debug, Default)] pub struct Language<'a> { @@ -25,58 +26,60 @@ impl<'a> Language<'a> { line_comment: &'a str, multi_line: &'a str, multi_line_end: &'a str) - -> Self { + -> RefCell { - Language { + RefCell::new(Language { name: name, line_comment: line_comment, multi_line: multi_line, multi_line_end: multi_line_end, ..Self::default() - } + }) } - pub fn new_c(name: &'a str) -> Self { - Language { + pub fn new_raw(name: &'a str) -> Self { + Language { name: name, ..Self::default() } + } + + pub fn new_c(name: &'a str) -> RefCell { + RefCell::new(Language { name: name, line_comment: "//", multi_line: "/*", multi_line_end: "*/", ..Self::default() - } + }) } - pub fn new_html(name: &'a str) -> Self { - Language { + pub fn new_html(name: &'a str) -> RefCell { + RefCell::new(Language { name: name, line_comment: "", ..Self::default() - } + }) } - pub fn new_blank(name: &'a str) -> Self { - Language { name: name, ..Self::default() } + pub fn new_blank(name: &'a str) -> RefCell { + RefCell::new(Language { name: name, ..Self::default() }) } - pub fn new_single(name: &'a str, line_comment: &'a str) -> Self { - Language { + pub fn new_single(name: &'a str, line_comment: &'a str) -> RefCell { + RefCell::new(Language { name: name, line_comment: line_comment, - multi_line: "", - multi_line_end: "", ..Self::default() - } + }) } - pub fn new_multi(name: &'a str, multi_line: &'a str, multi_line_end: &'a str) -> Self { - Language { + pub fn new_multi(name: &'a str, multi_line: &'a str, multi_line_end: &'a str) -> RefCell { + RefCell::new(Language { name: name, multi_line: multi_line, multi_line_end: multi_line_end, ..Self::default() - } + }) } pub fn is_empty(&self) -> bool { diff --git a/src/main.rs b/src/main.rs index bb45b72..4f16a34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,8 @@ #[macro_use] extern crate clap; - +#[macro_use] +extern crate maplit; #[macro_use] pub mod macros; pub mod language; @@ -14,7 +15,6 @@ use std::cell::RefCell; use std::io::Read; use std::path::Path; use std::fs::File; -use std::collections::BTreeMap; use clap::App; @@ -23,137 +23,143 @@ use language::Language; use fsutil::{get_all_files, contains_comments}; const ROW: &'static str = "-----------------------------------------------------------------------\ ---------"; +const BLANKS: &'static str = "blanks"; +const COMMENTS: &'static str = "comments"; +const CODE: &'static str = "code"; +const FILES: &'static str = "files"; +const TOTAL: &'static str = "total"; + fn main() { let yaml = load_yaml!("../cli.yml"); let matches = App::from_yaml(yaml).get_matches(); - // Big list of languages, this should changed if there is ever a map! macro. - let action_script = RefCell::new(Language::new_c("ActionScript")); - let bash = RefCell::new(Language::new_single("BASH", "#")); - let batch = RefCell::new(Language::new_single("Batch", "REM")); - let c = RefCell::new(Language::new_c("C")); - let c_header = RefCell::new(Language::new_c("C Header")); - let c_sharp = RefCell::new(Language::new_c("C#")); - let clojure = RefCell::new(Language::new_single("Clojure", ";,#,#_")); - let coffee_script = RefCell::new(Language::new("CoffeeScript", "#", "###", "###")); - let cold_fusion = RefCell::new(Language::new("ColdFusion", "")); - let cf_script = RefCell::new(Language::new_c("ColdFusion CFScript")); - let cpp = RefCell::new(Language::new_c("C++")); - let cpp_header = RefCell::new(Language::new_c("C++ Header")); - let css = RefCell::new(Language::new_c("CSS")); - let d = RefCell::new(Language::new_c("D")); - let dart = RefCell::new(Language::new_c("Dart")); - let lisp = RefCell::new(Language::new("LISP", ";", "#|", "|#")); - let fortran_legacy = RefCell::new(Language::new_single("FORTRAN Legacy", "c,C,!,*")); - let fortran_modern = RefCell::new(Language::new_single("FORTRAN Modern", "!")); - let go = RefCell::new(Language::new_c("Go")); - let haskell = RefCell::new(Language::new_single("Haskell", "--")); - let html = RefCell::new(Language::new_html("HTML")); - let jai = RefCell::new(Language::new_c("JAI")); - let java = RefCell::new(Language::new_c("Java")); - let java_script = RefCell::new(Language::new_c("JavaScript")); - let julia = RefCell::new(Language::new("Julia", "#", "#=", "=#")); - let json = RefCell::new(Language::new_blank("JSON")); - let jsx = RefCell::new(Language::new_c("JSX")); - let less = RefCell::new(Language::new_c("LESS")); - let markdown = RefCell::new(Language::new_blank("Markdown")); - let objective_c = RefCell::new(Language::new_c("Objective-C")); - let objective_cpp = RefCell::new(Language::new_c("Objective-C++")); - let ocaml = RefCell::new(Language::new_multi("OCaml", "(*", "*)")); - let php = RefCell::new(Language::new("PHP", "#,//", "/*", "*/")); - let pascal = RefCell::new(Language::new("Pascal", "//,(*", "{", "}")); - let perl = RefCell::new(Language::new("Perl", "#", "=", "=cut")); - let python = RefCell::new(Language::new("Python", "#", "'''", "'''")); - let r = RefCell::new(Language::new_single("R", "#")); - let ruby = RefCell::new(Language::new("Ruby", "#", "=begin", "=end")); - let ruby_html = RefCell::new(Language::new_html("Ruby HTML")); - let rust = RefCell::new(Language::new("Rust", "//,///,//!", "/*", "*/")); - let sass = RefCell::new(Language::new_c("Sass")); - let sml = RefCell::new(Language::new_multi("Standard ML", "(*", "*)")); - let sql = RefCell::new(Language::new("SQL", "--", "/*", "*/")); - let swift = RefCell::new(Language::new_c("Swift")); - let tex = RefCell::new(Language::new_single("TeX", "%")); - let toml = RefCell::new(Language::new_single("TOML", "#")); - let type_script = RefCell::new(Language::new_c("TypeScript")); - let xml = RefCell::new(Language::new_html("XML")); - let yaml = RefCell::new(Language::new_single("YAML", "#")); + let action_script = Language::new_c("ActionScript"); + let bash = Language::new_single("BASH", "#"); + let batch = Language::new_single("Batch", "REM"); + let c = Language::new_c("C"); + let c_header = Language::new_c("C Header"); + let c_sharp = Language::new_c("C#"); + let clojure = Language::new_single("Clojure", ";,#,#_"); + let coffee_script = Language::new("CoffeeScript", "#", "###", "###"); + let cold_fusion = Language::new("ColdFusion", ""); + let cf_script = Language::new_c("ColdFusion CFScript"); + let cpp = Language::new_c("C++"); + let cpp_header = Language::new_c("C++ Header"); + let css = Language::new_c("CSS"); + let d = Language::new_c("D"); + let dart = Language::new_c("Dart"); + let lisp = Language::new("LISP", ";", "#|", "|#"); + let fortran_legacy = Language::new_single("FORTRAN Legacy", "c,C,!,*"); + let fortran_modern = Language::new_single("FORTRAN Modern", "!"); + let go = Language::new_c("Go"); + let haskell = Language::new_single("Haskell", "--"); + let html = Language::new_html("HTML"); + let jai = Language::new_c("JAI"); + let java = Language::new_c("Java"); + let java_script = Language::new_c("JavaScript"); + let julia = Language::new("Julia", "#", "#=", "=#"); + let json = Language::new_blank("JSON"); + let jsx = Language::new_c("JSX"); + let less = Language::new_c("LESS"); + let markdown = Language::new_blank("Markdown"); + let objective_c = Language::new_c("Objective-C"); + let objective_cpp = Language::new_c("Objective-C++"); + let ocaml = Language::new_multi("OCaml", "(*", "*)"); + let php = Language::new("PHP", "#,//", "/*", "*/"); + let pascal = Language::new("Pascal", "//,(*", "{", "}"); + let perl = Language::new("Perl", "#", "=", "=cut"); + let python = Language::new("Python", "#", "'''", "'''"); + let r = Language::new_single("R", "#"); + let ruby = Language::new("Ruby", "#", "=begin", "=end"); + let ruby_html = Language::new_html("Ruby HTML"); + let rust = Language::new("Rust", "//,///,//!", "/*", "*/"); + let sass = Language::new_c("Sass"); + let sml = Language::new_multi("Standard ML", "(*", "*)"); + let sql = Language::new("SQL", "--", "/*", "*/"); + let swift = Language::new_c("Swift"); + let tex = Language::new_single("TeX", "%"); + let toml = Language::new_single("TOML", "#"); + let type_script = Language::new_c("TypeScript"); + let xml = Language::new_html("XML"); + let yaml = Language::new_single("YAML", "#"); // Languages are placed inside a BTreeMap, in order to print alphabetically by default - let mut languages: BTreeMap<&str, &RefCell> = 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("f03", &fortran_modern); - languages.insert("f08", &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("jai", &jai); - 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("ml", &ocaml); - languages.insert("mli", &ocaml); - 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("sml", &sml); - languages.insert("sql", &sql); - languages.insert("swift", &swift); - languages.insert("tex", &tex); - languages.insert("sty", &tex); - languages.insert("toml", &toml); - languages.insert("ts", &type_script); - languages.insert("xml", &xml); - languages.insert("yaml", &yaml); - languages.insert("yml", &yaml); + let mut languages = btreemap! { + "as" => &action_script, + "bat" => &batch, + "btm" => &batch, + "cmd" => &batch, + "bash" => &bash, + "sh" => &bash, + "c" => &c, + "ec" => &c, + "pgc" => &c, + "cs" => &c_sharp, + "clj" => &clojure, + "coffee" => &coffee_script, + "cfm" => &cold_fusion, + "cfc" => &cf_script, + "cc" => &cpp, + "cpp" => &cpp, + "cxx" => &cpp, + "pcc" => &cpp, + "c++" => &cpp, + "css" => &css, + "d" => &d, + "dart" => &dart, + "el" => &lisp, + "lisp" => &lisp, + "lsp" => &lisp, + "sc" => &lisp, + "f" => &fortran_legacy, + "f77" => &fortran_legacy, + "for" => &fortran_legacy, + "ftn" => &fortran_legacy, + "pfo" => &fortran_legacy, + "f90" => &fortran_modern, + "f95" => &fortran_modern, + "f03" => &fortran_modern, + "f08" => &fortran_modern, + "go" => &go, + "h" => &c_header, + "hs" => &haskell, + "hpp" => &cpp_header, + "hh" => &cpp_header, + "html" => &html, + "jai" => &jai, + "java" => &java, + "js" => &java_script, + "jl" => &julia, + "json" => &json, + "jsx" => &jsx, + "less" => &less, + "m" => &objective_c, + "md" => &markdown, + "ml" => &ocaml, + "mli" => &ocaml, + "mm" => &objective_cpp, + "php" => &php, + "pas" => &pascal, + "pl" => &perl, + "py" => &python, + "r" => &r, + "rake" => &ruby, + "rb" => &ruby, + "rhtml" => &ruby_html, + "rs" => &rust, + "sass" => &sass, + "scss" => &sass, + "sml" => &sml, + "sql" => &sql, + "swift" => &swift, + "tex" => &tex, + "sty" => &tex, + "toml" => &toml, + "ts" => &type_script, + "xml" => &xml, + "yaml" => &yaml, + "yml" => &yaml, + }; // Print every supported language. if matches.is_present("languages") { @@ -170,8 +176,8 @@ fn main() { let paths = matches.values_of("input").unwrap(); let mut ignored_directories: Vec = Vec::new(); - if let Some(user_ignored) = matches.value_of("exclude") { - for ignored in user_ignored.split(",") { + if let Some(user_ignored) = matches.values_of("exclude") { + for ignored in user_ignored { ignored_directories.push(ignored.to_owned()); } } @@ -179,9 +185,7 @@ fn main() { 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()) - } + BLANKS | CODE | COMMENTS | FILES | TOTAL => sort.push_str(&*sort_by.to_lowercase()), _ => unreachable!(), } } @@ -208,7 +212,7 @@ fn main() { } } - let mut total = Language::new_blank("Total"); + let mut total = Language::new_raw("Total"); for (_, language) in &mut languages { if language.borrow().printed { @@ -273,7 +277,7 @@ fn main() { language.borrow_mut().printed = true; if sort_empty { println!("{}", *language.borrow()); - if matches.is_present("files") { + if matches.is_present(FILES) { println!("{}", ROW); for file in &language.borrow().files { println!("{}", file); @@ -295,41 +299,41 @@ fn main() { if !sort_empty { let mut unsorted_vec: Vec<(&&str, &&RefCell)> = languages.iter().collect(); match &*sort { - "files" => { - unsorted_vec.sort_by(|a, b| { - let a = a.1.borrow(); - let b = b.1.borrow(); - b.files.len().cmp(&a.files.len()) - }) - } - "total" => { - unsorted_vec.sort_by(|a, b| { - let a = a.1.borrow(); - let b = b.1.borrow(); - b.lines.cmp(&a.lines) - }) - } - "blanks" => { + BLANKS => { unsorted_vec.sort_by(|a, b| { let a = a.1.borrow(); let b = b.1.borrow(); b.blanks.cmp(&a.blanks) }) } - "comments" => { + COMMENTS => { unsorted_vec.sort_by(|a, b| { let a = a.1.borrow(); let b = b.1.borrow(); b.comments.cmp(&a.comments) }) } - "code" => { + CODE => { unsorted_vec.sort_by(|a, b| { let a = a.1.borrow(); let b = b.1.borrow(); b.code.cmp(&a.code) }) } + FILES => { + unsorted_vec.sort_by(|a, b| { + let a = a.1.borrow(); + let b = b.1.borrow(); + b.files.len().cmp(&a.files.len()) + }) + } + TOTAL => { + unsorted_vec.sort_by(|a, b| { + let a = a.1.borrow(); + let b = b.1.borrow(); + b.lines.cmp(&a.lines) + }) + } _ => unreachable!(), }