Merge pull request #1 from elianiva/hhh

refactor: use more rust features
This commit is contained in:
Reinaldy Rafli 2021-11-14 21:08:55 +07:00 committed by GitHub
commit d2add7de89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 181 additions and 191 deletions

View File

@ -1,8 +1,13 @@
use std::{env, fs::{self, File}, io::{self, Error, Write}, path::{Path, PathBuf}}; use std::{
env,
fs::{self, File},
io::{self, Error, Write},
path::{Path, PathBuf},
};
extern crate dirs; extern crate dirs;
#[derive(Debug,Clone)] #[derive(Debug)]
pub struct Settings { struct Settings {
end_of_line: String, end_of_line: String,
indent_size: i32, indent_size: i32,
indent_style: String, indent_style: String,
@ -14,199 +19,193 @@ pub struct Settings {
max_line_length: i32, max_line_length: i32,
} }
impl Settings {
fn new() -> Self {
Settings {
end_of_line: String::from("lf"),
indent_size: 4,
indent_style: String::from("space"),
tab_width: 4,
charset: String::from("utf-8"),
root: true,
trim_trailing_whitespace: true,
insert_final_newline: true,
max_line_length: 80,
}
}
}
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let current_path: PathBuf = Path::new(".editorconfig").to_path_buf(); let current_path: PathBuf = Path::new(".editorconfig").to_path_buf();
// Check if the user supplied any args // Check if the user supplied any args
if args.len() > 1 { if args.len() > 1 {
if args[1] == "default" { match args[1].as_str() {
let default_path: PathBuf = dirs::home_dir().unwrap().join(".editorconfig"); "default" => {
// Check if there is default editorconfig if let Some(home_dir) = dirs::home_dir() {
// already exists on `~/.editorconfig` let default_path = home_dir.join(".editorconfig");
if !Path::new(default_path.as_os_str()).exists() { let is_default_cfg_exists = Path::new(default_path.as_os_str()).exists();
println!("Looks like there is no default .editorconfig on your home directory. Creating one..");
let p: Settings = prompt();
// If not, create one
match create_config(default_path, p.clone()) {
Ok(_) => println!("Successfully created .editorconfig on your home directory."),
Err(e) => println!("Error: {}", e)
}
match create_config(current_path, p.clone()) { // Check if there is default editorconfig
Ok(_) => println!("Successfully created .editorconfig on current directory."), // already exists on `~/.editorconfig`
Err(e) => println!("Error: {}", e) if !is_default_cfg_exists {
} println!("Looks like there is no default .editorconfig on your home directory. Creating one..");
let settings = get_user_settings();
// If not, create one
match create_config(&default_path, &settings) {
Ok(_) => println!(
"Successfully created .editorconfig on your home directory."
),
Err(e) => println!("Error: {}", e),
}
match create_config(&current_path, &settings) {
Ok(_) => {
println!("Successfully created .editorconfig on current directory.")
}
Err(e) => println!("Error: {}", e),
}
}
// If there is, print a message
println!("Using default .editorconfig...\n");
match fs::read_to_string(default_path) {
Ok(s) => match create_config(&current_path, &parse_settings(s)) {
Ok(_) => println!("Successfully created .editorconfig"),
Err(e) => println!("Error: {}", e),
},
Err(e) => println!("Error: {}", e),
}
} else {
println!("Failed to get home directory. Exiting...");
}
return; return;
} }
"version" | "--version" | "-v" => {
// If there is, print a message println!("add-editorconfig 0.1.0");
println!("Using default .editorconfig...\n"); return;
match fs::read_to_string(default_path) { }
Ok(s) => { "help" | "--help" | "-h" | _ => {
match create_config(current_path, parse_settings(s)) { println!(
Ok(_) => println!("Successfully created .editorconfig"), "
Err(e) => println!("Error: {}", e) add-editorconfig
} Small and simple CLI app to generate .editorconfig based on a given settings.
},
Err(e) => println!("Error: {}", e), Usage:
add-editorconfig - Create an .editorconfig in the current directory
add-editorconfig default - Create an .editorconfig with the default config
from .editorconfig that exists on the home directory.
add-editorconfig help - Print this help command
add-editorconfig version - Show current version
If you had encountered with any bugs, please open an issue at:
https://github.com/aldy505/add-editorconfig
"
);
return;
} }
return;
} else if args[1] == "version" || args[1] == "--version" || args[1] == "-v" {
println!("add-editorconfig 0.1.0");
return;
} else if args[1] == "help" || args[1] == "--help" || args[1] == "-h" {
println!("add-editorconfig");
println!("Small and simple CLI app to generate .editorconfig based on a given settings.\n");
println!("Usage:");
println!(" add-editorconfig - Create an .editorconfig in the current directory");
println!(" add-editorconfig default - Create an .editorconfig with the default config");
println!(" from .editorconfig that exists on the home directory.");
println!(" add-editorconfig help - Print this help command");
println!(" add-editorconfig version - Show current version\n");
println!("If you had encountered with any bugs, please open an issue at:");
println!("https://github.com/aldy505/add-editorconfig");
return;
} }
} }
let p: Settings = prompt(); let settings = get_user_settings();
match create_config(current_path, p) { match create_config(&current_path, &settings) {
Ok(_) => println!("Successfully created .editorconfig"), Ok(_) => println!("Successfully created .editorconfig"),
Err(e) => println!("Error: {}", e) Err(e) => println!("Error: {}", e),
} }
} }
pub fn default_settings() -> Settings { fn prompt(text: &str, temp: &mut String) {
return Settings { print!("{}", text);
end_of_line: String::from("lf"), io::stdout().flush().unwrap();
indent_size: 4, io::stdin().read_line(temp).unwrap();
indent_style: String::from("space"),
tab_width: 4,
charset: String::from("utf-8"),
root: true,
trim_trailing_whitespace: true,
insert_final_newline: true,
max_line_length: 80
};
} }
pub fn prompt() -> Settings { fn get_user_settings() -> Settings {
let mut settings: Settings = Settings { let mut settings = Settings::new();
..default_settings()
};
let mut temp = String::new(); let mut temp = String::new();
println!("Fill the config with the provided options."); println!("Fill the config with the provided options.");
println!("Entering nothing will set the parameter to its' default value.\n"); println!("Entering nothing will set the parameter to its default value.\n");
// indent_style // indent_style
print!("Indentation style (space / tabs): "); prompt("Indentation style (space / tabs): ", &mut temp);
io::stdout().flush().unwrap(); settings.indent_style = match temp.trim() {
io::stdin().read_line(&mut temp).unwrap(); "tabs" => String::from("tabs"),
if temp.trim() == "tabs" { _ => String::from("space"),
settings.indent_style = String::from("tabs"); };
} else {
settings.indent_style = String::from("space");
}
temp = String::from(""); temp = String::from("");
// indent_size // indent_size
print!("Indent size (number): "); prompt("Indent size (number): ", &mut temp);
io::stdout().flush().unwrap(); if let Ok(indent_size) = temp.trim().parse::<i32>() {
io::stdin().read_line(&mut temp).unwrap(); settings.indent_size = indent_size;
if temp.trim().parse::<i32>().is_ok() {
settings.indent_size = temp.trim().parse::<i32>().unwrap();
} else {
settings.indent_size = 4;
}
temp = String::from("");
// tab_width
print!("Tab width (number): ");
io::stdout().flush().unwrap();
io::stdin().read_line(&mut temp).unwrap();
if temp.trim().parse::<i32>().is_ok() {
settings.tab_width = temp.trim().parse::<i32>().unwrap();
} else {
settings.tab_width = 4;
} }
temp = String::from(""); temp = String::from("");
// tab_width // tab_width
print!("End of line (lf / crlf / cr): "); prompt("Tab width (number): ", &mut temp);
io::stdout().flush().unwrap(); settings.tab_width = match temp.trim().parse::<i32>() {
io::stdin().read_line(&mut temp).unwrap(); Ok(tab_width) => tab_width,
if temp.trim() == "lf" { Err(_) => 4,
settings.end_of_line = String::from("lf"); };
} else if temp.trim() == "crlf" { temp = String::from("");
settings.end_of_line = String::from("crlf");
} else if temp.trim() == "cr" { // tab_width
settings.end_of_line = String::from("cr"); prompt("End of line (lf / crlf / cr): ", &mut temp);
} else { settings.end_of_line = match temp.trim() {
settings.end_of_line = String::from("lf"); "crlf" => String::from("crlf"),
} "cr" => String::from("cr"),
"lf" | _ => String::from("lf"),
};
temp = String::from(""); temp = String::from("");
// charset // charset
print!("Charset (latin1 / utf-8 / utf-16be / utf-16le / utf-8-bom): "); prompt(
io::stdout().flush().unwrap(); "Charset (latin1 / utf-8 / utf-16be / utf-16le / utf-8-bom): ",
io::stdin().read_line(&mut temp).unwrap(); &mut temp,
if temp.trim() == "latin1" { );
settings.charset = String::from("latin1"); settings.charset = match temp.trim() {
} else if temp.trim() == "utf-8" { "latin1" => String::from("latin1"),
settings.charset = String::from("utf-8"); "utf-16be" => String::from("utf-16be"),
} else if temp.trim() == "utf-16be" { "utf-16le" => String::from("utf-16le"),
settings.charset = String::from("utf-16be"); "utf-8-bom" => String::from("utf-8-bom"),
} else if temp.trim() == "utf-16le" { "utf-8" | _ => String::from("utf-8"),
settings.charset = String::from("utf-16le"); };
} else if temp.trim() == "utf-8-bom" {
settings.charset = String::from("utf-8-bom");
} else {
settings.charset = String::from("utf-8");
}
temp = String::from(""); temp = String::from("");
// trim_trailing_whitespace // trim_trailing_whitespace
print!("Trim trailing whitespace (true / false): "); prompt("Trim trailing whitespace (true / false): ", &mut temp);
io::stdout().flush().unwrap(); settings.trim_trailing_whitespace = match temp.trim() {
io::stdin().read_line(&mut temp).unwrap(); "true" => true,
if temp.trim() == "true" { _ => false,
settings.trim_trailing_whitespace = true; };
} else {
settings.trim_trailing_whitespace = false;
}
temp = String::from(""); temp = String::from("");
// insert_final_newline // insert_final_newline
print!("Insert final newline (true / false): "); prompt("Insert final newline (true / false): ", &mut temp);
io::stdout().flush().unwrap(); settings.insert_final_newline = match temp.trim() {
io::stdin().read_line(&mut temp).unwrap(); "true" => true,
if temp.trim() == "true" { _ => false,
settings.insert_final_newline = true; };
} else {
settings.insert_final_newline = false;
}
temp = String::from(""); temp = String::from("");
// max_line_length // max_line_length
print!("Max line length (number): "); prompt("Max line length (number): ", &mut temp);
io::stdout().flush().unwrap(); settings.max_line_length = match temp.trim().parse::<i32>() {
io::stdin().read_line(&mut temp).unwrap(); Ok(max_len) => max_len,
if temp.trim().parse::<i32>().is_ok() { Err(_) => 80,
settings.max_line_length = temp.trim().parse::<i32>().unwrap(); };
} else {
settings.max_line_length = 80;
}
print!("\n"); print!("\n");
return settings; settings
} }
pub fn create_config(path: PathBuf, settings: Settings) -> Result<(), Error> { fn create_config(path: &PathBuf, settings: &Settings) -> Result<(), Error> {
let mut file = File::create(path)?; let mut file = File::create(path)?;
let config: Vec<String> = vec![ let config: Vec<String> = vec![
format!("root = {}", settings.root), format!("root = {}", settings.root),
format!(""), format!(""),
@ -216,54 +215,45 @@ pub fn create_config(path: PathBuf, settings: Settings) -> Result<(), Error> {
format!("indent_style = {}", settings.indent_style), format!("indent_style = {}", settings.indent_style),
format!("tab_width = {}", settings.tab_width), format!("tab_width = {}", settings.tab_width),
format!("charset = {}", settings.charset), format!("charset = {}", settings.charset),
format!("trim_trailing_whitespace = {}", settings.trim_trailing_whitespace), format!(
"trim_trailing_whitespace = {}",
settings.trim_trailing_whitespace
),
format!("insert_final_newline = {}", settings.insert_final_newline), format!("insert_final_newline = {}", settings.insert_final_newline),
format!("max_line_length = {}", settings.max_line_length), format!("max_line_length = {}", settings.max_line_length),
]; ];
let w = file.write_all(config.join("\n").as_bytes());
return w; file.write_all(config.join("\n").as_bytes())
} }
pub fn parse_settings(str: String) -> Settings { fn parse_settings(str: String) -> Settings {
let s: Vec<&str> = str.split_terminator("\n").collect(); let s: Vec<&str> = str.split_terminator("\n").collect();
let mut settings: Settings = Settings { let mut settings: Settings = Settings::new();
..default_settings()
};
for x in s.iter() {
let kv = x.split("=").collect::<Vec<&str>>();
match kv[0].trim() {
"end_of_line" => {
settings.end_of_line = kv[1].trim().to_string();
},
"indent_size" => {
settings.indent_size = kv[1].trim().parse::<i32>().unwrap();
},
"indent_style" => {
settings.indent_style = kv[1].trim().to_string();
},
"tab_width" => {
settings.tab_width = kv[1].trim().parse::<i32>().unwrap();
},
"charset" => {
settings.charset = kv[1].trim().to_string();
},
"root" => {
settings.root = kv[1].trim().to_string().parse::<bool>().unwrap();
},
"trim_trailing_whitespace" => {
settings.trim_trailing_whitespace = kv[1].trim().parse::<bool>().unwrap();
},
"insert_final_newline" => {
settings.insert_final_newline = kv[1].trim().parse::<bool>().unwrap();
},
"max_line_length" => {
settings.max_line_length = kv[1].trim().parse::<i32>().unwrap();
},
_ => {
continue;
}
}
};
return settings; for x in s.iter() {
// biar bisa kek destructure doang ribet banget elah
let (key, value) = match &x.split("=").collect::<Vec<&str>>()[..] {
&[key, value] => (key.trim(), value.trim()),
_ => continue, // not a valid key-value pair, we'll skip
};
match key {
"end_of_line" => settings.end_of_line = value.to_string(),
"indent_size" => settings.indent_size = value.parse::<i32>().unwrap(),
"indent_style" => settings.indent_style = value.to_string(),
"tab_width" => settings.tab_width = value.parse::<i32>().unwrap(),
"charset" => settings.charset = value.to_string(),
"root" => settings.root = value.to_string().parse::<bool>().unwrap(),
"trim_trailing_whitespace" => {
settings.trim_trailing_whitespace = value.parse::<bool>().unwrap()
}
"insert_final_newline" => {
settings.insert_final_newline = value.parse::<bool>().unwrap();
}
"max_line_length" => settings.max_line_length = value.parse::<i32>().unwrap(),
_ => continue,
}
}
settings
} }