Skip to content

Commit c120cae

Browse files
committed
feat(commit): implement questions 'filter' support with evaluations
Supported APIs: Common Python, commitizen.cz.utils.* functions Example YAML configurations: --- commitizen: name: cz_customize customize: questions: - ... - type: input name: scope message: 'Scope of the change :' filter: 'lambda text: commitizen.cz.utils.required_validator(text, msg="! Error: Scope is required")' default: '' - type: input name: subject message: 'Title of the commit (starting in lower case and without period) :' filter: 'lambda text: commitizen.cz.utils.required_validator(text.strip(".").strip(), msg="! Error: Title is required")' default: '' - type: input name: body message: 'Additional contextual message (Empty to skip) :' default: 'Issue: #...' filter: 'commitizen.cz.utils.multiple_line_breaker' --- Signed-off-by: Adrian DC <[email protected]>
1 parent ef9dc84 commit c120cae

File tree

3 files changed

+55
-4
lines changed

3 files changed

+55
-4
lines changed

commitizen/commands/commit.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
from commitizen import factory, git, out
99
from commitizen.config import BaseConfig
1010
from commitizen.cz.exceptions import CzException
11-
from commitizen.cz.utils import get_backup_file_path
11+
from commitizen.cz.utils import (
12+
get_backup_file_path,
13+
multiple_line_breaker,
14+
)
1215
from commitizen.exceptions import (
1316
CommitError,
1417
CommitMessageLengthExceededError,
@@ -49,8 +52,20 @@ def prompt_commit_questions(self) -> str:
4952
# Prompt user for the commit message
5053
cz = self.cz
5154
questions = cz.questions()
55+
5256
for question in filter(lambda q: q["type"] == "list", questions):
5357
question["use_shortcuts"] = self.config.settings["use_shortcuts"]
58+
59+
# Import allowed modules for 'filter'
60+
global commitizen
61+
import commitizen.cz.utils
62+
63+
for question in filter(lambda q: isinstance(q.get("filter", None), str), questions):
64+
question_filter = [
65+
multiple_line_breaker(question['filter'].replace('\\n', '\n'))
66+
]
67+
question["filter"] = eval('\n'.join(question_filter))
68+
5469
try:
5570
answers = questionary.prompt(questions, style=cz.style)
5671
except ValueError as err:

docs/customization.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ commitizen:
175175
| `message` | `str` | `None` | Detail description for the question. |
176176
| `choices` | `list` | `None` | (OPTIONAL) The choices when `type = list`. Either use a list of values or a list of dictionaries with `name` and `value` keys. Keyboard shortcuts can be defined via `key`. See examples above. |
177177
| `default` | `Any` | `None` | (OPTIONAL) The default value for this question. |
178-
| `filter` | `str` | `None` | (Optional) Validator for user's answer. **(Work in Progress)** |
178+
| `filter` | `str` | `None` | (OPTIONAL) Validator for user's answer. The string is evaluated into a Python function, either use `commitizen.cz.utils.*` or lambda functions like `lambda text: text.strip(".").strip()` |
179179
[different-question-types]: https://github.com/tmbo/questionary#different-question-types
180180

181181
#### Shortcut keys

tests/test_cz_customize.py

+38-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
type = "input"
3333
name = "message"
3434
message = "Body."
35+
filter = "commitizen.cz.utils.multiple_line_breaker"
3536
3637
[[tool.commitizen.customize.questions]]
3738
type = "confirm"
@@ -84,7 +85,8 @@
8485
{
8586
"type": "input",
8687
"name": "message",
87-
"message": "Body."
88+
"message": "Body.",
89+
"filter": "commitizen.cz.utils.multiple_line_breaker"
8890
},
8991
{
9092
"type": "confirm",
@@ -134,6 +136,7 @@
134136
- type: input
135137
name: message
136138
message: Body.
139+
filter: 'commitizen.cz.utils.multiple_line_breaker'
137140
- type: confirm
138141
name: show_message
139142
message: Do you want to add body message in commit?
@@ -442,7 +445,40 @@ def test_questions(config):
442445
],
443446
"message": "Select the type of change you are committing",
444447
},
445-
{"type": "input", "name": "message", "message": "Body."},
448+
{
449+
"type": "input",
450+
"name": "message",
451+
"message": "Body.",
452+
"filter": "commitizen.cz.utils.multiple_line_breaker",
453+
},
454+
{
455+
"type": "confirm",
456+
"name": "show_message",
457+
"message": "Do you want to add body message in commit?",
458+
},
459+
]
460+
assert list(questions) == expected_questions
461+
462+
463+
def test_questions_filter(config):
464+
cz = CustomizeCommitsCz(config)
465+
questions = cz.questions()
466+
expected_questions = [
467+
{
468+
"type": "list",
469+
"name": "change_type",
470+
"choices": [
471+
{"value": "feature", "name": "feature: A new feature."},
472+
{"value": "bug fix", "name": "bug fix: A bug fix."},
473+
],
474+
"message": "Select the type of change you are committing",
475+
},
476+
{
477+
"type": "input",
478+
"name": "message",
479+
"message": "Body.",
480+
"filter": "commitizen.cz.utils.multiple_line_breaker",
481+
},
446482
{
447483
"type": "confirm",
448484
"name": "show_message",

0 commit comments

Comments
 (0)