made the main.rs file more ergonomic, used btreemap litreal, and updated to clap 2.0

This commit is contained in:
Aaronepower 2016-02-03 16:15:52 +00:00
parent 0c1a609fe8
commit 0a03887a34
5 changed files with 193 additions and 179 deletions

18
Cargo.lock generated
View file

@ -2,8 +2,9 @@
name = "tokei" name = "tokei"
version = "1.3.1" version = "1.3.1"
dependencies = [ 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)", "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]] [[package]]
@ -13,19 +14,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "0.3.3" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "clap" name = "clap"
version = "1.5.5" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"ansi_term 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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]] [[package]]
@ -33,6 +34,11 @@ name = "glob"
version = "0.2.10" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "strsim" name = "strsim"
version = "0.4.0" version = "0.4.0"
@ -45,6 +51,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "yaml-rust" name = "yaml-rust"
version = "0.2.2" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"

View file

@ -18,5 +18,6 @@ debug = true
opt-level = 3 opt-level = 3
[dependencies] [dependencies]
clap = {version = "1.5.5", features = ["yaml"]} clap = {version = "2.0.1", features = ["yaml"]}
maplit = "*"
glob = "0.2.10" glob = "0.2.10"

View file

@ -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) [![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/) [![](https://img.shields.io/github/release/Aaronepower/tokei.svg)](https://github.com/Aaronepower/tokei/releases/tag/1.1.1/)

View file

@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
use std::fmt; use std::fmt;
use std::cell::RefCell;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Language<'a> { pub struct Language<'a> {
@ -25,58 +26,60 @@ impl<'a> Language<'a> {
line_comment: &'a str, line_comment: &'a str,
multi_line: &'a str, multi_line: &'a str,
multi_line_end: &'a str) multi_line_end: &'a str)
-> Self { -> RefCell<Self> {
Language { RefCell::new(Language {
name: name, name: name,
line_comment: line_comment, line_comment: line_comment,
multi_line: multi_line, multi_line: multi_line,
multi_line_end: multi_line_end, multi_line_end: multi_line_end,
..Self::default() ..Self::default()
} })
} }
pub fn new_c(name: &'a str) -> Self { pub fn new_raw(name: &'a str) -> Self {
Language { Language { name: name, ..Self::default() }
}
pub fn new_c(name: &'a str) -> RefCell<Self> {
RefCell::new(Language {
name: name, name: name,
line_comment: "//", line_comment: "//",
multi_line: "/*", multi_line: "/*",
multi_line_end: "*/", multi_line_end: "*/",
..Self::default() ..Self::default()
} })
} }
pub fn new_html(name: &'a str) -> Self { pub fn new_html(name: &'a str) -> RefCell<Self> {
Language { RefCell::new(Language {
name: name, name: name,
line_comment: "<!--", line_comment: "<!--",
multi_line: "<!--", multi_line: "<!--",
multi_line_end: "-->", multi_line_end: "-->",
..Self::default() ..Self::default()
} })
} }
pub fn new_blank(name: &'a str) -> Self { pub fn new_blank(name: &'a str) -> RefCell<Self> {
Language { name: name, ..Self::default() } RefCell::new(Language { name: name, ..Self::default() })
} }
pub fn new_single(name: &'a str, line_comment: &'a str) -> Self { pub fn new_single(name: &'a str, line_comment: &'a str) -> RefCell<Self> {
Language { RefCell::new(Language {
name: name, name: name,
line_comment: line_comment, line_comment: line_comment,
multi_line: "",
multi_line_end: "",
..Self::default() ..Self::default()
} })
} }
pub fn new_multi(name: &'a str, multi_line: &'a str, multi_line_end: &'a str) -> Self { pub fn new_multi(name: &'a str, multi_line: &'a str, multi_line_end: &'a str) -> RefCell<Self> {
Language { RefCell::new(Language {
name: name, name: name,
multi_line: multi_line, multi_line: multi_line,
multi_line_end: multi_line_end, multi_line_end: multi_line_end,
..Self::default() ..Self::default()
} })
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {

View file

@ -4,7 +4,8 @@
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;
#[macro_use]
extern crate maplit;
#[macro_use] #[macro_use]
pub mod macros; pub mod macros;
pub mod language; pub mod language;
@ -14,7 +15,6 @@ use std::cell::RefCell;
use std::io::Read; use std::io::Read;
use std::path::Path; use std::path::Path;
use std::fs::File; use std::fs::File;
use std::collections::BTreeMap;
use clap::App; use clap::App;
@ -23,137 +23,143 @@ use language::Language;
use fsutil::{get_all_files, contains_comments}; use fsutil::{get_all_files, contains_comments};
const ROW: &'static str = "-----------------------------------------------------------------------\ 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() { fn main() {
let yaml = load_yaml!("../cli.yml"); let yaml = load_yaml!("../cli.yml");
let matches = App::from_yaml(yaml).get_matches(); 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 = Language::new_c("ActionScript");
let action_script = RefCell::new(Language::new_c("ActionScript")); let bash = Language::new_single("BASH", "#");
let bash = RefCell::new(Language::new_single("BASH", "#")); let batch = Language::new_single("Batch", "REM");
let batch = RefCell::new(Language::new_single("Batch", "REM")); let c = Language::new_c("C");
let c = RefCell::new(Language::new_c("C")); let c_header = Language::new_c("C Header");
let c_header = RefCell::new(Language::new_c("C Header")); let c_sharp = Language::new_c("C#");
let c_sharp = RefCell::new(Language::new_c("C#")); let clojure = Language::new_single("Clojure", ";,#,#_");
let clojure = RefCell::new(Language::new_single("Clojure", ";,#,#_")); let coffee_script = Language::new("CoffeeScript", "#", "###", "###");
let coffee_script = RefCell::new(Language::new("CoffeeScript", "#", "###", "###")); let cold_fusion = Language::new("ColdFusion", "<!---", "<!---", "--->");
let cold_fusion = RefCell::new(Language::new("ColdFusion", "<!---", "<!---", "--->")); let cf_script = Language::new_c("ColdFusion CFScript");
let cf_script = RefCell::new(Language::new_c("ColdFusion CFScript")); let cpp = Language::new_c("C++");
let cpp = RefCell::new(Language::new_c("C++")); let cpp_header = Language::new_c("C++ Header");
let cpp_header = RefCell::new(Language::new_c("C++ Header")); let css = Language::new_c("CSS");
let css = RefCell::new(Language::new_c("CSS")); let d = Language::new_c("D");
let d = RefCell::new(Language::new_c("D")); let dart = Language::new_c("Dart");
let dart = RefCell::new(Language::new_c("Dart")); let lisp = Language::new("LISP", ";", "#|", "|#");
let lisp = RefCell::new(Language::new("LISP", ";", "#|", "|#")); let fortran_legacy = Language::new_single("FORTRAN Legacy", "c,C,!,*");
let fortran_legacy = RefCell::new(Language::new_single("FORTRAN Legacy", "c,C,!,*")); let fortran_modern = Language::new_single("FORTRAN Modern", "!");
let fortran_modern = RefCell::new(Language::new_single("FORTRAN Modern", "!")); let go = Language::new_c("Go");
let go = RefCell::new(Language::new_c("Go")); let haskell = Language::new_single("Haskell", "--");
let haskell = RefCell::new(Language::new_single("Haskell", "--")); let html = Language::new_html("HTML");
let html = RefCell::new(Language::new_html("HTML")); let jai = Language::new_c("JAI");
let jai = RefCell::new(Language::new_c("JAI")); let java = Language::new_c("Java");
let java = RefCell::new(Language::new_c("Java")); let java_script = Language::new_c("JavaScript");
let java_script = RefCell::new(Language::new_c("JavaScript")); let julia = Language::new("Julia", "#", "#=", "=#");
let julia = RefCell::new(Language::new("Julia", "#", "#=", "=#")); let json = Language::new_blank("JSON");
let json = RefCell::new(Language::new_blank("JSON")); let jsx = Language::new_c("JSX");
let jsx = RefCell::new(Language::new_c("JSX")); let less = Language::new_c("LESS");
let less = RefCell::new(Language::new_c("LESS")); let markdown = Language::new_blank("Markdown");
let markdown = RefCell::new(Language::new_blank("Markdown")); let objective_c = Language::new_c("Objective-C");
let objective_c = RefCell::new(Language::new_c("Objective-C")); let objective_cpp = Language::new_c("Objective-C++");
let objective_cpp = RefCell::new(Language::new_c("Objective-C++")); let ocaml = Language::new_multi("OCaml", "(*", "*)");
let ocaml = RefCell::new(Language::new_multi("OCaml", "(*", "*)")); let php = Language::new("PHP", "#,//", "/*", "*/");
let php = RefCell::new(Language::new("PHP", "#,//", "/*", "*/")); let pascal = Language::new("Pascal", "//,(*", "{", "}");
let pascal = RefCell::new(Language::new("Pascal", "//,(*", "{", "}")); let perl = Language::new("Perl", "#", "=", "=cut");
let perl = RefCell::new(Language::new("Perl", "#", "=", "=cut")); let python = Language::new("Python", "#", "'''", "'''");
let python = RefCell::new(Language::new("Python", "#", "'''", "'''")); let r = Language::new_single("R", "#");
let r = RefCell::new(Language::new_single("R", "#")); let ruby = Language::new("Ruby", "#", "=begin", "=end");
let ruby = RefCell::new(Language::new("Ruby", "#", "=begin", "=end")); let ruby_html = Language::new_html("Ruby HTML");
let ruby_html = RefCell::new(Language::new_html("Ruby HTML")); let rust = Language::new("Rust", "//,///,//!", "/*", "*/");
let rust = RefCell::new(Language::new("Rust", "//,///,//!", "/*", "*/")); let sass = Language::new_c("Sass");
let sass = RefCell::new(Language::new_c("Sass")); let sml = Language::new_multi("Standard ML", "(*", "*)");
let sml = RefCell::new(Language::new_multi("Standard ML", "(*", "*)")); let sql = Language::new("SQL", "--", "/*", "*/");
let sql = RefCell::new(Language::new("SQL", "--", "/*", "*/")); let swift = Language::new_c("Swift");
let swift = RefCell::new(Language::new_c("Swift")); let tex = Language::new_single("TeX", "%");
let tex = RefCell::new(Language::new_single("TeX", "%")); let toml = Language::new_single("TOML", "#");
let toml = RefCell::new(Language::new_single("TOML", "#")); let type_script = Language::new_c("TypeScript");
let type_script = RefCell::new(Language::new_c("TypeScript")); let xml = Language::new_html("XML");
let xml = RefCell::new(Language::new_html("XML")); let yaml = Language::new_single("YAML", "#");
let yaml = RefCell::new(Language::new_single("YAML", "#"));
// Languages are placed inside a BTreeMap, in order to print alphabetically by default // Languages are placed inside a BTreeMap, in order to print alphabetically by default
let mut languages: BTreeMap<&str, &RefCell<Language>> = BTreeMap::new(); let mut languages = btreemap! {
languages.insert("as", &action_script); "as" => &action_script,
languages.insert("bat", &batch); "bat" => &batch,
languages.insert("btm", &batch); "btm" => &batch,
languages.insert("cmd", &batch); "cmd" => &batch,
languages.insert("bash", &bash); "bash" => &bash,
languages.insert("sh", &bash); "sh" => &bash,
languages.insert("c", &c); "c" => &c,
languages.insert("ec", &c); "ec" => &c,
languages.insert("pgc", &c); "pgc" => &c,
languages.insert("cs", &c_sharp); "cs" => &c_sharp,
languages.insert("clj", &clojure); "clj" => &clojure,
languages.insert("coffee", &coffee_script); "coffee" => &coffee_script,
languages.insert("cfm", &cold_fusion); "cfm" => &cold_fusion,
languages.insert("cfc", &cf_script); "cfc" => &cf_script,
languages.insert("cc", &cpp); "cc" => &cpp,
languages.insert("cpp", &cpp); "cpp" => &cpp,
languages.insert("cxx", &cpp); "cxx" => &cpp,
languages.insert("pcc", &cpp); "pcc" => &cpp,
languages.insert("c++", &cpp); "c++" => &cpp,
languages.insert("css", &css); "css" => &css,
languages.insert("d", &d); "d" => &d,
languages.insert("dart", &dart); "dart" => &dart,
languages.insert("el", &lisp); "el" => &lisp,
languages.insert("lisp", &lisp); "lisp" => &lisp,
languages.insert("lsp", &lisp); "lsp" => &lisp,
languages.insert("sc", &lisp); "sc" => &lisp,
languages.insert("f", &fortran_legacy); "f" => &fortran_legacy,
languages.insert("f77", &fortran_legacy); "f77" => &fortran_legacy,
languages.insert("for", &fortran_legacy); "for" => &fortran_legacy,
languages.insert("ftn", &fortran_legacy); "ftn" => &fortran_legacy,
languages.insert("pfo", &fortran_legacy); "pfo" => &fortran_legacy,
languages.insert("f90", &fortran_modern); "f90" => &fortran_modern,
languages.insert("f95", &fortran_modern); "f95" => &fortran_modern,
languages.insert("f03", &fortran_modern); "f03" => &fortran_modern,
languages.insert("f08", &fortran_modern); "f08" => &fortran_modern,
languages.insert("go", &go); "go" => &go,
languages.insert("h", &c_header); "h" => &c_header,
languages.insert("hs", &haskell); "hs" => &haskell,
languages.insert("hpp", &cpp_header); "hpp" => &cpp_header,
languages.insert("hh", &cpp_header); "hh" => &cpp_header,
languages.insert("html", &html); "html" => &html,
languages.insert("jai", &jai); "jai" => &jai,
languages.insert("java", &java); "java" => &java,
languages.insert("js", &java_script); "js" => &java_script,
languages.insert("jl", &julia); "jl" => &julia,
languages.insert("json", &json); "json" => &json,
languages.insert("jsx", &jsx); "jsx" => &jsx,
languages.insert("less", &less); "less" => &less,
languages.insert("m", &objective_c); "m" => &objective_c,
languages.insert("md", &markdown); "md" => &markdown,
languages.insert("ml", &ocaml); "ml" => &ocaml,
languages.insert("mli", &ocaml); "mli" => &ocaml,
languages.insert("mm", &objective_cpp); "mm" => &objective_cpp,
languages.insert("php", &php); "php" => &php,
languages.insert("pas", &pascal); "pas" => &pascal,
languages.insert("pl", &perl); "pl" => &perl,
languages.insert("py", &python); "py" => &python,
languages.insert("r", &r); "r" => &r,
languages.insert("rake", &ruby); "rake" => &ruby,
languages.insert("rb", &ruby); "rb" => &ruby,
languages.insert("rhtml", &ruby_html); "rhtml" => &ruby_html,
languages.insert("rs", &rust); "rs" => &rust,
languages.insert("sass", &sass); "sass" => &sass,
languages.insert("scss", &sass); "scss" => &sass,
languages.insert("sml", &sml); "sml" => &sml,
languages.insert("sql", &sql); "sql" => &sql,
languages.insert("swift", &swift); "swift" => &swift,
languages.insert("tex", &tex); "tex" => &tex,
languages.insert("sty", &tex); "sty" => &tex,
languages.insert("toml", &toml); "toml" => &toml,
languages.insert("ts", &type_script); "ts" => &type_script,
languages.insert("xml", &xml); "xml" => &xml,
languages.insert("yaml", &yaml); "yaml" => &yaml,
languages.insert("yml", &yaml); "yml" => &yaml,
};
// Print every supported language. // Print every supported language.
if matches.is_present("languages") { if matches.is_present("languages") {
@ -170,8 +176,8 @@ fn main() {
let paths = matches.values_of("input").unwrap(); let paths = matches.values_of("input").unwrap();
let mut ignored_directories: Vec<String> = Vec::new(); let mut ignored_directories: Vec<String> = Vec::new();
if let Some(user_ignored) = matches.value_of("exclude") { if let Some(user_ignored) = matches.values_of("exclude") {
for ignored in user_ignored.split(",") { for ignored in user_ignored {
ignored_directories.push(ignored.to_owned()); ignored_directories.push(ignored.to_owned());
} }
} }
@ -179,9 +185,7 @@ fn main() {
let mut sort = String::new(); let mut sort = String::new();
if let Some(sort_by) = matches.value_of("sort") { if let Some(sort_by) = matches.value_of("sort") {
match &*sort_by.to_lowercase() { match &*sort_by.to_lowercase() {
"files" | "total" | "blanks" | "comments" | "code" => { BLANKS | CODE | COMMENTS | FILES | TOTAL => sort.push_str(&*sort_by.to_lowercase()),
sort.push_str(&*sort_by.to_lowercase())
}
_ => unreachable!(), _ => 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 { for (_, language) in &mut languages {
if language.borrow().printed { if language.borrow().printed {
@ -273,7 +277,7 @@ fn main() {
language.borrow_mut().printed = true; language.borrow_mut().printed = true;
if sort_empty { if sort_empty {
println!("{}", *language.borrow()); println!("{}", *language.borrow());
if matches.is_present("files") { if matches.is_present(FILES) {
println!("{}", ROW); println!("{}", ROW);
for file in &language.borrow().files { for file in &language.borrow().files {
println!("{}", file); println!("{}", file);
@ -295,41 +299,41 @@ fn main() {
if !sort_empty { if !sort_empty {
let mut unsorted_vec: Vec<(&&str, &&RefCell<Language>)> = languages.iter().collect(); let mut unsorted_vec: Vec<(&&str, &&RefCell<Language>)> = languages.iter().collect();
match &*sort { match &*sort {
"files" => { BLANKS => {
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" => {
unsorted_vec.sort_by(|a, b| { unsorted_vec.sort_by(|a, b| {
let a = a.1.borrow(); let a = a.1.borrow();
let b = b.1.borrow(); let b = b.1.borrow();
b.blanks.cmp(&a.blanks) b.blanks.cmp(&a.blanks)
}) })
} }
"comments" => { COMMENTS => {
unsorted_vec.sort_by(|a, b| { unsorted_vec.sort_by(|a, b| {
let a = a.1.borrow(); let a = a.1.borrow();
let b = b.1.borrow(); let b = b.1.borrow();
b.comments.cmp(&a.comments) b.comments.cmp(&a.comments)
}) })
} }
"code" => { CODE => {
unsorted_vec.sort_by(|a, b| { unsorted_vec.sort_by(|a, b| {
let a = a.1.borrow(); let a = a.1.borrow();
let b = b.1.borrow(); let b = b.1.borrow();
b.code.cmp(&a.code) 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!(), _ => unreachable!(),
} }