summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenedict <benedict@0xb8000.de>2016-11-11 21:53:37 +0100
committerBenedict <benedict@0xb8000.de>2016-11-12 19:29:52 +0100
commitf8fb703ac7bb2767e2659a6e7ec7fa3a64c4168a (patch)
treec0028e8e613460c7e727e38d8d93906c6239a4fd
intial commit: line of code in rust
-rw-r--r--Cargo.lock4
-rw-r--r--Cargo.toml6
-rw-r--r--src/config.rs96
-rw-r--r--src/main.rs81
4 files changed, 187 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..0d14a1a
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,4 @@
+[root]
+name = "loc"
+version = "0.1.0"
+
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..3916615
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "loc"
+version = "0.1.0"
+authors = ["Benedict Boerger <benedict.boerger@cs.tu-dortmund.de>"]
+
+[dependencies]
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..b054c00
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,96 @@
+use std::fs::File;
+use std::option::Option;
+use std::process::*;
+use std::env::home_dir;
+use std::io::*;
+use std::io::ErrorKind::Other;
+
+static LOCAL_CONF_FILE_NAME: &'static str = ".loc.config";
+static GLOBAL_CONF_FILE_NAME: &'static str = "/etc/loc/config";
+
+pub struct CommentTokens {
+ pub file_ending: String,
+ pub single_line: String,
+ pub begin_comment_block: String,
+ pub end_comment_block: String,
+}
+
+pub fn read_config() -> Result<Vec<CommentTokens>>{
+ // first read the local files .loc.config
+ let mut local_error = false;
+ let mut global_error = false;
+ let mut user_error = false;
+ let mut conf: Vec<CommentTokens> = Vec::new();
+
+ match read_config_file(LOCAL_CONF_FILE_NAME, &mut conf) {
+ Ok(_i) => {},
+ Err(_e) => {local_error = true},
+ }
+
+ if let Some(mut x) = home_dir() {
+ x.push(LOCAL_CONF_FILE_NAME);
+ let user_conf_file_name = x.to_str().unwrap();
+
+ match read_config_file(user_conf_file_name, &mut conf) {
+ Ok(_i) => {},
+ Err(_e) => { user_error = true},
+ }
+ }
+
+ match read_config_file(GLOBAL_CONF_FILE_NAME,&mut conf) {
+ Ok(_i) => {},
+ Err(_e) => {global_error= true},
+ }
+
+ // quit programm if could not read any config file
+ if local_error && global_error && user_error {
+ println!("failed to read config files:\n\
+ {}: \n\
+ {}:", LOCAL_CONF_FILE_NAME,
+ GLOBAL_CONF_FILE_NAME);
+ exit(1);
+ }
+
+ Ok(conf)
+}
+
+fn read_config_file(config_file: &str, conf: &mut Vec<CommentTokens>) -> Result<i32> {
+ let f = try!(File::open(config_file));
+ let bufread = BufReader::new(f);
+
+ for (index, line) in bufread.lines().enumerate() {
+ match parse_config_file_line(&try!(line)) {
+ Ok(conf_tok) => conf.push(conf_tok),
+ Err(e)=> println!("error file {}, line {}: {}", config_file, index+1, e),
+ }
+
+ }
+
+ Ok(10)
+}
+
+fn config_file_line_unwrap_element(elem: Option<&str>) -> Result<String>{
+ match elem {
+ Some(line) => Ok(line.to_string()),
+ None => Err(Error::new(Other, "must have four tokens")),
+ }
+}
+
+fn parse_config_file_line(line: &str) -> Result<CommentTokens>{
+ let mut tokens = line.split_whitespace();
+
+ let conf = CommentTokens {
+ file_ending : try!(config_file_line_unwrap_element(tokens.next())),
+ single_line : try!(config_file_line_unwrap_element(tokens.next())),
+ begin_comment_block : try!(config_file_line_unwrap_element(tokens.next())),
+ end_comment_block : try!(config_file_line_unwrap_element(tokens.next())),
+ };
+
+ // there should not be anymore value otherwise print warning
+ // for wrong config file format
+ if tokens.next() != None {
+ return Err(Error::new(Other, "more than four tokens"));
+ }
+
+ Ok(conf)
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..57a8196
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,81 @@
+use std::fs::File;
+use std::env;
+use std::path::Path;
+use std::io::*;
+
+mod config;
+
+fn omit_line(line: String, in_comment_section: &mut bool, comment_tokens: &config::CommentTokens) -> bool {
+ let s = line.trim();
+ let begin_comment_section = s.starts_with(comment_tokens.begin_comment_block.as_str());
+ let end_comment_section = s.starts_with(comment_tokens.end_comment_block.as_str());
+
+ if begin_comment_section {
+ *in_comment_section = true;
+ return true;
+ }
+ else if *in_comment_section && !end_comment_section {
+ return true;
+ }
+ else if *in_comment_section && end_comment_section {
+ *in_comment_section = false;
+ return true;
+ }
+
+ s.starts_with(comment_tokens.single_line.as_str()) || s.is_empty()
+}
+
+fn get_config<'a>(config: &'a Vec<config::CommentTokens>, extension: &str) -> Option<&'a config::CommentTokens> {
+ for conf in config.iter() {
+ if conf.file_ending == extension {
+ return Some(conf);
+ }
+ }
+ None
+}
+
+fn count_lines(filename: &str, config: &mut Vec<config::CommentTokens>) -> Result<i32>{
+ let mut sum = 0;
+ let mut in_comment_section = false;
+
+ // do we have config for this type of file?
+ let extension = match Path::new(filename).extension() {
+ Some(ext) => ext.to_str().unwrap(),
+ None => return Err(Error::new(std::io::ErrorKind::Other, "could not get extension")),
+ };
+
+ let comment_tokens = match get_config(&config, extension) {
+ Some(conf) => conf,
+ None => return Err(Error::new(std::io::ErrorKind::NotFound, "config not found")),
+ };
+
+ let bufread = BufReader::new(try!(File::open(filename)));
+ for line in bufread.lines() {
+ if omit_line(try!(line), &mut in_comment_section, &comment_tokens) {
+ continue;
+ }
+ sum += 1;
+ }
+ Ok(sum)
+}
+
+fn main() {
+ let mut config = match config::read_config() {
+ Err(e) => panic!("error reading config file(s): {}", e),
+ Ok(i) => i,
+ };
+
+ let mut sum = 0;
+
+ // TODO read files from standard input option
+ // TODO read all file below this dictionary
+ for argument in env::args().skip(1) {
+ match count_lines(argument.as_str(), &mut config) {
+ Ok(i) => {
+ println!("{}\t: {}", i, argument);
+ sum += i; },
+ Err(e) => println!("error for file {}: {}", argument, e),
+ }
+ }
+ println!("{}\t: total", sum);
+}