351 lines
12 KiB
Python
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() |