Custom Text Tags link

Ren'Py has support for defining your own text tags. These text tags can manipulate the text and text tags defined within, including adding and removing text and other text tags.

Custom text tags are created by assigning a text tag function to an entry in one of the following dictionaries.

define config.custom_text_tags = { } link

Maps text tag names to text tag functions, when the text tag can wrap other text.

define config.self_closing_custom_text_tags = { } link

Maps text tag names to a self-closing text tag functions, when the text tag does not wrap other text.


The functions may be called at any moment as part of the prediction process. For that reason, their behavior should not depend on the state of the game (global variables, typically) and they should not induce side-effects (calling Statement Equivalents for example, or changing global variables).

A text tag function takes three arguments: The tag itself, the argument for the tag, and a list of content tuples. For example, for the text:

"{big=2}Hello, {b}World{/b}{/big}"

The tag will be "big", the argument will be the string "2", and the list of content tuples will be:

    (renpy.TEXT_TEXT, "Hello, "),
    (renpy.TEXT_TAG, "b"),
    (renpy.TEXT_TEXT, "World"),
    (renpy.TEXT_TAG, "/b"),

The text tag function should return a new list of content tuples, which is used to replace the text tag and its contents.

Content tuples consist of two components. The first component is one of the the constants in the following list. The second component varies based on the first component, as described below.


The second component is text that is intended for display to the user.


The second component is the contents of a text tag, without the enclosing braces.


The second component is a displayable to be embedded into the text.


This represents a break between paragraphs, and the second component is undefined (but must be present).

A self-closing text tag function is similar, except that it does not take the third argument.

Lists of tokens can be passed to Text() when its tokenized argument is True.


The dialogue text tags {p}, {w}, {nw}, and {fast} are processed before custom text tags, and should either be not included inside a custom text tag, or passed through unchanged.

Examples link

The example big text tag works like the {size} text tag, but applies a multiplier to its argument.

init python:

    def big_tag(tag, argument, contents):

        size = int(argument) * 20

        return [
                (renpy.TEXT_TAG, u"size={}".format(size)),
            ] + contents + [
                (renpy.TEXT_TAG, u"/size"),

    config.custom_text_tags["big"] = big_tag

"This is {big=3}BIG!{/big}"

The example rot13 text tag applies the ROT13 transform to text. Note that ROT26 – ROT13 applied twice – is just normal text.

init python:

    def rot13_transform(s):

        ROT13 = { }

        for i, j in zip("ABCDEFGHIJKLM", "NOPQRSTUVWXYZ"):
             ROT13[i] = j
             ROT13[j] = i

             i = i.lower()
             j = j.lower()

             ROT13[i] = j
             ROT13[j] = i

        return "".join(ROT13.get(i, i) for i in s)

    def rot13_tag(tag, argument, contents):
        rv = [ ]

        for kind, text in contents:

            if kind == renpy.TEXT_TEXT:
                text = rot13_transform(text)

            rv.append((kind, text))

        return rv

    config.custom_text_tags["rot13"] = rot13_tag

"Rot0. {rot13}Rot13. {rot13}Rot26. {/rot13}Rot13. {/rot13}Rot0."

The bang text tag inserts a specific image into the text, and doesn't require a closing tag.

init python:
    def bang_tag(tag, argument):
        return [ ( renpy.TEXT_TAG, "size=40"), (renpy.TEXT_TEXT, "!"), (renpy.TEXT_TAG, "/size") ]

    config.self_closing_custom_text_tags["bang"] = bang_tag

"This is awesome{bang}"