Skip to content

Commit 6980c47

Browse files
committed
Expose code intend guides
1 parent 8f85ece commit 6980c47

File tree

6 files changed

+74
-22
lines changed

6 files changed

+74
-22
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
- Optimized startup https://github.com/Textualize/textual/pull/5869
1313
- New blank visual which makes background faster to render (note this will break snapshots tests this version) https://github.com/Textualize/textual/pull/5869
14+
- Exposed `code_indent_guides` boolean on Markdown widget
1415

1516
## [3.4.0] - 2025-06-14
1617

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ docs-online-nav:
5252

5353
.PHONY: docs-serve
5454
docs-serve: clean-screenshot-cache docs-online-nav
55-
$(run) mkdocs serve --config-file mkdocs-nav-online.yml
55+
TEXTUAL_THEME=dracula $(run) mkdocs serve --config-file mkdocs-nav-online.yml
5656
rm -f mkdocs-nav-online.yml
5757

5858
.PHONY: docs-serve-offline
@@ -76,7 +76,7 @@ clean-offline-docs:
7676

7777
.PHONY: docs-deploy
7878
docs-deploy: clean-screenshot-cache docs-online-nav
79-
$(run) mkdocs gh-deploy --config-file mkdocs-nav-online.yml
79+
TEXTUAL_THEME=dracula $(run) mkdocs gh-deploy --config-file mkdocs-nav-online.yml
8080
rm -f mkdocs-nav-online.yml
8181

8282
.PHONY: build

docs/examples/widgets/markdown.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,58 @@
22
from textual.widgets import Markdown
33

44
EXAMPLE_MARKDOWN = """\
5-
# Markdown Document
5+
## Markdown
66
7-
This is an example of Textual's `Markdown` widget.
8-
9-
## Features
10-
11-
Markdown syntax and extensions are supported.
12-
13-
- Typography *emphasis*, **strong**, `inline code` etc.
14-
- Headers
15-
- Lists (bullet and ordered)
7+
- Typography *emphasis*, **strong**, `inline code` etc.
8+
- Headers
9+
- Lists
1610
- Syntax highlighted code blocks
17-
- Tables!
11+
- Tables and more
12+
13+
## Quotes
14+
15+
> I must not fear.
16+
> > Fear is the mind-killer.
17+
> > Fear is the little-death that brings total obliteration.
18+
> > I will face my fear.
19+
> > > I will permit it to pass over me and through me.
20+
> > > And when it has gone past, I will turn the inner eye to see its path.
21+
> > > Where the fear has gone there will be nothing. Only I will remain.
22+
23+
## Tables
24+
25+
| Name | Type | Default | Description |
26+
| --------------- | ------ | ------- | ---------------------------------- |
27+
| `show_header` | `bool` | `True` | Show the table header |
28+
| `fixed_rows` | `int` | `0` | Number of fixed rows |
29+
| `fixed_columns` | `int` | `0` | Number of fixed columns |
30+
31+
## Code blocks
32+
33+
```python
34+
def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
35+
\"\"\"Iterate and generate a tuple with a flag for last value.\"\"\"
36+
iter_values = iter(values)
37+
try:
38+
previous_value = next(iter_values)
39+
except StopIteration:
40+
return
41+
for value in iter_values:
42+
yield False, previous_value
43+
previous_value = value
44+
yield True, previous_value
45+
```
46+
47+
1848
"""
1949

2050

2151
class MarkdownExampleApp(App):
52+
2253
def compose(self) -> ComposeResult:
23-
yield Markdown(EXAMPLE_MARKDOWN)
54+
markdown = Markdown(EXAMPLE_MARKDOWN)
55+
markdown.code_indent_guides = False
56+
yield markdown
2457

2558

2659
if __name__ == "__main__":

docs/examples/widgets/markdown_viewer.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
3434
## Code Blocks
3535
36-
Code blocks are syntax highlighted, with guidelines.
36+
Code blocks are syntax highlighted.
3737
3838
```python
3939
class ListViewExample(App):
@@ -45,12 +45,24 @@ def compose(self) -> ComposeResult:
4545
)
4646
yield Footer()
4747
```
48+
49+
## Litany Against Fear
50+
51+
I must not fear.
52+
Fear is the mind-killer.
53+
Fear is the little-death that brings total obliteration.
54+
I will face my fear.
55+
I will permit it to pass over me and through me.
56+
And when it has gone past, I will turn the inner eye to see its path.
57+
Where the fear has gone there will be nothing. Only I will remain.
4858
"""
4959

5060

5161
class MarkdownExampleApp(App):
5262
def compose(self) -> ComposeResult:
53-
yield MarkdownViewer(EXAMPLE_MARKDOWN, show_table_of_contents=True)
63+
markdown_viewer = MarkdownViewer(EXAMPLE_MARKDOWN, show_table_of_contents=True)
64+
markdown_viewer.code_indent_guides = False
65+
yield markdown_viewer
5466

5567

5668
if __name__ == "__main__":

docs/widget_gallery.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ Display and interact with a Markdown document (adds a table of contents and brow
162162
[MarkdownViewer reference](./widgets/markdown_viewer.md){ .md-button .md-button--primary }
163163

164164

165-
```{.textual path="docs/examples/widgets/markdown_viewer.py" columns="100" lines="42"}
165+
```{.textual path="docs/examples/widgets/markdown_viewer.py" columns="140" lines="50" press="tab,down"}
166166
```
167167

168168
## Markdown
@@ -172,7 +172,7 @@ Display a markdown document.
172172
[Markdown reference](./widgets/markdown.md){ .md-button .md-button--primary }
173173

174174

175-
```{.textual path="docs/examples/widgets/markdown.py"}
175+
```{.textual path="docs/examples/widgets/markdown.py" columns="140" lines="51"}
176176
```
177177

178178
## MaskedInput

src/textual/widgets/_markdown.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ def __init__(self, headers: list[Text], rows: list[list[Text]]):
478478
def render(self) -> Table:
479479
table = Table(
480480
expand=True,
481-
box=box.SIMPLE_HEAVY,
481+
box=box.SIMPLE_HEAD,
482482
style=self.rich_style,
483483
header_style=self.get_component_rich_style("markdown-table--header"),
484484
border_style=self.get_component_rich_style("markdown-table--lines"),
@@ -504,7 +504,7 @@ class MarkdownTable(MarkdownBlock):
504504
DEFAULT_CSS = """
505505
MarkdownTable {
506506
width: 100%;
507-
background: $surface;
507+
background: $background 80%;
508508
}
509509
"""
510510

@@ -635,7 +635,7 @@ def _block(self) -> Syntax:
635635
self.code,
636636
lexer=self.lexer,
637637
word_wrap=False,
638-
indent_guides=True,
638+
indent_guides=self._markdown.code_indent_guides,
639639
padding=(1, 2),
640640
theme=self.theme,
641641
)
@@ -722,6 +722,9 @@ class Markdown(Widget):
722722
code_light_theme: reactive[str] = reactive("material-light")
723723
"""The theme to use for code blocks when the App theme is light."""
724724

725+
code_indent_guides: reactive[bool] = reactive(True)
726+
"""Should code fences display indent guides?"""
727+
725728
def __init__(
726729
self,
727730
markdown: str | None = None,
@@ -1157,6 +1160,9 @@ class MarkdownViewer(VerticalScroll, can_focus=False, can_focus_children=True):
11571160
"""
11581161

11591162
show_table_of_contents = reactive(True)
1163+
"""Show the table of contents?"""
1164+
code_indent_guides: reactive[bool] = reactive(True)
1165+
"""Should code fences display indent guides?"""
11601166
top_block = reactive("")
11611167

11621168
navigator: var[Navigator] = var(Navigator)
@@ -1241,7 +1247,7 @@ def compose(self) -> ComposeResult:
12411247
parser_factory=self._parser_factory, open_links=self._open_links
12421248
)
12431249
markdown.can_focus = True
1244-
yield markdown
1250+
yield markdown.data_bind(MarkdownViewer.code_indent_guides)
12451251
yield MarkdownTableOfContents(markdown)
12461252

12471253
def _on_markdown_table_of_contents_updated(

0 commit comments

Comments
 (0)