Files
overcode/utils/autocomplete.py

351 lines
12 KiB
Python

#!/usr/bin/env python3
"""
OverCode Auto-completion System - Smart command suggestions and tab completion
"""
import os
import re
import difflib
from typing import List, Dict, Tuple
from colorama import Fore, Style, init
init(autoreset=True)
class AutoComplete:
"""Advanced auto-completion system for OverCode"""
def __init__(self):
# Core commands
self.commands = {
'help': 'Show available commands and help',
'new': 'Create a new file with templates',
'run': 'Execute an OverCode file',
'game': 'Launch the gaming center',
'theme': 'Change shell theme',
'clear': 'Clear the screen',
'ls': 'List directory contents',
'cd': 'Change directory',
'exit': 'Exit OverCode shell',
'stats': 'Show session statistics',
'fastfetch': 'Show system information',
'credits': 'Show project credits'
}
# Command arguments and subcommands
self.command_args = {
'new': {
'templates': ['hello', 'demo', 'games', 'web', 'ai', 'crypto'],
'extensions': ['.ovc'],
'syntax': 'new <filename>:<template>'
},
'game': {
'games': ['snake', 'tetris', '2048', 'life', 'adventure', 'mines',
'pong', 'breakout', 'memory', 'hangman', 'rps', 'quiz'],
'syntax': 'game [game_name]'
},
'theme': {
'themes': ['cyberpunk', 'matrix', 'ocean', 'sunset', 'hacker'],
'syntax': 'theme [theme_name]'
},
'run': {
'extensions': ['.ovc'],
'syntax': 'run <filename>'
}
}
# File patterns
self.file_patterns = {
'.ovc': 'OverCode polyglot files',
'.py': 'Python files',
'.js': 'JavaScript files',
'.php': 'PHP files',
'.go': 'Go files',
'.rs': 'Rust files',
'.java': 'Java files',
'.cpp': 'C++ files',
'.c': 'C files'
}
# Fuzzy matching threshold
self.fuzzy_threshold = 0.6
def complete(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
"""Main completion method"""
words = line.split()
if not words:
return list(self.commands.keys())
# First word - complete command names
if len(words) == 1 and not line.endswith(' '):
return self._complete_command(text)
# Command arguments
command = words[0]
if command in self.command_args:
return self._complete_args(command, text, words[1:])
# File completion
return self._complete_files(text)
def _complete_command(self, text: str) -> List[str]:
"""Complete command names"""
matches = []
for cmd in self.commands:
if cmd.startswith(text.lower()):
matches.append(cmd)
# Add fuzzy matches if no exact matches
if not matches:
matches = self._fuzzy_match(text, list(self.commands.keys()))
return sorted(matches)
def _complete_args(self, command: str, text: str, args: List[str]) -> List[str]:
"""Complete command arguments"""
cmd_info = self.command_args[command]
# Game completion
if command == 'game':
return self._fuzzy_match(text, cmd_info['games'])
# Theme completion
elif command == 'theme':
return self._fuzzy_match(text, cmd_info['themes'])
# New file template completion
elif command == 'new':
if ':' in text:
# Template completion after colon
filename, template_part = text.split(':', 1)
matches = self._fuzzy_match(template_part, cmd_info['templates'])
return [f"{filename}:{match}" for match in matches]
else:
# File completion or template suggestion
file_matches = self._complete_files(text, ['.ovc'])
if not file_matches:
return [f"{text}:{template}" for template in cmd_info['templates']]
return file_matches
# File completion for run command
elif command == 'run':
return self._complete_files(text, ['.ovc'])
return []
def _complete_files(self, text: str, extensions: List[str] = None) -> List[str]:
"""Complete file names"""
try:
# Get current directory files
current_dir = os.getcwd()
files = os.listdir(current_dir)
matches = []
for file in files:
# Filter by extensions if specified
if extensions:
if not any(file.endswith(ext) for ext in extensions):
continue
if file.startswith(text):
matches.append(file)
# Add directories
for item in files:
if os.path.isdir(os.path.join(current_dir, item)):
if item.startswith(text):
matches.append(item + '/')
return sorted(matches)
except (OSError, PermissionError):
return []
def _fuzzy_match(self, text: str, candidates: List[str]) -> List[str]:
"""Fuzzy string matching for suggestions"""
if not text:
return candidates
matches = difflib.get_close_matches(
text.lower(),
[c.lower() for c in candidates],
n=10,
cutoff=self.fuzzy_threshold
)
# Return original case versions
result = []
for match in matches:
for candidate in candidates:
if candidate.lower() == match:
result.append(candidate)
break
return result
def suggest_correction(self, command: str) -> str:
"""Suggest correction for mistyped commands"""
# Try fuzzy matching on commands
matches = self._fuzzy_match(command, list(self.commands.keys()))
if matches:
suggestion = matches[0]
return f"{Fore.YELLOW}Did you mean: {Fore.CYAN}{suggestion}{Fore.YELLOW}?"
return ""
def show_command_help(self, command: str) -> str:
"""Show help for specific command"""
if command in self.commands:
help_text = f"{Fore.CYAN}{command}{Fore.WHITE} - {self.commands[command]}"
if command in self.command_args:
cmd_info = self.command_args[command]
help_text += f"\n{Fore.YELLOW}Syntax: {cmd_info['syntax']}"
if 'games' in cmd_info:
help_text += f"\n{Fore.GREEN}Games: {', '.join(cmd_info['games'])}"
elif 'themes' in cmd_info:
help_text += f"\n{Fore.GREEN}Themes: {', '.join(cmd_info['themes'])}"
elif 'templates' in cmd_info:
help_text += f"\n{Fore.GREEN}Templates: {', '.join(cmd_info['templates'])}"
return help_text
return f"{Fore.RED}Command '{command}' not found"
def get_command_suggestions(self, partial_command: str) -> List[Tuple[str, str]]:
"""Get command suggestions with descriptions"""
matches = self._complete_command(partial_command)
return [(cmd, self.commands[cmd]) for cmd in matches[:5]]
def smart_suggest(self, line: str) -> str:
"""Provide smart suggestions based on context"""
words = line.strip().split()
if not words:
return f"{Fore.CYAN}💡 Try: help, new, game, theme, run"
command = words[0]
# Unknown command
if command not in self.commands:
correction = self.suggest_correction(command)
if correction:
return correction
return f"{Fore.RED}Unknown command. {Fore.CYAN}Type 'help' for available commands."
# Incomplete command
if len(words) == 1:
if command in self.command_args:
cmd_info = self.command_args[command]
return f"{Fore.YELLOW}💡 Syntax: {cmd_info['syntax']}"
# Command-specific suggestions
if command == 'new' and len(words) == 2:
arg = words[1]
if ':' not in arg:
templates = self.command_args['new']['templates']
return f"{Fore.YELLOW}💡 Add template: {Fore.CYAN}{arg}:<template> {Fore.WHITE}({', '.join(templates)})"
elif command == 'game' and len(words) == 1:
games = self.command_args['game']['games'][:5]
return f"{Fore.YELLOW}💡 Available games: {Fore.CYAN}{', '.join(games)}..."
elif command == 'theme' and len(words) == 1:
themes = self.command_args['theme']['themes']
return f"{Fore.YELLOW}💡 Available themes: {Fore.CYAN}{', '.join(themes)}"
return ""
class SmartPrompt:
"""Enhanced prompt with auto-completion hints"""
def __init__(self, autocomplete: AutoComplete):
self.autocomplete = autocomplete
self.history = []
self.history_index = -1
def get_input(self, prompt: str) -> str:
"""Get input with smart suggestions"""
try:
# Simple input for now - in real implementation would use readline
user_input = input(prompt).strip()
if user_input:
self.history.append(user_input)
self.history_index = len(self.history)
return user_input
except KeyboardInterrupt:
print("\n^C")
return ""
except EOFError:
return "exit"
def show_suggestions(self, partial_line: str):
"""Show contextual suggestions"""
suggestions = self.autocomplete.smart_suggest(partial_line)
if suggestions:
print(suggestions)
def show_completions(self, text: str, line: str):
"""Show available completions"""
completions = self.autocomplete.complete(text, line, 0, len(text))
if completions:
print(f"\n{Fore.CYAN}Suggestions:")
for i, comp in enumerate(completions[:8]): # Show max 8
print(f" {Fore.YELLOW}{i+1}.{Fore.WHITE} {comp}")
if len(completions) > 8:
print(f" {Fore.LIGHTBLACK_EX}... and {len(completions) - 8} more")
# Integration with the main shell
def setup_autocomplete(shell_instance):
"""Set up auto-completion for the shell"""
autocomplete = AutoComplete()
smart_prompt = SmartPrompt(autocomplete)
# Add completion method to shell
def complete_command(self, text, line, begidx, endidx):
return autocomplete.complete(text, line, begidx, endidx)
shell_instance.complete_command = complete_command
shell_instance.autocomplete = autocomplete
shell_instance.smart_prompt = smart_prompt
return autocomplete
# Demo and testing functions
def demo_autocomplete():
"""Demonstrate auto-completion features"""
print(Fore.CYAN + "🔍 OverCode Auto-completion Demo")
print("=" * 50)
ac = AutoComplete()
# Test command completion
print(f"\n{Fore.WHITE}Command completion for 'g':")
matches = ac._complete_command('g')
for match in matches:
print(f" {Fore.GREEN}{match}")
# Test fuzzy matching
print(f"\n{Fore.WHITE}Fuzzy matching for 'tem':")
matches = ac._fuzzy_match('tem', ac.command_args['theme']['themes'])
for match in matches:
print(f" {Fore.YELLOW}{match}")
# Test suggestions
print(f"\n{Fore.WHITE}Smart suggestions:")
test_commands = ['gam', 'new hello.ovc', 'theme', 'unknown_command']
for cmd in test_commands:
suggestion = ac.smart_suggest(cmd)
print(f" '{cmd}'{suggestion}")
print(f"\n{Fore.GREEN}✨ Auto-completion demo complete!")
if __name__ == "__main__":
demo_autocomplete()