diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 0816b2e50..852dff76c 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -8,7 +8,10 @@ from commitizen import factory, git, out from commitizen.config import BaseConfig from commitizen.cz.exceptions import CzException -from commitizen.cz.utils import get_backup_file_path +from commitizen.cz.utils import ( + get_backup_file_path, + multiple_line_breaker, +) from commitizen.exceptions import ( CommitError, CommitMessageLengthExceededError, @@ -49,8 +52,22 @@ def prompt_commit_questions(self) -> str: # Prompt user for the commit message cz = self.cz questions = cz.questions() + for question in filter(lambda q: q["type"] == "list", questions): question["use_shortcuts"] = self.config.settings["use_shortcuts"] + + # Import allowed modules for 'filter' + global commitizen + import commitizen.cz.utils + + for question in filter( + lambda q: isinstance(q.get("filter", None), str), questions + ): + question_filter = [ + multiple_line_breaker(question["filter"].replace("\\n", "\n")) + ] + question["filter"] = eval("\n".join(question_filter)) + try: answers = questionary.prompt(questions, style=cz.style) except ValueError as err: diff --git a/docs/customization.md b/docs/customization.md index 3e9ae7f50..590db86d0 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -175,7 +175,7 @@ commitizen: | `message` | `str` | `None` | Detail description for the question. | | `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. | | `default` | `Any` | `None` | (OPTIONAL) The default value for this question. | -| `filter` | `str` | `None` | (Optional) Validator for user's answer. **(Work in Progress)** | +| `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()` | [different-question-types]: https://github.com/tmbo/questionary#different-question-types #### Shortcut keys diff --git a/tests/test_cz_customize.py b/tests/test_cz_customize.py index 469b78f88..0444d6b45 100644 --- a/tests/test_cz_customize.py +++ b/tests/test_cz_customize.py @@ -32,6 +32,7 @@ type = "input" name = "message" message = "Body." + filter = "commitizen.cz.utils.multiple_line_breaker" [[tool.commitizen.customize.questions]] type = "confirm" @@ -84,7 +85,8 @@ { "type": "input", "name": "message", - "message": "Body." + "message": "Body.", + "filter": "commitizen.cz.utils.multiple_line_breaker" }, { "type": "confirm", @@ -134,6 +136,7 @@ - type: input name: message message: Body. + filter: 'commitizen.cz.utils.multiple_line_breaker' - type: confirm name: show_message message: Do you want to add body message in commit? @@ -442,7 +445,40 @@ def test_questions(config): ], "message": "Select the type of change you are committing", }, - {"type": "input", "name": "message", "message": "Body."}, + { + "type": "input", + "name": "message", + "message": "Body.", + "filter": "commitizen.cz.utils.multiple_line_breaker", + }, + { + "type": "confirm", + "name": "show_message", + "message": "Do you want to add body message in commit?", + }, + ] + assert list(questions) == expected_questions + + +def test_questions_filter(config): + cz = CustomizeCommitsCz(config) + questions = cz.questions() + expected_questions = [ + { + "type": "list", + "name": "change_type", + "choices": [ + {"value": "feature", "name": "feature: A new feature."}, + {"value": "bug fix", "name": "bug fix: A bug fix."}, + ], + "message": "Select the type of change you are committing", + }, + { + "type": "input", + "name": "message", + "message": "Body.", + "filter": "commitizen.cz.utils.multiple_line_breaker", + }, { "type": "confirm", "name": "show_message",