Befoul Demonstration

print("befoul is a wrapper around colorful. All the normal things should work.")
print(f"Like the simple attributes to {bf.bold}turn bold on{bf.no_bold} and off again.")
befoul is a wrapper around colorful. All the normal things should work.
Like the simple attributes to turn bold on and off again.
print("As well as calling as a function", bf.underlined("to get a wrapped string"), "that resets at its end.")
As well as calling as a function to get a wrapped string that resets at its end.
print(f"But because balancing {{('')}} is {bf.orange('annoying')},")
print(f"we hack up an {bf.bold_orangeRed:alternative!}")
But because balancing {('')} is annoying,
we hack up an alternative!
print(f"""\
Everything in a {bf.italic_underlined:replacement field} that comes after a {bf.bold_blinkrapid::} is
a {bf.underlined_italic:format spec}. Well, it's supposed to be, anyway.

But format specs may contain spaces and {bf.underlined:even
newlines}! {bf.mediumAquamarine:No quotes required.}
""")
Everything in a replacement field that comes after a : is
a format spec. Well, it's supposed to be, anyway.

But format specs may contain spaces and even
newlines! No quotes required.

print(f"""F-strings even {bf.bold_chocolate:let us {bf.underlined_darkOliveGreen:nest} one level} deep.""")
print("""Good old {bf.bold_chocolate:format() {bf.underlined_darkOliveGreen:can nest} {how_many}} as well.""".format(bf=bf, how_many='once'))
F-strings even let us nest one level deep.
Good old format() can nest once as well.
from types import SimpleNamespace

adlibs = SimpleNamespace(
    occupation="artist",
    who="you",
    code="an expression",
    i18n="internationalization"
)
print(f"""\
An {bf.underlined(adlibs.occupation)} like {adlibs.who} still uses the () syntax for expressions.
Or perhaps {bf.underlined | adlibs.who} prefer the pipe syntax?
You might use one style with both {bf.bold(adlibs.code): and text} in the same field!

I haven't tried this with {bf.bold|adlibs.i18n: templates}. Might take some explaining.
""")
An artist like you still uses the () syntax for expressions.
Or perhaps you prefer the pipe syntax?
You might use one style with both an expression and text in the same field!

I haven't tried this with internationalization templates. Might take some explaining.

em = bf.underlined_darkOrchid
show = 'illustrate'
print(f"""\
This isn't specific to {em:befoul}, but I thought I should {em|show} that if you use
the {em:same} style {em:over} and {em & bf.bold:over} again, you don't have to {em:rebuild
it} every time! Keep it in a {em & bf.inversed:variable!{bf.on_deepPink:!}!} 
""")
This isn't specific to befoul, but I thought I should illustrate that if you use
the same style over and over again, you don't have to rebuild
it every time! Keep it in a variable!!! 

print(f"""\
There's one thing left we haven't talked about. What if you had been planning
on using that format spec — for formatting???

The format spec isn't as important for text as it is for other types, but you
still might have been using it to justify text
║{'center':^40}║
║{' or left':<20}{'and right ':>20}║
""")
There's one thing left we haven't talked about. What if you had been planning
on using that format spec — for formatting???

The format spec isn't as important for text as it is for other types, but you
still might have been using it to justify text
║                 center                 ║
║ or left                      and right ║

from textwrap import dedent

SPEC_SEPARATOR = r'\a'

print(f"""Befoul will split your format spec on {bf.bold|SPEC_SEPARATOR}.
The first part will be treated as text as we've been doing,
but everything after {bf.bold|SPEC_SEPARATOR} it'll use as a traditional string format spec.

Colorful's support for this is a bit buggy at the moment, as we see in this example rendered
with correct formatting in no color, and too-small fields with color:
""")

# TODO: link to existing bug about format spec
# TODO: file PR for with_setup not passing new colormode,
#       setup doing 'if colormode' instead of 'if none'
for colormode in (bf.NO_COLORS, bf.TRUE_COLORS):
    with bf.with_setup(colormode) as c:
        c.colormode = colormode
        print(dedent(f"""
        colors={c.colormode}
        ╔{'═'*40}╗
        ║{c.bold:THINGS\a^40}║
        ║{c.underlined: Thing One\a<20}{c.red:1000 \a>20}║
        """))
Befoul will split your format spec on \a.
The first part will be treated as text as we've been doing,
but everything after \a it'll use as a traditional string format spec.

Colorful's support for this is a bit buggy at the moment, as we see in this example rendered
with correct formatting in no color, and too-small fields with color:


colors=0
╔════════════════════════════════════════╗
║                 THINGS                 ║
║ Thing One                         1000 ║


colors=16777215
╔════════════════════════════════════════╗
║          THINGS          ║
║ Thing One1000 

See #37. I expect that's fixable without upsetting the implementation too much.

import datetime
now = datetime.datetime.now()
# TODO: file bug about cf.bold(1) + cf.bold(2) orig_string vs styled_string discrepancy
n = 12
print(f"""\
Take advantage of nesting: {bf.bold:today is {now:%A}}
If you do need to replace in the format string before applying style: {bf.bold | f"{now:%{n}A}"}
""")

# In order for {bf.bold|now:%A} to work, we'd need lazy evaluation:
#  1. x.setStyle(bold)
#  2. x.setValue(now)
#  3. x.setFormat('%A')
#  4. x.style.render(x.value.format(x.fmt))
#
# and how would split-fmt apply?
# you'd need {bf.bold|now:%A⧸tail⧸tailFmt}
# and then would you do
#  - format(value) + format(tail)
#  - format(format(value) + tail)