Skip to content

[0] is being considered a markup tag #5768

Open
@kuhnchris

Description

@kuhnchris

Have you checked closed issues? (https://github.com/Textualize/textual/issues?q=is%3Aissue+is%3Aclosed) Yes

Have you checked against the most recent version of Textual? (https://pypi.org/search/?q=textual) Yes

The bug

  • Trying to create a Static with markup=True with predefined text "[0] Hello World".
    => Crash

  • Trying to escape the text results in a non-escaped string.
    => Crash

According to McGugan:

[0] shouldn't be considered a tag and shouldn't need escaping. If it is throwing a markup error, that is a bug. Please file an issue.

Error:

MarkupError: Expected markup style value (found '0] Hello World!').

MRE:

from textual.app import App
from textual.widgets import Footer, Static
from textual.markup import escape
class TextualApp(App):

    DEFAULT_CSS = """
    /* any needed CSS  here */
    """

    def compose(self):
        yield Static(escape("[0] Hello World!"))
        yield Footer()

    # code that causes a bug here

textual diagnose:

<!-- This is valid Markdown, please paste the following directly in to a GitHub issue -->
# Textual Diagnostics

## Versions

| Name    | Value  |
|---------|--------|
| Textual | 3.1.1  |
| Rich    | 14.0.0 |

## Python

| Name           | Value                                |
|----------------|--------------------------------------|
| Version        | 3.12.9                               |
| Implementation | CPython                              |
| Compiler       | GCC 13.2.1 20240309                  |
| Executable     | /home/kuhnchris/test/venv/bin/python |

## Operating System

| Name    | Value                                             |
|---------|---------------------------------------------------|
| System  | Linux                                             |
| Release | 6.12.21-0-lts                                     |
| Version | #1-Alpine SMP PREEMPT_DYNAMIC 2025-04-01 11:09:17 |

## Terminal

| Name                 | Value          |
|----------------------|----------------|
| Terminal Application | *Unknown*      |
| TERM                 | xterm-256color |
| COLORTERM            | truecolor      |
| FORCE_COLOR          | *Not set*      |
| NO_COLOR             | *Not set*      |

## Rich Console options

| Name           | Value                |
|----------------|----------------------|
| size           | width=289, height=98 |
| legacy_windows | False                |
| min_width      | 1                    |
| max_width      | 289                  |
| is_terminal    | True                 |
| encoding       | utf-8                |
| max_height     | 98                   |
| justify        | None                 |
| overflow       | None                 |
| no_wrap        | False                |
| highlight      | None                 |
| markup         | None                 |
| height         | None                 |

Technical workaround:
(by David Fokkema)

import re

escape("[1]", _escape=re.compile(r"(\\*)(\[[a-z0-9#/@][^[]*?])").sub)

(by kuhnchris)

outputText.replace("[", "\\[")

Full Stack log (textual run --dev):

fullStackTrace.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions