Вход Регистрация
Файл: vendor/psy/psysh/src/Readline/Hoa/ConsoleCursor.php
Строк: 312
<?php

/**
 * Hoa
 *
 *
 * @license
 *
 * New BSD License
 *
 * Copyright © 2007-2017, Hoa community. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Hoa nor the names of its contributors may be
 *       used to endorse or promote products derived from this software without
 *       specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

namespace PsyReadlineHoa;

/**
 * Class HoaConsoleCursor.
 *
 * Allow to manipulate the cursor.
 */
class ConsoleCursor
{
    
/**
     * Move the cursor.
     * Steps can be:
     *     • u, up,    ↑ : move to the previous line;
     *     • U, UP       : move to the first line;
     *     • r, right, → : move to the next column;
     *     • R, RIGHT    : move to the last column;
     *     • d, down,  ↓ : move to the next line;
     *     • D, DOWN     : move to the last line;
     *     • l, left,  ← : move to the previous column;
     *     • L, LEFT     : move to the first column.
     * Steps can be concatened by a single space if $repeat is equal to 1.
     */
    
public static function move(string $stepsint $repeat 1)
    {
        if (
$repeat) {
            return;
        } elseif (
=== $repeat) {
            
$handle explode(' '$steps);
        } else {
            
$handle explode(' '$steps1);
        }

        
$tput Console::getTput();
        
$output Console::getOutput();

        foreach (
$handle as $step) {
            switch (
$step) {
                case 
'u':
                case 
'up':
                case 
'↑':
                    
$output->writeAll(
                        
str_replace(
                            
'%p1%d',
                            
$repeat,
                            
$tput->get('parm_up_cursor')
                        )
                    );

                    break;

                case 
'U':
                case 
'UP':
                    static::
moveTo(null1);

                    break;

                case 
'r':
                case 
'right':
                case 
'→':
                    
$output->writeAll(
                        
str_replace(
                            
'%p1%d',
                            
$repeat,
                            
$tput->get('parm_right_cursor')
                        )
                    );

                    break;

                case 
'R':
                case 
'RIGHT':
                    static::
moveTo(9999);

                    break;

                case 
'd':
                case 
'down':
                case 
'↓':
                    
$output->writeAll(
                        
str_replace(
                            
'%p1%d',
                            
$repeat,
                            
$tput->get('parm_down_cursor')
                        )
                    );

                    break;

                case 
'D':
                case 
'DOWN':
                    static::
moveTo(null9999);

                    break;

                case 
'l':
                case 
'left':
                case 
'←':
                    
$output->writeAll(
                        
str_replace(
                            
'%p1%d',
                            
$repeat,
                            
$tput->get('parm_left_cursor')
                        )
                    );

                    break;

                case 
'L':
                case 
'LEFT':
                    static::
moveTo(1);

                    break;
            }
        }
    }

    
/**
     * Move to the line X and the column Y.
     * If null, use the current coordinate.
     */
    
public static function moveTo(int $x nullint $y null)
    {
        if (
null === $x || null === $y) {
            
$position = static::getPosition();

            if (
null === $x) {
                
$x $position['x'];
            }

            if (
null === $y) {
                
$y $position['y'];
            }
        }

        
Console::getOutput()->writeAll(
            
str_replace(
                [
'%i%p1%d''%p2%d'],
                [
$y$x],
                
Console::getTput()->get('cursor_address')
            )
        );
    }

    
/**
     * Get current position (x and y) of the cursor.
     */
    
public static function getPosition(): array
    {
        
$tput Console::getTput();
        
$user7 $tput->get('user7');

        if (
null === $user7) {
            return [
                
'x' => 0,
                
'y' => 0,
            ];
        }

        
Console::getOutput()->writeAll($user7);

        
$input Console::getInput();

        
// Read $tput->get('user6').
        
$input->read(2); // skip 33 and [.

        
$x null;
        
$y null;
        
$handle = &$y;

        while (
true) {
            
$char $input->readCharacter();

            switch (
$char) {
                case 
';':
                    
$handle = &$x;

                    break;

                case 
'R':
                    break 
2;

                default:
                    
$handle .= $char;
            }
        }

        return [
            
'x' => (int) $x,
            
'y' => (int) $y,
        ];
    }

    
/**
     * Save current position.
     */
    
public static function save()
    {
        
Console::getOutput()->writeAll(
            
Console::getTput()->get('save_cursor')
        );
    }

    
/**
     * Restore cursor to the last saved position.
     */
    
public static function restore()
    {
        
Console::getOutput()->writeAll(
            
Console::getTput()->get('restore_cursor')
        );
    }

    
/**
     * Clear the screen.
     * Part can be:
     *     • a, all,   ↕ : clear entire screen and static::move(1, 1);
     *     • u, up,    ↑ : clear from cursor to beginning of the screen;
     *     • r, right, → : clear from cursor to the end of the line;
     *     • d, down,  ↓ : clear from cursor to end of the screen;
     *     • l, left,  ← : clear from cursor to beginning of the screen;
     *     •    line,  ↔ : clear all the line and static::move(1).
     * Parts can be concatenated by a single space.
     */
    
public static function clear(string $parts 'all')
    {
        
$tput Console::getTput();
        
$output Console::getOutput();

        foreach (
explode(' '$parts) as $part) {
            switch (
$part) {
                case 
'a':
                case 
'all':
                case 
'↕':
                    
$output->writeAll($tput->get('clear_screen'));
                    static::
moveTo(11);

                    break;

                case 
'u':
                case 
'up':
                case 
'↑':
                    
$output->writeAll("33[1J");

                    break;

                case 
'r':
                case 
'right':
                case 
'→':
                    
$output->writeAll($tput->get('clr_eol'));

                    break;

                case 
'd':
                case 
'down':
                case 
'↓':
                    
$output->writeAll($tput->get('clr_eos'));

                    break;

                case 
'l':
                case 
'left':
                case 
'←':
                    
$output->writeAll($tput->get('clr_bol'));

                    break;

                case 
'line':
                case 
'↔':
                    
$output->writeAll("r".$tput->get('clr_eol'));

                    break;
            }
        }
    }

    
/**
     * Hide the cursor.
     */
    
public static function hide()
    {
        
Console::getOutput()->writeAll(
            
Console::getTput()->get('cursor_invisible')
        );
    }

    
/**
     * Show the cursor.
     */
    
public static function show()
    {
        
Console::getOutput()->writeAll(
            
Console::getTput()->get('cursor_visible')
        );
    }

    
/**
     * Colorize cursor.
     * Attributes can be:
     *     •  n,         normal           : normal;
     *     •  b,         bold             : bold;
     *     •  u,         underlined       : underlined;
     *     •  bl,        blink            : blink;
     *     •  i,         inverse          : inverse;
     *     • !b,        !bold             : normal weight;
     *     • !u,        !underlined       : not underlined;
     *     • !bl,       !blink            : steady;
     *     • !i,        !inverse          : positive;
     *     • fg(color), foreground(color) : set foreground to “color”;
     *     • bg(color), background(color) : set background to “color”.
     * “color” can be:
     *     • default;
     *     • black;
     *     • red;
     *     • green;
     *     • yellow;
     *     • blue;
     *     • magenta;
     *     • cyan;
     *     • white;
     *     • 0-256 (classic palette);
     *     • #hexa.
     * Attributes can be concatenated by a single space.
     */
    
public static function colorize(string $attributes)
    {
        static 
$_rgbTo256 null;

        if (
null === $_rgbTo256) {
            
$_rgbTo256 = [
                
'000000''800000''008000''808000''000080''800080',
                
'008080''c0c0c0''808080''ff0000''00ff00''ffff00',
                
'0000ff''ff00ff''00ffff''ffffff''000000''00005f',
                
'000087''0000af''0000d7''0000ff''005f00''005f5f',
                
'005f87''005faf''005fd7''005fff''008700''00875f',
                
'008787''0087af''0087d7''0087ff''00af00''00af5f',
                
'00af87''00afaf''00afd7''00afff''00d700''00d75f',
                
'00d787''00d7af''00d7d7''00d7ff''00ff00''00ff5f',
                
'00ff87''00ffaf''00ffd7''00ffff''5f0000''5f005f',
                
'5f0087''5f00af''5f00d7''5f00ff''5f5f00''5f5f5f',
                
'5f5f87''5f5faf''5f5fd7''5f5fff''5f8700''5f875f',
                
'5f8787''5f87af''5f87d7''5f87ff''5faf00''5faf5f',
                
'5faf87''5fafaf''5fafd7''5fafff''5fd700''5fd75f',
                
'5fd787''5fd7af''5fd7d7''5fd7ff''5fff00''5fff5f',
                
'5fff87''5fffaf''5fffd7''5fffff''870000''87005f',
                
'870087''8700af''8700d7''8700ff''875f00''875f5f',
                
'875f87''875faf''875fd7''875fff''878700''87875f',
                
'878787''8787af''8787d7''8787ff''87af00''87af5f',
                
'87af87''87afaf''87afd7''87afff''87d700''87d75f',
                
'87d787''87d7af''87d7d7''87d7ff''87ff00''87ff5f',
                
'87ff87''87ffaf''87ffd7''87ffff''af0000''af005f',
                
'af0087''af00af''af00d7''af00ff''af5f00''af5f5f',
                
'af5f87''af5faf''af5fd7''af5fff''af8700''af875f',
                
'af8787''af87af''af87d7''af87ff''afaf00''afaf5f',
                
'afaf87''afafaf''afafd7''afafff''afd700''afd75f',
                
'afd787''afd7af''afd7d7''afd7ff''afff00''afff5f',
                
'afff87''afffaf''afffd7''afffff''d70000''d7005f',
                
'd70087''d700af''d700d7''d700ff''d75f00''d75f5f',
                
'd75f87''d75faf''d75fd7''d75fff''d78700''d7875f',
                
'd78787''d787af''d787d7''d787ff''d7af00''d7af5f',
                
'd7af87''d7afaf''d7afd7''d7afff''d7d700''d7d75f',
                
'd7d787''d7d7af''d7d7d7''d7d7ff''d7ff00''d7ff5f',
                
'd7ff87''d7ffaf''d7ffd7''d7ffff''ff0000''ff005f',
                
'ff0087''ff00af''ff00d7''ff00ff''ff5f00''ff5f5f',
                
'ff5f87''ff5faf''ff5fd7''ff5fff''ff8700''ff875f',
                
'ff8787''ff87af''ff87d7''ff87ff''ffaf00''ffaf5f',
                
'ffaf87''ffafaf''ffafd7''ffafff''ffd700''ffd75f',
                
'ffd787''ffd7af''ffd7d7''ffd7ff''ffff00''ffff5f',
                
'ffff87''ffffaf''ffffd7''ffffff''080808''121212',
                
'1c1c1c''262626''303030''3a3a3a''444444''4e4e4e',
                
'585858''606060''666666''767676''808080''8a8a8a',
                
'949494''9e9e9e''a8a8a8''b2b2b2''bcbcbc''c6c6c6',
                
'd0d0d0''dadada''e4e4e4''eeeeee',
            ];
        }

        
$tput Console::getTput();

        if (
>= $tput->count('max_colors')) {
            return;
        }

        
$handle = [];

        foreach (
explode(' '$attributes) as $attribute) {
            switch (
$attribute) {
                case 
'n':
                case 
'normal':
                    
$handle[] = 0;

                    break;

                case 
'b':
                case 
'bold':
                    
$handle[] = 1;

                    break;

                case 
'u':
                case 
'underlined':
                    
$handle[] = 4;

                    break;

                case 
'bl':
                case 
'blink':
                    
$handle[] = 5;

                    break;

                case 
'i':
                case 
'inverse':
                    
$handle[] = 7;

                    break;

                case 
'!b':
                case 
'!bold':
                    
$handle[] = 22;

                    break;

                case 
'!u':
                case 
'!underlined':
                    
$handle[] = 24;

                    break;

                case 
'!bl':
                case 
'!blink':
                    
$handle[] = 25;

                    break;

                case 
'!i':
                case 
'!inverse':
                    
$handle[] = 27;

                    break;

                default:
                    if (
=== preg_match('#^([^(]+)(([^)]+))$#'$attribute$m)) {
                        break;
                    }

                    
$shift 0;

                    switch (
$m[1]) {
                        case 
'fg':
                        case 
'foreground':
                            
$shift 0;

                            break;

                        case 
'bg':
                        case 
'background':
                            
$shift 10;

                            break;

                        default:
                            break 
2;
                    }

                    
$_handle 0;
                    
$_keyword true;

                    switch (
$m[2]) {
                        case 
'black':
                            
$_handle 30;

                            break;

                        case 
'red':
                            
$_handle 31;

                            break;

                        case 
'green':
                            
$_handle 32;

                            break;

                        case 
'yellow':
                            
$_handle 33;

                            break;

                        case 
'blue':
                            
$_handle 34;

                            break;

                        case 
'magenta':
                            
$_handle 35;

                            break;

                        case 
'cyan':
                            
$_handle 36;

                            break;

                        case 
'white':
                            
$_handle 37;

                            break;

                        case 
'default':
                            
$_handle 39;

                            break;

                        default:
                            
$_keyword false;

                            if (
256 <= $tput->count('max_colors') &&
                                
'#' === $m[2][0]) {
                                
$rgb hexdec(substr($m[2], 1));
                                
$r = ($rgb >> 16) & 255;
                                
$g = ($rgb >> 8) & 255;
                                
$b $rgb 255;
                                
$distance null;

                                foreach (
$_rgbTo256 as $i => $_rgb) {
                                    
$_rgb hexdec($_rgb);
                                    
$_r = ($_rgb >> 16) & 255;
                                    
$_g = ($_rgb >> 8) & 255;
                                    
$_b $_rgb 255;

                                    
$d sqrt(
                                        (
$_r $r) ** 2
                                      
+ ($_g $g) ** 2
                                      
+ ($_b $b) ** 2
                                    
);

                                    if (
null === $distance ||
                                        
$d <= $distance) {
                                        
$distance $d;
                                        
$_handle $i;
                                    }
                                }
                            } else {
                                
$_handle = (int) ($m[2]);
                            }
                    }

                    if (
true === $_keyword) {
                        
$handle[] = $_handle $shift;
                    } else {
                        
$handle[] = (38 $shift).';5;'.$_handle;
                    }
            }
        }

        
Console::getOutput()->writeAll("33[".implode(';'$handle).'m');

        return;
    }

    
/**
     * Change color number to a specific RGB color.
     */
    
public static function changeColor(int $fromCodeint $toColor)
    {
        
$tput Console::getTput();

        if (
true !== $tput->has('can_change')) {
            return;
        }

        
$r = ($toColor >> 16) & 255;
        
$g = ($toColor >> 8) & 255;
        
$b $toColor 255;

        
Console::getOutput()->writeAll(
            
str_replace(
                [
                    
'%p1%d',
                    
'rgb:',
                    
'%p2%{255}%*%{1000}%/%2.2X/',
                    
'%p3%{255}%*%{1000}%/%2.2X/',
                    
'%p4%{255}%*%{1000}%/%2.2X',
                ],
                [
                    
$fromCode,
                    
'',
                    
sprintf('%02x'$r),
                    
sprintf('%02x'$g),
                    
sprintf('%02x'$b),
                ],
                
$tput->get('initialize_color')
            )
        );

        return;
    }

    
/**
     * Set cursor style.
     * Style can be:
     *     • b, block,     ▋: block;
     *     • u, underline, _: underline;
     *     • v, vertical,  |: vertical.
     */
    
public static function setStyle(string $stylebool $blink true)
    {
        if (
defined('PHP_WINDOWS_VERSION_PLATFORM')) {
            return;
        }

        switch (
$style) {
            case 
'u':
            case 
'underline':
            case 
'_':
                
$_style 2;

                break;

            case 
'v':
            case 
'vertical':
            case 
'|':
                
$_style 5;

                break;

            case 
'b':
            case 
'block':
            case 
'▋':
            default:
                
$_style 1;

                break;
        }

        if (
false === $blink) {
            ++
$_style;
        }

        
// Not sure what tput entry we can use here…
        
Console::getOutput()->writeAll("33[".$_style.' q');

        return;
    }

    
/**
     * Make a stupid “bip”.
     */
    
public static function bip()
    {
        
Console::getOutput()->writeAll(
            
Console::getTput()->get('bell')
        );
    }
}

/*
 * Advanced interaction.
 */
Console::advancedInteraction();
Онлайн: 1
Реклама