The formatter module

The Formatter uses a Theme to highlight text according to a token’s action attribute. The action is mapped to a TextFormat by the theme.

It is possible to add more Themes to a formatter, coupled to a certain language, so that the formatter can switch to that theme for embedded pieces of text of that language.

All kinds of text formatting and/or highlighting can be implemented by using or inheriting of Formatter. If you need to convert the TextFormats from the theme to something else, you can provide a factory to Formatter to do that.

There is also a SimpleFormatter which just churns out the standard action of each token as a HTML class string, for example mapping Literal.Number to "literal number", without needing a Theme.

If you need more special behaviour, you can inherit from Formatter and reimplement format_ranges(), to do other things or to use a different FormatContext.

class FormatCache(theme, base, textformat, baseformat, unparsed)

Bases: tuple

FormatCache is a named tuple encapsulating formatting logic.

At least two attributes must be defined:

textformat(action)

is called to return formatting information for the specified standard action.

baseformat(role, state)

is called to return general formatting information from a Theme, converted using the factory that was given to the formatter. See the baseformat() method of Theme.

Both callables may return None. The three other attributes can be None; they are:

theme

a reference to the format cache’s Theme object.

base

the result of baseformat("window", "default"), indicating the general format of the text window (color, font, background color, etc). See the baseformat() method of Theme.

unparsed

the result of textformat(StandardAction("_Unparsed")), which denotes the text format to use for unparsed text. A Theme can define that by putting properties in the .parce ._unparsed class. By default unparsed text is not formatted.

base

Alias for field number 1

baseformat

Alias for field number 3

textformat

Alias for field number 2

theme

Alias for field number 0

unparsed

Alias for field number 4

class FormatRange(pos, end, textformat)

Bases: tuple

A named tuple denoting a text range from pos to end that should be formatted with textformat.

The textformat can be any object, that depends on the factory function that is used to convert a standard action or (when using a Theme) a TextFormat to something you can use for the output format you want to create.

end

Alias for field number 1

pos

Alias for field number 0

textformat

Alias for field number 2

class AbstractFormatter[source]

Bases: object

A Formatter formats text based on the action of tokens.

baseformat(role='window', state='default', language=None)[source]

Return the base format for the specified role and state.

This is the value returned by Theme.baseformat(role, state), converted by our factory (and cached of course).

If the language is given, the theme added for that language is consulted.

If the theme does not provide a baseformat, or no theme was added for the specified language, None is returned.

textformat(action, language=None)[source]

Return the text format for the specified action.

This is the value returned by Theme.textformat(action), converted by our factory (and cached of course).

If the language is given, the theme added for that language is consulted.

If the theme does not provide a text format for the action, or no theme was added for the specified language, None is returned.

format_caches()[source]

Should return a dictionary mapping language to FormatCache.

A FormatCache normally encapsulates a theme. The key None should be present and denotes the default theme. Other keys should be Language subclasses, and their theme is used for tokens that originate from that language.

format_ranges(tree, start=0, end=None, format_context=None)[source]

Yield FormatRange(pos, end, format) three-tuples.

The format is the value returned by Theme.textformat() for the token’s action, converted by our factory (and cached of course). Ranges with a TextFormat for which our factory returns None are skipped.

format_text(text, tree, start=0, end=None, format_context=None)[source]

Yield all text in tuples(text, format).

For unparsed pieces of text, or pieces that had no format mapped to the action, the format is None. The FormatContext, if given, is passed on to format_ranges().

format_document(cursor, format_context=None)[source]

Yield all text in the cursor’s selection in tuples(text, format).

For unparsed pieces of text, or pieces that had no format mapped to the action, the format is None.The FormatContext, if given, is passed on to format_ranges(). For example:

>>> from parce import Cursor, Document, theme_by_name
>>> from parce.lang.css import Css
>>> from parce.formatter import Formatter
>>> factory = lambda tf: tf.css_properties() or None
>>> f = Formatter(theme_by_name(), factory)
>>> d = Document(Css.root, "h1 { color: red; }")
>>> c = Cursor(d).select_all()
>>> list(f.format_document(c))
[('h1', {'color': '#00008b', 'font-weight': 'bold'}),
 (' ', None),
 ('{', {'font-weight': 'bold'}),
 (' ', None),
 ('color', {'color': '#4169e1', 'font-weight': 'bold'}),
 (': ', None), ('red', {'color': '#2e8b57'}),
 ('; ', None),
 ('}', {'font-weight': 'bold'})]
class Formatter(theme=None, factory=None)[source]

Bases: parce.formatter.AbstractFormatter

A Formatter is used to format or highlight text according to a Theme.

Supply the theme, and an optional factory that converts a TextFormat to something else. For example:

>>> from parce import root, find, theme_by_name
>>> from parce.formatter import Formatter
>>> tree = root(find("css"), "h1 { color: red; }")
>>> f = Formatter(theme_by_name('default'))
>>> list(f.format_ranges(tree))
[FormatRange(pos=0, end=2, textformat=<TextFormat color=Color(r=0, g=0,b=139, a=1.0), font_weight='bold'>),
 FormatRange(pos=3, end=4, textformat=<TextFormat font_weight='bold'>),
 FormatRange(pos=5, end=10, textformat=<TextFormat color=Color(r=65, g=105, b=225, a=1.0), font_weight='bold'>),
 FormatRange(pos=12, end=15, textformat=<TextFormat color=Color(r=46, g=139, b=87, a=1.0)>),
 FormatRange(pos=17, end=18, textformat=<TextFormat font_weight='bold'>)]

The default factory just yields the TextFormat right from the theme, unless the format is empty, evaluating to None.

And here is an example using a factory that converts the textformat to a dictionary of css properties, e.g. to use for inline CSS highlighting. Note that when the factory returns None, a range is skipped, so we return None in case a dictionary ends up empty:

>>> factory = lambda tf: tf.css_properties() or None
>>> f = Formatter(theme_by_name('default'), factory)
>>> list(f.format_ranges(tree))
[FormatRange(pos=0, end=2, textformat={'color': '#00008b', 'font-weight': 'bold'}),
 FormatRange(pos=3, end=4, textformat={'font-weight': 'bold'}),
 FormatRange(pos=5, end=10, textformat={'color': '#4169e1', 'font-weight': 'bold'}),
 FormatRange(pos=12, end=15, textformat={'color': '#2e8b57'}),
 FormatRange(pos=17, end=18, textformat={'font-weight': 'bold'})]

In addition to the default theme (which is required), other themes can be added coupled to a specific language. This allows the formatter to switch theme based on the language of the text.

format_caches()[source]

Reimplemented to return the format caches added by add_theme().

The format cache caches formatting information from the theme, to enable fast formatting.

add_theme(theme, language=None, add_baseformat=False)[source]

Add a Theme.

If language is None, the theme becomes the default theme. If a Language is specified, the theme will be used for tokens from that language.

If add_baseformat is True, the theme’s baseformat (window) will be added to all the theme’s text formats.

get_theme(language=None)[source]

Return the theme for the specified language.

If language is None, the default theme is returned. Returns None if the language has no specific theme.

remove_theme(language)[source]

Remove the theme for the specified language.

copy_themes(formatter)[source]

Copy all themes from the other formatter.

class SimpleFormatter[source]

Bases: parce.formatter.AbstractFormatter

A formatter that simply yields a HTML class string for every action.

For example:

>>> import parce.formatter
>>> tree = parce.root(parce.find("css"), "h1 { color: red; }")
>>> f = parce.formatter.SimpleFormatter()
>>> list(f.format_ranges(tree))
[FormatRange(pos=0, end=2, textformat='name tag'),
 FormatRange(pos=3, end=4, textformat='delimiter bracket'),
 FormatRange(pos=5, end=10, textformat='name property definition'),
 FormatRange(pos=10, end=11, textformat='delimiter'),
 FormatRange(pos=12, end=15, textformat='literal color'),
 FormatRange(pos=15, end=16, textformat='delimiter'),
 FormatRange(pos=17, end=18, textformat='delimiter bracket')]

This formatter does not use a theme; language switches are ignored.

format_caches()[source]

Reimplemented to return a FormatCache with a factory that converts an action to a css class string.

class FormatContext[source]

Bases: object

FormatContext can be used to track theme changes during formatting.

A FormatContext instance can be given to the AbstractFormatter.format_ranges() method of a formatter.

Inheriting from this class and implementing the methods enable you to react to theme changes during formatting.

start(fcache)[source]

Called when formatting starts, with the default Theme’s format cache.

switch(fcache)[source]

Called whenever formatting switches to a different theme.

done()[source]

Called when formatting has finished.