Skip to content

Commit ed822de

Browse files
committed
feat: ✨ conditional form steps
1 parent ba36b29 commit ed822de

File tree

8 files changed

+97
-52
lines changed

8 files changed

+97
-52
lines changed

coco.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,21 @@ theme:
4545
footer:fg: "#ffffff"
4646
footer:sec: "#000000"
4747

48+
useEmoji: true
49+
askScope: false
50+
askBody: true
51+
askFooter: true
52+
askBreakingChange: true
53+
4854
# scopes:
4955
# - "source"
5056
# - "meta"
51-
# - "keyword"
57+
# - "keyword"
58+
59+
# types:
60+
# - name: "feat"
61+
# description: "A new feature"
62+
# emoji: "✨"
63+
# - name: "fix"
64+
# description: "A bug fix"
65+
# emoji: "🐛"

coco/src/cli/cfg.rs

Whitespace-only changes.

coco/src/cli/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod action;
2+
pub mod cfg;
23
pub mod helpver;

coco/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ async fn main() -> Result<()> {
2626
let action = get_action()?;
2727

2828
match action {
29-
Action::Help | Action::Version => handle_cli_action(action)?,
3029
Action::Coco(stage_check) => match git::list_staged(Some("./")) {
3130
Ok(staged) => {
3231
if staged.is_empty() && stage_check {
@@ -65,6 +64,8 @@ async fn main() -> Result<()> {
6564
}
6665
Err(e) => println!("{}: {}", "Error listing staged files".red(), e),
6766
},
67+
// Handle other actions
68+
a => handle_cli_action(a)?,
6869
}
6970

7071
Ok(())

coco/src/view/main_component.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ use {
88
},
99
};
1010

11+
// TODO: implement debug-only fps counter
12+
// Create a small component that will be displayed in the bottom right corner of the screen
13+
// and that will show the current FPS of the app. This will be useful to debug performance
14+
// issues and to see how the app is performing in different scenarios.
15+
//
16+
// it should only be displayed when the app is compiled in debug mode
17+
1118
/// The global application status, which will be used to display different UIs based on the status.
1219
#[derive(Clone, Default, PartialEq)]
1320
#[allow(dead_code)]

coco/src/view/sections/builder.rs

Lines changed: 12 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ mod commit;
33
mod preview;
44
mod scope;
55
mod r#type;
6+
mod navigation {
7+
pub mod form_step;
8+
}
69

710
use {
811
breaking::BreakingChangeStep,
912
cc_core::{
10-
config::Theme,
13+
config::{CocoConfig, Theme},
1114
state::{MutexAppState, StepStatus},
1215
},
1316
commit::CommitStep,
@@ -16,74 +19,34 @@ use {
1619
ratatui::prelude::{Frame, Rect},
1720
Component, ComponentAccessors,
1821
},
22+
navigation::form_step::FormStep,
1923
preview::PreviewStep,
2024
r#type::TypeStep,
2125
scope::ScopeStep,
22-
strum::{Display, EnumString},
2326
};
2427

25-
// TODO: conditional builder steps
26-
// - use the config to determine which steps to show, by reading the ask_* fields
27-
// - also, implement the missing `use_emoji` field, to be able to disable emojis in the
28-
// generated commit messages
29-
30-
#[derive(Default, EnumString, Display, PartialEq, Eq, Clone)]
31-
#[strum(serialize_all = "kebab-case")]
32-
enum FormStep {
33-
#[default]
34-
Type,
35-
Scope,
36-
Commit,
37-
BreakingChange,
38-
Preview,
39-
}
40-
41-
impl FormStep {
42-
fn next(&self) -> Option<Self> {
43-
let next = match self {
44-
Self::Type => Self::Scope,
45-
Self::Scope => Self::Commit,
46-
Self::Commit => Self::BreakingChange,
47-
Self::BreakingChange => Self::Preview,
48-
Self::Preview => return None,
49-
};
50-
51-
Some(next)
52-
}
53-
54-
fn prev(&self) -> Option<Self> {
55-
let prev = match self {
56-
Self::Type => return None,
57-
Self::Scope => Self::Type,
58-
Self::Commit => Self::Scope,
59-
Self::BreakingChange => Self::Commit,
60-
Self::Preview => Self::BreakingChange,
61-
};
62-
63-
Some(prev)
64-
}
65-
}
66-
6728
component! {
6829
pub struct BuilderSection {
69-
_theme: Theme,
7030
app_state: MutexAppState,
7131
current_step: FormStep,
32+
config: CocoConfig,
7233
}
7334
}
7435

7536
impl BuilderSection {
7637
pub fn new(theme: Theme, app_state: MutexAppState) -> Self {
38+
let config = { app_state.lock().unwrap().config.clone() };
39+
7740
Self {
78-
_theme: theme.clone(),
7941
app_state: app_state.clone(),
8042
current_step: FormStep::Type,
43+
config,
8144
children: children!(
8245
"type" => TypeStep::new(theme.clone(), app_state.clone()).as_active(),
8346
"scope" => ScopeStep::new(theme.clone(), app_state.clone()),
8447
"commit" => CommitStep::new(theme.clone(), app_state.clone()),
8548
"breaking-change" => BreakingChangeStep::new(theme.clone(), app_state.clone()),
86-
"preview" => PreviewStep::new(theme.clone(), app_state.clone())
49+
"preview" => PreviewStep::new(theme, app_state)
8750
),
8851
..Default::default()
8952
}
@@ -116,8 +79,8 @@ impl BuilderSection {
11679
impl Component for BuilderSection {
11780
fn receive_message(&mut self, message: String) {
11881
match message.as_str() {
119-
"builder:next" => self.set_step(self.current_step.next()),
120-
"builder:prev" => self.set_step(self.current_step.prev()),
82+
"builder:next" => self.set_step(self.current_step.next(&self.config)),
83+
"builder:prev" => self.set_step(self.current_step.prev(&self.config)),
12184
"builder:restart" => self.set_step(Some(FormStep::Type)),
12285
_ => {}
12386
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use cc_core::config::CocoConfig;
2+
use strum::{Display, EnumString};
3+
4+
#[derive(Default, EnumString, Display, PartialEq, Eq, Clone)]
5+
#[strum(serialize_all = "kebab-case")]
6+
pub enum FormStep {
7+
#[default]
8+
Type,
9+
Scope,
10+
Commit,
11+
BreakingChange,
12+
Preview,
13+
}
14+
15+
impl FormStep {
16+
pub fn next(&self, config: &CocoConfig) -> Option<Self> {
17+
let next = match self {
18+
Self::Type => Self::Scope,
19+
Self::Scope => Self::Commit,
20+
Self::Commit => Self::BreakingChange,
21+
Self::BreakingChange => Self::Preview,
22+
Self::Preview => return None,
23+
};
24+
25+
// if the next step is disabled by the config, skip it by going to the next one
26+
if !is_step_enabled(&next, config) {
27+
return next.next(config);
28+
}
29+
30+
Some(next)
31+
}
32+
33+
pub fn prev(&self, config: &CocoConfig) -> Option<Self> {
34+
let prev = match self {
35+
Self::Type => return None,
36+
Self::Scope => Self::Type,
37+
Self::Commit => Self::Scope,
38+
Self::BreakingChange => Self::Commit,
39+
Self::Preview => Self::BreakingChange,
40+
};
41+
42+
// if the previous step is disabled by the config, skip it by going to the previous one
43+
if !is_step_enabled(&prev, config) {
44+
return prev.prev(config);
45+
}
46+
47+
Some(prev)
48+
}
49+
}
50+
51+
fn is_step_enabled(step: &FormStep, config: &CocoConfig) -> bool {
52+
match step {
53+
FormStep::Type => true,
54+
FormStep::Scope => config.ask_scope,
55+
FormStep::Commit => true,
56+
FormStep::BreakingChange => config.ask_breaking_change,
57+
FormStep::Preview => true,
58+
}
59+
}

core/src/config/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ fn ctype(name: &str, emoji: &str, description: &str) -> CommitKind {
100100
}
101101
}
102102

103-
#[derive(Debug)]
103+
#[derive(Debug, Clone)]
104104
pub struct CocoConfig {
105105
pub theme: Theme,
106106
pub use_emoji: bool,

0 commit comments

Comments
 (0)