public function parse($argv = null, $exit = true) {
        $formatOutputBak = $this->formatOutput;
        // Only format commands if we are exiting.
        if (!$exit) {
            $this->formatOutput = false;
        }
        if (!$exit) {
            ob_start();
        }

        $args = $this->parseRaw($argv);

        $hasCommand = $this->hasCommand();

        if ($hasCommand && !$args->getCommand()) {
            // If no command is given then write a list of commands.
            $this->writeUsage($args);
            $this->writeCommands();
            $result = null;
        } elseif ($args->getOpt('help') || $args->getOpt('?')) {
            // Write the help.
            $this->writeUsage($args);
            $this->writeHelp($args->getCommand());
            $result = null;
        } else {
            // Validate the arguments against the schema.
            $validArgs = $this->validate($args);
            $result = $validArgs;
        }
        if (!$exit) {
            $this->formatOutput = $formatOutputBak;
            $output = ob_get_clean();
            if ($result === null) {
                throw new \Exception(trim($output));
            }
        } elseif ($result === null) {
            exit();
        }
        return $result;
    }