Files
7000pctAUTO 543058584e
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
Add CLI commands and Gitea Actions workflow
2026-01-31 15:27:58 +00:00

201 lines
5.5 KiB
Python

"""Explain command for Local Code Assistant."""
from pathlib import Path
from typing import Optional
import click
from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from local_code_assistant.commands.base import BaseCommand
from local_code_assistant.prompts.templates import LanguageConfig, PromptTemplates
from local_code_assistant.services.ollama import OllamaService
console = Console()
class ExplainCommand(BaseCommand):
"""Command for explaining code."""
def __init__(self, ollama: OllamaService, config):
"""Initialize explain command.
Args:
ollama: Ollama service instance.
config: Configuration service instance.
"""
super().__init__(ollama, config)
self.supported_languages = LanguageConfig.get_supported_languages()
def run(
self,
code: str,
language: Optional[str] = None,
format_markdown: bool = False
) -> str:
"""Execute code explanation.
Args:
code: Code to explain.
language: Programming language (auto-detected if not provided).
format_markdown: Whether to format as markdown.
Returns:
Explanation text.
"""
if not self.ollama.check_connection():
raise click.ClickException(
"Cannot connect to Ollama. Make sure it's running."
)
if language is None:
language = self._detect_language(code)
if language not in self.supported_languages:
language = "text"
console.print("[dim]Analyzing code...[/dim]")
full_prompt = PromptTemplates.code_explanation(
language=language,
code=code
)
system_prompt = PromptTemplates.build_system_prompt(
"You are explaining code to a developer. Be clear and concise."
)
try:
explanation = self.ollama.generate(
prompt=full_prompt,
model=self._get_model(),
system=system_prompt,
temperature=self._get_temperature(0.3)
)
self._display_output(explanation, format_markdown)
return explanation
except Exception as e:
raise click.ClickException(f"Explanation failed: {str(e)}") from e
def run_file(
self,
file: Path,
format_markdown: bool = False
) -> str:
"""Explain code from a file.
Args:
file: Path to file.
format_markdown: Whether to format as markdown.
Returns:
Explanation text.
"""
if not file.exists():
raise click.ClickException(f"File not found: {file}")
code = file.read_text()
language = self._detect_language_from_file(file)
return self.run(code, language, format_markdown)
def _detect_language(self, code: str) -> str:
"""Detect programming language from code content.
Args:
code: Source code.
Returns:
Detected language.
"""
if "def " in code or "import " in code or "class " in code:
return "python"
elif "function " in code or "const " in code or "let " in code:
return "javascript"
elif "interface " in code or "type " in code or ": string" in code:
return "typescript"
elif "func " in code or "package " in code:
return "go"
elif "fn " in code or "let " in code or "struct " in code:
return "rust"
return "text"
def _detect_language_from_file(self, file: Path) -> str:
"""Detect language from file extension.
Args:
file: File path.
Returns:
Language name.
"""
suffix = file.suffix.lower()
language_map = {
".py": "python",
".js": "javascript",
".ts": "typescript",
".tsx": "typescript",
".go": "go",
".rs": "rust"
}
return language_map.get(suffix, "text")
def _display_output(self, explanation: str, as_markdown: bool):
"""Display explanation.
Args:
explanation: Explanation text.
as_markdown: Whether to render as markdown.
"""
if as_markdown:
console.print(Panel(Markdown(explanation), title="Explanation"))
else:
console.print(Panel(explanation, title="Explanation"))
@click.command()
@click.argument("file", type=click.Path(exists=True, path_type=Path))
@click.option(
"--language", "-l",
type=click.Choice(LanguageConfig.get_supported_languages()),
default=None,
help="Programming language (auto-detected if not specified)"
)
@click.option(
"--markdown/--no-markdown",
default=False,
help="Format output as markdown"
)
@click.pass_context
def explain_cmd(
ctx: click.Context,
file: Path,
language: Optional[str],
markdown: bool
):
"""Explain code from a file.
Example:
local-code-assistant explain script.py
local-code-assistant explain app.ts --markdown
\f
Args:
ctx: Click context.
file: Path to file to explain.
language: Programming language.
markdown: Format as markdown.
"""
config = ctx.obj["config"]
ollama_service = OllamaService(config)
ctx.obj["ollama_service"] = ollama_service
command = ExplainCommand(ollama_service, config)
command.run_file(file, markdown)