Example #1
0
 public function listen()
 {
     Cursor::setStyle('β–‹', true);
     do {
         Cursor::colorize('b fg(yellow) bg(blue)');
         echo 'β—Ό datatext > ';
         Cursor::colorize('!b fg(default) bg(default)');
         $line = $this->readline->readLine(' ');
         if ($line === 'fake') {
             $rows = [];
             $size = Window::getSize();
             for ($i = 0; $i < $size['y'] - 4; $i++) {
                 $row = [];
                 for ($j = 0; $j < 10; $j++) {
                     $row[] = $this->faker->name;
                 }
                 $rows[] = $row;
             }
             $table = new Table($rows, ['headers' => ['a', 'b', 'c', 'd', 'e'], 'stickyColumns' => [2]]);
             $navigable = new NavigableTable($table);
             $navigable->render();
         } else {
             echo '< ', $line, "\n";
         }
     } while (false !== $line && 'quit' !== $line);
 }
Example #2
0
 function __construct($options = [])
 {
     if (array_key_exists('columnOffset', $options)) {
         if (!is_integer($options['columnOffset'])) {
             throw new \InvalidArgumentException('Invalid column offset. Not an integer');
         }
         $this->columnOffset = $options['columnOffset'];
     }
     $this->screenEstate = Window::getSize();
     if (array_key_exists('screenEstate', $options)) {
         foreach (['x', 'y'] as $dimension) {
             if (array_key_exists($dimension, $options['screenEstate'])) {
                 if (!is_integer($options['screenEstate'][$dimension])) {
                     throw new \InvalidArgumentException('Invalid screen estate dimension. Not an integer');
                 }
                 $this->screenEstate[$dimension] = $options['screenEstate'][$dimension];
             }
         }
     }
 }
Example #3
0
 /**
  * Main method.
  *
  * @return int
  */
 function main()
 {
     $operation = 0;
     $location = null;
     $updateServer = Updater::DEFAULT_UPDATE_SERVER;
     while (false !== ($c = $this->getOption($v))) {
         switch ($c) {
             case '__ambiguous':
                 $this->resolveOptionAmbiguity($v);
                 break;
             case 'f':
                 $operation = static::OPERATION_FETCH | Updater::FORMAT_PHAR;
                 break;
             case 'z':
                 $operation = static::OPERATION_FETCH | Updater::FORMAT_ZIP;
                 break;
             case 'a':
                 $operation = static::OPERATION_APPLY;
                 $location = $v;
                 break;
             case 's':
                 $updateServer = $v;
                 break;
             case 'h':
             case '?':
             default:
                 return $this->usage();
                 break;
         }
     }
     $updateServer = rtrim($updateServer, '/') . '/';
     if (0 !== (static::OPERATION_FETCH & $operation)) {
         $updatesDotJson = Updater::getUpdateUrl($updateServer);
         $versions = @file_get_contents($updatesDotJson);
         if (empty($versions)) {
             throw new Exception\Console('Oh no! We are not able to check if a new version exists… ' . 'Contact us at http://sabre.io/ ' . '(tried URL %s).', 0, $updatesDotJson);
         }
         $versions = json_decode($versions, true);
         /**
          * Expected format:
          *     {
          *         "1.0.1": {
          *             "phar": "https://…",
          *             "zip" : "https://…"
          *         },
          *         "1.0.0": {
          *             "phar": "https://…",
          *             "zip" : "https://…"
          *         },
          *         …
          *     }
          */
         $versionsToFetch = Updater::filterVersions($versions, Version::VERSION, $operation);
         $windowWidth = Window::getSize()['x'];
         $progress = function ($percent) use($windowWidth) {
             Cursor::clear('↔');
             $message = 'Downloading… ';
             $barWidth = $windowWidth - mb_strlen($message);
             if ($percent <= 0) {
                 $color = '#c74844';
             } elseif ($percent <= 25) {
                 $color = '#cb9a3d';
             } elseif ($percent <= 50) {
                 $color = '#dcb11e';
             } elseif ($percent <= 75) {
                 $color = '#aed633';
             } else {
                 $color = '#54b455';
             }
             echo $message;
             Cursor::colorize('foreground(' . $color . ') background(' . $color . ')');
             echo str_repeat('|', $percent * $barWidth / 100);
             Cursor::colorize('normal');
         };
         foreach ($versionsToFetch as $versionNumber => $versionUrl) {
             list(, $versionUrlBasename) = Uri\split($versionUrl);
             $fileIn = new File\Read($versionUrl, File::MODE_READ, null, true);
             $fileOut = new File\Write(SABRE_KATANA_PREFIX . '/data/share/update/' . $versionUrlBasename);
             echo "\n", 'Fetch version ', $versionNumber, ' from ', $versionUrl, "\n", 'Waiting…', "\n";
             $fileIn->on('connect', function () {
                 Cursor::clear('↔');
                 echo 'Downloading… ';
             });
             $fileIn->on('progress', function (Core\Event\Bucket $bucket) use($progress) {
                 static $previousPercent = 0;
                 $data = $bucket->getData();
                 $current = $data['transferred'];
                 $max = $data['max'];
                 $percent = $current * 100 / $max;
                 $delta = $percent - $previousPercent;
                 if (1 <= $delta) {
                     $previousPercent = $percent;
                     $progress($percent);
                 }
             });
             $fileIn->open();
             $fileOut->writeAll($fileIn->readAll());
             echo "\n", 'Fetched at ', $fileOut->getStreamName(), '.', "\n";
         }
         return 0;
     } elseif (static::OPERATION_APPLY === $operation) {
         if (false === file_exists($location)) {
             throw new Exception\Console('Update %s is not found.', 1, $location);
         }
         $processus = new Console\Processus(Core::getPHPBinary(), [$location, '--extract' => SABRE_KATANA_PREFIX, '--overwrite']);
         $processus->on('input', function () {
             return false;
         });
         $processus->on('output', function (Core\Event\Bucket $bucket) {
             echo $bucket->getData()['line'], "\n";
         });
         $processus->run();
         if (true === $processus->isSuccessful()) {
             echo 'sabre/katana updated!', "\n";
         } else {
             echo 'Something wrong happened!', "\n";
         }
         return $processus->getExitCode();
     } else {
         return $this->usage();
     }
 }
Example #4
0
 /**
  * Main method.
  *
  * @return int
  */
 function main()
 {
     $verbose = !(Console::isDirect(STDOUT) || !OS_WIN);
     while (false !== ($c = $this->getOption($v))) {
         switch ($c) {
             case '__ambiguous':
                 $this->resolveOptionAmbiguity($v);
                 break;
             case 'v':
                 $verbose = $v;
                 break;
             case 'h':
             case '?':
             default:
                 return $this->usage();
         }
     }
     if (true === Installer::isInstalled()) {
         echo 'The application is already installed.', "\n";
         return 1;
     }
     $oldTitle = Window::getTitle();
     Window::setTitle('Installation of sabre/katana');
     $form = ['baseUrl' => '/', 'email' => null, 'password' => null, 'database' => ['driver' => 'sqlite', 'host' => '', 'port' => '', 'name' => '', 'username' => '', 'password' => '']];
     $readline = new Console\Readline();
     if (true === $verbose) {
         $windowWidth = Window::getSize()['x'];
         $labelMaxWidth = 35;
         $inputMaxWidth = $windowWidth - $labelMaxWidth;
         $numberOfSteps = 5;
         $input = function ($default = '') use($inputMaxWidth) {
             return Text::colorize($default . str_repeat(' ', $inputMaxWidth - mb_strlen($default)), 'foreground(black) background(#cccccc)');
         };
         $resetInput = function ($default = '') use($input, $labelMaxWidth) {
             Cursor::move('β†’', $labelMaxWidth);
             echo $input($default);
             Cursor::move('LEFT');
             Cursor::move('β†’', $labelMaxWidth);
             Cursor::colorize('foreground(black) background(#cccccc)');
         };
         echo Text::colorize('Installation of sabre/' . "\n" . Welcome::LOGO, 'foreground(yellow)'), "\n\n", static::getBaseURLInfo(), "\n\n", 'Choose the base URL:               ', $input('/'), "\n", 'Your administrator login:          '******'Choose the administrator password: '******'Choose the administrator email:    ', $input(), "\n", 'Choose the database driver:        ', 'πŸ”˜ SQLite βšͺ️ MySQL', "\n";
         Window::scroll('↑', 10);
         Cursor::move('↑', 10);
         Cursor::move('↑', $numberOfSteps);
         Cursor::move('β†’', $labelMaxWidth);
         // Disable arrow up and down.
         $no_echo = function ($readline) {
             return $readline::STATE_NO_ECHO;
         };
         $readline->addMapping("", $no_echo);
         $readline->addMapping("", $no_echo);
         $step = function ($index, $label, callable $validator, $errorMessage, $default = '') use($numberOfSteps, &$readline, $resetInput, $labelMaxWidth) {
             Cursor::colorize('foreground(black) background(#cccccc)');
             do {
                 $out = $readline->readLine();
                 if (empty($out)) {
                     $out = $default;
                 }
                 $valid = $validator($out);
                 if (true !== $valid) {
                     Cursor::move('↑');
                     $resetInput($default);
                     Cursor::save();
                     Cursor::move('LEFT');
                     Cursor::move('↓', $numberOfSteps - $index + 1);
                     list($title, $message) = explode("\n", $errorMessage);
                     Cursor::colorize('foreground(white) background(red)');
                     echo $title, "\n";
                     Cursor::colorize('foreground(red) background(normal)');
                     echo $message;
                     Cursor::restore();
                 } else {
                     Cursor::save();
                     Cursor::move('LEFT');
                     Cursor::move('↓', $numberOfSteps - $index - 1);
                     Cursor::colorize('normal');
                     Cursor::clear('↓');
                     Cursor::restore();
                 }
             } while (true !== $valid);
             if ($numberOfSteps !== $index + 1) {
                 Cursor::move('β†’', $labelMaxWidth);
             }
             Cursor::colorize('normal');
             return $out;
         };
         $progress = function ($percent, $message) use($windowWidth) {
             static $margin = 4;
             $barWidth = $windowWidth - $margin * 2;
             Cursor::move('LEFT');
             Cursor::move('↑', 1);
             Cursor::clear('↓');
             if ($percent <= 0) {
                 $color = '#c74844';
             } elseif ($percent <= 25) {
                 $color = '#cb9a3d';
             } elseif ($percent <= 50) {
                 $color = '#dcb11e';
             } elseif ($percent <= 75) {
                 $color = '#aed633';
             } else {
                 $color = '#54b455';
             }
             echo str_repeat(' ', $margin);
             Cursor::colorize('foreground(' . $color . ') background(' . $color . ')');
             echo str_repeat('|', $percent * $barWidth / 100);
             Cursor::move('LEFT ↓');
             Cursor::colorize('background(normal)');
             echo str_repeat(' ', $margin) . $message;
             Cursor::colorize('normal');
             sleep(1);
         };
     } else {
         echo 'Installation of sabre/' . "\n" . Welcome::LOGO, "\n\n", static::getBaseURLInfo(), "\n\n";
         $step = function ($index, $label, callable $validator, $errorMessage, $default = '') use(&$readline) {
             do {
                 echo $label;
                 if (!empty($default)) {
                     echo ' [default: ', $default, ']';
                 }
                 $out = $readline->readLine(': ');
                 if (empty($out)) {
                     $out = $default;
                 }
                 $valid = $validator($out);
                 if (true !== $valid) {
                     echo $errorMessage, "\n";
                 }
             } while (true !== $valid);
             return $out;
         };
         $progress = function ($percent, $message) {
             echo $message, "\n";
         };
     }
     $form['baseUrl'] = $step(0, 'Choose the base URL', function ($baseUrl) use($verbose) {
         $valid = Installer::checkBaseUrl($baseUrl);
         if (true === $valid && true === $verbose) {
             Cursor::move('↓');
         }
         return $valid;
     }, 'Base URL must start and end by a slash' . "\n" . 'Check the Section β€œThe base URL” on http://sabre.io/dav/gettingstarted/.', '/');
     if (false === $verbose) {
         echo 'Your administrator login: '******'password'] = $step(1, 'Choose the administrator password', function ($administratorPassword) {
         return Installer::checkPassword($administratorPassword . $administratorPassword);
     }, 'Password must not be empty' . "\n" . 'An empty password is not a password anymore!');
     $readline = $oldReadline;
     $form['email'] = $step(2, 'Choose the administrator email', function ($administratorEmail) {
         return Installer::checkEmail($administratorEmail . $administratorEmail);
     }, 'Email is invalid' . "\n" . 'The given email seems invalid.');
     $databaseDriver =& $form['database']['driver'];
     if (true === $verbose) {
         $radioReadline = new Console\Readline\Password();
         $radioReadline->addMapping('\\e[D', function () use($labelMaxWidth, &$databaseDriver) {
             $databaseDriver = 'sqlite';
             Cursor::save();
             Cursor::move('LEFT');
             Cursor::move('β†’', $labelMaxWidth);
             Cursor::clear('β†’');
             echo 'πŸ”˜ SQLite βšͺ️ MySQL';
             Cursor::restore();
         });
         $radioReadline->addMapping('\\e[C', function () use($labelMaxWidth, &$databaseDriver) {
             $databaseDriver = 'mysql';
             Cursor::save();
             Cursor::move('LEFT');
             Cursor::move('β†’', $labelMaxWidth);
             Cursor::clear('β†’');
             echo 'βšͺ️ SQLite πŸ”˜ MySQL';
             Cursor::restore();
         });
         Cursor::hide();
         $radioReadline->readLine();
         Cursor::show();
         unset($databaseDriver);
         if ('mysql' === $form['database']['driver']) {
             echo 'Choose MySQL host:                 ', $input(), "\n", 'Choose MySQL port:                 ', $input('3306'), "\n", 'Choose MySQL username:             '******'Choose MySQL password:             '******'Choose MySQL database name:        ', $input(), "\n";
             Window::scroll('↑', 10);
             Cursor::move('↑', 10);
             $numberOfSteps = 5;
             Cursor::move('↑', $numberOfSteps);
             Cursor::move('β†’', $labelMaxWidth);
             Cursor::colorize('foreground(black) background(#cccccc)');
         }
     } else {
         $form['database']['driver'] = $step(3, 'Choose the database driver (sqlite or mysql)', function ($databaseDriver) {
             return in_array($databaseDriver, ['sqlite', 'mysql']);
         }, 'Database driver is invalid' . "\n" . 'Database driver must be `sqlite` or `mysql`', 'sqlite');
     }
     if ('mysql' === $form['database']['driver']) {
         $form['database']['host'] = $step(0, 'Choose MySQL host', function () {
             return true;
         }, '');
         $form['database']['port'] = $step(1, 'Choose MySQL port', function ($port) {
             return false !== filter_var($port, FILTER_VALIDATE_INT);
         }, 'Port is invalid' . "\n" . 'Port must be an integer.', '3306');
         $form['database']['username'] = $step(2, 'Choose MySQL username', function () {
             return true;
         }, '');
         $oldReadline = $readline;
         $readline = new Console\Readline\Password();
         $form['database']['password'] = $step(3, 'Choose MySQL password', function () {
             return true;
         }, '');
         $readline = $oldReadline;
         $form['database']['name'] = $step(3, 'Choose MySQL database name', function () {
             return true;
         }, '');
     }
     $readline->readLine("\n" . 'Ready to install? (Enter to continue, Ctrl-C to abort)');
     echo "\n\n";
     try {
         $progress(5, 'Create configuration file…');
         $configuration = Installer::createConfigurationFile(Server::CONFIGURATION_FILE, ['baseUrl' => $form['baseUrl'], 'database' => $form['database']]);
         $progress(25, 'Configuration file created πŸ‘!');
         $progress(30, 'Create the database…');
         $database = Installer::createDatabase($configuration);
         $progress(50, 'Database created πŸ‘!');
         $progress(55, 'Create administrator profile…');
         Installer::createAdministratorProfile($configuration, $database, $form['email'], $form['password']);
         $progress(75, 'Administrator profile created πŸ‘!');
         $progress(100, 'sabre/katana is ready!');
     } catch (\Exception $e) {
         $progress(-1, 'An error occured: ' . $e->getMessage());
         if (null !== ($previous = $e->getPrevious())) {
             echo 'Underlying error: ' . $previous->getMessage();
         }
         echo "\n", 'You are probably likely to run: ' . '`make uninstall` before trying again.', "\n";
         return 2;
     }
     list($dirname) = Uri\split($form['baseUrl']);
     echo "\n\n", 'The administration interface will be found at this path: ', '<your website>', $dirname, '/admin.php.', "\n";
     Window::setTitle($oldTitle);
 }
Example #5
0
 /**
  * Make a render of an operation.
  *
  * @accesss public
  * @param string  $text      The operation text.
  * @param bool    $status    The operation status.
  * @return void
  */
 public function status($text, $status)
 {
     $window = \Hoa\Console\Window::getSize();
     $out = ' ' . \Hoa\Console\Chrome\Text::colorize('*', 'foreground(yellow)') . ' ' . $text . str_pad(' ', $window['x'] - strlen(preg_replace('#' . "" . '\\[[0-9]+m#', '', $text)) - 8) . ($status === true ? '[' . \Hoa\Console\Chrome\Text::colorize('ok', 'foreground(green)') . ']' : '[' . \Hoa\Console\Chrome\Text::colorize('!!', 'foreground(white) background(red)') . ']');
     echo $out, "\n";
     return;
 }
Example #6
0
         * @return  void
         */
        public static function copy($data)
        {
            if (OS_WIN) {
                return;
            }
            echo "]52;;" . base64_encode($data) . "\\";
            return;
        }
    }
}
namespace {
    /**
     * Advanced interaction.
     */
    \Hoa\Console::advancedInteraction();
    /**
     * Event.
     */
    if (function_exists('pcntl_signal')) {
        \Hoa\Console\Window::getInstance();
        pcntl_signal(SIGWINCH, function () {
            static $_window = null;
            if (null === $_window) {
                $_window = \Hoa\Console\Window::getInstance();
            }
            \Hoa\Core\Event::notify('hoa://Event/Console/Window:resize', $_window, new \Hoa\Core\Event\Bucket(array('size' => \Hoa\Console\Window::getSize())));
        });
    }
}
Example #7
0
 /**
  * Tab binding.
  *
  * @access  public
  * @param   \Hoa\Console\Readline  $self    Self.
  * @return  int
  */
 public function _bindTab(Readline $self)
 {
     $autocompleter = $self->getAutocompleter();
     $state = static::STATE_CONTINUE | static::STATE_NO_ECHO;
     if (null === $autocompleter) {
         return $state;
     }
     $current = $self->getLineCurrent();
     $line = $self->getLine();
     if (0 === $current) {
         return $state;
     }
     $matches = preg_match_all('#' . $autocompleter->getWordDefinition() . '#u', $line, $words, PREG_OFFSET_CAPTURE);
     if (0 === $matches) {
         return $state;
     }
     for ($i = 0, $max = count($words[0]); $i < $max && $current > $words[0][$i][1]; ++$i) {
     }
     $word = $words[0][$i - 1];
     if ('' === trim($word[0])) {
         return $state;
     }
     $prefix = mb_substr($word[0], 0, $current - $word[1]);
     $solution = $autocompleter->complete($prefix);
     $length = mb_strlen($prefix);
     if (null === $solution) {
         return $state;
     }
     if (is_array($solution)) {
         $_solution = $solution;
         $count = count($_solution) - 1;
         $cWidth = 0;
         $window = \Hoa\Console\Window::getSize();
         $wWidth = $window['x'];
         $cursor = \Hoa\Console\Cursor::getPosition();
         array_walk($_solution, function (&$value) use(&$cWidth) {
             $handle = mb_strlen($value);
             if ($handle > $cWidth) {
                 $cWidth = $handle;
             }
             return;
         });
         array_walk($_solution, function (&$value) use(&$cWidth) {
             $handle = mb_strlen($value);
             if ($handle >= $cWidth) {
                 return;
             }
             $value .= str_repeat(' ', $cWidth - $handle);
             return;
         });
         $mColumns = (int) floor($wWidth / ($cWidth + 2));
         $mLines = (int) ceil(($count + 1) / $mColumns);
         --$mColumns;
         $i = 0;
         if (0 > $window['y'] - $cursor['y'] - $mLines) {
             \Hoa\Console\Window::scroll('↑', $mLines);
             \Hoa\Console\Cursor::move('↑', $mLines);
         }
         \Hoa\Console\Cursor::save();
         \Hoa\Console\Cursor::hide();
         \Hoa\Console\Cursor::move('↓ LEFT');
         \Hoa\Console\Cursor::clear('↓');
         foreach ($_solution as $j => $s) {
             echo "", $s, "";
             if ($i++ < $mColumns) {
                 echo '  ';
             } else {
                 $i = 0;
                 if (isset($_solution[$j + 1])) {
                     echo "\n";
                 }
             }
         }
         \Hoa\Console\Cursor::restore();
         \Hoa\Console\Cursor::show();
         ++$mColumns;
         $read = array(STDIN);
         $mColumn = -1;
         $mLine = -1;
         $coord = -1;
         $unselect = function () use(&$mColumn, &$mLine, &$coord, &$_solution, &$cWidth) {
             \Hoa\Console\Cursor::save();
             \Hoa\Console\Cursor::hide();
             \Hoa\Console\Cursor::move('↓ LEFT');
             \Hoa\Console\Cursor::move('β†’', $mColumn * ($cWidth + 2));
             \Hoa\Console\Cursor::move('↓', $mLine);
             echo "" . $_solution[$coord] . "";
             \Hoa\Console\Cursor::restore();
             \Hoa\Console\Cursor::show();
             return;
         };
         $select = function () use(&$mColumn, &$mLine, &$coord, &$_solution, &$cWidth) {
             \Hoa\Console\Cursor::save();
             \Hoa\Console\Cursor::hide();
             \Hoa\Console\Cursor::move('↓ LEFT');
             \Hoa\Console\Cursor::move('β†’', $mColumn * ($cWidth + 2));
             \Hoa\Console\Cursor::move('↓', $mLine);
             echo "" . $_solution[$coord] . "";
             \Hoa\Console\Cursor::restore();
             \Hoa\Console\Cursor::show();
             return;
         };
         $init = function () use(&$mColumn, &$mLine, &$coord, &$select) {
             $mColumn = 0;
             $mLine = 0;
             $coord = 0;
             $select();
             return;
         };
         while (true) {
             @stream_select($read, $write, $except, 30, 0);
             if (empty($read)) {
                 $read = array(STDIN);
                 continue;
             }
             switch ($char = $self->_read()) {
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = max(0, $coord - $mColumns);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = min($count, $coord + $mColumns);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "\t":
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = min($count, $coord + 1);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = max(0, $coord - 1);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "\n":
                     if (-1 !== $mColumn && -1 !== $mLine) {
                         $tail = mb_substr($line, $current);
                         $current -= $length;
                         $self->setLine(mb_substr($line, 0, $current) . $solution[$coord] . $tail);
                         $self->setLineCurrent($current + mb_strlen($solution[$coord]));
                         \Hoa\Console\Cursor::move('←', $length);
                         echo $solution[$coord];
                         \Hoa\Console\Cursor::clear('β†’');
                         echo $tail;
                         \Hoa\Console\Cursor::move('←', mb_strlen($tail));
                     }
                 default:
                     $mColumn = -1;
                     $mLine = -1;
                     $coord = -1;
                     \Hoa\Console\Cursor::save();
                     \Hoa\Console\Cursor::move('↓ LEFT');
                     \Hoa\Console\Cursor::clear('↓');
                     \Hoa\Console\Cursor::restore();
                     if ("" !== $char && "\n" !== $char) {
                         $self->setBuffer($char);
                         return $self->_readLine($char);
                     }
                     break 2;
             }
         }
         return $state;
     }
     $tail = mb_substr($line, $current);
     $current -= $length;
     $self->setLine(mb_substr($line, 0, $current) . $solution . $tail);
     $self->setLineCurrent($current + mb_strlen($solution));
     \Hoa\Console\Cursor::move('←', $length);
     echo $solution;
     \Hoa\Console\Cursor::clear('β†’');
     echo $tail;
     \Hoa\Console\Cursor::move('←', mb_strlen($tail));
     return $state;
 }
Example #8
0
 /**
  * My own wordwrap (just force the wordwrap() $cut parameter)..
  *
  * @access  public
  * @param   string  $text     Text to wrap.
  * @param   int     $width    Line width.
  * @param   string  $break    String to make the break.
  * @return  string
  */
 public static function wordwrap($text, $width = null, $break = "\n")
 {
     if (null === $width) {
         $window = \Hoa\Console\Window::getSize();
         $width = $window['x'];
     }
     return wordwrap($text, $width, $break, true);
 }
Example #9
0
     * Set clipboard value.
     *
     * @param   string  $data    Data to copy.
     * @return  void
     */
    public static function copy($data)
    {
        if (OS_WIN) {
            return;
        }
        echo "]52;;" . base64_encode($data) . "\\";
        return;
    }
}
/**
 * Advanced interaction.
 */
Console::advancedInteraction();
/**
 * Event.
 */
if (function_exists('pcntl_signal')) {
    Window::getInstance();
    pcntl_signal(SIGWINCH, function () {
        static $_window = null;
        if (null === $_window) {
            $_window = Window::getInstance();
        }
        Core\Event::notify('hoa://Event/Console/Window:resize', $_window, new Core\Event\Bucket(['size' => \Window::getSize()]));
    });
}
Example #10
0
 /**
  * Tab binding.
  *
  * @access  public
  * @param   Readline  $self    Self.
  * @return  int
  */
 public function _bindTab(Readline $self)
 {
     $autocompleter = $self->getAutocompleter();
     $state = static::STATE_CONTINUE | static::STATE_NO_ECHO;
     if (null === $autocompleter) {
         return $state;
     }
     $current = $self->getLineCurrent();
     $line = $self->getLine();
     // we need at least 1 char to work with
     // and if it's the start of a line, we'll echo it.
     if (0 === $current || trim($line) === '') {
         $this->appendLine("\t");
         $this->_buffer .= "\t";
         return static::STATE_CONTINUE;
     }
     $matches = preg_match_all('#' . $autocompleter->getWordDefinition() . '#u', $line, $words, PREG_OFFSET_CAPTURE);
     if (0 === $matches) {
         return $state;
     }
     for ($i = 0, $max = count($words[1]); $i < $max && $current > $words[1][$i][1]; ++$i) {
     }
     $word = $words[1][$i - 1];
     if ('' === trim($word[0])) {
         return $state;
     }
     $prefix = mb_substr($word[0], 0, $current - $word[1]);
     //Debug::log('prefix', compact('line','current','words','word','prefix'));
     $solution = $autocompleter->complete($prefix);
     #Debug::log('solution', $solution);
     if (null === $solution || empty($solution)) {
         return $state;
     }
     if (preg_match('/[\\S]+([\\W]+)([\\S]*)/', $prefix, $m, PREG_OFFSET_CAPTURE)) {
         #Debug::log('matchPrefix', compact('prefix', 'm'));
         $suffixLength = mb_strlen($m[2][0]);
         $prefix = mb_substr($prefix, -$suffixLength);
         $tail = mb_substr($line, $current);
         $head = mb_substr($line, 0, $current - $suffixLength);
         $line = $head . $tail;
         $current -= $suffixLength;
         $length = $suffixLength;
     } else {
         $length = mb_strlen($prefix);
         $tail = mb_substr($line, $current);
         $head = mb_substr($line, 0, $current - $length);
         $line = $head . $tail;
         $current -= $length;
     }
     #Debug::log('completionSetup', compact('prefix','line','current','head','tail','length'));
     if (is_array($solution)) {
         if (count($solution) === 1) {
             $line = $head . $solution[0] . $tail;
             $self->setLine($line);
             $self->setLineCurrent($current + mb_strlen($solution[0]));
             $self->setBuffer($line);
             Cursor::move('left', $length);
             echo $solution[0];
             Cursor::clear('right');
             echo $tail;
             Cursor::move('left', mb_strlen($tail));
             #Debug::log('completion', array(
             #  'line'    =>$self->getLine(),
             #  'current' =>$self->getLineCurrent(),
             #  'buffer'  =>$self->getBuffer(),
             #));
             return $state;
         }
         $_solution = $solution;
         $window = Window::getSize();
         $cursor = Cursor::getPosition();
         $wWidth = $window['x'];
         while (1) {
             $count = count($_solution) - 1;
             $cWidth = 0;
             array_walk($_solution, function ($value) use(&$cWidth) {
                 $handle = mb_strlen($value);
                 if ($handle > $cWidth) {
                     $cWidth = $handle;
                 }
             });
             array_walk($_solution, function (&$value) use($cWidth) {
                 $handle = mb_strlen($value);
                 if ($handle < $cWidth) {
                     $value .= str_repeat(' ', $cWidth - $handle);
                 }
             });
             $mColumns = (int) floor($wWidth / ($cWidth + 2));
             $mLines = (int) ceil(($count + 1) / $mColumns);
             --$mColumns;
             if ($mLines >= $window['y']) {
                 $toRemove = ($mLines - $window['y']) * $mColumns + 1;
                 for ($i = 0; $i < $toRemove; $i++) {
                     array_pop($_solution);
                 }
             } else {
                 break;
             }
         }
         $pos = Cursor::getPosition();
         if ($window['y'] - $cursor['y'] - $mLines < 0) {
             echo str_repeat("\n", $mLines + 1);
             Cursor::move('up', $mLines + 1);
             Cursor::clear('LEFT');
             echo $this->getPrefix() . $this->getLine() . "\n";
             Cursor::move('up LEFT');
             Cursor::move('right', $pos['x'] - 1);
         }
         Cursor::save();
         Cursor::hide();
         Cursor::move('down LEFT');
         Cursor::clear('down');
         $i = 0;
         foreach ($_solution as $j => $s) {
             echo "", $s, "";
             if ($i++ < $mColumns) {
                 echo '  ';
             } else {
                 $i = 0;
                 if (isset($_solution[$j + 1])) {
                     echo "\n";
                 }
             }
         }
         Cursor::restore();
         Cursor::show();
         ++$mColumns;
         $read = array(STDIN);
         $mColumn = -1;
         $mLine = -1;
         $coord = -1;
         $unselect = function () use(&$mColumn, &$mLine, &$coord, &$_solution, &$cWidth) {
             Cursor::save();
             Cursor::hide();
             Cursor::move('down LEFT');
             Cursor::move('right', $mColumn * ($cWidth + 2));
             Cursor::move('down', $mLine);
             echo "" . $_solution[$coord] . "";
             Cursor::restore();
             Cursor::show();
         };
         $select = function () use(&$mColumn, &$mLine, &$coord, &$_solution, &$cWidth) {
             Cursor::save();
             Cursor::hide();
             Cursor::move('down LEFT');
             Cursor::move('right', $mColumn * ($cWidth + 2));
             Cursor::move('down', $mLine);
             echo "" . $_solution[$coord] . "";
             Cursor::restore();
             Cursor::show();
         };
         $init = function () use(&$mColumn, &$mLine, &$coord, &$select) {
             $mColumn = 0;
             $mLine = 0;
             $coord = 0;
             $select();
         };
         while (true) {
             @stream_select($read, $write, $except, 30, 0);
             if (empty($read)) {
                 $read = array(STDIN);
                 continue;
             }
             switch ($char = $self->_read()) {
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = max(0, $coord - $mColumns);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = min($count, $coord + $mColumns);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "\t":
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = min($count, $coord + 1);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "":
                     if (-1 === $mColumn && -1 === $mLine) {
                         $init();
                         break;
                     }
                     $unselect();
                     $coord = max(0, $coord - 1);
                     $mLine = (int) floor($coord / $mColumns);
                     $mColumn = $coord % $mColumns;
                     $select();
                     break;
                 case "\n":
                     if (-1 !== $mColumn && -1 !== $mLine) {
                         $self->setLine($head . $solution[$coord] . $tail);
                         $self->setLineCurrent($current + mb_strlen($solution[$coord]));
                         Cursor::move('left', $length);
                         echo $solution[$coord];
                         Cursor::clear('right');
                         echo $tail;
                         Cursor::move('left', mb_strlen($tail));
                     }
                 default:
                     $mColumn = -1;
                     $mLine = -1;
                     $coord = -1;
                     Cursor::save();
                     Cursor::move('down LEFT');
                     Cursor::clear('down');
                     Cursor::restore();
                     if ("" !== $char && "\n" !== $char) {
                         $self->setBuffer($char);
                         return $self->_readLine($char);
                     }
                     break 2;
             }
         }
         return $state;
     }
 }