Skip to content

Commit

Permalink
feat(cli): ✨ add new flag --message to automatize pipelines
Browse files Browse the repository at this point in the history
  • Loading branch information
romancitodev committed Aug 4, 2024
1 parent 5eeff0e commit 79b7cee
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 63 deletions.
8 changes: 6 additions & 2 deletions sc.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Generated automatically by CLI

[[scopes]]
name = "core"
description = "the core of the repo"

[[scopes]]
name = "tools"

[[scopes]]
name = "cli"
7 changes: 4 additions & 3 deletions src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ pub struct CliConfig {
#[clap(long, help = "set custom path to load config.")]
pub(super) config: Option<PathBuf>,

#[clap(short, long)]
pub(super) message: Option<String>,

#[clap(flatten)]
pub(super) sc_config: SimpleCommitsConfig,

Expand Down Expand Up @@ -43,6 +40,10 @@ pub struct SimpleCommitsConfig {
#[clap(skip)]
pub config: PathBuf,

#[clap(short, long)]
#[serde(skip)]
pub message: Option<String>,

#[clap(skip)]
#[serde(flatten)]
#[merge(strategy = swap_option)]
Expand Down
13 changes: 6 additions & 7 deletions src/tui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub fn init() {
#[derive(Clone, Default, Debug)]
pub struct AppData {
pub commit: CommitBuilder,
pub action: Action,
}

#[allow(dead_code)]
Expand Down Expand Up @@ -61,10 +60,10 @@ impl Action {
pub type StepResult = Result<(), Error>;

/// A trait to setup steps along the TUI app.
#[allow(dead_code)]

pub trait Step {
fn before_run(
&self,
&mut self,
_prompt: &mut Promptuity<Stderr>,
_state: &mut AppData,
_config: &mut SimpleCommitsConfig,
Expand All @@ -73,7 +72,7 @@ pub trait Step {
}

fn after_run(
&self,
&mut self,
_prompt: &mut Promptuity<Stderr>,
_state: &mut AppData,
_config: &mut SimpleCommitsConfig,
Expand All @@ -82,7 +81,7 @@ pub trait Step {
}

fn run(
&self,
&mut self,
prompt: &mut Promptuity<Stderr>,
state: &mut AppData,
config: &mut SimpleCommitsConfig,
Expand All @@ -91,11 +90,11 @@ pub trait Step {

#[macro_export]
macro_rules! gen_steps {
($($module:ident),*) => {
($($struct:ty),*) => {
{
let steps: Vec<Box<dyn super::Step>> = vec![
$(
Box::new(self::$module::_Step),
Box::new(<$struct>::default()),
)*
];
steps
Expand Down
6 changes: 3 additions & 3 deletions src/tui/steps/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ use crate::{
};

#[derive(Default)]
pub struct _Step;
pub struct Definition;

impl Step for _Step {
impl Step for Definition {
fn run(
&self,
&mut self,
p: &mut Promptuity<Stderr>,
state: &mut crate::tui::AppData,
_: &mut SimpleCommitsConfig,
Expand Down
24 changes: 19 additions & 5 deletions src/tui/steps/emoji.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,32 @@ use crate::tui::widgets::{Autocomplete, AutocompletePriority};
use crate::tui::{Step, StepResult};

#[derive(Default)]
pub struct _Step;
pub struct Emoji {
skip: bool,
}

impl Step for Emoji {
fn before_run(
&mut self,
_: &mut promptuity::Promptuity<std::io::Stderr>,
_: &mut crate::tui::AppData,
config: &mut SimpleCommitsConfig,
) -> StepResult {
self.skip = config.git.as_ref().is_some_and(|cfg| cfg.skip_emojis);

Ok(())
}

impl Step for _Step {
fn run(
&self,
&mut self,
p: &mut promptuity::Promptuity<std::io::Stderr>,
state: &mut crate::tui::AppData,
config: &mut SimpleCommitsConfig,
_: &mut SimpleCommitsConfig,
) -> StepResult {
if config.git.as_ref().is_some_and(|cfg| cfg.skip_emojis) {
if self.skip {
return Ok(());
}

let emojis_mapped = EMOJIS
.map(|emoji| {
SelectOption::new(
Expand Down
95 changes: 63 additions & 32 deletions src/tui/steps/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,56 +11,87 @@ use crate::{
};

#[derive(Default)]
pub struct _Step;
pub struct Execute {
skip: bool,
action: Action,
cmd: Vec<String>,
}

impl Step for _Step {
fn run(
&self,
p: &mut Promptuity<Stderr>,
impl Step for Execute {
fn before_run(
&mut self,
_: &mut Promptuity<Stderr>,
state: &mut crate::tui::AppData,
config: &mut SimpleCommitsConfig,
) -> StepResult {
self.skip = config
.git
.as_ref()
.map(|cfg| cfg.skip_preview)
.unwrap_or(false);

let commit = state.commit.clone().build()?;
let mut command = vec![
"git".to_string(),
"commit".to_string(),
"-m".to_string(),
format!("{0}", commit.0),
];
let cmd = command.first().expect("unreachable!").clone();
if let Some(git) = &config.git {
command = git
.commit_template
.as_ref()
.map(|msg| {
msg.iter()
.map(|m| m.replace("{{message}}", &commit.0.to_string()))
.collect::<Vec<String>>()
})
.unwrap_or(command);

let cmd = command
.first()
.expect("The commit template cannot be empty");
if git.skip_preview {
state.action = Action::Commit(cmd.clone(), (command[1..]).to_vec());
state.action.execute_action();
return Ok(());
let command = {
let base = ["git", "commit", "-m", &commit.0]
.iter()
.map(|s| String::from(*s))
.collect::<Vec<_>>();

if let Some(cfg) = &config.git {
cfg.commit_template.as_ref().map_or_else(
|| base,
|cfg| {
cfg.iter()
.map(|msg| msg.replace("{{message}}", &commit.0))
.collect::<Vec<_>>()
},
)
} else {
base
}
};

self.cmd = command;

Ok(())
}

fn run(
&mut self,
p: &mut Promptuity<Stderr>,
state: &mut crate::tui::AppData,
_: &mut SimpleCommitsConfig,
) -> StepResult {
if self.skip {
let (head, tail) = self.cmd.split_first().unwrap();
self.action = Action::Commit(head.clone(), tail.to_vec());
return Ok(());
}

let commit = state.commit.clone().build()?;

let execute =
p.prompt(Confirm::new("Do you want to execute this command?").with_default(true))?;
if !execute {
p.step("Commit preview")?;
p.log(commit.0)?;
p.log(BLANK_CHARACTER)?;
} else {
state.action = Action::Commit(cmd.clone(), (command[1..]).to_vec());

state.action.execute_action();
let (head, tail) = self.cmd.split_first().unwrap();
self.action = Action::Commit(head.clone(), tail.to_vec());
};

Ok(())
}

fn after_run(
&mut self,
_: &mut Promptuity<Stderr>,
_: &mut crate::tui::AppData,
_config: &mut SimpleCommitsConfig,
) -> StepResult {
self.action.execute_action();
Ok(())
}
}
38 changes: 33 additions & 5 deletions src/tui/steps/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,33 @@ use crate::{
};

#[derive(Default)]
pub struct _Step;
pub struct Title {
skip: bool,
title: Option<String>,
}

impl Step for Title {
fn before_run(
&mut self,
_: &mut promptuity::Promptuity<std::io::Stderr>,
_: &mut crate::tui::AppData,
config: &mut SimpleCommitsConfig,
) -> StepResult {
self.skip = config.message.as_ref().is_some();
self.title = config.message.clone();
Ok(())
}

impl Step for _Step {
fn run(
&self,
&mut self,
p: &mut promptuity::Promptuity<std::io::Stderr>,
state: &mut crate::tui::AppData,
_: &mut crate::tui::AppData,
_: &mut SimpleCommitsConfig,
) -> StepResult {
if self.skip {
return Ok(());
}

let msg = p.prompt(
Input::new("Enter a brief title of the commit").with_validator(|text: &String| {
valid_length(
Expand All @@ -24,7 +42,17 @@ impl Step for _Step {
)
}),
)?;
state.commit.set_title(Some(msg));
self.title = Some(msg);
Ok(())
}

fn after_run(
&mut self,
_: &mut promptuity::Promptuity<std::io::Stderr>,
state: &mut crate::tui::AppData,
_: &mut SimpleCommitsConfig,
) -> StepResult {
state.commit.set_title(self.title.clone());
Ok(())
}
}
12 changes: 10 additions & 2 deletions src/tui/steps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,25 @@ pub fn init(
config: &mut SimpleCommitsConfig,
) -> Result<(), Error> {
let mut state = AppData::default();
let steps = gen_steps![commit, scopes, emoji, message, exec];
let mut steps = gen_steps![
commit::Definition,
scopes::Scope,
emoji::Emoji,
message::Title,
exec::Execute
];

prompt.with_intro("Simple Commit").begin()?;

for step in steps {
for step in steps.iter_mut() {
let _before = step.before_run(prompt, &mut state, config);
let res = step.run(prompt, &mut state, config);
if let Err(err) = res {
let msg = format!("❌ Error: {:?}", err);
error!(target: "tui::steps", "{}", msg.bright_red());
return Err(Error::Prompt(String::from("Error")));
}
let _after = step.after_run(prompt, &mut state, config);
info!(target: "tui::steps", "steps: {state:#?}");
}

Expand Down
9 changes: 5 additions & 4 deletions src/tui/steps/scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use crate::{
};

#[derive(Default)]
pub struct _Step;
pub struct Scope;

impl Step for _Step {
impl Step for Scope {
fn run(
&self,
&mut self,
p: &mut promptuity::Promptuity<std::io::Stderr>,
state: &mut crate::tui::AppData,
config: &mut SimpleCommitsConfig,
Expand All @@ -38,11 +38,12 @@ impl Step for _Step {
let scope = (!scope.is_empty()).then_some(scope);
state.commit.set_scope(scope.clone());

// FIX: Error on global path
if let Some(scope) = scope {
if let Some(scopes) = &mut config.scopes {
if !scopes.exists(&scope) {
debug!(target: "steps::scope", "This shit works");
scopes.add_scope(scope.clone());
scopes.add_scope(scope);
if let Err(err) = config.update() {
error!(target: "step::scope", "This shit aint work! {}", err);
}
Expand Down

0 comments on commit 79b7cee

Please sign in to comment.