Skip to content

Usage in PTG

So the things you read before are all great and all, but where do you apply them? Glad you (definitely) asked!

The markup module exports the tim name; this is an instance of MarkupLanguage. tim is going to be your best pal for handling anything related to TIM parsing.

Why do we use classes to represent a static language?

There are a couple of aspects of TIM that require keeping track of some 'state', e.g. aliases and macros. This state, referred to as context internally, is passed in to all parsing functions to provide the data needed to apply the non-built-in tags.

MarkupLanguage keeps track of some context that can be modified with the alias and define methods, and passes this state into every parse* call for you!

Fun fact: You can use TIM in most widgets! See the styling docs for more info.



The most important method to know about is parse. It takes some TIM string, and returns formatted text to display in the terminal.

from pytermgui import tim

print(tim.parse("[lightgreen]This is some [italic]styled[/italic] text!"))

docs/src/tim/ This is some  styled  text!


Since calling print on parsed text every time can get a bit repetitive, we have a helper function to do it for you! Just call print with the same positional and keyword arguments as you would use for the builtin print, and see the magic!

You can print non-TIM text with this method as well, but you might wanna use the escape function if you want to make sure to keep things from being parsed. Though at that point, you might as well use the builtin print!

from pytermgui import tim

    "[slategrey italic]So much formatting, [!shuffle !upper]where[/!] does it all fit?"

docs/src/tim/ So much formatting, EHEWR DOES IT ALL FIT?


As mentioned above, you can modify the TIM parser's state to enable custom behaviour. The first of these is aliasing tags, which essentially makes one tag expand to any other groups of tags while parsing.


Alias tags are detected as tags that had no previous meaning, e.g. aren't included in the builtin tags and are not macros. At the moment it is not possible to re-define tags.

from pytermgui import tim

tim.alias("my-tag1", "@surface primary+1")

# Recursive tags also work!
tim.alias("my-tag2", "my-tag1 italic")

    "[my-tag1]My first tag\n\n"
    + "[/my-tag1]By default, aliases generate an unsetter\n\n"
    + "[my-tag2]My second tag"

docs/src/tim/ My first tag By default, aliases generate an unsetter My second tag


You can also define macros using the define method. Macros are Python functions you can call from TIM to transform your text. They can only be referenced from TIM, definition must come from the outer Python context.

There are a couple of simple macros defined by default, such as !upper, !capitalize and !lower. These are all tied to the respective Python str methods.

from pytermgui import tim

tim.print("[!upper]some text")
tim.print("[!lower]SOME OTHER TEXT")
tim.print("[!gradient(210) italic]Fancy lookin' text")

docs/src/tim/ SOME TEXT some other text Fan cy  loo kin ' t ext

A favored example of mine is creating a simple localization layer for your application. You can define a macro, !lang, that is given a localization-id and returns some localized text. This can then be used in any place that TIM is accepted, since it is defined on the global instance.

from pytermgui import tim


    "welcome": {
        "en": "Welcome to the documentation",
        "hu": "Üdv a dokumentációban",

def macro_lang(key: str) -> str:
    translation = TRANSLATIONS.get(key)

    if translation is None:
        return key

    return translation[LANGUAGE]

tim.define("!lang", macro_lang)

for LANGUAGE in ["en", "hu"]:

    tim.print(f"[bold]LANGUAGE: [/ 157]{LANGUAGE!r}")
    tim.print("--> [!lang]welcome[/!lang]")

docs/src/tim/ LANGUAGE:  'en' --> Welcome to the documentation LANGUAGE:  'hu' --> Üdv a dokumentációban