This commit is contained in:
136
app/src/git_commit_generator/interactive.py
Normal file
136
app/src/git_commit_generator/interactive.py
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
"""Interactive mode for message refinement."""
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.prompt import Prompt
|
||||||
|
from rich.text import Text
|
||||||
|
|
||||||
|
|
||||||
|
class Action(Enum):
|
||||||
|
"""User action options in interactive mode."""
|
||||||
|
|
||||||
|
ACCEPT = "a"
|
||||||
|
EDIT = "e"
|
||||||
|
REGENERATE = "r"
|
||||||
|
QUIT = "q"
|
||||||
|
|
||||||
|
|
||||||
|
class InteractiveMode:
|
||||||
|
"""Interactive mode handler for message refinement."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initialize interactive mode."""
|
||||||
|
self.console = Console()
|
||||||
|
|
||||||
|
def show_message(self, message: str) -> None:
|
||||||
|
"""Display a message to the user."""
|
||||||
|
self.console.print(Text(message, style="bold green"))
|
||||||
|
|
||||||
|
def show_diff(self, diff: str) -> None:
|
||||||
|
"""Display the diff being analyzed."""
|
||||||
|
self.console.print("\n[bold]Changes detected:[/bold]")
|
||||||
|
self.console.print(diff[:500] + "..." if len(diff) > 500 else diff)
|
||||||
|
|
||||||
|
def prompt_for_action(self, current_message: str) -> tuple[Action, Optional[str]]:
|
||||||
|
"""Prompt user for action."""
|
||||||
|
self.console.print("\n[bold]Generated commit message:[/bold]")
|
||||||
|
self.console.print(f"[cyan]{current_message}[/cyan]")
|
||||||
|
|
||||||
|
self.console.print("\n[bold]Options:[/bold]")
|
||||||
|
self.console.print(" [green](a)[/green]ccept message")
|
||||||
|
self.console.print(" [green](e)[/green]dit message")
|
||||||
|
self.console.print(" [green](r)[/green]egenerate")
|
||||||
|
self.console.print(" [green](q)[/green]uit")
|
||||||
|
|
||||||
|
choice = Prompt.ask(
|
||||||
|
"What would you like to do?",
|
||||||
|
choices=["a", "e", "r", "q"],
|
||||||
|
default="a",
|
||||||
|
).lower()
|
||||||
|
|
||||||
|
if choice == "a":
|
||||||
|
return Action.ACCEPT, None
|
||||||
|
elif choice == "e":
|
||||||
|
edited = Prompt.ask("Enter new commit message", default=current_message)
|
||||||
|
return Action.ACCEPT, edited
|
||||||
|
elif choice == "r":
|
||||||
|
return Action.REGENERATE, None
|
||||||
|
else:
|
||||||
|
return Action.QUIT, None
|
||||||
|
|
||||||
|
def confirm_commit(self, message: str) -> bool:
|
||||||
|
"""Confirm the commit message before proceeding."""
|
||||||
|
self.console.print(f"\n[bold]Final commit message:[/bold]")
|
||||||
|
self.console.print(f"[green]{message}[/green]")
|
||||||
|
|
||||||
|
confirm = Prompt.ask(
|
||||||
|
"Proceed with commit?",
|
||||||
|
choices=["y", "n"],
|
||||||
|
default="y",
|
||||||
|
).lower()
|
||||||
|
|
||||||
|
return confirm == "y"
|
||||||
|
|
||||||
|
def show_error(self, error: str) -> None:
|
||||||
|
"""Display an error message."""
|
||||||
|
self.console.print(Text(f"Error: {error}", style="bold red"))
|
||||||
|
|
||||||
|
def show_info(self, info: str) -> None:
|
||||||
|
"""Display an info message."""
|
||||||
|
self.console.print(Text(info, style="blue"))
|
||||||
|
|
||||||
|
def show_connection_status(
|
||||||
|
self, connected: bool, model: Optional[str] = None
|
||||||
|
) -> None:
|
||||||
|
"""Show Ollama connection status."""
|
||||||
|
if connected:
|
||||||
|
status = f"[green]Connected to Ollama[/green]"
|
||||||
|
if model:
|
||||||
|
status += f" (model: {model})"
|
||||||
|
self.console.print(status)
|
||||||
|
else:
|
||||||
|
self.console.print(
|
||||||
|
Text(
|
||||||
|
"Could not connect to Ollama. Make sure it's running.",
|
||||||
|
style="bold red",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def show_no_changes_warning(self) -> None:
|
||||||
|
"""Show warning when no changes detected."""
|
||||||
|
self.console.print(
|
||||||
|
Text(
|
||||||
|
"No changes detected. Stage some files with 'git add' or use --unstaged flag.",
|
||||||
|
style="bold yellow",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def show_help(self) -> None:
|
||||||
|
"""Show help information."""
|
||||||
|
help_text = """
|
||||||
|
[bold]Git Commit Message Generator[/bold]
|
||||||
|
|
||||||
|
A CLI tool that generates conventional git commit messages using local LLMs.
|
||||||
|
|
||||||
|
[bold]Commands:[/bold]
|
||||||
|
generate Generate a commit message from staged/unstaged changes
|
||||||
|
changelog Generate CHANGELOG.md from git history
|
||||||
|
config Configure settings
|
||||||
|
|
||||||
|
[bold]Options:[/bold]
|
||||||
|
--unstaged Include unstaged changes
|
||||||
|
--staged Include only staged changes (default)
|
||||||
|
--model Specify which model to use
|
||||||
|
--interactive, -i Use interactive mode
|
||||||
|
|
||||||
|
[bold]Environment Variables:[/bold]
|
||||||
|
OLLAMA_HOST Ollama server URL (default: http://localhost:11434)
|
||||||
|
OLLAMA_MODEL Default model to use
|
||||||
|
"""
|
||||||
|
self.console.print(help_text)
|
||||||
|
|
||||||
|
|
||||||
|
def get_interactive_mode() -> InteractiveMode:
|
||||||
|
"""Get InteractiveMode instance."""
|
||||||
|
return InteractiveMode()
|
||||||
Reference in New Issue
Block a user