CLImate

PHPのためのターミナル出力ライブラリ。カラー、パディング、フォーマットなど、美しいCLI出力を簡単に作成できます。

phpcliterminaloutputstyling

フレームワーク

CLImate

概要

CLImateは、PHPのためのターミナル出力ライブラリです。カラー、パディング、フォーマットなど、美しいCLI出力を簡単に作成できます。ターミナル出力の見た目を重視する開発者に人気で、他のCLIフレームワークと組み合わせて使用されることが多い、専門的な出力ライブラリです。

詳細

CLImateはコマンドライン出力の視覚的体験を向上させることに特化したライブラリです。テキストのスタイリング、テーブル、プログレスバー、アニメーション、対話的な入力など、豊富な機能を提供し、プロフェッショナルなCLIアプリケーションの見た目を実現します。

主な特徴

  • 豊富な色とスタイル: 16色、256色、TrueColorをサポート
  • テーブル表示: カスタマイズ可能な美しいテーブル
  • プログレスバー: 多様なスタイルのプログレス表示
  • 対話的入力: プロンプト、選択肢、確認ダイアログ
  • テキスト装飾: パディング、アライメント、ボーダー
  • アニメーション: スピナー、点滅効果
  • JSON/CSV出力: 構造化データの整形出力
  • ターミナル検出: ターミナル機能の自動検出

メリット・デメリット

メリット

  • 美しい出力: プロフェッショナルで視覚的に魅力的な表示
  • 豊富な機能: 包括的な出力とフォーマット機能
  • 使いやすいAPI: 直感的で学習しやすいインターフェース
  • 柔軟性: 他のCLIライブラリとの組み合わせが容易
  • クロスプラットフォーム: Windows、Linux、macOSで動作
  • ターミナル対応: 様々なターミナル環境での適切な表示

デメリット

  • 専門性: CLI出力に特化しており、全体的なCLIフレームワークではない
  • 学習コスト: 豊富な機能を活用するには時間が必要
  • パフォーマンス: 装飾の多い出力は処理速度に影響する場合がある
  • 依存関係: 出力のためだけに外部ライブラリを追加する必要

主要リンク

書き方の例

インストールと基本設定

composer require league/climate

基本的なテキスト出力

<?php
require_once 'vendor/autoload.php';

use League\CLImate\CLImate;

$climate = new CLImate;

// 基本的なテキスト出力
$climate->out('通常のテキスト');

// 色付きテキスト
$climate->red('赤いテキスト');
$climate->green('緑のテキスト');
$climate->blue('青いテキスト');
$climate->yellow('黄色いテキスト');

// 背景色
$climate->backgroundRed('赤い背景');
$climate->backgroundGreen('緑の背景');

// 複合スタイル
$climate->bold('太字テキスト');
$climate->underline('下線付きテキスト');
$climate->bold()->red('太字の赤いテキスト');
$climate->underline()->blue()->backgroundYellow('複合スタイル');

// チェーンメソッド
$climate
    ->bold()
    ->green()
    ->out('チェーンしたスタイル');

テーブル表示の例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

// 基本的なテーブル
$data = [
    [
        'name'    => '田中太郎',
        'age'     => 30,
        'city'    => '東京',
        'email'   => '[email protected]'
    ],
    [
        'name'    => '佐藤花子', 
        'age'     => 25,
        'city'    => '大阪',
        'email'   => '[email protected]'
    ],
    [
        'name'    => '鈴木一郎',
        'age'     => 35, 
        'city'    => '名古屋',
        'email'   => '[email protected]'
    ]
];

$climate->table($data);

// カスタムヘッダーのテーブル
$climate->green()->bold()->out('社員一覧');
$climate->table($data);

// 動的テーブル作成
$climate->yellow()->out('動的テーブル例:');

$dynamicData = [];
for ($i = 1; $i <= 5; $i++) {
    $dynamicData[] = [
        'ID' => $i,
        'Product' => "商品{$i}",
        'Price' => rand(1000, 10000),
        'Stock' => rand(0, 100)
    ];
}

$climate->table($dynamicData);

プログレスバーの例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

// 基本的なプログレスバー
$climate->green()->out('ファイル処理中...');

$progress = $climate->progress()->total(100);

for ($i = 0; $i <= 100; $i++) {
    $progress->current($i);
    usleep(50000); // 50ms待機
}

$climate->green()->out('処理完了!');

// カスタムプログレスバー
$climate->yellow()->out('データベース移行中...');

$progress = $climate->progress()->total(50);
$progress->label('Migration Progress');

for ($i = 0; $i <= 50; $i++) {
    $progress->current($i, "Processing record {$i}/50");
    usleep(100000); // 100ms待機
}

$climate->green()->out('移行完了!');

対話的入力の例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

$climate->green()->bold()->out('ユーザー登録システム');
$climate->out('');

// テキスト入力
$name = $climate->input('お名前を入力してください:')->prompt();

// パスワード入力(非表示)
$password = $climate->password('パスワードを入力してください:')->prompt();

// 数値入力(バリデーション付き)
$age = $climate->input('年齢を入力してください:')->accept(function($response) {
    return is_numeric($response) && $response > 0 && $response < 150;
}, 'Invalid age. Please enter a number between 1 and 149.')->prompt();

// 選択肢
$gender = $climate->radio('性別を選択してください:', [
    'male' => '男性',
    'female' => '女性', 
    'other' => 'その他'
])->prompt();

// 複数選択
$interests = $climate->checkboxes('興味のある分野を選択してください:', [
    'programming' => 'プログラミング',
    'design' => 'デザイン',
    'music' => '音楽',
    'sports' => 'スポーツ',
    'reading' => '読書'
])->prompt();

// 確認
$confirm = $climate->confirm('以上の内容で登録しますか?');

if ($confirm) {
    $climate->green()->out('登録が完了しました!');
    
    // 結果表示
    $climate->yellow()->out('登録内容:');
    $climate->table([
        ['項目', '値'],
        ['名前', $name],
        ['年齢', $age],
        ['性別', $gender],
        ['興味', implode(', ', $interests)]
    ]);
} else {
    $climate->red()->out('登録がキャンセルされました。');
}

パディングとアライメントの例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

// パディング
$climate->green()->out('パディング例:');

$climate->tab()->out('タブでインデント');
$climate->tab(2)->out('2つのタブでインデント');

// カスタムパディング
$climate->padding(10)->out('10文字のパディング');
$climate->padding(5, '=')->out('カスタムパディング文字');

// アライメント
$climate->yellow()->out('アライメント例:');

$climate->center('中央揃えテキスト');
$climate->right('右揃えテキスト');

// 複合パディング
$climate->tab()->green()->bold()->out('階層構造の表示:');
$climate->tab(2)->out('サブアイテム1');
$climate->tab(2)->out('サブアイテム2');
$climate->tab(3)->blue()->out('ネストされたアイテム');

ボーダーとボックスの例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

// シンプルなボーダー
$climate->border();
$climate->out('ボーダーで囲まれたテキスト');
$climate->border();

// カスタムボーダー
$climate->border('=', 50);
$climate->center('カスタムボーダー');
$climate->border('=', 50);

// 複数ラインのボックス
$climate->green()->border('-', 60);
$climate->green()->out('システム情報');
$climate->border('-', 60);

$systemInfo = [
    'OS' => PHP_OS,
    'PHP Version' => PHP_VERSION,
    'Memory Limit' => ini_get('memory_limit'),
    'Max Execution Time' => ini_get('max_execution_time') . 's'
];

foreach ($systemInfo as $key => $value) {
    $climate->tab()->out("{$key}: {$value}");
}

$climate->border('-', 60);

JSONとCSV出力の例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

$data = [
    [
        'id' => 1, 
        'name' => '商品A',
        'price' => 1000,
        'category' => 'Electronics'
    ],
    [
        'id' => 2,
        'name' => '商品B', 
        'price' => 2000,
        'category' => 'Books'
    ],
    [
        'id' => 3,
        'name' => '商品C',
        'price' => 1500,
        'category' => 'Clothing'
    ]
];

// JSON出力
$climate->yellow()->out('JSON形式:');
$climate->json($data);

$climate->out('');

// 整形されたJSON
$climate->yellow()->out('整形されたJSON:');
$climate->dump($data);

アニメーションとスピナーの例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

// スピナーアニメーション
$climate->green()->out('データ処理中...');

$spinner = ['|', '/', '-', '\\'];
$spinnerIndex = 0;

for ($i = 0; $i < 20; $i++) {
    $climate->inline("\r処理中 " . $spinner[$spinnerIndex]);
    $spinnerIndex = ($spinnerIndex + 1) % count($spinner);
    usleep(200000); // 200ms
}

$climate->out("\r処理完了!       ");

// 点滅効果
$climate->yellow()->out('重要な通知:');
for ($i = 0; $i < 5; $i++) {
    $climate->inline("\r" . ($i % 2 ? '★' : '☆') . ' システムアップデート利用可能 ' . ($i % 2 ? '★' : '☆'));
    usleep(500000); // 500ms
}
$climate->out('');

エラーハンドリングとログの例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

class Logger
{
    private $climate;
    
    public function __construct(CLImate $climate)
    {
        $this->climate = $climate;
    }
    
    public function info($message)
    {
        $this->climate->blue()->out('[INFO] ' . date('Y-m-d H:i:s') . ' - ' . $message);
    }
    
    public function warning($message)
    {
        $this->climate->yellow()->out('[WARNING] ' . date('Y-m-d H:i:s') . ' - ' . $message);
    }
    
    public function error($message)
    {
        $this->climate->red()->out('[ERROR] ' . date('Y-m-d H:i:s') . ' - ' . $message);
    }
    
    public function success($message)
    {
        $this->climate->green()->out('[SUCCESS] ' . date('Y-m-d H:i:s') . ' - ' . $message);
    }
}

// 使用例
$logger = new Logger($climate);

$logger->info('アプリケーションを開始しています...');
$logger->info('設定ファイルを読み込み中...');

try {
    // 何らかの処理
    $logger->success('設定ファイルの読み込みが完了しました');
    
    // エラーをシミュレート
    if (rand(0, 1)) {
        throw new Exception('データベース接続エラー');
    }
    
    $logger->success('処理が正常に完了しました');
    
} catch (Exception $e) {
    $logger->error($e->getMessage());
    $logger->warning('処理を続行できません');
}

$logger->info('アプリケーションを終了します');

高度な機能の組み合わせ例

<?php
use League\CLImate\CLImate;

$climate = new CLImate;

// アプリケーションヘッダー
$climate->clear(); // 画面クリア
$climate->green()->bold()->border('=', 70);
$climate->green()->bold()->center('データ分析ツール v1.0.0');
$climate->green()->bold()->border('=', 70);
$climate->out('');

// メニュー表示
$climate->yellow()->bold()->out('利用可能な操作:');
$climate->tab()->out('1. データインポート');
$climate->tab()->out('2. データ分析');
$climate->tab()->out('3. レポート生成');
$climate->tab()->out('4. 設定');
$climate->tab()->out('5. 終了');
$climate->out('');

// 選択肢
$choice = $climate->radio('操作を選択してください:', [
    '1' => 'データインポート',
    '2' => 'データ分析', 
    '3' => 'レポート生成',
    '4' => '設定',
    '5' => '終了'
])->prompt();

switch ($choice) {
    case '1':
        $climate->green()->out('データインポートを開始します...');
        
        $file = $climate->input('CSVファイルのパスを入力してください:')->prompt();
        
        if (file_exists($file)) {
            $progress = $climate->progress()->total(100);
            $progress->label('インポート中');
            
            for ($i = 0; $i <= 100; $i += 10) {
                $progress->current($i);
                usleep(300000);
            }
            
            $climate->green()->bold()->out('✓ インポートが完了しました!');
        } else {
            $climate->red()->out('✗ ファイルが見つかりません');
        }
        break;
        
    case '2':
        $climate->blue()->out('データ分析を実行中...');
        
        // 分析結果の表示
        $analysisData = [
            ['項目', '値', 'ステータス'],
            ['総レコード数', '1,234', '✓'],
            ['エラーレコード', '12', '⚠'],
            ['処理時間', '2.3秒', '✓'],
            ['メモリ使用量', '45MB', '✓']
        ];
        
        $climate->table($analysisData);
        break;
        
    case '5':
        $climate->red()->out('アプリケーションを終了します...');
        break;
        
    default:
        $climate->yellow()->out('この機能は現在開発中です。');
}

$climate->out('');
$climate->border('-', 70);
$climate->center('ありがとうございました');
$climate->border('-', 70);