Skip to content

Commit 7ef38b7

Browse files
committed
feat(cz-commit): enable multi-line body input in interactive prompt
Add multiline support to the commit body question using prompt_toolkit's native multiline mode. Enter skips on empty input and inserts a newline otherwise.
1 parent 35196da commit 7ef38b7

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

commitizen/cz/conventional_commits/conventional_commits.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55

66
from commitizen import defaults
77
from commitizen.cz.base import BaseCommitizen
8-
from commitizen.cz.utils import multiple_line_breaker, required_validator
8+
from commitizen.cz.utils import (
9+
get_multiline_key_bindings,
10+
multiple_line_breaker,
11+
required_validator,
12+
)
913

1014
if TYPE_CHECKING:
1115
from commitizen.question import CzQuestion
@@ -133,6 +137,8 @@ def questions(self) -> list[CzQuestion]:
133137
"Provide additional contextual information about the code changes: (press [enter] to skip)\n"
134138
),
135139
"filter": multiple_line_breaker,
140+
"multiline": True,
141+
"key_bindings": get_multiline_key_bindings(),
136142
},
137143
{
138144
"type": "confirm",

commitizen/cz/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
import os
22
import re
33
import tempfile
4+
from functools import lru_cache
45
from pathlib import Path
56

7+
from prompt_toolkit.key_binding import KeyBindings, KeyPressEvent
8+
69
from commitizen import git
710
from commitizen.cz import exceptions
811

912
_RE_LOCAL_VERSION = re.compile(r"\+.+")
1013

1114

15+
@lru_cache(maxsize=1)
16+
def get_multiline_key_bindings() -> KeyBindings:
17+
kb = KeyBindings()
18+
19+
@kb.add("enter")
20+
def handle_enter(event: KeyPressEvent) -> None:
21+
buff = event.app.current_buffer
22+
if buff.text == "":
23+
buff.validate_and_handle()
24+
else:
25+
buff.insert_text("\n")
26+
27+
return kb
28+
29+
1230
def required_validator(answer: str, msg: object = None) -> str:
1331
if not answer:
1432
raise exceptions.AnswerRequiredError(msg)

commitizen/question.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from collections.abc import Callable
22
from typing import Literal, TypedDict
33

4+
from prompt_toolkit.key_binding import KeyBindings
5+
46

57
class Choice(TypedDict, total=False):
68
value: str
@@ -21,6 +23,8 @@ class InputQuestion(TypedDict, total=False):
2123
name: str
2224
message: str
2325
filter: Callable[[str], str]
26+
multiline: bool
27+
key_bindings: KeyBindings
2428

2529

2630
class ConfirmQuestion(TypedDict):

0 commit comments

Comments
 (0)