diff --git a/shell_speak/interactive.py b/shell_speak/interactive.py index 7630378..e4446bc 100644 --- a/shell_speak/interactive.py +++ b/shell_speak/interactive.py @@ -2,18 +2,20 @@ import os import shutil -from typing import Callable, Optional +from collections.abc import Generator from prompt_toolkit import PromptSession from prompt_toolkit.completion import Completer, Completion +from prompt_toolkit.document import Document from prompt_toolkit.history import FileHistory +from prompt_toolkit.key_binding import KeyBindings, KeyPressEvent from prompt_toolkit.keys import Keys -from prompt_toolkit.key_binding import KeyBindings from shell_speak.config import ensure_data_dir, get_data_dir +from shell_speak.history import get_history_manager from shell_speak.library import get_loader from shell_speak.matcher import get_matcher -from shell_speak.history import get_history_manager +from shell_speak.models import CommandMatch from shell_speak.output import ( console, display_command, @@ -21,17 +23,18 @@ from shell_speak.output import ( display_help_header, display_history, ) -from shell_speak.models import CommandMatch class ShellSpeakCompleter(Completer): """Auto-completion for shell-speak.""" - def __init__(self): + def __init__(self) -> None: self._loader = get_loader() self._history_manager = get_history_manager() - def get_completions(self, document, complete_event): + def get_completions( + self, document: Document, complete_event: object + ) -> Generator[Completion, None, None]: text = document.text_before_cursor last_word = text.split()[-1] if text.split() else "" @@ -60,29 +63,29 @@ def create_key_bindings() -> KeyBindings: kb = KeyBindings() @kb.add(Keys.ControlC) - def _(event): + def _(event: KeyPressEvent) -> None: event.app.exit() @kb.add(Keys.ControlL) - def _(event): + def _(event: KeyPressEvent) -> None: os.system("clear" if os.name == "posix" else "cls") return kb -def get_terminal_size() -> tuple: +def get_terminal_size() -> tuple[int, int]: """Get terminal size.""" return shutil.get_terminal_size() -def run_interactive_mode(): +def run_interactive_mode() -> None: # noqa: C901 """Run the interactive shell mode.""" ensure_data_dir() display_help_header() history_file = get_data_dir() / ".history" - session = PromptSession( + session: PromptSession[str] = PromptSession( history=FileHistory(str(history_file)), completer=ShellSpeakCompleter(), key_bindings=create_key_bindings(), @@ -165,8 +168,8 @@ def run_interactive_mode(): console.print("[error]Invalid index[/]") continue - tool = _detect_tool(user_input) - match = _process_query(user_input, tool) + detected_tool: str | None = _detect_tool(user_input) + match = _process_query(user_input, detected_tool) if match: history_manager.add(user_input, match.command, match.pattern.tool, match.explanation) @@ -174,7 +177,7 @@ def run_interactive_mode(): console.print("\n[info]Goodbye![/]") -def _detect_tool(query: str) -> Optional[str]: +def _detect_tool(query: str) -> str | None: """Detect which tool the query is about.""" query_lower = query.lower() @@ -195,7 +198,7 @@ def _detect_tool(query: str) -> Optional[str]: return None -def _process_query(query: str, tool: Optional[str]) -> Optional[CommandMatch]: +def _process_query(query: str, tool: str | None) -> CommandMatch | None: """Process a user query and display the result.""" matcher = get_matcher() match = matcher.match(query, tool) @@ -209,7 +212,7 @@ def _process_query(query: str, tool: Optional[str]) -> Optional[CommandMatch]: return None -def _show_interactive_help(): +def _show_interactive_help() -> None: """Show help for interactive mode.""" help_text = """ [bold]Shell Speak - Interactive Help[/bold]