use std::{fs, io};
use std::error::Error;
use clap::Parser;
use dirs::config_dir;
#[derive(Parser, Debug)]
#[command(version, after_help = "Supported languages\n\tc\n\trust")]
struct Args {
#[arg(short, long)]
file_type: String,
}
impl Args {
fn build() -> Args {
Args::parse()
}
}
#[derive(Debug)]
pub struct ClInfo {
args: Args,
file_info: FileInfo,
}
#[derive(Debug)]
struct FileInfo {
extension: String,
contents: String,
}
impl ClInfo {
pub fn build() -> Result<ClInfo, Box<dyn Error>> {
let args = Args::build();
let file_info = ClInfo::get_file_info(&args.file_type)?;
Ok(
ClInfo {
args,
file_info,
}
)
}
pub fn run(self) -> Result<(), Box<dyn Error>> {
ClInfo::write_basic_file(&self)?;
Ok(())
}
fn get_file_info(file_type: &String) -> Result<FileInfo, Box<dyn Error>> {
let path = match config_dir() {
Some(path) => path,
None => return Err("Couldnt find config directory".into()),
};
let path = match path.to_str() {
Some(path) => path,
None => return Err("config directory couldnt be parsed as a string".into()),
};
let mut config_dir: String = String::from(path);
config_dir.push_str("/prgf/prgf_langs.txt");
let file = fs::read_to_string(config_dir)?;
let lang = "// ".to_owned() + file_type;
let mut extension = String::new();
let mut contents = String::new();
let mut flag = false;
for line in file.lines() {
if line.starts_with(&lang) && !flag {
extension = ClInfo::get_extension(line.to_string())?;
flag = true;
continue;
}
if flag {
if line.starts_with("//") {
break;
}
contents.push_str(&line.to_string());
contents.push('\n');
}
}
Ok( FileInfo {
extension,
contents,
})
}
fn get_extension(ext_line: String) -> Result<String, &'static str> {
let mut ext_itter = ext_line.split(" ");
let extension = match ext_itter.nth(2) {
Some(ext) => ext,
None => return Err("Extension not found in prgf_langs.txt"),
};
Ok(extension.to_string())
}
fn write_basic_file(&self) -> Result<(), io::Error> {
let mut file_name = String::from("main");
file_name.push_str(&self.file_info.extension);
fs::write(&file_name, &self.file_info.contents)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn content_test_rust() {
let file_type = String::from("rust");
let result = String::from("fn main() {\n println!(\"Get programming\\n\");\n}\n");
let file_info = ClInfo::get_file_info(&file_type).unwrap();
let contents = file_info.contents;
assert_eq!(result, contents);
}
#[test]
fn content_test_c() {
let file_type = String::from("c");
let result = String::from("#include <stdio.h>\n\nint main(void) {\n printf(\"Get programming\\n\");\n\n return 0;\n}\n");
let file_info = ClInfo::get_file_info(&file_type).unwrap();
let contents = file_info.contents;
assert_eq!(result, contents);
}
#[test]
fn extension_test() {
let result = String::from(".rs");
let extension = ClInfo::get_extension("// rust .rs".to_string()).unwrap();
assert_eq!(result, extension);
}
}