text:
<?php

/**
 * This script handles the command line interface commands to Pyrus
 *
 * Each command is a separate method, and will be called with the arguments
 * entered by the end user.
 *
 * @category  Pyrus
 * @package   Pyrus
 * @author    Greg Beaver <cellog@php.net>
 * @copyright 2010 The PEAR Group
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
 * @link      https://github.com/pyrus/Pyrus
 */
namespace Pyrus\ScriptFrontend;
use Pyrus\ScriptFrontend;

class Commands implements \Pyrus\LogInterface
{
    public $commands = array();
    // for unit-testing ease
    public static $configclass = 'Pyrus\Config';
    protected $verbose;
    protected $term = array(
        'bold'   => '',
        'normal' => '',
    );
    /**
     * The actual scriptfrontend
     *
     * @var \Pyrus\ScriptFrontend
     */
    protected static $commandParser;

    function exceptionHandler($e)
    {
        if ($this->verbose > 3) {
            echo $e;
        }
        if ($e instanceof \PEAR2\Exception) {
            $causes = array();
            $e->getCauseMessage($causes);
            $causeMsg = '';
            foreach ($causes as $i => $cause) {
                $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
                       . $cause['message'] . "\n";
            }
            echo $causeMsg;
        } else {
            echo $e->getMessage(), "\n";
        }
    }

    function __construct($debugging = false)
    {
        if (!$debugging) {
            set_exception_handler(array($this, 'exceptionHandler'));
        }

        \Pyrus\Logger::attach($this);
        if (!isset(static::$commandParser)) {
            $schemapath = \Pyrus\Main::getDataPath() . '/customcommand-2.0.xsd';
            $defaultcommands = \Pyrus\Main::getDataPath() . '/built-in-commands.xml';

            // Check for a local-developer-commands.xml file
            $localcommands = false;
            if (file_exists(\Pyrus\Main::getDataPath() . '/local-developer-commands.xml')) {
                $localcommands = realpath(\Pyrus\Main::getDataPath() . '/local-developer-commands.xml');
            }

            $parser = new \Pyrus\XMLParser;
            $commands = $parser->parse($defaultcommands, $schemapath);
            $commands = $commands['commands']['command'];

            if ($localcommands) {
                // Add in local commands
                $localcommands = $parser->parse($localcommands, $schemapath);
                $commands = array_merge($commands, $localcommands['commands']['command']);
            }

            if ('@PACKAGE_VERSION@' == '@'.'PACKAGE_VERSION@') {
                $version = '2.0.0a4'; // running from git
            } else {
                $version = '@PACKAGE_VERSION@';
            }

            static::$commandParser = new \Pyrus\ScriptFrontend(array(
                    'version' => $version,
                    'description' => 'Pyrus, the PHP manager',
                    'name' => 'php ' . basename($_SERVER['argv'][0])
                )
            );

            // set up our custom renderer for help options
            static::$commandParser->accept(new \Pyrus\ScriptFrontend\Renderer(static::$commandParser));

            // set up command-less options and argument
            static::$commandParser->addOption('verbose', array(
                'short_name'  => '-v',
                'long_name'   => '--verbose',
                'action'      => 'Counter',
                'description' => 'increase verbosity'
            ));

            static::$commandParser->addOption('paranoid', array(
                'short_name'  => '-p',
                'long_name'   => '--paranoid',
                'action'      => 'Counter',
                'description' => 'set or increase paranoia level'
            ));

            \Pyrus\PluginRegistry::registerFrontend($this);
            \Pyrus\PluginRegistry::addCommand($commands);
        }

        $term = getenv('TERM');
        if (function_exists('posix_isatty') && !posix_isatty(1)) {
            // output is being redirected to a file or through a pipe
        } elseif ($term) {
            if (preg_match('/^(xterm|vt220|linux)/', $term)) {
                $this->term['bold']   = sprintf("%c%c%c%c", 27, 91, 49, 109);
                $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
            } elseif (preg_match('/^vt100/', $term)) {
                $this->term['bold']   = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
                $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
            }
        }
    }

    function mapCommand($commandinfo)
    {
        $command = static::$commandParser->addCommand($commandinfo['name'], array(
            'description' => $commandinfo['summary'],
            'aliases' => array($commandinfo['shortcut']),
            'renderer' => new \Pyrus\ScriptFrontend\Renderer,
        ));

        if (isset($commandinfo['options']['option'])) {
            $options = $commandinfo['options']['option'];
            if (!isset($options[0])) {
                $options = array($options);
            }

            foreach ($options as $option) {
                switch (key($option['type'])) {
                    case 'bool' :
                        $action = 'StoreTrue';
                        break;
                    case 'string' :
                        $action = 'StoreString';
                        break;
                    case 'int' :
                        $action = 'StoreInt';
                        break;
                    case 'float' :
                        $action = 'StoreFloat';
                        break;
                    case 'counter' :
                        $action = 'Counter';
                        break;
                    case 'callback' :
                        $func = $option['type']['callback'];
                        $class = $commandinfo['class'];
                        $callback = function ($value, $option, $result, $parser) use ($func, $class) {
                            return $class::$func($value);
                        };
                        $action = 'Callback';
                        break;
                    case 'set' :
                        $action = 'StoreString';
                        $choice = $option['set']['value'];
                        settype($choice, 'array');
                        break;
                }

                $info = array(
                    'short_name' => empty($option['shortopt']) ? null : '-' . $option['shortopt'],
                    'long_name' => empty($option['name']) ? null : '--' . $option['name'],
                    'description' => $option['doc'],
                    'action' => $action,
                );

                if ($action == 'Callback') {
                    $info['callback'] = $callback;
                }

                if (isset($option['default'])) {
                    $info['default'] = $option['default'];
                }

                if (isset($choice)) {
                    $info['choices'] = $choice;
                    $choice = null;
                }

                if ($info['long_name'] != null) {
                    $command->addOption(str_replace('-', '_', $option['name']), $info);
                } elseif ($info['shortopt'] != null) {
                    $command->addOption(str_replace('-', '_', $option['shortopt']), $info);
                } else {
                    throw new Exception('Invalid command ' . $commandinfo['name'] . ': No option name or shortopt was provided.');
                }
            }
        }

        if (isset($commandinfo['arguments']['argument'])) {
            $args = $commandinfo['arguments']['argument'];
            if (!isset($args[0])) {
                $args = array($args);
            }

            foreach ($args as $arg) {
                $command->addArgument($arg['name'], array(
                    'description' => $arg['doc'],
                    'multiple' => (bool) $arg['multiple'],
                    'optional' => (bool) $arg['optional'],
                ));
            }
        }
    }

    function _bold($text)
    {
        if (empty($this->term['bold'])) {
            return strtoupper($text);
        }

        return $this->term['bold'] . $text . $this->term['normal'];
    }

    function addDeveloperCommands($type)
    {
        $schemapath = \Pyrus\Main::getDataPath() . '/customcommand-2.0.xsd';
        $defaultcommands = \Pyrus\Main::getDataPath() . '/' . $type . 'commands.xml';

        $parser = new \Pyrus\XMLParser;
        $commands = $parser->parse($defaultcommands, $schemapath);
        $commands = $commands['commands']['command'];
        \Pyrus\PluginRegistry::addCommand($commands);
    }

    /**
     * This method acts as a controller which dispatches the request to the
     * correct command/method.
     *
     * <code>
     * $cli = \Pyrus\ScriptFrontend\Commands;
     * $cli->run($args = array (0 => 'install',
     *                          1 => 'PEAR2/Pyrus_Developer/package.xml'));
     * </code>
     *
     * The above code will dispatch to the install command
     *
     * @param array $args An array of command line arguments.
     *
     * @return int
     */
    function run($args)
    {
        try {
            $sig = \Pyrus\Main::getSignature();
            if ($sig) {
                echo "Pyrus version ", \Pyrus\Main::VERSION, ' ',
                     $sig['hash_type'], ': ', $sig['hash'], "\n";
            }

            $this->_findPEAR($args);
            $this->verbose = \Pyrus\Config::current()->verbose;

            // scan for custom commands/roles/tasks
            \Pyrus\Config::current()->pluginregistry->scan();

            if (!isset(static::$commandParser->commands['make'])) {
                $this->addDeveloperCommands('developer');
            }

            if (!isset(static::$commandParser->commands['scs-update'])) {
                $this->addDeveloperCommands('scs');
            }

            $result = static::$commandParser->parse(count($args) + 1, array_merge(array('cruft'), $args));
            if ($result->options['verbose']) {
                $this->verbose = $result->options['verbose'];
            }

            if ($result->options['paranoid']) {
                \Pyrus\Main::$paranoid = $result->options['paranoid'];
            }

            if ($info = \Pyrus\PluginRegistry::getCommandInfo($result->command_name)) {
                if ($this instanceof $info['class']) {
                    if ($info['function'] == 'dummyStub' || $info['function'] == 'scsDummyStub') {
                        $this->{$info['function']}($result);
                    } else {
                        $this->{$info['function']}($result->command->args, $result->command->options);
                    }
                } else {
                    $class = new $info['class'];
                    return (int)!$class->{$info['function']}($this, $result->command->args, $result->command->options);
                }
            } else {
                $this->help(array('command' => isset($args[0]) ? $args[0] : null));
            }
        } catch (\PEAR2\Console\CommandLine\Exception $e) {
            static::$commandParser->displayError($e->getMessage(), false);
            if (
                   $e->getCode() == \PEAR2\Console\CommandLine\Exception::ARGUMENT_REQUIRED
                || $e->getCode() == \PEAR2\Console\CommandLine\Exception::OPTION_UNKNOWN) {
                $this->help(array('command' => $args[0]));
            } else {
                static::$commandParser->displayUsage(false);
            }
        }
    }

    function ask($question, array $choices = null, $default = null)
    {
        if (is_array($choices)) {
            foreach ($choices as $i => $choice) {
                if (is_int($i) && ($default === null || ($default !== null && !is_string($default)))) {
                    $is_int = false;
                } else {
                    $is_int = true;
                }
                break;
            }
        }
previous:
        echo $question,"\n";
        if ($choices !== null) {
            echo "Please choose:\n";
            foreach ($choices as $i => $choice) {
                if ($is_int) {
                    echo '  ',$choice,"\n";
                } else {
                    echo '  [',$i,'] ',$choice,"\n";
                }
            }
        }
        if ($default !== null) {
            echo '[',$default,']';
        }
        echo ' : ';
        $answer = $this->_readStdin();

        if (!strlen($answer)) {
            if ($default !== null) {
                $answer = $default;
            } else {
                $answer = null;
            }
        } elseif ($choices !== null) {
            if (($is_int && in_array($answer, $choices)) || (!$is_int && array_key_exists($answer, $choices))) {
                return $answer;
            } else {
                echo "Please choose one choice\n";
                goto previous;
            }
        }
        return $answer;
    }

    function _readStdin($amount = 1024)
    {
        return trim(fgets(STDIN, $amount));
    }

    protected function _findPEAR(&$arr)
    {
        $configclass = static::$configclass;
        if (isset($arr[0]) && @file_exists($arr[0]) && @is_dir($arr[0])) {
            $maybe = array_shift($arr);
            $maybe = realpath($maybe);
            echo "Using PEAR installation found at $maybe\n";
            $config = $configclass::singleton($maybe);
            return;
        }

        if (!$configclass::userInitialized()) {
            $this->_initializeConfiguration();
        }

        $config = $configclass::singleton();
        $path = $config->path;
        if (strpos($path, PATH_SEPARATOR)) {
            echo "Using PEAR installations found at $path\n";
        } else {
            echo "Using PEAR installation found at $path\n";
        }
    }

    protected function _initializeConfiguration()
    {
        echo "Pyrus: No user configuration file detected\n";

        if ('yes' !== $this->ask("It appears you have not used Pyrus before, welcome!  Initialize install?", array('yes', 'no'), 'yes')) {
            echo "OK, thank you, finishing execution now\n";
            exit;
        }

        $configclass = static::$configclass;
        echo "Great.  We will store your configuration in:\n  ",$configclass::getDefaultUserConfigFile(),"\n";
        previous:
        $path = $this->ask("Where would you like to install packages by default?", null, getcwd());
        echo "You have chosen:\n", $path, "\n";
        if (!realpath($path)) {
            echo " this path does not yet exist\n";
            if ('yes' !== $this->ask("Create it?", array('yes', 'no'), 'yes')) {
                goto previous;
            }
        } elseif (!is_dir($path)) {
            echo $path," exists, and is not a directory\n";
            goto previous;
        }

        $config = $configclass::singleton($path);
        $config->saveConfig();
        echo "Thank you, enjoy using Pyrus\n";
        echo "Documentation is at http://pear.php.net\n";
    }

    function dummyStub($command)
    {
        if ('yes' === $this->ask('The "' . $command->command_name .
                                 '" command is in the developer tools.  Install developer tools?',
                    array('yes', 'no'), 'no')) {
            return $this->upgrade(array('package' => array('pyrus.net/Pyrus_Developer-alpha')),
                           array('plugin' => true, 'force' => false, 'optionaldeps' => false));
        }
    }

    function scsDummyStub($command)
    {
        if ('yes' === $this->ask('The "' . $command->command_name .
                                 '" command is in the simple channel server tools.  ' .
                                 'Install simple channel server tools?',
                    array('yes', 'no'), 'no')) {
            return $this->upgrade(array('package' => array('pyrus.net/Pyrus_SimpleChannelServer-alpha')),
                           array('plugin' => true, 'force' => false, 'optionaldeps' => false));
        }
    }

    /**
     * Search for known packages matching a query
     *
     * @param array $args Array of command line arguments
     */
    function search($args)
    {
        echo 'Searching for '.$args['query'].PHP_EOL;

        $search = new Commands\Search();
        $results = $search->query($args['query']);

        if (false === $results) {
            echo 'No results found.'.PHP_EOL;
            return;
        }

        echo count($results) . ' packages found:'.PHP_EOL;
        foreach ($results as $name=>$result) {
            echo $name.PHP_EOL;
        }
        echo PHP_EOL.'For information on a specific package, type: pyrus info channel/PackageName'.PHP_EOL;
    }

    /**
     * Display the help dialog and list all commands supported.
     *
     * @param array $args Array of command line arguments
     */
    function help($args)
    {
        if (!isset($args['command']) || $args['command'] === 'help') {
            static::$commandParser->displayUsage();
        } else {
            $info = \Pyrus\PluginRegistry::getCommandInfo($args['command']);
            if (!$info) {
                // This command is not known, but it could be an alias
                foreach (static::$commandParser->commands as $command) {
                    foreach ($command->aliases as $alias) {
                        if ($args['command'] == $alias) {
                            // Found a match
                            $args['command'] = $command->name;
                            return $this->help($args);
                        }
                    }
                }
                foreach ($args as $arg) {
                    switch ($arg) {
                        case 'package' :
                        case 'make' :
                        case 'run-phpt' :
                        case 'pickle' :
                            if ('yes' === $this->ask('The "' . $arg .
                                                     '" command is in the developer tools.  Install developer tools?',
                                        array('yes', 'no'), 'no')) {
                                return $this->upgrade(array('package' =>
                                                            array('pear2.php.net/Pyrus_Developer-alpha')),
                                               array('plugin' => true, 'force' => false, 'optionaldeps' => false));
                            }
                        default :
                            break;
                    }
                }
                echo "Unknown command: $args[command]\n";
                static::$commandParser->displayUsage();
            } else {
                static::$commandParser->commands[$args['command']]->doc = $info['doc'];
                static::$commandParser->commands[$args['command']]->displayUsage(false);
            }
        }
    }

    /**
     * install a local or remote package
     *
     * @param array $args
     */
    function install($args, $options)
    {
        if ($options['plugin']) {
            \Pyrus\Main::$options['install-plugins'] = true;
        }

        if ($options['force']) {
            \Pyrus\Main::$options['force'] = true;
        }

        if (isset($options['packagingroot']) && $options['packagingroot']) {
            \Pyrus\Main::$options['packagingroot'] = $options['packagingroot'];
        }

        if ($options['optionaldeps']) {
            \Pyrus\Main::$options['optionaldeps'] = $options['optionaldeps'];
        }

        \Pyrus\Installer::begin();
        try {
            $packages = array();
            foreach ($args['package'] as $arg) {
                \Pyrus\Installer::prepare($packages[] = new \Pyrus\Package($arg));
            }

            \Pyrus\Installer::commit();
            foreach (\Pyrus\Installer::getInstalledPackages() as $package) {
                echo 'Installed ' . $package->channel . '/' . $package->name . '-' .
                    $package->version['release'] . "\n";
                if ($package->type === 'extsrc' || $package->type === 'zendextsrc') {
                    echo " ==> To build this PECL package, use the build command\n";
                }
            }

            $optionals = \Pyrus\Installer::getIgnoredOptionalDeps();
            if (count($optionals)) {
                echo "Optional dependencies that will not be installed, use --optionaldeps:\n";
            }

            foreach ($optionals as $dep => $packages) {
                echo $dep, ' depended on by ', implode(', ', array_keys($packages)), "\n";
            }
        } catch (\Exception $e) {

            if ($e instanceof \Pyrus\Channel\Exception
                && strpos($arg, '/') === false) {
                echo "Sorry there was an error retrieving "
                    . \Pyrus\Config::current()->default_channel
                    . "/{$arg} from the default channel\n";
            }

            // If this is an undiscovered channel, handle it gracefully
            if ($e instanceof \Pyrus\Package\Exception
                && $e->getPrevious() instanceof \Pyrus\ChannelRegistry\Exception
                && $e->getPrevious()->getPrevious() instanceof \Pyrus\ChannelRegistry\ParseException
                && $e->getPrevious()->getPrevious()->why == 'channel'
                && strpos($arg, '/') !== false) {

                $channel = substr($arg, 0, strrpos($arg, '/'));

                echo "Sorry, the channel \"{$channel}\" is unknown.\n";

                return $this->installUnknownChannelExceptionHandler($args, $options, $e, $channel);
            }

            if ($e instanceof \Pyrus\ChannelRegistry\Exception
                && $e->getPrevious() instanceof \Pyrus\ChannelRegistry\ParseException
                && $e->getPrevious()->why == 'channel'
                // @todo Ugh, fix this mess
                && preg_match('/^unknown channel \"(.*)\" in \"(.*)\"$/', $e->getPrevious()->getMessage(), $matches)) {
                echo "Sorry, $arg references an unknown channel {$matches[1]} for {$matches[2]}\n";

                return $this->installUnknownChannelExceptionHandler($args, $options, $e, $matches[1]);
            }

            $this->exceptionHandler($e);
            exit(1);
        }
    }

    protected function installUnknownChannelExceptionHandler($args, $options, \Exception $e, $channel)
    {
        if (\Pyrus\Config::current()->auto_discover
            || 'yes' === $this->ask('Do you want to add this channel and continue?', array('yes', 'no'), 'yes')) {
            $this->channelDiscover(array('channel' => $channel));
            $this->install($args, $options);
            return;
        }
        echo "Ok. I understand.\n";
        $this->exceptionHandler($e);
        exit(1);
    }

    /**
     * uninstall an installed package
     *
     * @param array $args
     */
    function uninstall($args, $options)
    {
        if ($options['plugin']) {
            \Pyrus\Main::$options['install-plugins'] = true;
        }
        \Pyrus\Uninstaller::begin();
        $packages = $non = $failed = array();
        foreach ($args['package'] as $arg) {
            try {
                if (!isset(\Pyrus\Config::current()->registry->package[$arg])) {
                    $non[] = $arg;
                    continue;
                }
                $packages[] = \Pyrus\Uninstaller::prepare($arg);
            } catch (\Exception $e) {
                $failed[] = $arg;
            }
        }
        \Pyrus\Uninstaller::commit();
        foreach ($non as $package) {
            echo "Package $package not installed, cannot uninstall\n";
        }
        foreach ($packages as $package) {
            echo 'Uninstalled ', $package->channel, '/', $package->name, "\n";
        }
        foreach ($failed as $package) {
            echo "Package $package could not be uninstalled\n";
        }
    }

    /**
     * download a remote package
     *
     * @param array $args
     */
    function download($args)
    {
        \Pyrus\Main::$options['downloadonly'] = true;
        \Pyrus\Config::current()->download_dir = getcwd();
        $packages = array();
        foreach ($args['package'] as $arg) {
            try {
                $packages[] = array(new \Pyrus\Package($arg), $arg);
            } catch (\Exception $e) {
                echo "failed to init $arg for download (", $e->getMessage(), ")\n";
            }
        }
        foreach ($packages as $package) {
            $arg = $package[1];
            $package = $package[0];
            echo "Downloading ", $arg, '...';
            try {
                if ($package->isRemote()) {
                    $package->download();
                } else {
                    $package->copyTo(getcwd());
                }
                $path = $package->getInternalPackage()->getTarballPath();
                echo "\ndone ($path)\n";
            } catch (\Exception $e) {
                echo 'failed! (', $e->getMessage(), ")\n";
            }
        }
    }

    /**
     * Upgrade a package
     *
     * @param array $args
     */
    function upgrade($args, $options)
    {
        \Pyrus\Main::$options['upgrade'] = true;
        $this->install($args, $options);
    }

    /**
     * list all the installed packages
     *
     * @param array $args
     */
    function listPackages()
    {
        $reg = \Pyrus\Config::current()->registry;
        $creg = \Pyrus\Config::current()->channelregistry;
        $cascade = array(array($reg, $creg));
        $p = $reg;
        $c = $creg;
        while ($p = $p->getParent()) {
            $c = $c->getParent();
            $cascade[] = array($p, $c);
        }
        array_reverse($cascade);
        foreach ($cascade as $p) {
            $c = $p[1];
            $p = $p[0];
            echo "Listing installed packages [", $p->getPath(), "]:\n";
            $packages = array();
            foreach ($c as $channel) {
                \Pyrus\Config::current()->default_channel = $channel->name;
                $packages[$channel->name] = array();
                foreach ($p->package as $package) {
                    $packages[$channel->name][$package->name] = $package;
                }
            }
            asort($packages);
            foreach ($packages as $channel => $channel_packages) {
                echo "[channel $channel]:\n";
                if (!count($channel_packages)) {
                    echo '(no packages installed in channel ' . $channel . ')' . PHP_EOL;
                    continue;
                }
                ksort($channel_packages);
                foreach ($channel_packages as $package) {
                    $data = array($package->name,
                                  $package->version['release'],
                                  $package->stability['release'],
                                  );
                    // @TODO add CLI table output
                    echo implode($data, ' ') . PHP_EOL;
                }
            }
        }
    }

    /**
     * List all the known channels
     *
     * @param array $args
     */
    function listChannels()
    {
        $creg = \Pyrus\Config::current()->channelregistry;
        $cascade = array($creg);
        while ($c = $creg->getParent()) {
            $cascade[] = $c;
            $creg = $c;
        }
        array_reverse($cascade);
        foreach ($cascade as $c) {
            echo "Listing channels [", $c->getPath(), "]:\n";
            $chans = array();
            foreach ($c as $channel) {
                $chans[$channel->name] = $channel->alias;
            }
            ksort($chans);
            foreach ($chans as $channel => $alias) {
                echo $channel . ' (' . $alias . ")\n";
            }
        }
    }

    /**
     * This command can remotely connect to a channel server and grab the
     * channel information then add it to the current pyrus managed repo.
     * Also work from local paths, raw channel.xml and full URLs
     *
     * @param array $args $args[0] can be a channel name (eg:pear.unl.edu),
     *                    full url and local path
     */
    function channelDiscover($args)
    {
        try {
            $channel = new \Pyrus\ChannelFile($args['channel']);
        } catch (\Exception $e) {
            echo "Discovery of channel ", $args['channel'], " failed: ", $e->getMessage(), "\n";
            return;
        }

        $chan = new \Pyrus\Channel($channel);
        \Pyrus\Config::current()->channelregistry->add($chan);
        echo "Discovery of channel ", $chan->name, " successful\n";
    }

    function channelDel($args)
    {
        $chan = \Pyrus\Config::current()->channelregistry->get($args['channel'], false);
        if (count(\Pyrus\Config::current()->registry->listPackages($chan->name))) {
            echo "Cannot remove channel ", $chan->name, " packages are installed\n";
            exit(1);
        }
        \Pyrus\Config::current()->channelregistry->delete($chan);
        echo "Deleting channel ", $chan->name, " successful\n";
    }

    function upgradeRegistry($args, $options)
    {
        if (!file_exists($args['path']) || !is_dir($args['path'])) {
            echo "Cannot upgrade registries at ", $args['path'], ", path does not exist or is not a directory\n";
            exit(1);
        }
        echo "Upgrading registry at path ", $args['path'], "\n";
        $registries = \Pyrus\Registry::detectRegistries($args['path']);
        if (!count($registries)) {
            echo "No registries found\n";
            exit;
        }
        if (!in_array('Pear1', $registries)) {
            echo "Registry already upgraded\n";
            exit;
        }
        $pear1 = new \Pyrus\Registry\Pear1($args['path']);
        if (!in_array('Sqlite3', $registries)) {
            $sqlite3 = new \Pyrus\Registry\Sqlite3($args['path']);
            $sqlite3->cloneRegistry($pear1);
        }
        if (!in_array('Xml', $registries)) {
            $xml = new \Pyrus\Registry\Xml($args['path']);
            $sqlite3 = new \Pyrus\Registry\Sqlite3($args['path']);
            $xml->cloneRegistry($sqlite3);
        }
        if ($options['removeold']) {
            \Pyrus\Registry\Pear1::removeRegistry($args['path']);
        }
    }

    function runScripts($args)
    {
        $runner = new \Pyrus\ScriptRunner($this);
        $reg = \Pyrus\Config::current()->registry;
        foreach ($args['package'] as $package) {
            $package = $reg->package[$package];
            $runner->run($package);
        }
    }

    /**
     * Display pyrus configuration vars
     *
     */
    protected function configShow($args, $options)
    {
        $conf = $current = \Pyrus\Config::current();
        if ($options['plugin']) {
            echo "Plugin configuration:\n";
            $conf = \Pyrus\Config::singleton(\Pyrus\Config::current()->plugins_dir);
        }
        echo "System paths:\n";
        foreach ($conf->mainsystemvars as $var) {
            echo "  $var => " . $conf->$var . "\n";
        }
        echo "Custom System paths:\n";
        foreach ($conf->customsystemvars as $var) {
            echo "  $var => " . $conf->$var . "\n";
        }
        echo "User config (from ", $conf->userfile, "):\n";
        foreach ($conf->mainuservars as $var) {
            echo "  $var => " . $conf->$var . "\n";
        }
        echo "(variables specific to ", $conf->default_channel, "):\n";
        foreach ($conf->mainchannelvars as $var) {
            echo "  $var => " . $conf->$var . "\n";
        }
        echo "Custom User config (from " . $conf->userfile . "):\n";
        foreach ($conf->customuservars as $var) {
            echo "  $var => " . $conf->$var . "\n";
        }
        echo "(variables specific to ", $conf->default_channel, "):\n";
        foreach ($conf->customchannelvars as $var) {
            echo "  $var => " . $conf->$var . "\n";
        }
    }

    /**
     * Get a configuration option.
     *
     * @param array $args
     */
    function get($args, $options)
    {
        if (empty($args['variable'])) {
            return $this->configShow($args, $options);
        }

        $conf = $current = \Pyrus\Config::current();
        if ($options['plugin']) {
            $conf = \Pyrus\Config::singleton(\Pyrus\Config::current()->plugins_dir);
        }

        if ($options['channel']) {
            $oldDefaultChannel = $conf->default_channel;
            $channel = $conf->channelregistry->get($options['channel'], false);
            $conf->default_channel = $channel->name;
        }
        if (
            in_array($args['variable'], $conf->uservars)
            || in_array($args['variable'], $conf->systemvars)
        ) {
            echo $conf->{$args['variable']} . PHP_EOL;
        } else {
            echo "Unknown config variable: $args[variable]\n";
            exit(1);
        }

        if ($options['channel']) {
            $conf->default_channel = $oldDefaultChannel;
        }
        if ($options['plugin']) {
            \Pyrus\Config::setCurrent($current->path);
        }
    }

    /**
     * Set a configuration option.
     *
     * @param array $args
     */
    function set($args, $options)
    {
        $conf = $current = \Pyrus\Config::current();

        if ($options['plugin']) {
            $conf = \Pyrus\Config::singleton(\Pyrus\Config::current()->plugins_dir);
        }
        if (in_array($args['variable'], $conf->channelvars)) {
            if ($options['channel']) {
                $oldDefaultChannel = $conf->default_channel;
                $channel = $conf->channelregistry->get($options['channel'], false);
                $conf->default_channel = $channel->name;
            }

            echo "Setting $args[variable] for " . $conf->default_channel . " in " . $conf->userfile . "\n";
            $conf->{$args['variable']} = $args['value'];

            if ($options['channel']) {
                $conf->default_channel = $oldDefaultChannel;
            }
        } elseif (in_array($args['variable'], $conf->uservars)) {
            echo "Setting $args[variable] in " . $conf->userfile . "\n";
            $conf->{$args['variable']} = $args['value'];
        } elseif (in_array($args['variable'], $conf->systemvars)) {
            echo "Setting $args[variable] in system paths\n";
            $conf->{$args['variable']} = $args['value'];
        } else {
            echo "Unknown config variable: $args[variable]\n";
            exit(1);
        }
        $conf->saveConfig();
        if ($options['plugin']) {
            \Pyrus\Config::setCurrent($current->path);
        }
    }

    /**
     * Set up a pear path managed by pyrus.
     *
     * @param array $args Arguments
     */
    function mypear($args)
    {
        echo "Setting my pear repositories to:\n";
        echo implode("\n", $args['path']) . "\n";
        $args = implode(PATH_SEPARATOR, $args['path']);
        \Pyrus\Config::current()->my_pear_path = $args;
        \Pyrus\Config::current()->saveConfig();
    }

    function build($args)
    {
        echo "Building PECL extensions\n";
        $builder = new \Pyrus\PECLBuild($this);
        foreach ($args['PackageName'] as $arg) {
            $package = \Pyrus\Config::current()->registry->package[$arg];
            $builder->installBuiltStuff($package, $builder->build($package));
        }
    }

    function info($args, $options)
    {
        if (!$options['forceremote']) {
            if (file_exists($args['package'])) {
                $package = new \Pyrus\Package($args['package']);
                $installed = false;
            } elseif (isset(\Pyrus\Config::current()->registry->package[$args['package']])) {
                $package = \Pyrus\Config::current()->registry->package[$args['package']];
                $installed = true;
            }
        }
        if (!isset($package)) {
            $installed = false;
            $package = new \Pyrus\Package($args['package'], $options['forceremote']);
        }
        echo $this->wrap($package->name . ' (' . $package->channel . ' Channel)'), "\n";
        echo str_repeat('-', 80), "\n";
        // this next line ensures we get an accurate reading on a remote abstract package
        if (!$installed && $package->isRemote()) {
            $package->grabEntirePackagexml();
        }
        if (!isset($args['field'])) {
            echo 'Package type: ';
            switch ($package->type) {
                case 'php' :
                    echo "PHP package\n";
                    break;
                case 'extsrc' :
                    echo "Extension source package\n";
                    break;
                case 'zendextsrc' :
                    echo "Zend Extension source package\n";
                    break;
                case 'extbin' :
                    echo "Extension binary package\n";
                    break;
                case 'zendextbin' :
                    echo "Zend Extension binary package\n";
                    break;
                case 'bundle' :
                    echo "Package Bundle\n";
                    break;
            }
            echo 'Version:      ', $package->version['release'], ' (API ', $package->version['api'], "), ";
            echo 'Stability:    ', $package->stability['release'], ' (API ', $package->stability['api'], ")\n";
            echo 'Release Date: ', $package->date;
            if ($package->time) {
                echo ' ', $package->time;
            }
            echo "\n";
            echo "Package Summary: ", $this->columnWrap($package->summary, strlen("Package Summary: ")), "\n";
            echo "Package Description Excerpt:\n   ",
                 $this->columnWrap(substr(rtrim($package->description), 0, 171) . '...', 3), "\n";
            echo '(`php pyrus.phar info ' . $args['package'] . " description` for full description)\n";
            echo "Release Notes Excerpt:\n   ",
                $this->columnWrap(substr(rtrim($package->notes), 0, 171) . '...', 3), "\n";
            echo '(`php pyrus.phar info ' . $args['package'] . " notes` for full release notes)\n";
            if ($installed) {
                // check for upgrades
                try {
                    $tester = new \Pyrus\Package($package->channel . '/' . $package->name, true);
                    $upgrades = $tester->getAllUpgrades($package->version['release']);
                    if (count($upgrades)) {
                        echo "Upgrades available:\n";
                        foreach ($upgrades as $info) {
                            echo '  Version ', $info['v'], ' (', $info['s'], ")\n";
                        }
                    }
                } catch (\Exception $e) {
                    // ignore problems here, no need to freak out if checking for upgrades fails
                    if ($this->verbose > 3) {
                        echo $e;
                    }
                }
            }
        } elseif ($args['field'] == 'description') {
            echo "Package Description:\n   ", $this->columnWrap(trim($package->description), 3), "\n";
        } elseif ($args['field'] == 'notes') {
            echo "Release Notes:\n   ", $this->columnWrap($package->notes, 3), "\n";
        } elseif ($args['field'] == 'files') {
            if ($installed) {
                echo "Package Files (installed):\n";
                foreach (\Pyrus\Config::current()->registry->info($package->name, $package->channel,
                                                                       'installedfiles') as $file => $info) {
                    echo $file, ' (', $info['role'], ")\n";
                }
            } else {
                if ($package->isRemote()) {
                    echo "Package Files:\n";
                    foreach ($package->contents as $file) {
                        echo $file->name, ' (', $file->role, ")\n";
                    }
                } else {
                    echo "Package Files (as would be installed):\n";
                    foreach ($package->installcontents as $file) {
                        echo $file->name, ' (', $file->role, ")\n";
                    }
                }
            }
        } else {
            echo "Unknown sub-field ", $args['field'], " must be one of description, notes, or files\n";
        }
    }

    function listUpgrades()
    {
        $config = \Pyrus\Config::current();
        $reg = $config->registry;
        foreach ($config->channelregistry as $channel) {
            $packages = $reg->listPackages($channel->name);
            if (!count($packages)) {
                echo "(no packages installed in channel ", $channel->name, ")\n";
                continue;
            }
            $upgrades = array();
            foreach ($packages as $package) {
                try {
                    $version = $reg->info($package, $channel->name, 'version');
                    $tester = $channel->remotepackage[$package];
                    // find a version newer than us
                    $fakedep = new \Pyrus\PackageFile\v2\Dependencies\Package(
                        'required', 'package', null, array('name' => $package,
                                            'channel' => $channel->name, 'uri' => null,
                                            'min' => $version, 'max' => null,
                                            'recommended' => null, 'exclude' => array($version),
                                            'providesextension' => null, 'conflicts' => null), 0);
                    $tester->figureOutBestVersion($fakedep);
                } catch (\Exception $e) {
                    continue;
                }
                $upgrades[$package] = array($tester->version['release'], $tester->stability['release'], $tester->date);
            }
            if (!count($upgrades)) {
                echo "(no upgrades for packages installed in channel ", $channel->name, ")\n";
                continue;
            }
            asort($upgrades);
            echo "Upgrades for channel ", $channel->name, ":\n";
            foreach ($upgrades as $package => $upgrade) {
                echo '  ', $package, ' ', $upgrade[0], ' (' . $upgrade[1], ", released ", $upgrade[2], ")\n";
            }
        }
    }

    function listAll($args, $options)
    {
        $reg = \Pyrus\Config::current()->registry;
        echo "Remote packages for channel ", $args['channel'], ":\n";
        if ($options['basic']) {
            foreach (\Pyrus\Config::current()->channelregistry[$args['channel']]->remotecategories as $category) {
                echo $category->name, ":\n";
                foreach ($category->basiclist as $package) {
                    $installed = $reg->exists($package['package'], $args['channel']) ? '  *' : '   ';
                    echo $installed, $package['package'], ' latest stable: ', $package['stable'],
                        ', latest release: ', $package['latest']['v'], ' (', $package['latest']['s'], ")\n";
                }
            }
            return;
        }
        foreach (\Pyrus\Config::current()->channelregistry[$args['channel']]->remotecategories as $category) {
            echo $category->name, ":\n";
            $pnames = array();
            $summaries = array();
            $pnameinfo = array();
            $versions = array();
            try {
                foreach ($category as $package) {
                    $installed = ' ';
                    if ($package->isUpgradeable()) {
                        $installed = '!';
                    } elseif ($reg->exists($package->name, $args['channel'])) {
                        $installed = '*';
                    }
                    $found = false;
                    foreach ($package as $version => $latest) {
                        $found = true;
                        break;
                    }
                    $pnames[] = $package->name;
                    $summaries[] = $package->summary;
                    if (!$found) {
                        $versions[] = '--';
                        $pnameinfo[$package->name] = array('installed' => $installed,
                                                           'summary' => $package->summary,
                                                           'latest' => 'n/a');
                        continue;
                    }
                    $versions[] = $version;
                    $latest['v'] = $version;

                    $pnameinfo[$package->name] = array('installed' => $installed,
                                                       'summary' => $package->summary,
                                                       'latest' => $latest);
                }
            } catch (\Exception $e) {
                echo "Error: Category has broken REST (", $e->getMessage(), ")\n";
                continue;
            }
            $widths = array(1, 25, 8, 51);
            foreach ($pnameinfo as $package => $info) {
                if (is_string($info['latest'])) {
                    $text = array($info['installed'], $package, $info['latest'], $info['summary']);
                } else {
                    $text = array($info['installed'], $package, $info['latest']['v'], $info['summary']);
                }
                echo $this->wrapMultiColumns($text, $widths) . "\n";
            }
            echo "Key: * = installed, ! = upgrades available\n";
        }
    }

    protected function wrap($text)
    {
        return wordwrap($text, 80, "\n", false);
    }

    /**
     * Borrowed from PEAR2_Console_CommandLine
     */
    protected function columnWrap($text, $cw)
    {
        $tokens = explode("\n", $this->wrap($text));
        $ret    = $tokens[0];
        $chunks = $this->wrap(trim(substr($text, strlen($ret))), 80 - $cw);
        $tokens = explode("\n", $chunks);
        foreach ($tokens as $token) {
            if (!empty($token)) {
                $ret .= "\n" . str_repeat(' ', $cw) . $token;
            }
        }
        return $ret;
    }
    static function wrapMultiColumns($text, $widths)
    {
        $max = 0;
        foreach ($text as $col => $cell) {
            $text[$col] = explode("\n", wordwrap($cell, $widths[$col], "\n", false));
            $newtext = array();
            foreach ($text[$col] as $subcell) {
                if (strlen($subcell) > $widths[$col]) {
                    $split = explode("\n", wordwrap($subcell, $widths[$col], "\\\n", true));
                    foreach ($split as $subcell) {
                        $newtext[] = $subcell;
                    }
                } else {
                    $newtext[] = $subcell;
                }
                $text[$col] = $newtext;
            }
            if (count($text[$col]) > $max) {
                $max = count($text[$col]);
            }
        }

        $ret = '';
        for ($i = 0; $i < $max; $i++) {
            if ($ret) {
                $ret .= "\n";
            }
            foreach ($text as $col => $cell) {
                if ($col && !$previousWasLong) {
                    $ret .= ' ';
                }
                if ($col) {
                    $ret .= ' ';
                }
                if (isset($cell[$i])) {
                    $ret .= str_pad($cell[$i], $widths[$col], ' ');
                    if (strlen($cell[$i]) > $widths[$col]) {
                        $previousWasLong = true;
                    } else {
                        $previousWasLong = false;
                    }
                } else {
                    $ret .= str_repeat(' ', $widths[$col]);
                    $previousWasLong = false;
                }
            }
        }
        return $ret;
    }

    function __call($func, $params)
    {
        if ($func === 'confirmDialog') {
            return $this->_confirmDialog($params[0]);
        }
        if ($func === 'display') {
            return $this->_display($params[0]);
        }
        if ($func === 'ask') {
            return call_user_func_array(array($this, 'ask'), $params);
        }
        throw new \Exception('Unknown method ' . $func . ' in class Pyrus\ScriptFrontend\Commands');
    }

    /**
     * Ask for user input, confirm the answers and continue until the user is satisfied
     * @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
     *              'text to display', 'type' => 'string'[, default => 'default value'])
     * @return array
     */
    function _confirmDialog($params)
    {
        $answers = $prompts = $types = array();
        foreach ($params as $param) {
            $prompts[$param['name']] = $param['prompt'];
            $types[$param['name']]   = $param['type'];
            $answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
        }

        $tried = false;
        do {
            if ($tried) {
                $i = 1;
                foreach ($answers as $var => $value) {
                    if (!strlen($value)) {
                        echo $this->_bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
                    }
                    $i++;
                }
            }

            $answers = $this->_userDialog('', $prompts, $types, $answers);
            $tried   = true;
        } while (is_array($answers) && count(array_filter($answers)) != count($prompts));

        return $answers;
    }

    function _display($text)
    {
        echo $text, "\n";
    }

    function _userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
    {
        if (!is_array($prompts)) {
            return array();
        }

        $testprompts = array_keys($prompts);
        $result      = $defaults;

        reset($prompts);
        if (count($prompts) === 1) {
            foreach ($prompts as $key => $prompt) {
                $type    = $types[$key];
                $default = isset($defaults[$key]) ? $defaults[$key] : false;
                print "$prompt ";
                if ($default) {
                    print "[$default] ";
                }
                print ": ";

                $line         = $this->_readStdin(2048);
                $result[$key] =  ($default && trim($line) == '') ? $default : trim($line);
            }

            return $result;
        }

        $first_run = true;
        while (true) {
            $descLength = max(array_map('strlen', $prompts));
            $descFormat = "%-{$descLength}s";
            $last       = count($prompts);

            $i = 0;
            foreach ($prompts as $n => $var) {
                $res = isset($result[$n]) ? $result[$n] : null;
                printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
            }
            print "\n1-$last, 'all', 'abort', or Enter to continue: ";

            $tmp = $this->_readStdin();
            if (empty($tmp)) {
                break;
            }

            if ($tmp == 'abort') {
                return false;
            }

            if (isset($testprompts[(int)$tmp - 1])) {
                $var     = $testprompts[(int)$tmp - 1];
                $desc    = $prompts[$var];
                $current = @$result[$var];
                print "$desc [$current] : ";
                $tmp = $this->_readStdin();
                if ($tmp !== '') {
                    $result[$var] = $tmp;
                }
            } elseif ($tmp == 'all') {
                foreach ($prompts as $var => $desc) {
                    $current = $result[$var];
                    print "$desc [$current] : ";
                    $tmp = $this->_readStdin();
                    if (trim($tmp) !== '') {
                        $result[$var] = trim($tmp);
                    }
                }
            }

            $first_run = false;
        }

        return $result;
    }

    function log($level, $message)
    {
        static $data = array();
        if (\Pyrus\Config::initializing()) {
            // we can't check verbose until initializing is complete, so save
            // the message, and only display the log after config is initialized
            $data[] = array($level, $message);
            return;
        }

        if (count($data)) {
            $save = $data;
            $data = array();
            foreach ($save as $info) {
                $this->log($info[0], $info[1]);
            }
        }

        if ($level <= $this->verbose) {
            if (strlen($message) && $message[strlen($message)-1] !== "\r") {
                echo $message . "\n";
            } else {
                echo $message;
            }
        }
    }
}


text:
Typee - Chapter 10
THE HEAD OF THE VALLEY—CAUTIOUS ADVANCE—A PATH—FRUIT—DISCOVERY OF TWO OF THE NATIVES—THEIR SINGULAR CONDUCT—APPROACH TOWARDS THE INHABITED PARTS OF THE VALE—SENSATION PRODUCED BY OUR APPEARANCE—RECEPTION AT THE HOUSE OF ONE OF THE NATIVES
HOW to obtain the fruit which we felt convinced must grow near at hand was our first thought.
Typee or Happar? A frightful death at the hands of the fiercest of cannibals, or a kindly reception from a gentler race of savages? Which? But it was too late now to discuss a question which would so soon be answered.
The part of the valley in which we found ourselves appeared to be altogether uninhabited. An almost impenetrable thicket extended from side to side, without presenting a single plant affording the nourishment we had confidently calculated upon; and with this object, we followed the course of the stream, casting quick glances as we proceeded into the thick jungles on each hand. My companion—to whose solicitations I had yielded in descending into the valley—now that the step was taken, began to manifest a degree of caution I had little expected from him. He proposed that in the event of our finding an adequate supply of fruit, we should remain in this unfrequented portion of the country—where we should run little chance of being surprised by its occupants, whoever they might be—until sufficiently recruited to resume our journey; when laying a store of food equal to our wants, we might easily regain the bay of Nukuheva, after the lapse of a sufficient interval to ensure the departure of our vessel.
I objected strongly to this proposition, plausible as it was, as the difficulties of the route would be almost insurmountable, unacquainted as we were with the general bearings of the country, and I reminded my companion of the hardships which we had already encountered in our uncertain wanderings; in a word, I said that since we had deemed it advisable to enter the valley, we ought manfully to face the consequences, whatever they might be; the more especially as I was convinced there was no alternative left us but to fall in with the natives at once, and boldly risk the reception they might give us; and that as to myself, I felt the necessity of rest and shelter, and that until I had obtained them, I should be wholly unable to encounter such sufferings as we had lately passed through. To the justice of these observations Toby somewhat reluctantly assented.
We were surprised that, after moving as far as we had along the valley, we should still meet with the same impervious thickets; and thinking, that although the borders of the stream might be lined for some distance with them, yet beyond there might be more open ground, I requested Toby to keep a bright look-out upon one side, while I did the same on the other, in order to discover some opening in the bushes, and especially to watch for the slightest appearance of a path or anything else that might indicate the vicinity of the islanders.
What furtive and anxious glances we cast into those dim-looking shadows! With what apprehensions we proceeded, ignorant at what moment we might be greeted by the javelin of some ambushed savage. At last my companion paused, and directed my attention to a narrow opening in the foliage. We struck into it, and it soon brought us by an indistinctly traced path to a comparatively clear space, at the further end of which we descried a number of the trees, the native name of which is 'annuee', and which bear a most delicious fruit. What a race! I hobbling over the ground like some decrepid wretch, and Toby leaping forward like a greyhound. He quickly cleared one of the trees on which there were two or three of the fruit, but to our chagrin they proved to be much decayed; the rinds partly opened by the birds, and their hearts half devoured. However, we quickly despatched them, and no ambrosia could have been more delicious.
We looked about us uncertain whither to direct our steps, since the path we had so far followed appeared to be lost in the open space around us. At last we resolved to enter a grove near at hand, and had advanced a few rods, when, just upon its skirts, I picked up a slender bread-fruit shoot perfectly green, and with the tender bark freshly stripped from it. It was still slippery with moisture, and appeared as if it had been but that moment thrown aside. I said nothing, but merely held it up to Toby, who started at this undeniable evidence of the vicinity of the savages.
The plot was now thickening.—A short distance further lay a little faggot of the same shoots bound together with a strip of bark. Could it have been thrown down by some solitary native, who, alarmed at seeing us, had hurried forward to carry the tidings of our approach to his countrymen?—Typee or Happar?—But it was too late to recede, so we moved on slowly, my companion in advance casting eager glances under the trees on each side, until all at once I saw him recoil as if stung by an adder. Sinking on his knee, he waved me off with one hand, while with the other he held aside some intervening leaves, and gazed intently at some object.
Disregarding his injunction, I quickly approached him and caught a glimpse of two figures partly hidden by the dense foliage; they were standing close together, and were perfectly motionless. They must have previously perceived us, and withdrawn into the depths of the wood to elude our observation.
My mind was at once made up. Dropping my staff, and tearing open the package of things we had brought from the ship, I unrolled the cotton cloth, and holding it in one hand picked with the other a twig from the bushes beside me, and telling Toby to follow my example, I broke through the covert and advanced, waving the branch in token of peace towards the shrinking forms before me. They were a boy and a girl, slender and graceful, and completely naked, with the exception of a slight girdle of bark, from which depended at opposite points two of the russet leaves of the bread-fruit tree. An arm of the boy, half screened from sight by her wild tresses, was thrown about the neck of the girl, while with the other he held one of her hands in his; and thus they stood together, their heads inclined forward, catching the faint noise we made in our progress, and with one foot in advance, as if half inclined to fly from our presence.
As we drew near, their alarm evidently increased. Apprehensive that they might fly from us altogether, I stopped short and motioned them to advance and receive the gift I extended towards them, but they would not; I then uttered a few words of their language with which I was acquainted, scarcely expected that they would understand me, but to show that we had not dropped from the clouds upon them. This appeared to give them a little confidence, so I approached nearer, presenting the cloth with one hand, and holding the bough with the other, while they slowly retreated. At last they suffered us to approach so near to them that we were enabled to throw the cotton cloth across their shoulders, giving them to understand that it was theirs, and by a variety of gestures endeavouring to make them understand that we entertained the highest possible regard for them.
The frightened pair now stood still, whilst we endeavoured to make them comprehend the nature of our wants. In doing this Toby went through with a complete series of pantomimic illustrations—opening his mouth from ear to ear, and thrusting his fingers down his throat, gnashing his teeth and rolling his eyes about, till I verily believe the poor creatures took us for a couple of white cannibals who were about to make a meal of them. When, however, they understood us, they showed no inclination to relieve our wants. At this juncture it began to rain violently, and we motioned them to lead us to some place of shelter. With this request they appeared willing to comply, but nothing could evince more strongly the apprehension with which they regarded us, than the way in which, whilst walking before us, they kept their eyes constantly turned back to watch every movement we made, and even our very looks.
'Typee or Happar, Toby?' asked I as we walked after them.
'Of course Happar,' he replied, with a show of confidence which was intended to disguise his doubts.
'We shall soon know,' I exclaimed; and at the same moment I stepped forward towards our guides, and pronouncing the two names interrogatively and pointing to the lowest part of the valley, endeavoured to come to the point at once. They repeated the words after me again and again, but without giving any peculiar emphasis to either, so that I was completely at a loss to understand them; for a couple of wilier young things than we afterwards found them to have been on this particular occasion never probably fell in any traveller's way.
More and more curious to ascertain our fate, I now threw together in the form of a question the words 'Happar' and 'Motarkee', the latter being equivalent to the word 'good'. The two natives interchanged glances of peculiar meaning with one another at this, and manifested no little surprise; but on the repetition of the question after some consultation together, to the great joy of Toby, they answered in the affirmative. Toby was now in ecstasies, especially as the young savages continued to reiterate their answer with great energy, as though desirous of impressing us with the idea that being among the Happars, we ought to consider ourselves perfectly secure.
Although I had some lingering doubts, I feigned great delight with Toby at this announcement, while my companion broke out into a pantomimic abhorrence of Typee, and immeasurable love for the particular valley in which we were; our guides all the while gazing uneasily at one another as if at a loss to account for our conduct.
They hurried on, and we followed them; until suddenly they set up a strange halloo, which was answered from beyond the grove through which we were passing, and the next moment we entered upon some open ground, at the extremity of which we descried a long, low hut, and in front of it were several young girls. As soon as they perceived us they fled with wild screams into the adjoining thickets, like so many startled fawns. A few moments after the whole valley resounded with savage outcries, and the natives came running towards us from every direction.
Had an army of invaders made an irruption into their territory they could not have evinced greater excitement. We were soon completely encircled by a dense throng, and in their eager desire to behold us they almost arrested our progress; an equal number surrounded our youthful guides, who with amazing volubility appeared to be detailing the circumstances which had attended their meeting with us. Every item of intelligence appeared to redouble the astonishment of the islanders, and they gazed at us with inquiring looks.
At last we reached a large and handsome building of bamboos, and were by signs told to enter it, the natives opening a lane for us through which to pass; on entering without ceremony, we threw our exhausted frames upon the mats that covered the floor. In a moment the slight tenement was completely full of people, whilst those who were unable to obtain admittance gazed at us through its open cane-work.
It was now evening, and by the dim light we could just discern the savage countenances around us, gleaming with wild curiosity and wonder; the naked forms and tattooed limbs of brawny warriors, with here and there the slighter figures of young girls, all engaged in a perfect storm of conversation, of which we were of course the one only theme, whilst our recent guides were fully occupied in answering the innumerable questions which every one put to them. Nothing can exceed the fierce gesticulation of these people when animated in conversation, and on this occasion they gave loose to all their natural vivacity, shouting and dancing about in a manner that well nigh intimidated us.
Close to where we lay, squatting upon their haunches, were some eight or ten noble-looking chiefs—for such they subsequently proved to be—who, more reserved than the rest, regarded us with a fixed and stern attention, which not a little discomposed our equanimity. One of them in particular, who appeared to be the highest in rank, placed himself directly facing me, looking at me with a rigidity of aspect under which I absolutely quailed. He never once opened his lips, but maintained his severe expression of countenance, without turning his face aside for a single moment. Never before had I been subjected to so strange and steady a glance; it revealed nothing of the mind of the savage, but it appeared to be reading my own.
After undergoing this scrutiny till I grew absolutely nervous, with a view of diverting it if possible, and conciliating the good opinion of the warrior, I took some tobacco from the bosom of my frock and offered it to him. He quietly rejected the proffered gift, and, without speaking, motioned me to return it to its place.
In my previous intercourse with the natives of Nukuheva and Tior, I had found that the present of a small piece of tobacco would have rendered any of them devoted to my service. Was this act of the chief a token of his enmity? Typee or Happar? I asked within myself. I started, for at the same moment this identical question was asked by the strange being before me. I turned to Toby, the flickering light of a native taper showed me his countenance pale with trepidation at this fatal question. I paused for a second, and I know not by what impulse it was that I answered 'Typee'. The piece of dusky statuary nodded in approval, and then murmured 'Motarkee!' 'Motarkee,' said I, without further hesitation 'Typee motarkee.'
What a transition! The dark figures around us leaped to their feet, clapped their hands in transport, and shouted again and again the talismanic syllables, the utterance of which appeared to have settled everything.
When this commotion had a little subsided, the principal chief squatted once more before me, and throwing himself into a sudden rage, poured forth a string of philippics, which I was at no loss to understand, from the frequent recurrence of the word Happar, as being directed against the natives of the adjoining valley. In all these denunciations my companion and I acquiesced, while we extolled the character of the warlike Typees. To be sure our panegyrics were somewhat laconic, consisting in the repetition of that name, united with the potent adjective 'motarkee'. But this was sufficient, and served to conciliate the good will of the natives, with whom our congeniality of sentiment on this point did more towards inspiring a friendly feeling than anything else that could have happened.
At last the wrath of the chief evaporated, and in a few moments he was as placid as ever. Laying his hand upon his breast, he gave me to understand that his name was 'Mehevi', and that, in return, he wished me to communicate my appellation. I hesitated for an instant, thinking that it might be difficult for him to pronounce my real name, and then with the most praiseworthy intentions intimated that I was known as 'Tom'. But I could not have made a worse selection; the chief could not master it. 'Tommo,' 'Tomma', 'Tommee', everything but plain 'Tom'. As he persisted in garnishing the word with an additional syllable, I compromised the matter with him at the word 'Tommo'; and by that name I went during the entire period of my stay in the valley. The same proceeding was gone through with Toby, whose mellifluous appellation was more easily caught.
An exchange of names is equivalent to a ratification of good will and amity among these simple people; and as we were aware of this fact, we were delighted that it had taken place on the present occasion.
Reclining upon our mats, we now held a kind of levee, giving audience to successive troops of the natives, who introduced themselves to us by pronouncing their respective names, and retired in high good humour on receiving ours in return. During this ceremony the greatest merriment prevailed nearly every announcement on the part of the islanders being followed by a fresh sally of gaiety, which induced me to believe that some of them at least were innocently diverting the company at our expense, by bestowing upon themselves a string of absurd titles, of the humour of which we were of course entirely ignorant.
All this occupied about an hour, when the throng having a little diminished, I turned to Mehevi and gave him to understand that we were in need of food and sleep. Immediately the attentive chief addressed a few words to one of the crowd, who disappeared, and returned in a few moments with a calabash of 'poee-poee', and two or three young cocoanuts stripped of their husks, and with their shells partly broken. We both of us forthwith placed one of these natural goblets to our lips, and drained it in a moment of the refreshing draught it contained. The poee-poee was then placed before us, and even famished as I was, I paused to consider in what manner to convey it to my mouth.
This staple article of food among the Marquese islanders is manufactured from the produce of the bread-fruit tree. It somewhat resembles in its plastic nature our bookbinders' paste, is of a yellow colour, and somewhat tart to the taste.
Such was the dish, the merits of which I was now eager to discuss. I eyed it wistfully for a moment, and then, unable any longer to stand on ceremony, plunged my hand into the yielding mass, and to the boisterous mirth of the natives drew it forth laden with the poee-poee, which adhered in lengthy strings to every finger. So stubborn was its consistency, that in conveying my heavily-weighted hand to my mouth, the connecting links almost raised the calabash from the mats on which it had been placed. This display of awkwardness—in which, by-the-bye, Toby kept me company—convulsed the bystanders with uncontrollable laughter.
As soon as their merriment had somewhat subsided, Mehevi, motioning us to be attentive, dipped the forefinger of his right hand in the dish, and giving it a rapid and scientific twirl, drew it out coated smoothly with the preparation. With a second peculiar flourish he prevented the poee-poee from dropping to the ground as he raised it to his mouth, into which the finger was inserted and drawn forth perfectly free from any adhesive matter.
This performance was evidently intended for our instruction; so I again essayed the feat on the principles inculcated, but with very ill success.
A starving man, however, little heeds conventional proprieties, especially on a South-Sea Island, and accordingly Toby and I partook of the dish after our own clumsy fashion, beplastering our faces all over with the glutinous compound, and daubing our hands nearly to the wrist. This kind of food is by no means disagreeable to the palate of a European, though at first the mode of eating it may be. For my own part, after the lapse of a few days I became accustomed to its singular flavour, and grew remarkably fond of it.
So much for the first course; several other dishes followed it, some of which were positively delicious. We concluded our banquet by tossing off the contents of two more young cocoanuts, after which we regaled ourselves with the soothing fumes of tobacco, inhaled from a quaintly carved pipe which passed round the circle.
During the repast, the natives eyed us with intense curiosity, observing our minutest motions, and appearing to discover abundant matter for comment in the most trifling occurrence. Their surprise mounted the highest, when we began to remove our uncomfortable garments, which were saturated with rain. They scanned the whiteness of our limbs, and seemed utterly unable to account for the contrast they presented to the swarthy hue of our faces embrowned from a six months' exposure to the scorching sun of the Line. They felt our skin, much in the same way that a silk mercer would handle a remarkably fine piece of satin; and some of them went so far in their investigation as to apply the olfactory organ.
Their singular behaviour almost led me to imagine that they never before had beheld a white man; but a few moments' reflection convinced me that this could not have been the case; and a more satisfactory reason for their conduct has since suggested itself to my mind.
Deterred by the frightful stories related of its inhabitants, ships never enter this bay, while their hostile relations with the tribes in the adjoining valleys prevent the Typees from visiting that section of the island where vessels occasionally lie. At long intervals, however, some intrepid captain will touch on the skirts of the bay, with two or three armed boats' crews and accompanied by interpreters. The natives who live near the sea descry the strangers long before they reach their waters, and aware of the purpose for which they come, proclaim loudly the news of their approach. By a species of vocal telegraph the intelligence reaches the inmost recesses of the vale in an inconceivably short space of time, drawing nearly its whole population down to the beach laden with every variety of fruit. The interpreter, who is invariably a 'tabooed Kanaka'[1], leaps ashore with the goods intended for barter, while the boats, with their oars shipped, and every man on his thwart, lie just outside the surf, heading off the shore, in readiness at the first untoward event to escape to the open sea. As soon as the traffic is concluded, one of the boats pulls in under cover of the muskets of the others, the fruit is quickly thrown into her, and the transient visitors precipitately retire from what they justly consider so dangerous a vicinity.
The intercourse occurring with Europeans being so restricted, no wonder that the inhabitants of the valley manifested so much curiosity with regard to us, appearing as we did among them under such singular circumstances. I have no doubt that we were the first white men who ever penetrated thus far back into their territories, or at least the first who had ever descended from the head of the vale. What had brought us thither must have appeared a complete mystery to them, and from our ignorance of the language it was impossible for us to enlighten them. In answer to inquiries which the eloquence of their gestures enabled us to comprehend, all that we could reply was, that we had come from Nukuheva, a place, be it remembered, with which they were at open war. This intelligence appeared to affect them with the most lively emotions. 'Nukuheva motarkee?' they asked. Of course we replied most energetically in the negative.
Then they plied us with a thousand questions, of which we could understand nothing more than that they had reference to the recent movements of the French, against whom they seemed to cherish the most fierce hatred. So eager were they to obtain information on this point, that they still continued to propound their queries long after we had shown that we were utterly unable to answer them. Occasionally we caught some indistinct idea of their meaning, when we would endeavour by every method in our power to communicate the desired intelligence. At such times their gratification was boundless, and they would redouble their efforts to make us comprehend them more perfectly. But all in vain; and in the end they looked at us despairingly, as if we were the receptacles of invaluable information; but how to come at it they knew not.
After a while the group around us gradually dispersed, and we were left about midnight (as we conjectured) with those who appeared to be permanent residents of the house. These individuals now provided us with fresh mats to lie upon, covered us with several folds of tappa, and then extinguishing the tapers that had been burning, threw themselves down beside us, and after a little desultory conversation were soon sound asleep.
The word 'Kanaka' is at the present day universally used in the South Seas by Europeans to designate the Islanders. In the various dialects of the principal groups it is simply a sexual designation applied to the males; but it is now used by the natives in their intercourse with foreigners in the same sense in which the latter employ it. A 'Tabooed Kanaka' is an islander whose person has been made to a certain extent sacred by the operation of a singular custom hereafter to be explained.

redpajama_set_name: RedPajamaCommonCrawl


Petra is the epitome of a tomboy. She's able to do all of the sporty activities while keeping your lower half locked in. Petra is our most friendly bottom. But don't fret, she'll keep your private parts private.


This is a placeholder page for Julie Anglim, which means this person is not currently on this site. We do suggest using the tools below to find Julie Anglim.
You are visiting the placeholder page for Julie Anglim. This page is here because someone used our placeholder utility to look for Julie Anglim. We created this page automatically in hopes Julie Anglim would find it. If you are not Julie Anglim, but are an alumni of Herndon High School Herndon, VA, register on this site for free now.


Note: Insurance is not included in the shipping prices as the cost depends on the value of the item. If you would like extra cover insurance please let me know by sending me an email to hello@lilspaces.com and I can organise a shipping quote and send you a separate PayPal invoice. You will need to tell me the country where the item needs to be shipped to.
We recommend you use trackable shipping services and get extra cover insurance when returning an item, so you can make sure that the item is returned to us and that you can track the status of your return shipment. We cannot accept responsibility for items lost in transit to us.
We want to make sure we are offering the best service and products to our lil customers so we are meticulous when it comes to checking and packing items before shipment. However, if you receive your item and it is faulty we are happy to provide a full refund. Please email a photo of it to us at hello@lilspaces.com, then send it back to us in its original packaging within 7 days so we can see what went wrong.
Important note: Faulty doesn't equal damage caused by during shipping or your local Customs Office. As much as we wish we did we don't have control over the shipping process so we cannot be held liable for things going wrong during shipping e.g. Damage or lost packages. That is why we recommend extra cover insurance on all our packages.
IS EXTRA COVER INSURANCE ALREADY INCLUDED IN THE PRICE OF SHIPPING?
No. If you would like extra cover insurance please email me and I will send you a separate PayPal invoice. The insurance cost will depend on the value of your item(s).
We currently accept Direct Deposit and PayPal. You can also use all major credit cards through Paypal without needing a PayPal account.
Please note that payment by Direct Deposit may take 2 to 3 business days to clear into our account and will affect delivery times. Full payment is required before items are dispatched.
HOW DO I BECOME A WHOLESALE PARTNER/STOCKIST FOR LiL SPACES PRODUCTS?
We offer wholesale rates on Lil Spaces branded products to resellers with a storefront or online stores. If you are interested in becoming a stockist we would love to hear from you!
If you qualify as a wholesale customer shoot us an email at hello@lilspaces.com telling us a little bit about your store. Include your web address (url) and attach some cool photos to get the process started. We will send you a wholesale application form for you to fill out and return to us.
Lil Spaces reserves the right to reject applications based on our sole discretion.
How do I go about making my purchase?
Once your wholesale partner application is approved you will be assigned a unique customer identifier code and be provided with your login details and a discount code. When you are ready to place your order, login to lilspaces.com and make your purchase.
HOW DO I BECOME A TRADE PARTNER FOR LiL SPACES PRODUCTS?
We offer trade discounts on Lil Spaces branded products to interior designers. If you are interested in becoming a trade partner we would love to hear from you!
If you qualify as a Trade partner shoot us an email at hello@lilspaces.com telling us a little bit about you. Include your web address (url) and attach some cool photos of your work to get the process started. We will send you a trade partner application form for you to fill out and return to us.
We will then send you a trade partner application form for you to fill out and return to us.
Ten to twenty percent depending on the product.
No, there are no minimum orders.
Once your trade partner application is approved you will be assigned a unique identifier. When you are ready to make a purchase email us and we will issue you with a one off discount code to make the purchase on our website.
If you share your personal information with us we will only use it for the purpose of which you gave us the information. We will not sell or share your details with another party. Registering on our site automatically subscribes you to Lil Spaces - but don't worry, we won't spam you with annoying daily emails! You can contact us at any time to have your details removed.
I PREFER BLUE OVER GREEN! CAN I CUSTOMISE A PRINT?
We are always on the hunt for sophistifun (sophisticated yet fun) kids products. Drop us a line at hello@lilspaces.com if you have something you think our customers might be interested in. It is important to us be able to offer our customers unique products one would not see everywhere.
WHAT IS YOUR COPYWRIGHT POLICY?
All artwork remains the copyright of Lil Spaces. This includes the original concepts unique to our designs, our posters and prints, paper structures we have designed, graphic features, illustrations, and any other design elements and ideas published under our copyright. All text, images and photographs are copyright Lil Spaces.
Do not change, re-draw or recreate our designs. This is strictly prohibited.
We are more than happy for you to use our printable PDF files for personal use and we hope you enjoy using them. For these uses, you can print the high resolution pages as many times as you like.
All our files are 'read only'. Please don't change or redraw our designs or edit our content. Only use them by printing them in their original form. Do not make derivative works or use any parts of our designs.
All artwork remains the copyright of Lil Spaces. This includes the original concepts unique to our designs, paper structures we have designed, graphic features, illustrations and any other design elements and ideas published under our copyright. All text, images and photographs are copyright Lil Spaces.
We're cool with you telling others about our downloads (in fact we love it) but always link to our webpages and DO NOT link to the pdf files directly. Never host the files on your websites or blogs.
Feel free to share the projects you have made on social media but we would appreciate it if you would mention you got it from Lil Spaces and always tag @lilspaces and #lilspaces.
Can I share your work on my blog or website?
We love being feature on blogs. If you would like to feature our content on your site and blog, you're welcome to use up to 2 images of each project, excluding tutorial images, with your own text. Never reproduce our text and tutorials. Always link to our webpages for the original download and DO NOT link to the pdf files directly. Never host the files on your websites or blogs.
Any commercial redistribution or resale of the original files or of the printed results is strictly prohibited. Do not use the printed results as part of commercial displays, editorials and events without licence and written permission. If you have a proposal please contact us.
ALL YOU NEED TO KNOW ABOUT YOUR CLOUD LIGHT?
How do I turn my cloud light on/off?
There is an on/off switch located at the bottom of the cloud light. This is also the area where you insert the 2 x AAA batteries provided. You just need to peel back the little pouch/flap and when done press it back in place. This information is also in the leaflet provided in the box.
How long will the LED bulb last and is it easily replaceable?
The LED lights generally last tens of thousands of hours as they don't draw a lot of power. The bulb is only replaceable on the large cloud light but unfortunately not replaceable on the small. Just un screw it and take it to a hardware or lighting shop and purchase a replacement. If you have no luck with this you can always purchase a replacement bulb from us just shoot us an email.
How do I keep my cloud light clean?
We recommend you take it down from the ceiling hook, take it outside and give it a gentle tap the whole way around. Alternatively you could also give it a gentle tap where it hangs. Try using a low powered dust catcher vacuum, nothing too powerful though as the lights are quite delicate but we would only recommend this option as a last resort.
ARE THERE ANY ADDITIONAL TAXES FOR ORDERS OUTSIDE OF AUSTRALIA?
For orders outside of Australia additional customs charges or taxes may imply depending on the country in which you reside. For example: VAT in UK and Europe.
We encourage you to investigate this further so there are no nasty surprises.


text:
Steve Anthony
Tuesday, Jun 26, 2018, 14:54
CEU begins recruitment for 2019-2020 academic year
Despite fulfilling all the conditions set by Hungary's amended higher education law, the Central European University (CEU) is still waiting for the government's approval to continue operating in Budapest. Even so, the CEU Board of Trustees has authorized the university to begin recruitment for the 2019-2020 academic year.
On the question of whether the government will sign an agreement with CEU permitting it to continue its activity in Hungary, Prime Minister Viktor Orbán responded in Parliament Monday by saying that "a good decision needs time" and "the quality of the decision is more important than the date."
Last month, CEU President and Rector Michael Ignatieff said that the university has fulfilled its obligations "and now it is time for the government of Hungary to fulfill theirs." He added that "CEU cannot go into another academic year in a situation of legal uncertainty. We call on the government to sign the agreement without further delay."
While this has still not happened, CEU released a statement Tuesday saying that the university's Board of Trustees, at its June 23 meeting, had authorized CEU to open recruitment in Budapest for the 2019-2020 academic year, according to the university's regular recruitment schedule. They also strongly re-affirmed their commitment to the university in all circumstances.
However, the situation is still not totally clear, as the statement adds that, following the Board's decision in March to authorize the opening of a campus in Vienna, "the Board also approved the rental of an appropriate site in Vienna and recruitment for that site for September 2019."
Waiting game
In a lengthy analysis of the situation, online current affairs site hvg.hu cites unnamed sources as saying that the CEU management decided last fall that unless there was a change of government in spring 2018, or if no change were to subsequently occur in Fidesz policy with regard to CEU, then the university would shift its headquarters to Vienna within the next two years.
At the same time, the article also notes that Orbán has become, in a certain sense, a "prisoner" of the situation, as widespread press reports indicate that the fate of CEU could determine whether Fidesz is expelled from the European People's Party (EPP) group in the European Parliament.
An unnamed Fidesz source, described as influential and well versed in the details of the issue, told hvg.hu that Orbán had made a promise to EPP leaders not to hound CEU from Budapest, although the source was also quoted as adding that "he also undertook no guarantee that the university would not leave of its own accord."
The hvg.hu article concludes by speculating that both sides are playing a waiting game. On the one hand, it says, Orbán is waiting in case CEU indeed exits of its own accord - given that Ignatieff himself has said the institution needs certainty by mid-summer - and that he is therefore under no pressure to have an agreement with the university signed before the end of 2018.
On the other hand, according to the analysis, CEU is itself biding its time - despite the rector's earlier pronouncement - as there is still enough time for the institution to get ready for the beginning of the 2019-2020 academic year in Vienna. With a suitable venue located in the Austrian capital, and a memorandum of understanding signed, CEU can observe Orbán's dilemma in relative security, it adds.
Macron meets Orbán, opposition leaders in Budapest
Szijjártó meets with Ugandan counterpart in Budapest
Politics Foreign Affairs | Nov 22, 2021, 15:45
Orbán meets with Marine Le Pen in Budapest
Politics Foreign Affairs | Oct 27, 2021, 09:40


text:
About eToro
Why Choose eToro
Regulation and License
eToro Partners
Trade Markets on eToro
Market Hours & Fees
0% commission stocks
Daily Market Review
Brexit Trading
eToro Earnings Reports Calendar
eToro Professional Client
CopyPortfolios
Partner CopyPortfolios
Popular Investor
Help Log in DOWNLOAD THE APP SIGN UP
Jul 17, 2019 - Mati Greenspan
Catastrophic Cat & Mouse
Jul 17, 2019 - eToro
eToro Daily Update 17/07/2019
A Matter of National Security
Home / Blog / Market Insights / Weekly Market Review 03-09/08/2015
By eToro
Weekly Market Review 03-09/08/2015
Job Data to Pin Down Rate Hike?
In the week ahead, there are two key market-moving events that traders will want to zero in on. The first is Thursday's release of the Bank of England's rate decision and then on Friday, the Non-farms Payroll figures for July from the U.S. In terms of their importance to the global markets, however, Friday's NFP outcome would assuredly eclipse the BoE decision. Why would that be the case? Simply because the NFP results and the associated labor reports could tip the scales for the Federal Reserve Bank. Along with price stability, the Fed is mandated to ensure full employment. Monetary policy, then, is supposed to be a reflection of the FOMC's outlook of the U.S. labor market.
U.S. Wage Growth Fed's Likely Focus
So, what we are looking for on Friday, then, is of course, new private sector jobs created in July. But, even more relevant than new jobs and the unemployment rate, is wage growth and the overall participation rate. First, the Fed will want to see wages rising by more than 2% (year-over-year). Second, they would like to see an increase in the participation rate (that is the percentage of "qualified" individuals actually in the work force). Currently, the market is anticipating that the Fed could raise interest rates as soon as September. The market's supposition could be validated by strong performance in not just the actual NFP numbers, but wages and the participation rate, as well. If the market's expectations are, indeed, validated by a strong performance in those parameters, that would support the U.S. Dollar. Conversely, a disappointment could weigh on the greenback, depending, of course, on how big a disappointment.
Remember, we mentioned last week that Janet Yellen, the Fed Chair, seemed to be leaning toward a single rate hike in 2015. However, quite a few of the other FOMC members were pushing for more than a single one this year. If the labor data is an all around beat, we could see Ms. Yellen changing her tune and hinting on another rate hike later in the year. That would be very much in line with a number of her compatriots' way of thinking.
Decision Time for the Bank of England
Mark Carney, the Bank of England Governor, has in recent months notched up the hawkish rhetoric. Markets wonder if he will soon be putting his money where his mouth is. On Thursday, the BoE will be announcing its monetary policy decision. At the same time, they will be releasing the BoE's official Quarterly Inflation Report which shows the bank's inflation outlook. For ease of reference, the BoE target for inflation is 2%.
The BoE's Monetary Policy Committee (MPC) had previously stated that they believe inflation risk was likely to notably increase before the year's end. Further, the MPC believes that "unusually low contributions" of some of the core factors which make up the inflation rate are disguising the reality. And that is that the inflation rate would likely be closer to 1.5%, nearing the BoE's threshold. If the Inflation Report shows the MPC's growing concern over the inflation risk it could help crack the code for the timing of the next rate hike. If a rate hike looks closer, given greater inflationary fears, then the Pound Sterling could find support. At the same time, the London FTSE could turn softer. A signal that the BoE will continue on with its wait-and-see stance could provide support for the FTSE even as it weighs on Pound Sterling.
Down to Business
The U.S. labor market remains key for the Fed's decision on timing of the next rate increase. If the NFP, wage growth and participation rate are positive, it could support the Dollar even as it puts pressure on Wall Street, Gold and Oil. However, and this is a big however, if the data undershoots expectations by a wide margin, you can believe the markets will quickly dispel any notion of a September rate hike.
On the plate
RBA Rate Decision(Tuesday) – If the RBA decides to cut rates on the back of China's woes the Aussie could be hit.
BoE Rate Decision(Thursday) – If the Bank of England suggest rate hikes are closer than previously thought , then the Sterling could move higher especially against low yielders such as the JPY or the CHF.
Nonfarm Payrolls (Friday) – If the NFP posts a gain of more than 220K jobs it will support the dollar.
Average Hourly Earnings(Friday)- If wages grow by more than 2% YoY it will be viewed as a positive sign and a signal rate hikes are moving closer.
Chart of the week – DAX
Economic Calendar:
Real Time Economic Calendar provided by Investing.com.
Please upgrade to the latest version of these supported browsers. Thank you.
IE v11+
eToro is the world's leading social trading platform, offering a wide array of tools to invest in the capital markets. Create a portfolio with cryptocurrencies, stocks, commodities, ETFs and more.
TRADING & INVESTING
General Risk Disclosure
The eToro Economic Calendar
COPY AND GET COPIED
How stats are calculated
How to verify your eToro account
eToro Reviews
eToro Cookie Policy
HELP AND EDUCATION
Trading Academy
eToro Security Guidelines
The Definition of Leverage and Margin
SPECIAL OFFERS AND AFFILIATION
eToro Club
Trading Challenge (Asia)
CFDs are complex instruments and come with a high risk of losing money rapidly due to leverage. 66% of retail investor accounts lose money when trading CFDs with this provider. You should consider whether you understand how CFDs work, and whether you can afford to take the high risk of losing your money.
eToro (Europe) Ltd., a Financial Services Company authorised and regulated by the Cyprus Securities Exchange Commission (CySEC) under the license # 109/10.
eToro (UK) Ltd, a Financial Services Company authorised and regulated by the Financial Conduct Authority (FCA) under the license FRN 583263.
eToro AUS Capital Pty Ltd. is authorised by the Australian Securities and Investments Commission (ASIC) to provide financial services under Australian Financial Services License 491139.
Past performance is not an indication of future results.
General Risk Disclosure | Terms & Conditions
You should seek advice from an independent and suitably licensed financial advisor and ensure that you have the risk appetite, relevant experience and knowledge before you decide to trade. Under no circumstances shall eToro have any liability to any person or entity for (a) any loss or damage in whole or part caused by, resulting from, or relating to any transactions related to CFDs or (b) any direct, indirect, special, consequential or incidental damages whatsoever. Cryptocurrencies markets are unregulated services which are not governed by any specific European regulatory framework (including MiFID). Therefore when using our Cryptocurrencies Trading Service you will not benefit from the protections available to clients receiving MiFID regulated investment services, such as access to the Cyprus Investor Compensation Fund (ICF)/the Financial Services Compensation Scheme (FSCS) and the Financial Ombudsman Service for dispute resolution. Trading with eToro by following and/or copying or replicating the trades of other traders involves a high level of risks, even when following and/or copying or replicating the top-performing traders. Such risks includes the risk that you may be following/copying the trading decisions of possibly inexperienced/unprofessional traders, or traders whose ultimate purpose or intention, or financial status may differ from yours. Past performance of an eToro Community Member is not a reliable indicator of his future performance. Content on eToro's social trading platform is generated by members of its community and does not contain advice or recommendations by or on behalf of eToro - Your Social Investment Network.
Copyright © 2006-2018 eToro - Your Social Investment Network, All rights reserved.


Flexible Benefits scheme with extensive salary sacrifice scheme's.
37hr working week, with a 9 day fortnight (hours may vary depending on role, job requirement or site specifics arrangements). Flexible working arrangements may be considered depending on the role and subject to line manager approval.
and search for Req ID: 132583BR. Please complete the on-line instructions to create a profile and upload CV.