'Prints out particular pieces of a spec, depending on what is
in the format string.  The format strings you can provide are::
$_   Package name
$.   Full package name (with namespace)
$@   Version with \'@\' prefix
$%   Compiler with \'%\' prefix
$%@  Compiler with \'%\' prefix & compiler version with \'@\' prefix
$%+  Compiler with \'%\' prefix & compiler flags prefixed by name
$%@+ Compiler, compiler version, and compiler flags with same
prefixes as above
$+   Options
$=   Architecture prefixed by \'arch=\'
$/   7-char prefix of DAG hash with \'-\' prefix
You can also use full-string versions, which elide the prefixes::
${PACKAGE}       Package name
${VERSION}       Version
${COMPILER}      Full compiler string
${COMPILERNAME}  Compiler name
${COMPILERVER}   Compiler version
${COMPILERFLAGS} Compiler flags
${OPTIONS}       Options
${ARCHITECTURE}  Architecture
${SHA1}          Dependencies 8-char sha1 prefix
${HASH:len}      DAG hash with optional length specifier
${SPACK_ROOT}    The spack root directory
${SPACK_INSTALL} The default spack install directory,
${SPACK_PREFIX}/opt
${PREFIX}        The package prefix
Note these are case-insensitive: for example you can specify either
``${PACKAGE}`` or ``${package}``.
Optionally you can provide a width, e.g. ``$20_`` for a 20-wide name.
Like printf, you can provide \'-\' for left justification, e.g.
``$-20_`` for a left-justified name.
Anything else is copied verbatim into the output stream.
*Example:*  ``$_$@$+`` translates to the name, version, and options
of the package, but no dependencies, arch, or compiler.
TODO: allow, e.g., ``$6#`` to customize short hash length
TODO: allow, e.g., ``$//`` for full hash.'

def format(self, format_string='$_$@$%@+$+$=', **kwargs):

    color = kwargs.get('color', False)
    length = len(format_string)
    out = StringIO()
    named = escape = compiler = False
    named_str = fmt = ''
    def write(s, c):
        f = ((color_formats[c] + cescape(s)) + '@.')
        cwrite(f, stream=out, color=color)
    iterator = enumerate(format_string)
    for (i, c) in iterator:
        if escape:
            fmt = '%'
            if (c == '-'):
                fmt += c
                (i, c) = next(iterator)
            while (c in '0123456789'):
                fmt += c
                (i, c) = next(iterator)
            fmt += 's'
            if (c == '_'):
                name = (self.name if self.name else '')
                out.write((fmt % name))
            elif (c == '.'):
                out.write((fmt % self.fullname))
            elif (c == '@'):
                if (self.versions and (self.versions != _any_version)):
                    write((fmt % (c + str(self.versions))), c)
            elif (c == '%'):
                if self.compiler:
                    write((fmt % (c + str(self.compiler.name))), c)
                compiler = True
            elif (c == '+'):
                if self.variants:
                    write((fmt % str(self.variants)), c)
            elif (c == '='):
                if (self.architecture and str(self.architecture)):
                    a_str = ((('    arch' + c) + str(self.architecture)) + '    ')
                    write((fmt % a_str), c)
            elif (c == '/'):
                out.write(('/' + (fmt % self.dag_hash(7))))
            elif (c == '$'):
                if (fmt != '%s'):
                    raise ValueError("Can't    use    format    width    with    $$.")
                out.write('$')
            elif (c == '{'):
                named = True
                named_str = ''
            escape = False
        elif compiler:
            if (c == '@'):
                if (self.compiler and self.compiler.versions and (self.compiler.versions != _any_version)):
                    write((c + str(self.compiler.versions)), '%')
            elif (c == '+'):
                if self.compiler_flags:
                    write((fmt % str(self.compiler_flags)), '%')
                compiler = False
            elif (c == '$'):
                escape = True
                compiler = False
            else:
                out.write(c)
                compiler = False
        elif named:
            if (not (c == '}')):
                if (i == (length - 1)):
                    raise ValueError(("Error:    unterminated    ${    in    format:'%s'" % format_string))
                named_str += c
                continue
            named_str = named_str.upper()
            if (named_str == 'PACKAGE'):
                name = (self.name if self.name else '')
                write((fmt % self.name), '@')
            if (named_str == 'VERSION'):
                if (self.versions and (self.versions != _any_version)):
                    write((fmt % str(self.versions)), '@')
            elif (named_str == 'COMPILER'):
                if self.compiler:
                    write((fmt % self.compiler), '%')
            elif (named_str == 'COMPILERNAME'):
                if self.compiler:
                    write((fmt % self.compiler.name), '%')
            elif (named_str in ['COMPILERVER', 'COMPILERVERSION']):
                if self.compiler:
                    write((fmt % self.compiler.versions), '%')
            elif (named_str == 'COMPILERFLAGS'):
                if self.compiler:
                    write((fmt % str(self.compiler_flags)), '%')
            elif (named_str == 'OPTIONS'):
                if self.variants:
                    write((fmt % str(self.variants)), '+')
            elif (named_str == 'ARCHITECTURE'):
                if (self.architecture and str(self.architecture)):
                    write((fmt % str(self.architecture)), '=')
            elif (named_str == 'SHA1'):
                if self.dependencies:
                    out.write((fmt % str(self.dag_hash(7))))
            elif (named_str == 'SPACK_ROOT'):
                out.write((fmt % spack.prefix))
            elif (named_str == 'SPACK_INSTALL'):
                out.write((fmt % spack.store.root))
            elif (named_str == 'PREFIX'):
                out.write((fmt % self.prefix))
            elif named_str.startswith('HASH'):
                if named_str.startswith('HASH:'):
                    (_, hashlen) = named_str.split(':')
                    hashlen = int(hashlen)
                else:
                    hashlen = None
                out.write((fmt % self.dag_hash(hashlen)))
            named = False
        elif (c == '$'):
            escape = True
            if (i == (length - 1)):
                raise ValueError(("Error:    unterminated    $    in    format:    '%s'" % format_string))
        else:
            out.write(c)
    result = out.getvalue()
    return result
