use std::time::SystemTime;
use crate::{
cli::Commit,
commands::commit::helpers::get_remaining_subject_length
};
use dialoguer::{
FuzzySelect,
theme::ColorfulTheme,
Input,
Confirm,
};
use colored::Colorize;
pub fn commit_command(commit_options: Commit, start_time: SystemTime) {
let commit_standards_options = &[
"Conventional Commit Standard",
"Angular Commit Standard",
"None"
];
let selected_specification = FuzzySelect::with_theme(&ColorfulTheme::default())
.with_prompt("Select a commit message specification")
.default(0)
.items(&commit_standards_options[..])
.interact()
.unwrap();
println!("You selected: {}", commit_standards_options[selected_specification]);
let mut commit_message = String::new();
match selected_specification {
0 => {
commit_message = commit_conventional_commit_standard(&commit_options);
}
1 => {
commit_message = commit_conventional_commit_standard(&commit_options);
}
2 => {
commit_message = commit_conventional_commit_standard(&commit_options);
}
_ => {
println!("{}{}", "Error: ".red().bold(), "Invalid selection of commit specification.");
}
}
println!("{}", commit_message);
}
fn commit_conventional_commit_standard(commit_options: &Commit) -> String {
let commit_type_options = &[
"feat:\tA new feature",
"fix:\tA bug fix",
"docs:\tDocumentation only changes",
"style:\tChanges that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)",
"refactor:\tA code change that neither fixes a bug nor adds a feature",
"perf:\tA code change that improves performance",
"test:\tAdding missing tests or correcting existing tests",
"build:\tChanges that affect the build system or external dependencies (example scons, gulp, grunt, broccoli, npm, etc.)",
"ci:\tChanges to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs, etc.)",
"chore:\tOther changes that don't modify src/bin files",
"revert:\tReverts a previous commit",
];
let selected_commit_type = FuzzySelect::with_theme(&ColorfulTheme::default())
.with_prompt("Select the type of change that you're committing:")
.default(0)
.items(&commit_type_options[..])
.interact()
.unwrap();
let commit_type = commit_type_options[selected_commit_type].split(":").next().unwrap();
let scope: String = Input::new()
.with_prompt(
format!("{}{}:{}", "What is the scope of this change ", "(e.g. component or file name)".yellow().bold(), " (press enter to skip)".black().bold())
)
.default("".into())
.interact_text().unwrap();
let remaining_subject_length = get_remaining_subject_length(commit_type, &scope);
let subject: String = Input::new()
.with_prompt(
format!("{}{}{}{}:", "Write a short, imperative tense description of the change ", "(max ".yellow().bold(), remaining_subject_length.to_string().yellow().bold(), " chars)".yellow().bold())
)
.validate_with(|input: &String| -> Result<(), &str> {
if input.len() <= remaining_subject_length {
Ok(())
} else {
Err(
"Provided subject exceeds character limit"
)
}
})
.default("".into())
.interact_text().unwrap();
let body: String = Input::new()
.with_prompt(
format!("{}:{}", "Provide a longer description of the change", " (press enter to skip)".black().bold())
)
.default("".into())
.interact_text().unwrap();
let mut commit_message =
match scope.len() {
0 => format!("{}: {}\n\n{}", commit_type, subject, body),
_ => format!("{}({}): {}\n\n{}", commit_type, scope, subject, body)
};
let breaking_changes = Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Are there any breaking changes?")
.default(false)
.wait_for_newline(true)
.interact()
.unwrap();
let mut breaking_changes_section = String::new();
if breaking_changes {
let breaking_changes_message: String = Input::new()
.with_prompt(
format!("{}", "Provide a description of the breaking changes")
)
.default("".into())
.interact_text().unwrap();
breaking_changes_section = format!("\n\nBREAKING CHANGE:\n\n{}", breaking_changes_message)
}
commit_message += &breaking_changes_section;
let referenced_issues = Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Does this change affect any open issues")
.default(false)
.wait_for_newline(true)
.interact()
.unwrap();
let mut referenced_issues_section = String::new();
if referenced_issues {
let referenced_issues_message: String = Input::new()
.with_prompt(
format!("{}", r#"Add issue references (e.g. #193, #4892, etc.)"#)
)
.default("".into())
.interact_text().unwrap();
referenced_issues_section = format!("\n\nRefs: {}", referenced_issues_message)
}
commit_message += &referenced_issues_section;
commit_message
}
fn commit_angular_commit_standard(commit_options: &Commit) -> String {
"angular message".to_string()
}
fn commit_none(commit_options: &Commit) -> String {
"none message".to_string()
}