Skip to content

Commit

Permalink
Merge branch 'main' into fix-button-render-with-console-markup
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan authored Mar 26, 2024
2 parents 7cca00d + f432a00 commit 4b0b633
Show file tree
Hide file tree
Showing 19 changed files with 450 additions and 88 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## Unreleased

- Fixed `Button` not rendering correctly with console markup https://github.com/Textualize/textual/issues/4328


## [0.54.0] - 2023-03-26

### Fixed

- Fixed a crash in `TextArea` when undoing an edit to a selection the selection was made backwards https://github.com/Textualize/textual/issues/4301
- Fixed issue with flickering scrollbars https://github.com/Textualize/textual/pull/4315
- Fixed issue where narrow TextArea would repeatedly wrap due to scrollbar appearing/disappearing https://github.com/Textualize/textual/pull/4334
- Fix progress bar ETA not updating when setting `total` reactive https://github.com/Textualize/textual/pull/4316
- Fixed `Button` not rendering correctly with console markup https://github.com/Textualize/textual/issues/4328
- Exceptions inside `Widget.compose` or workers weren't bubbling up in tests https://github.com/Textualize/textual/issues/4282

### Changed

- ProgressBar won't show ETA until there is at least one second of samples https://github.com/Textualize/textual/pull/4316
- `Input` waits until an edit has been made, after entry to the widget, before offering a suggestion https://github.com/Textualize/textual/pull/4335

### Added

- Added `Document.start` and `end` location properties for convenience https://github.com/Textualize/textual/pull/4267

## [0.53.1] - 2023-03-18

Expand Down Expand Up @@ -1800,6 +1812,7 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040
- New handler system for messages that doesn't require inheritance
- Improved traceback handling

[0.54.0]: https://github.com/Textualize/textual/compare/v0.53.1...v0.54.0
[0.53.1]: https://github.com/Textualize/textual/compare/v0.53.0...v0.53.1
[0.53.0]: https://github.com/Textualize/textual/compare/v0.52.1...v0.53.0
[0.52.1]: https://github.com/Textualize/textual/compare/v0.52.0...v0.52.1
Expand Down
3 changes: 3 additions & 0 deletions docs/events/unmount.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
::: textual.events.Unmount
options:
heading_level: 1
4 changes: 4 additions & 0 deletions docs/widgets/text_area.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ This method is the programmatic equivalent of selecting some text and then pasti

Some other convenient methods are available, such as [`insert`][textual.widgets._text_area.TextArea.insert], [`delete`][textual.widgets._text_area.TextArea.delete], and [`clear`][textual.widgets._text_area.TextArea.clear].

!!! tip
The `TextArea.document.end` property returns the location at the end of the
document, which might be convenient when editing programmatically.

### Working with the cursor

#### Moving the cursor
Expand Down
1 change: 1 addition & 0 deletions mkdocs-nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ nav:
- "events/screen_resume.md"
- "events/screen_suspend.md"
- "events/show.md"
- "events/unmount.md"
- Styles:
- "styles/index.md"
- "styles/align.md"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "textual"
version = "0.53.1"
version = "0.54.0"
homepage = "https://github.com/Textualize/textual"
repository = "https://github.com/Textualize/textual"
documentation = "https://textual.textualize.io/"
Expand Down
9 changes: 8 additions & 1 deletion src/textual/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3006,11 +3006,18 @@ async def _broker_event(
return False
else:
event.stop()
if isinstance(action, (str, tuple)):
if isinstance(action, str) or (isinstance(action, tuple) and len(action) == 2):
await self.run_action(action, default_namespace=default_namespace) # type: ignore[arg-type]
elif callable(action):
await action()
else:
if isinstance(action, tuple) and self.debug:
# It's a tuple and made it this far, which means it'll be a
# malformed action. This is a no-op, but let's log that
# anyway.
log.warning(
f"Can't parse @{event_name} action from style meta; check your console markup syntax"
)
return False
return True

Expand Down
22 changes: 22 additions & 0 deletions src/textual/document/_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ def prepare_query(self, query: str) -> Query | None:
def line_count(self) -> int:
"""Returns the number of lines in the document."""

@property
@abstractmethod
def start(self) -> Location:
"""Returns the location of the start of the document (0, 0)."""
return (0, 0)

@property
@abstractmethod
def end(self) -> Location:
"""Returns the location of the end of the document."""

@overload
def __getitem__(self, line_index: int) -> str: ...

Expand Down Expand Up @@ -331,6 +342,17 @@ def line_count(self) -> int:
"""Returns the number of lines in the document."""
return len(self._lines)

@property
def start(self) -> Location:
"""Returns the location of the start of the document (0, 0)."""
return super().start

@property
def end(self) -> Location:
"""Returns the location of the end of the document."""
last_line = self._lines[-1]
return (self.line_count, len(last_line))

def get_index_from_location(self, location: Location) -> int:
"""Given a location, returns the index from the document's text.
Expand Down
2 changes: 1 addition & 1 deletion src/textual/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class Mount(Event, bubble=False, verbose=False):


class Unmount(Event, bubble=False, verbose=False):
"""Sent when a widget is unmounted and may not longer receive messages.
"""Sent when a widget is unmounted and may no longer receive messages.
- [ ] Bubbles
- [ ] Verbose
Expand Down
6 changes: 2 additions & 4 deletions src/textual/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -3618,10 +3618,8 @@ async def _compose(self) -> None:
raise TypeError(
f"{self!r} compose() method returned an invalid result; {error}"
) from error
except Exception:
from rich.traceback import Traceback

self.app.panic(Traceback())
except Exception as error:
self.app._handle_exception(error)
else:
self._extend_compose(widgets)
await self.mount_composed_widgets(widgets)
Expand Down
1 change: 1 addition & 0 deletions src/textual/widgets/_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ def _on_focus(self, _: Focus) -> None:
if self.cursor_blink:
self._blink_timer.resume()
self.app.cursor_position = self.cursor_screen_offset
self._suggestion = ""

async def _on_key(self, event: events.Key) -> None:
self._cursor_visible = True
Expand Down
8 changes: 7 additions & 1 deletion src/textual/widgets/_markdown.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import re
from pathlib import Path, PurePath
from typing import Callable, Iterable, Optional

Expand Down Expand Up @@ -149,7 +150,12 @@ def build_from_token(self, token: Token) -> None:
if token.children:
for child in token.children:
if child.type == "text":
content.append(child.content, style_stack[-1])
content.append(
# Ensure repeating spaces and/or tabs get squashed
# down to a single space.
re.sub(r"\s+", " ", child.content),
style_stack[-1],
)
if child.type == "hardbreak":
content.append("\n")
if child.type == "softbreak":
Expand Down
8 changes: 3 additions & 5 deletions src/textual/widgets/_text_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,8 @@ def _watch_indent_width(self) -> None:
self.scroll_cursor_visible()

def _watch_show_vertical_scrollbar(self) -> None:
self._rewrap_and_refresh_virtual_size()
if self.wrap_width:
self._rewrap_and_refresh_virtual_size()
self.scroll_cursor_visible()

def _watch_theme(self, theme: str) -> None:
Expand Down Expand Up @@ -2025,10 +2026,7 @@ def clear(self) -> EditResult:
Returns:
An EditResult relating to the deletion of all content.
"""
document = self.document
last_line = document[-1]
document_end = (document.line_count, len(last_line))
return self.delete((0, 0), document_end, maintain_selection_offset=False)
return self.delete((0, 0), self.document.end, maintain_selection_offset=False)

def _delete_via_keyboard(
self,
Expand Down
3 changes: 2 additions & 1 deletion src/textual/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ async def _run(self, app: App) -> None:

app.log.worker(Traceback())
if self.exit_on_error:
app._fatal_error()
worker_failed = WorkerFailed(self._error)
app._handle_exception(worker_failed)
else:
self.state = WorkerState.SUCCESS
app.log.worker(self)
Expand Down
Loading

0 comments on commit 4b0b633

Please sign in to comment.