docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,446 @@
<?php
declare(strict_types=1);
namespace App\Framework\Console\Components;
use App\Framework\Console\CommandHistory;
use App\Framework\Console\ConsoleColor;
use App\Framework\Console\ConsoleOutputInterface;
use App\Framework\Console\HistoryTab;
use App\Framework\Console\Screen\CursorControlCode;
use App\Framework\Console\Screen\ScreenControlCode;
use App\Framework\Console\TuiView;
use App\Framework\Discovery\ValueObjects\DiscoveredAttribute;
/**
* Handles all rendering and display logic for the TUI
*/
final readonly class TuiRenderer
{
public function __construct(
private ConsoleOutputInterface $output
) {
}
/**
* Render the current view based on state
*/
public function render(TuiState $state, CommandHistory $history): void
{
$this->clearScreen();
$this->renderHeader();
match ($state->getCurrentView()) {
TuiView::CATEGORIES => $this->renderCategories($state),
TuiView::COMMANDS => $this->renderCommands($state),
TuiView::SEARCH => $this->renderSearch($state),
TuiView::HISTORY => $this->renderHistory($state, $history),
TuiView::FORM => $this->renderForm($state),
TuiView::DASHBOARD => $this->renderDashboard($state),
TuiView::HELP => $this->renderHelp($state),
};
}
/**
* Clear screen and reset cursor
*/
private function clearScreen(): void
{
$this->output->write(ScreenControlCode::CLEAR_ALL->format());
$this->output->write(CursorControlCode::POSITION->format(1, 1));
}
/**
* Render header with title
*/
private function renderHeader(): void
{
$this->output->writeLine('');
$this->output->writeLine('🚀 Interactive Console - Modern TUI', ConsoleColor::BRIGHT_CYAN);
$this->output->writeLine(str_repeat('═', 60), ConsoleColor::GRAY);
$this->output->writeLine('');
}
/**
* Render categories view
*/
private function renderCategories(TuiState $state): void
{
$this->output->writeLine('📂 Select Category:', ConsoleColor::BRIGHT_YELLOW);
$this->output->writeLine('');
$categories = $state->getCategories();
foreach ($categories as $index => $category) {
$isSelected = $index === $state->getSelectedCategory();
$this->renderCategoryItem($category, $isSelected);
}
$this->output->newLine();
$this->renderNavigationBar([
"↑/↓: Navigate",
"Enter: Select",
"/: Search",
"R: History",
"D: Dashboard",
"F1: Help",
"Q: Quit",
]);
}
/**
* Render a category item
*/
private function renderCategoryItem(array $category, bool $isSelected): void
{
$icon = $category['icon'] ?? '📁';
$name = $category['name'];
$count = count($category['commands']);
$prefix = $isSelected ? '▶ ' : ' ';
$color = $isSelected ? ConsoleColor::BRIGHT_WHITE : ConsoleColor::WHITE;
$this->output->writeLine(
"{$prefix}{$icon} {$name} ({$count} commands)",
$color
);
}
/**
* Render commands view
*/
private function renderCommands(TuiState $state): void
{
$category = $state->getCurrentCategory();
if (! $category) {
return;
}
$icon = $category['icon'] ?? '📁';
$this->output->writeLine("📂 {$icon} {$category['name']} Commands:", ConsoleColor::BRIGHT_YELLOW);
$this->output->writeLine('');
foreach ($category['commands'] as $index => $command) {
$isSelected = $index === $state->getSelectedCommand();
$this->renderCommandItem($command, $isSelected);
}
$this->output->newLine();
$this->renderNavigationBar([
"↑/↓: Navigate",
"Enter: Execute",
"Space: Parameters",
"H: Help",
"V: Validate",
"/: Search",
"R: History",
"←: Back",
"Q: Quit",
]);
}
/**
* Render a command item
*/
private function renderCommandItem(object $command, bool $isSelected): void
{
$prefix = $isSelected ? '▶ ' : ' ';
$color = $isSelected ? ConsoleColor::BRIGHT_WHITE : ConsoleColor::WHITE;
// Handle DiscoveredAttribute objects
if ($command instanceof DiscoveredAttribute) {
$attribute = $command->createAttributeInstance();
if ($attribute === null) {
return;
}
$commandName = $attribute->name;
$commandDescription = $attribute->description ?? '';
} else {
// Fallback for legacy objects
$commandName = $command->name ?? 'Unknown Command';
$commandDescription = $command->description ?? '';
}
$this->output->writeLine("{$prefix}{$commandName}", $color);
if (! empty($commandDescription)) {
$descColor = ConsoleColor::GRAY;
$this->output->writeLine(" {$commandDescription}", $descColor);
}
}
/**
* Render search view
*/
private function renderSearch(TuiState $state): void
{
$this->output->writeLine('🔍 Search Commands:', ConsoleColor::BRIGHT_YELLOW);
$this->output->writeLine('');
// Search box
$query = $state->getSearchQuery();
$this->output->writeLine("Search: {$query}_", ConsoleColor::BRIGHT_WHITE);
$this->output->writeLine('');
// Results
$results = $state->getSearchResults();
if (empty($results)) {
if (! empty($query)) {
$this->output->writeLine('No commands found matching your search.', ConsoleColor::YELLOW);
} else {
$this->output->writeLine('Start typing to search commands...', ConsoleColor::GRAY);
}
} else {
$resultCount = count($results);
$this->output->writeLine("Found {$resultCount} result(s):", ConsoleColor::WHITE);
$this->output->writeLine('');
foreach ($results as $index => $command) {
$isSelected = $index === $state->getSelectedSearchResult();
$this->renderCommandItem($command, $isSelected);
}
$current = $state->getSelectedSearchResult() + 1;
$total = count($results);
if ($total > 1) {
$this->output->writeLine('');
$this->output->writeLine(" Showing result $current of $total", ConsoleColor::GRAY);
}
}
// Navigation shortcuts
$shortcuts = [
'Type: Search',
'Enter: Execute',
'Space: Parameters',
'H: Help',
'V: Validate',
'R: History',
'Esc: Back',
'D: Dashboard',
'Q: Exit',
];
$this->renderNavigationBar($shortcuts);
}
/**
* Render history view
*/
private function renderHistory(TuiState $state, CommandHistory $history): void
{
$this->output->writeLine('📚 Command History:', ConsoleColor::BRIGHT_YELLOW);
$this->output->writeLine('');
// Tab navigation
$this->renderHistoryTabs($state->getHistoryTab());
// History items
$items = $this->getHistoryItems($state->getHistoryTab(), $history);
if (empty($items)) {
$this->output->writeLine('No history available.', ConsoleColor::YELLOW);
} else {
foreach ($items as $index => $item) {
$isSelected = $index === $state->getSelectedHistoryItem();
$this->renderHistoryItem($item, $isSelected, $history);
}
}
$this->output->writeLine('');
$this->renderNavigationHelp([
"↑/↓: Navigate",
"←/→: Switch tabs",
"Enter: Execute command",
"Space: Parameters",
"H: Help",
"V: Validate",
"F: Toggle favorite",
"C: Clear history",
"/: Search",
"Q: Quit",
]);
}
/**
* Render history tabs
*/
private function renderHistoryTabs(HistoryTab $activeTab): void
{
$tabs = [
HistoryTab::RECENT,
HistoryTab::FREQUENT,
HistoryTab::FAVORITES,
];
$tabDisplay = [];
foreach ($tabs as $tab) {
$isActive = $tab === $activeTab;
$color = $isActive ? ConsoleColor::BRIGHT_WHITE : ConsoleColor::GRAY;
$prefix = $isActive ? '[' : ' ';
$suffix = $isActive ? ']' : ' ';
$tabDisplay[] = [
'text' => "{$prefix}{$tab->getIcon()} {$tab->getTitle()}{$suffix}",
'color' => $color,
];
}
foreach ($tabDisplay as $tab) {
$this->output->write($tab['text'], $tab['color']);
}
$this->output->writeLine('');
$this->output->writeLine('');
}
/**
* Render history item
*/
private function renderHistoryItem(array $item, bool $isSelected, CommandHistory $history): void
{
$prefix = $isSelected ? '▶ ' : ' ';
$color = $isSelected ? ConsoleColor::BRIGHT_WHITE : ConsoleColor::WHITE;
$command = $item['command'];
$isFavorite = $history->isFavorite($command);
$favoriteIcon = $isFavorite ? '⭐' : ' ';
$this->output->writeLine("{$prefix}{$favoriteIcon}{$command}", $color);
// Additional info based on type
$infoColor = ConsoleColor::GRAY;
if (isset($item['count'])) {
$this->output->writeLine(" Used {$item['count']} times", $infoColor);
}
if (isset($item['timestamp'])) {
$timeAgo = $this->timeAgo($item['timestamp']);
$this->output->writeLine(" {$timeAgo}", $infoColor);
}
}
/**
* Render form view placeholder
*/
private function renderForm(TuiState $state): void
{
$this->output->writeLine('📝 Interactive Form', ConsoleColor::BRIGHT_YELLOW);
$this->output->writeLine('Form functionality handled by InteractiveForm class', ConsoleColor::GRAY);
}
/**
* Render dashboard view
*/
private function renderDashboard(TuiState $state): void
{
$this->output->writeLine('📊 System Dashboard', ConsoleColor::BRIGHT_YELLOW);
$this->output->writeLine('');
$this->output->writeLine('Console system status and metrics', ConsoleColor::WHITE);
$this->output->writeLine('');
$this->renderNavigationBar([
"Categories: C",
"Search: /",
"History: R",
"Help: F1",
"Back: Esc",
"Quit: Q",
]);
}
/**
* Render help view
*/
private function renderHelp(TuiState $state): void
{
$this->output->writeLine('❓ Help & Shortcuts', ConsoleColor::BRIGHT_YELLOW);
$this->output->writeLine('');
$helpSections = [
'Navigation' => [
'↑/↓ Arrow Keys' => 'Navigate up and down in lists',
'←/→ Arrow Keys' => 'Navigate left/right, switch tabs',
'Enter' => 'Execute selected command',
'Esc' => 'Go back to previous view',
],
'Commands' => [
'Space' => 'Open interactive parameter form',
'H' => 'Show detailed command help',
'V' => 'Validate command signature',
'F1' => 'Show all commands help overview',
],
'Views' => [
'/' => 'Search commands',
'R' => 'Command history',
'D' => 'Dashboard',
'C' => 'Categories (from other views)',
],
'History' => [
'F' => 'Toggle command as favorite',
'C' => 'Clear command history',
],
];
foreach ($helpSections as $section => $items) {
$this->output->writeLine($section . ':', ConsoleColor::BRIGHT_WHITE);
foreach ($items as $key => $description) {
$this->output->writeLine(" {$key} - {$description}", ConsoleColor::WHITE);
}
$this->output->writeLine('');
}
$this->renderNavigationBar([
"Back: Esc",
"Categories: C",
"Quit: Q",
]);
}
/**
* Render navigation bar
*/
private function renderNavigationBar(array $items): void
{
$this->output->writeLine(str_repeat('─', 60), ConsoleColor::GRAY);
$this->output->writeLine(implode(' | ', $items), ConsoleColor::BRIGHT_BLUE);
}
/**
* Render navigation help
*/
private function renderNavigationHelp(array $items): void
{
$this->output->writeLine(str_repeat('─', 60), ConsoleColor::GRAY);
$this->output->writeLine(implode(' | ', $items), ConsoleColor::BRIGHT_BLUE);
}
/**
* Get history items based on tab
*/
private function getHistoryItems(HistoryTab $tab, CommandHistory $history): array
{
return match ($tab) {
HistoryTab::RECENT => $history->getRecentHistory(10),
HistoryTab::FREQUENT => $history->getFrequentCommands(10),
HistoryTab::FAVORITES => $history->getFavorites(),
};
}
/**
* Calculate time ago
*/
private function timeAgo(int $timestamp): string
{
$diff = time() - $timestamp;
if ($diff < 60) {
return "{$diff}s ago";
}
if ($diff < 3600) {
return floor($diff / 60) . "m ago";
}
if ($diff < 86400) {
return floor($diff / 3600) . "h ago";
}
return floor($diff / 86400) . "d ago";
}
}