maxHistorySize = $maxHistorySize; $storageDir = $storageDirectory ?? FilePath::create(sys_get_temp_dir() . '/console-history'); $this->historyFile = $storageDir->join('command_history.json'); $this->favoritesFile = $storageDir->join('command_favorites.json'); $this->loadHistory(); $this->loadFavorites(); } /** * Add a command to history */ public function addToHistory(string $commandName): void { // Remove if already exists to move to top $this->history = array_filter($this->history, fn ($entry) => $entry['command'] !== $commandName); // Add to beginning array_unshift($this->history, [ 'command' => $commandName, 'timestamp' => time(), 'count' => $this->getCommandCount($commandName) + 1, ]); // Limit history size if (count($this->history) > $this->maxHistorySize) { $this->history = array_slice($this->history, 0, $this->maxHistorySize); } $this->saveHistory(); } /** * Add command to favorites */ public function addToFavorites(string $commandName): void { if (! $this->isFavorite($commandName)) { $this->favorites[] = [ 'command' => $commandName, 'added_at' => time(), ]; $this->saveFavorites(); } } /** * Remove command from favorites */ public function removeFromFavorites(string $commandName): void { $this->favorites = array_filter( $this->favorites, fn ($entry) => $entry['command'] !== $commandName ); $this->favorites = array_values($this->favorites); // Re-index $this->saveFavorites(); } /** * Toggle favorite status */ public function toggleFavorite(string $commandName): bool { if ($this->isFavorite($commandName)) { $this->removeFromFavorites($commandName); return false; } else { $this->addToFavorites($commandName); return true; } } /** * Check if command is in favorites */ public function isFavorite(string $commandName): bool { return array_reduce( $this->favorites, fn ($carry, $entry) => $carry || $entry['command'] === $commandName, false ); } /** * Get recent command history */ public function getRecentHistory(int $limit = 10): array { return array_slice($this->history, 0, $limit); } /** * Get frequently used commands */ public function getFrequentCommands(int $limit = 10): array { $commands = $this->history; // Sort by usage count (descending) usort($commands, fn ($a, $b) => $b['count'] <=> $a['count']); return array_slice($commands, 0, $limit); } /** * Get all favorites */ public function getFavorites(): array { return $this->favorites; } /** * Get command usage statistics */ public function getCommandStats(string $commandName): array { $entry = array_find($this->history, fn ($entry) => $entry['command'] === $commandName); if (! $entry) { return [ 'command' => $commandName, 'count' => 0, 'last_used' => null, 'is_favorite' => $this->isFavorite($commandName), ]; } return [ 'command' => $commandName, 'count' => $entry['count'], 'last_used' => $entry['timestamp'], 'is_favorite' => $this->isFavorite($commandName), ]; } /** * Clear all history */ public function clearHistory(): void { $this->history = []; $this->saveHistory(); } /** * Clear all favorites */ public function clearFavorites(): void { $this->favorites = []; $this->saveFavorites(); } /** * Get suggestions based on partial input */ public function getSuggestions(string $partial, int $limit = 5): array { $suggestions = []; // Add matching favorites first foreach ($this->favorites as $favorite) { if (str_starts_with($favorite['command'], $partial)) { $suggestions[] = [ 'command' => $favorite['command'], 'type' => 'favorite', 'score' => 1000, // High priority for favorites ]; } } // Add matching recent commands foreach ($this->history as $entry) { $command = $entry['command']; if (str_starts_with($command, $partial) && ! $this->isFavorite($command)) { $suggestions[] = [ 'command' => $command, 'type' => 'recent', 'score' => 500 + $entry['count'], // Score based on usage count ]; } } // Sort by score (descending) and limit usort($suggestions, fn ($a, $b) => $b['score'] <=> $a['score']); return array_slice($suggestions, 0, $limit); } /** * Get command count from history */ private function getCommandCount(string $commandName): int { $entry = array_find($this->history, fn ($entry) => $entry['command'] === $commandName); return $entry ? $entry['count'] : 0; } /** * Load history from file */ private function loadHistory(): void { if ($this->historyFile->exists()) { $content = file_get_contents($this->historyFile->toString()); $decoded = json_decode($content, true); if (is_array($decoded)) { $this->history = $decoded; } } } /** * Save history to file */ private function saveHistory(): void { $this->ensureDirectoryExists($this->historyFile->getDirectory()); file_put_contents( $this->historyFile->toString(), json_encode($this->history, JSON_PRETTY_PRINT) ); } /** * Load favorites from file */ private function loadFavorites(): void { if ($this->favoritesFile->exists()) { $content = file_get_contents($this->favoritesFile->toString()); $decoded = json_decode($content, true); if (is_array($decoded)) { $this->favorites = $decoded; } } } /** * Save favorites to file */ private function saveFavorites(): void { $this->ensureDirectoryExists($this->favoritesFile->getDirectory()); file_put_contents( $this->favoritesFile->toString(), json_encode($this->favorites, JSON_PRETTY_PRINT) ); } /** * Ensure storage directory exists */ private function ensureDirectoryExists(FilePath $directory): void { if (! $directory->exists()) { mkdir($directory->toString(), 0755, true); } } }