Example #1
0
 /**
  * @brief Read a line, optionally setting the completer
  *
  * @param string $prompt The prompt to display
  * @param ReadlineAutoCompleter $completer The completer instance
  * @param boolean $autohistory Add command to history automatically (default is false)
  */
 static function read($prompt = null, ReadlineAutoCompleter $completer = null, $autohistory = false)
 {
     $oldcompleter = null;
     // If we got an autocompleter, assign it
     if ($completer) {
         // Save a copy of the old completer if any
         if (self::$completer && $completer !== self::$completer) {
             $oldcompleter = self::$completer;
         }
         // Assign and set up the proxy call
         self::$completer = $completer;
         readline_completion_function(array('Readline', '_rlAutoCompleteProxy'));
     }
     // Read the line
     $ret = readline($prompt);
     // Restore old completer (if any) and add the command to the history
     // if autohistory is enabled.
     if ($oldcompleter) {
         self::$completer = $oldcompleter;
     }
     if ($autohistory) {
         self::addHistory($ret);
     }
     return $ret;
 }
 public function register()
 {
     if (!function_exists('readline_completion_function')) {
         throw new \RuntimeException('require readline.');
     }
     readline_completion_function(array($this, 'callback'));
 }
Example #3
0
 protected static function _initCompletion()
 {
     self::$_readlineFile = sys_get_temp_dir() . '/phputils-data-history';
     // init read line
     readline_info('readline_name', 'data');
     readline_completion_function([__CLASS__, 'readlineCompletion']);
     is_file(self::$_readlineFile) and readline_read_history(self::$_readlineFile);
 }
Example #4
0
 public function __construct($commands, OutputInterface $outputInterface, Client &$ociClient)
 {
     $this->commands = $commands;
     $this->outputInterface = $outputInterface;
     $this->client =& $ociClient;
     $this->levels = [$this->commands['name']];
     $this->currentLevel = $this->commands;
     readline_completion_function([$this, 'readline_callback']);
 }
Example #5
0
 public function __construct($hint)
 {
     $this->_curr_shh = $this->_shh;
     $this->_hint = $hint;
     $this->_history_file = getenv('HOME') . '/.htsh_history';
     readline_completion_function(array($this, 'completionFunctor'));
     $this->helpInit();
     $this->handleSignals();
     $this->restoreRC();
 }
Example #6
0
 static function read($prompt = null)
 {
     if (self::$autocompleter != null) {
         readline_completion_function(self::$autocompleter);
     }
     $ret = readline($prompt);
     // if ($ret) return $ret;
     // return true;
     return $ret;
 }
 private function main()
 {
     \Cli::write(sprintf('Fuel %s - PHP %s (%s) (%s) [%s]', \Fuel::VERSION, phpversion(), php_sapi_name(), self::build_date(), PHP_OS));
     // Loop until they break it
     while (TRUE) {
         if (\Cli::$readline_support) {
             readline_completion_function(array(__CLASS__, 'tab_complete'));
         }
         if (!($__line = rtrim(trim(trim(\Cli::input('>>> ')), PHP_EOL), ';'))) {
             continue;
         }
         if ($__line == 'quit') {
             break;
         }
         // Add this line to history
         //$this->history[] = array_slice($this->history, 0, -99) + array($line);
         if (\Cli::$readline_support) {
             readline_add_history($__line);
         }
         if (self::is_immediate($__line)) {
             $__line = "return ({$__line})";
         }
         ob_start();
         // Unset the previous line and execute the new one
         $random_ret = \Str::random();
         try {
             $ret = eval("unset(\$__line); {$__line};");
         } catch (\Exception $e) {
             $ret = $random_ret;
             $__line = $e->getMessage();
         }
         // Error was returned
         if ($ret === $random_ret) {
             \Cli::error('Parse Error - ' . $__line);
             \Cli::beep();
         }
         if (ob_get_length() == 0) {
             if (is_bool($ret)) {
                 echo $ret ? 'true' : 'false';
             } elseif (is_string($ret)) {
                 echo addcslashes($ret, "....ÿ");
             } elseif (!is_null($ret)) {
                 var_export($ret);
             }
         }
         unset($ret);
         $out = ob_get_contents();
         ob_end_clean();
         if (strlen($out) > 0 && substr($out, -1) != PHP_EOL) {
             $out .= PHP_EOL;
         }
         echo $out;
         unset($out);
     }
 }
Example #8
0
 public static function readLine($prompt, ReadlineCompleter $compl = null, callable $filter = null)
 {
     if ($compl) {
         \readline_completion_function($compl);
     }
     $ret = \readline($prompt);
     if (self::$history_file) {
         readline_write_history(self::$history_file);
     }
     if ($filter) {
         $ret = $filter($ret);
     }
     return $ret;
 }
Example #9
0
 /**
  * @param ContainerInterface $container
  */
 public function __construct(ContainerInterface $container)
 {
     $this->hasReadline = function_exists('readline');
     $this->application = $container->get('ui.application');
     $file = getenv('HOME') . '/.history_phpguard';
     $this->historyFile = $file;
     $this->output = $container->get('ui.output');
     $this->container = $container;
     // @codeCoverageIgnoreStart
     if ($this->hasReadline) {
         readline_read_history($this->historyFile);
         readline_completion_function(array($this, 'autocompleter'));
     }
     // @codeCoverageIgnoreEnd
 }
Example #10
0
 /**
  *
  *
  */
 public function choose($prompt, $choices)
 {
     echo $prompt . ": \n";
     $choicesMap = array();
     // Not an indexed array
     if (!isset($choices[0])) {
         $i = 0;
         foreach ($choices as $choice => $value) {
             $i++;
             $choicesMap[$i] = $value;
             echo "\t" . $i . "  {$choice}\n";
         }
     } else {
         foreach ($choices as $choice => $desc) {
             $choicesMap[$choice] = $choice;
             echo "\t{$choice}: {$desc}\n";
         }
     }
     if ($this->style) {
         echo $this->formatter->getStartMark($this->style);
     }
     $completionItems = array_keys($choicesMap);
     $choosePrompt = "Please Choose 1-{$i} > ";
     while (1) {
         if (extension_loaded('readline')) {
             $success = readline_completion_function(function ($string, $index) use($completionItems) {
                 return $completionItems;
             });
             $answer = readline($choosePrompt);
             readline_add_history($answer);
         } else {
             echo $choosePrompt;
             $answer = rtrim(fgets(STDIN), "\n");
         }
         $answer = (int) trim($answer);
         if (is_integer($answer)) {
             if (isset($choicesMap[$answer])) {
                 if ($this->style) {
                     echo $this->formatter->getClearMark();
                 }
                 return $choicesMap[$answer];
             } else {
                 continue;
             }
         }
         break;
     }
 }
Example #11
0
    /**
     * Runs the shell.
     */
    public function run()
    {
        $this->application->setAutoExit(false);
        $this->application->setCatchExceptions(true);
        if ($this->hasReadline) {
            readline_read_history($this->history);
            readline_completion_function(array($this, 'autocompleter'));
        }
        $this->output->writeln($this->getHeader());
        $php = null;
        if ($this->processIsolation) {
            $finder = new PhpExecutableFinder();
            $php = $finder->find();
            $this->output->writeln(<<<EOF
<info>Running with process isolation, you should consider this:</info>
  * each command is executed as separate process,
  * commands don't support interactivity, all params must be passed explicitly,
  * commands output is not colorized.

EOF
);
        }
        while (true) {
            $command = $this->readline();
            if (false === $command) {
                $this->output->writeln("\n");
                break;
            }
            if ($this->hasReadline) {
                readline_add_history($command);
                readline_write_history($this->history);
            }
            if ($this->processIsolation) {
                $pb = new ProcessBuilder();
                $process = $pb->add($php)->add($_SERVER['argv'][0])->add($command)->inheritEnvironmentVariables(true)->getProcess();
                $output = $this->output;
                $process->run(function ($type, $data) use($output) {
                    $output->writeln($data);
                });
                $ret = $process->getExitCode();
            } else {
                $ret = $this->application->run(new StringInput($command), $this->output);
            }
            if (0 !== $ret) {
                $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
            }
        }
    }
Example #12
0
 function run()
 {
     $this->install_handler();
     readline_completion_function(array($this, 'callback_complete'));
     while ($this->prompting) {
         $w = NULL;
         $e = NULL;
         $r = array(STDIN);
         $n = stream_select($r, $w, $e, null);
         if ($n && in_array(STDIN, $r)) {
             // read a character, will call the callback when a newline is entered
             readline_callback_read_char();
         }
     }
     echo "Exit.\n";
 }
Example #13
0
 function cmdloop($intro = false)
 {
     $this->preloop();
     if ($this->completekey) {
         readline_completion_function(array($this, 'complete'));
     }
     if ($intro) {
         $this->intro = $intro;
     }
     if ($this->intro) {
         fwrite($this->stdout, $this->intro . "\n");
     }
     if (function_exists('pcntl_signal')) {
         pcntl_signal(SIGINT, function () {
             throw new Exception\KeyboardInterrupt();
         });
     }
     $stop = null;
     while (!$stop) {
         if ($this->cmdqueue) {
             $line = array_pop($this->cmdqueue);
         } elseif ($this->completekey) {
             $line = readline($this->prompt);
             if ($line) {
                 readline_add_history($line);
             } elseif ($line === false) {
                 $line = 'EOF';
             }
         } else {
             fwrite($this->stdout, $this->prompt);
             fflush($this->stdout);
             $line = $this->stdin->readline();
             if (!$line) {
                 $line = 'EOF';
             } else {
                 $line = rtrim($line, "\r\n");
             }
         }
         if (function_exists('pcntl_signal_dispatch')) {
             pcntl_signal_dispatch();
         }
         $line = $this->precmd($line);
         $stop = $this->onecmd($line);
         $stop = $this->postcmd($stop, $line);
     }
     $this->postloop();
 }
Example #14
0
 public static function init($paths = null, $history_path = null)
 {
     self::$_often = get_defined_functions();
     self::$_often = array_merge(self::$_often['internal'], get_declared_classes());
     if (is_null($paths)) {
         $paths = explode(PATH_SEPARATOR, get_include_path());
     }
     self::$_paths = $paths;
     if (self::_supportedReadline()) {
         readline_completion_function(array(__CLASS__, 'autocomplete'));
         self::$__last = null;
         if (is_null($history_path)) {
             if ($home = getenv('HOME')) {
                 $history_path = $home . '/.pprompt_history';
             }
         }
         if (self::$__history_path = $history_path) {
             readline_read_history(self::$__history_path);
         }
     }
     unset($paths);
     unset($history_path);
     unset($home);
     while (self::$__l = self::_readline(">> ")) {
         if (self::_supportedReadline()) {
             if (is_null(self::$__last) or self::$__l != self::$__last) {
                 readline_add_history(self::$__l);
             }
             if (self::$__history_path) {
                 readline_write_history(self::$__history_path);
             }
         }
         try {
             eval(self::$__l . ";");
             echo "\n";
         } catch (Exception $e) {
             echo $e->getMessage() . "\n";
             echo $e->getTraceAsString() . "\n";
         }
         self::$_vars = get_defined_vars();
         self::$__last = self::$__l;
     }
 }
Example #15
0
 protected function __construct()
 {
     if (!empty($_SERVER['HOME'])) {
         $this->historyFile = $_SERVER['HOME'] . '/.imc_history';
         if (!file_exists($this->historyFile)) {
             file_put_contents($this->historyFile, '');
         }
         readline_read_history($this->historyFile);
         $this->history = explode(file_get_contents($this->historyFile), "\n");
         if (isset($_ENV['HISTSIZE']) && $_ENV['HISTSIZE'] > 0) {
             $this->histSize = $_ENV['HISTSIZE'];
         }
     }
     readline_completion_function(array($this, 'completeCallback'));
     register_shutdown_function(array($this, 'fatalErrorShutdown'));
     # // Catch Ctrl+C, kill and SIGTERM
     pcntl_signal(SIGTERM, array($this, 'sigintShutdown'));
     pcntl_signal(SIGINT, array($this, 'sigintShutdown'));
 }
Example #16
0
 public function run($argv)
 {
     $this->display->msg("Welcome to DrutoCli");
     readline_completion_function(function ($text, $index) {
         return $this->autoComplete($text, $index);
     });
     if (isset($argv[1])) {
         $command = $argv[1];
         $drutoCommandClass = 'CliModules' . '\\' . ucwords($command) . '\\' . ucwords($command) . 'Command';
         $this->commandClassObj = new $drutoCommandClass();
         $this->commandClassObj->setParams($argv);
         if (isset($argv[2])) {
             $method = $argv[2];
         } else {
             $method = 'index';
         }
         call_user_func_array(array($this->commandClassObj, $method), $argv);
     }
 }
Example #17
0
 /**
  * Runs the shell.
  */
 public function run()
 {
     $this->application->setAutoExit(false);
     $this->application->setCatchExceptions(true);
     readline_read_history($this->history);
     readline_completion_function(array($this, 'autocompleter'));
     $this->output->writeln($this->getHeader());
     while (true) {
         $command = readline($this->application->getName() . ' > ');
         if (false === $command) {
             $this->output->writeln("\n");
             break;
         }
         readline_add_history($command);
         readline_write_history($this->history);
         if (0 !== ($ret = $this->application->run(new StringInput($command), $this->output))) {
             $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
         }
     }
 }
Example #18
0
 /**
  * Runs the shell.
  */
 public function run()
 {
     $this->application->setAutoExit(false);
     $this->application->setCatchExceptions(false);
     if ($this->hasReadline) {
         readline_read_history($this->history);
         readline_completion_function(array($this, 'autocompleter'));
     }
     $this->output->writeln($this->getHeader());
     while (true) {
         $command = $this->readline();
         if (false === $command) {
             $this->output->writeln("\n");
             break;
         }
         if ($this->hasReadline) {
             readline_add_history($command);
             readline_write_history($this->history);
         }
         $ret = $this->application->run(new StringInput($command), $this->output);
     }
 }
 public function loop()
 {
     /* The "completion" function will provide tab-completion at the prompt */
     readline_completion_function(array($this, 'completion'));
     while (true) {
         /* Use the current node as part of the prompt */
         $line = readline($this->currentNode->getNodePath() . ' > ');
         readline_add_history($line);
         /* The first word typed in is the command, the rest are arguments */
         $parts = explode(' ', $line);
         $cmd = array_shift($parts);
         /* Each command is a method, so call it if it exists */
         $cmd_function_name = "cmd_{$cmd}";
         if (is_callable(array($this, $cmd_function_name))) {
             try {
                 $this->{$cmd_function_name}($parts);
             } catch (Exception $e) {
                 print $e->getMessage() . "\n";
             }
         } else {
             print "Unknown Command: {$line}\n";
         }
     }
 }
 /**
  * Run the interactive Shell
  *
  * The shell command runs Flow's interactive shell. This shell allows for
  * entering commands like through the regular command line interface but
  * additionally supports autocompletion and a user-based command history.
  *
  * @return void
  */
 public function shellCommand()
 {
     if (!function_exists('readline_read_history')) {
         $this->outputLine('Interactive Shell is not available on this system!');
         $this->quit(1);
     }
     $subProcess = false;
     $pipes = array();
     $historyPathAndFilename = getenv('HOME') . '/.flow_' . md5(FLOW_PATH_ROOT);
     readline_read_history($historyPathAndFilename);
     readline_completion_function(array($this, 'autocomplete'));
     echo "Flow Interactive Shell\n\n";
     while (true) {
         $commandLine = readline('Flow > ');
         if ($commandLine == '') {
             echo "\n";
             break;
         }
         readline_add_history($commandLine);
         readline_write_history($historyPathAndFilename);
         $request = $this->requestBuilder->build($commandLine);
         $response = new Response();
         $command = $request->getCommand();
         if ($request === false || $command->getCommandIdentifier() === false) {
             echo "Bad command\n";
             continue;
         }
         if ($this->bootstrap->isCompiletimeCommand($command->getCommandIdentifier())) {
             $this->dispatcher->dispatch($request, $response);
             $response->send();
             if (is_resource($subProcess)) {
                 $this->quitSubProcess($subProcess, $pipes);
             }
         } else {
             if (is_resource($subProcess)) {
                 $subProcessStatus = proc_get_status($subProcess);
                 if ($subProcessStatus['running'] === false) {
                     proc_close($subProcess);
                 }
             }
             if (!is_resource($subProcess)) {
                 list($subProcess, $pipes) = $this->launchSubProcess();
                 if ($subProcess === false || !is_array($pipes)) {
                     echo "Failed launching the shell sub process for executing the runtime command.\n";
                     continue;
                 }
                 $this->echoSubProcessResponse($pipes);
             }
             fwrite($pipes[0], $commandLine . "\n");
             fflush($pipes[0]);
             $this->echoSubProcessResponse($pipes);
             if ($command->isFlushingCaches()) {
                 $this->quitSubProcess($subProcess, $pipes);
             }
         }
     }
     if (is_resource($subProcess)) {
         $this->quitSubProcess($subProcess, $pipes);
     }
     echo "Bye!\n";
 }
Example #21
0
 /**
  * Activate readline tab completion.
  */
 public function activate()
 {
     readline_completion_function(array(&$this, 'callback'));
 }
Example #22
0
 public function run()
 {
     $level = LogLevel::INFO;
     if (isset($this->options['debug'])) {
         $level = LogLevel::DEBUG;
     }
     $prompt = $this->app->name . '> ';
     $this->logger->addHandler(new ShellHandler($this, $level));
     while (ob_get_level() > 0) {
         ob_end_clean();
     }
     $this->parseArguments();
     if (function_exists('readline_completion_function')) {
         readline_completion_function(array($this, 'autoComplete'));
     }
     while (true) {
         try {
             $line = $this->get($prompt);
             if (!is_string($line)) {
                 $this->stop();
                 return;
             }
             if ($line === '') {
                 continue;
             }
             if ($line[0] == '!') {
                 $command = substr($line, 1);
                 if ($command == '') {
                     continue;
                 }
                 if ($command[0] == '=') {
                     $command = substr($command, 1);
                     $this->put(' => ' . $this->dump(eval('return ' . $command . ';')));
                 } else {
                     eval($command);
                 }
             } else {
                 if ($line[0] == '$') {
                     $this->put(' => ' . $this->dump(eval('return ' . $line . ';')));
                 } else {
                     $this->evalCommand($line);
                 }
             }
         } catch (\Exception $e) {
             $this->handleException($e);
         }
     }
 }
Example #23
0
\tsystem_reboot_sync();
\t
EOF;
    more($show_help_text);
}
$fp = fopen('php://stdin', 'r');
echo ".\n\n";
$pkg_interface = 'console';
$shell_active = true;
$tccommands = array();
function completion($string, $index)
{
    global $tccommands;
    return $tccommands;
}
readline_completion_function("completion");
if ($argc < 2) {
    echo "Welcome to the {$g['product_name']} php shell system\n";
    echo "Written by Scott Ullrich (sullrich@gmail.com)\n";
    echo "\nType \"help\" to show common usage scenarios.\n";
    echo "\nAvailable playback commands:\n     ";
    $files = scandir("/etc/phpshellsessions/");
    $tccommands[] = "playback";
    foreach ($files as $file) {
        if ($file != "." and $file != "..") {
            echo $file . " ";
            if (function_exists("readline_add_history")) {
                readline_add_history("playback {$file}");
                $tccommands[] = "{$file}";
            }
        }
 public function inputStream($var = array())
 {
     self::$suggestions = $var;
     if (PHP_OS == 'WINNT') {
         $input = trim(stream_get_line(STDIN, 1024, PHP_EOL));
     } else {
         readline_completion_function(array('self', 'getSuggestions'));
         $input = trim(readline($this->inputStream));
     }
     if ($input) {
         if (in_array(strtolower($input), array('exit', 'quit', 'q'))) {
             echo $this->colorize("ABORTING ...\n", 'red');
             exit;
         } else {
             return $input;
         }
     }
 }
Example #25
0
 public function loop()
 {
     for (;;) {
         if (Console::$have_readline) {
             readline_completion_function(array($this, "readline_complete"));
             $this->line = @readline(">> ");
         } else {
             print ">> ";
             $this->line = trim(fgets(STDIN));
         }
         if ($this->line === false || !Console::$have_readline && feof(STDIN)) {
             echo "\n";
             break;
         }
         if (strlen($this->line) == 0) {
             continue;
         }
         if (Console::$have_readline && (!isset($this->history) || $this->line != $this->history)) {
             readline_add_history($this->line);
             $this->history = $this->line;
         }
         if ($this->is_immediate($this->line)) {
             $this->line = "return (" . $this->line . ")";
         }
         ob_start();
         try {
             $ret = @eval($this->line . ";");
             if (ob_get_length() == 0) {
                 if (is_bool($ret)) {
                     echo $ret ? "true" : "false";
                 } else {
                     if (is_string($ret)) {
                         echo "'" . addcslashes($ret, "....ÿ") . "'";
                     } else {
                         if (!is_null($ret)) {
                             print_r($ret);
                         }
                     }
                 }
             }
             unset($ret);
         } catch (\Exception $exception) {
             $title = get_class($exception);
             /* activerecord includes the stack trace in the message, so strip
              * it out */
             if ($exception instanceof \ActiveRecord\DatabaseException) {
                 $title .= ": " . preg_replace("/\nStack trace:.*/s", "", $exception->getMessage());
             } elseif ($exception->getMessage()) {
                 $title .= ": " . $exception->getMessage() . " in " . $exception->getFile() . " on line " . $exception->getLine();
             }
             print $title . "\n";
             foreach ($exception->getTrace() as $call) {
                 print "    " . (isset($call["file"]) ? $call["file"] : $call["class"]) . ":" . (isset($call["line"]) ? $call["line"] : "") . " in " . $call["function"] . "()\n";
             }
         }
         $out = ob_get_contents();
         ob_end_clean();
         if (strlen($out) > 0 && substr($out, -1) != "\n") {
             $out .= "\n";
         }
         echo $out;
         unset($out);
     }
 }
Example #26
0
 /**
  * Interactive mode
  *
  * @param string        $title   Prompt title
  * @param \Closure      $cb      Line callback
  * @param bool|\Closure $auto_br Auto br or completion function
  */
 public static function interactive($title, $cb, $auto_br = true)
 {
     if ($auto_br instanceof \Closure) {
         readline_completion_function($auto_br);
     }
     while (true) {
         $input = readline($title);
         if ($input === false) {
             exit(0);
         }
         if (strlen($input) == 0) {
             continue;
         }
         readline_add_history($input);
         $cb($input);
         if ($auto_br === true) {
             echo PHP_EOL;
         }
     }
 }
Example #27
0
 /**
  * @uses Yiiic::onComplete()
  */
 protected function registerCompleteFn()
 {
     readline_completion_function([$this, 'onComplete']);
 }
Example #28
0
 /**
  * init the shell and change if readline support is available
  */
 public function __construct()
 {
     $this->code = '';
     $this->stdin = null;
     $this->have_readline = function_exists('readline');
     if ($this->have_readline) {
         readline_completion_function('PHP_Shell_readlineComplete');
     }
     $this->use_readline = true;
     $cmd = PHP_Shell_Commands::getInstance();
     $cmd->registerCommand('#^quit$#', $this, 'cmdQuit', 'quit', 'leaves the shell');
     $cmd->registerCommand('#^\\?$#', $this, 'cmdHelp', '?', 'show this help');
     $cmd->registerCommand('#^\\?\\s+license$#', $this, 'cmdLicense', '? license', 'show license of the shell');
 }
Example #29
0
 /**
  * Defines a completer
  *
  * @param   org.gnu.readline.Completer completer
  * @return  bool success
  * @throws  lang.IllegalArgumentException
  */
 public function setCompleter(Completer $completer)
 {
     ReadLine::registry('completer', $completer);
     return readline_completion_function('__complete');
 }
Example #30
0
    public static function main($options = array())
    {
        $shell = new iphp($options);
        print <<<END

Welcome to the PHOCOA shell! The PHOCOA shell is a powerful interactive PHP shell for allowing you to experiment with your application interactively.

Features include:
- autocomplete (tab key)
- readline support w/history
- automatically wired into your project's autoload

Enter a php statement at the prompt, and it will be evaluated. The variable \$_ will contain the result.

Example:

> new WFArray(array(1,2))
Array:
  0 => 1
  1 => 2
END Array

> \$_[0] + 1
2


END;
        // readline history
        if (function_exists('readline_read_history')) {
            readline_read_history($shell->historyFile());
            // doesn't seem to work, even though readline_list_history() shows the read items!
        }
        // install tab-complete
        if (function_exists('readline_completion_function')) {
            readline_completion_function(array($shell, 'readlineCompleter'));
        }
        while (true) {
            $shell->doCommand($shell->readline());
        }
    }