protected function renderSynopsis(BlockLayout $layout, ArgsFormat $argsFormat, $appName, $prefix = '', $lastOptional = false)
    {
        $nameParts = array();
        $argumentParts = array();

        $nameParts[] = '<u>'.($appName ?: 'console').'</u>';

        foreach ($argsFormat->getCommandNames() as $commandName) {
            $nameParts[] = '<u>'.$commandName->toString().'</u>';
        }

        foreach ($argsFormat->getCommandOptions() as $commandOption) {
            $nameParts[] = $commandOption->isLongNamePreferred()
                ? '--'.$commandOption->getLongName()
                : '-'.$commandOption->getShortName();
        }

        if ($lastOptional) {
            $lastIndex = count($nameParts) - 1;
            $nameParts[$lastIndex] = '['.$nameParts[$lastIndex].']';
        }

        foreach ($argsFormat->getOptions(false) as $option) {
            // \xC2\xA0 is a non-breaking space
            if ($option->isValueRequired()) {
                $format = "%s\xC2\xA0<%s>";
            } elseif ($option->isValueOptional()) {
                $format = "%s\xC2\xA0[<%s>]";
            } else {
                $format = '%s';
            }

            $optionName = $option->isLongNamePreferred()
                ? '--'.$option->getLongName()
                : '-'.$option->getShortName();

            $argumentParts[] = sprintf('['.$format.']', $optionName, $option->getValueName());
        }

        foreach ($argsFormat->getArguments() as $argument) {
            $argName = $argument->getName();

            $argumentParts[] = sprintf(
                $argument->isRequired() ? '<%s>' : '[<%s>]',
                $argName.($argument->isMultiValued() ? '1' : '')
            );

            if ($argument->isMultiValued()) {
                $argumentParts[] = sprintf('... [<%sN>]', $argName);
            }
        }

        $argsOpts = implode(' ', $argumentParts);
        $name = implode(' ', $nameParts);

        $layout->add(new LabeledParagraph($prefix.$name, $argsOpts, 1, false));
    }