27L7IZBULKDP76DFPUBKKJHLP7XIXN3KFKSMYS35TU6Y574LUUYQC ```### ChangelogA changelog can be generated using the conventional commits.It is inspired by [conventional changelog][2].Configuration follows the [conventional-changelog-config-spec][3]```shconvco changelog > CHANGELOG.md
}#[derive(Debug, StructOpt)]pub struct CommitCommand {/// A bug fix#[structopt(long, conflicts_with_all(&["feat", "build", "chore", "ci", "docs", "style", "refactor", "perf", "test"]))]pub fix: bool,/// A new feature#[structopt(long, conflicts_with_all(&["fix", "build", "chore", "ci", "docs", "style", "refactor", "perf", "test"]))]pub feat: bool,/// Changes that affect the build system or external dependencies#[structopt(long, conflicts_with_all(&["feat", "fix", "chore", "ci", "docs", "style", "refactor", "perf", "test"]))]pub build: bool,/// Other changes that don't modify src or test files#[structopt(long, conflicts_with_all(&["feat", "fix", "build", "ci", "docs", "style", "refactor", "perf", "test"]))]pub chore: bool,/// Changes to CI configuration files and scripts#[structopt(long, conflicts_with_all(&["feat", "fix", "build", "chore", "docs", "style", "refactor", "perf", "test"]))]pub ci: bool,/// Documentation only changes#[structopt(long, conflicts_with_all(&["feat", "fix", "build", "chore", "ci", "style", "refactor", "perf", "test"]))]pub docs: bool,/// Changes that do not affect the meaning of the code (e.g. formatting)#[structopt(long, conflicts_with_all(&["feat", "fix", "build", "chore", "ci", "docs", "refactor", "perf", "test"]))]pub style: bool,/// A code change that neither fixes a bug nor adds a feature#[structopt(long, conflicts_with_all(&["feat", "fix", "build", "chore", "ci", "docs", "style", "perf", "test"]))]pub refactor: bool,/// A code change that improves performance#[structopt(long, conflicts_with_all(&["feat", "fix", "build", "chore", "ci", "docs", "style", "refactor", "test"]))]pub perf: bool,/// Adding missing tests or correcting existing tests#[structopt(long, conflicts_with_all(&["feat", "fix", "build", "chore", "ci", "docs", "style", "refactor", "perf"]))]pub test: bool,/// Introduces a breaking change#[structopt(long)]pub breaking: bool,/// Extra arguments passed to the git command#[structopt(last = true)]pub extra_args: Vec<String>,
use crate::{cli::CommitCommand, Command, Error};use std::{io,io::{Read, Write},process::ExitStatus,};fn read_single_line(prompt: &str) -> Result<String, Error> {let mut out = io::stdout();write!(out, "{}", prompt)?;out.flush()?;let mut value = String::new();io::stdin().read_line(&mut value)?;// remove the newlineOk(value.trim().to_owned())}fn read_multi_line(prompt: &str) -> Result<String, Error> {let mut out = io::stdout();writeln!(out, "{}", prompt)?;writeln!(out, "Press CTRL+D to stop")?;out.flush()?;let mut value = String::new();io::stdin().read_to_string(&mut value)?;// remove the newlinesOk(value.trim().to_owned())}impl CommitCommand {fn type_as_string(&self) -> &str {if self.build {"build"} else if self.chore {"chore"} else if self.ci {"ci"} else if self.docs {"docs"} else if self.feat {"feat"} else if self.fix {"fix"} else if self.perf {"perf"} else if self.refactor {"refactor"} else if self.style {"style"} else if self.test {"test"} else {unreachable!()}}fn commit(&self,scope: String,description: String,body: String,breaking_change: String,issues: String,) -> Result<ExitStatus, Error> {let mut first_line = self.type_as_string().to_owned();if !scope.is_empty() {first_line.push('(');first_line.push_str(scope.as_str());first_line.push(')');}if self.breaking || !breaking_change.is_empty() {first_line.push('!');}first_line.push_str(": ");first_line.push_str(description.as_str());// build the commandlet mut cmd = std::process::Command::new("git");cmd.args(&["commit", "-m", first_line.as_str()]);if !body.is_empty() {cmd.args(&["-m", body.as_str()]);}if !breaking_change.is_empty() {cmd.args(&["-m",format!("BREAKING CHANGE: {}", breaking_change).as_str(),]);}if !issues.is_empty() {cmd.args(&["-m", format!("Refs: {}", issues).as_str()]);}if !self.extra_args.is_empty() {cmd.args(&self.extra_args);}Ok(cmd.status()?)}}impl Command for CommitCommand {fn exec(&self) -> Result<(), Error> {let scope = read_single_line("optional scope: ")?;let description = read_single_line("description: ")?;let body = read_multi_line("optional body:")?;let breaking_change = read_single_line("optional BREAKING CHANGE: ")?;let issues = read_single_line("optional issues (e.g. #2, #8): ")?;self.commit(scope, description, body, breaking_change, issues)?;Ok(())}}