diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index f6e942e5d..6e2ca38c2 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -18,7 +18,3 @@ Give as much detail as you can. Example code of how you would like it to work wo **What problem does it solve for you?** What problem do you have that this feature would solve? I may be able to suggest an existing way of solving it. - -**Did I help** - -If I was able to resolve your problem, consider [sponsoring](https://github.com/sponsors/willmcgugan) my work on Rich, or [buy me a coffee](https://ko-fi.com/willmcgugan) to say thanks. diff --git a/CHANGELOG.md b/CHANGELOG.md index a93d06391..6a0e3e518 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,18 +9,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added options to TimeRemainingColumn to render a compact time format and render elapsed time when a task is + finished. https://github.com/Textualize/rich/pull/1992 - Added ProgressColumn `MofNCompleteColumn` to display raw `completed/total` column (similar to DownloadColumn, - but displays values as ints, does not convert to floats or add bit/bytes units). + but displays values as ints, does not convert to floats or add bit/bytes units). https://github.com/Textualize/rich/pull/1941 ### Fixed -- In Jupyter mode make the link target be set to "_blank" +- In Jupyter mode make the link target be set to "\_blank" - Fix some issues with markup handling around "[" characters https://github.com/Textualize/rich/pull/1950 +- Fix syntax lexer guessing. +- Fixed Pretty measure not respecting expand_all https://github.com/Textualize/rich/issues/1998 +- Collapsed definitions for single-character spinners, to save memory and reduce import time. -### Added +### Changed -- Add support for enum.Flag in ReprHighlighter https://github.com/Textualize/rich/pull/1920 +- Improved support for enum.Flag in ReprHighlighter https://github.com/Textualize/rich/pull/1920 +- Tree now respects justify=None, i.e. won't pad to right https://github.com/Textualize/rich/issues/1690 ## [11.2.0] - 2022-02-08 @@ -122,8 +128,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed issue with progress bar not rendering markup https://github.com/willmcgugan/rich/issues/1721 - Fixed race condition when exiting Live https://github.com/willmcgugan/rich/issues/1530 -[10.15.0]: https://github.com/willmcgugan/rich/compare/v10.14.0...v10.15.0 - ## [10.14.0] - 2021-11-16 ### Fixed @@ -420,7 +424,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [9.12.1] - 2021-02-27 -### Fixed +### Fixed - Fixed deadlock in Progress https://github.com/willmcgugan/rich/issues/1061 @@ -477,7 +481,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed error message for tracebacks with broken `__str__` https://github.com/willmcgugan/rich/issues/980 - Fixed markup edge case https://github.com/willmcgugan/rich/issues/987 -### Added +### Added - Added cheeky sponsorship request to test card - Added `quiet` argument to Console constructor @@ -536,7 +540,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [9.8.0] - 2021-01-11 -### Added +### Added - Added **rich_measure** for tree - Added rich.align.VerticalCenter @@ -625,7 +629,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [9.4.0] - 2020-12-12 -### Added +### Added - Added rich.live https://github.com/willmcgugan/rich/pull/382 - Added algin parameter to Rule and Console.rule @@ -634,7 +638,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added style parameter to Console.log - Added rich.diagnose command -### Changed +### Changed - Table.add_row style argument now applies to entire line and not just cells - Added end_section parameter to Table.add_row to force a line underneath row @@ -645,7 +649,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [9.3.0] - 2020-12-1 -### Added +### Added - Added get_datetime parameter to Console, to allow for repeatable tests - Added get_time parameter to Console @@ -745,7 +749,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [8.0.0] - 2020-10-03 -### Added +### Added - Added Console.bell method - Added Set to types that Console.print will automatically pretty print @@ -770,7 +774,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Console.begin_capture, Console.end_capture and Console.capture - Added Table.title_justify and Table.caption_justify https://github.com/willmcgugan/rich/issues/301 -### Changed +### Changed - Improved formatting of exceptions - Enabled Rich exceptions in logging https://github.com/taliraj @@ -789,7 +793,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Text.remove_suffix - Added Text.append_tokens -### Changed +### Changed - Text.tabs_to_spaces was renamed to Text.expand_tabs, which works in place rather than returning a new instance - Renamed Column.index to Column.\_index @@ -1073,7 +1077,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr ## [3.0.2] - 2020-07-02 -### Added +### Added - Added rich.styled.Styled class to apply styles to renderable - Table.add_row now has an optional style parameter @@ -1186,7 +1190,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - Added 'transient' option to Progress -### Changed +### Changed - Truncated overly long text in Rule with ellipsis overflow @@ -1308,7 +1312,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - Optimizations for Segment, Console and Table -### Added +### Added - Added Console.clear method - Added exporting of links to HTML @@ -1330,7 +1334,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr ## [1.1.6] - 2020-05-17 -### Added +### Added - Added rich.align.Align class - Added justify argument to Console.print and console.log @@ -1349,7 +1353,7 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - Fixes for legacy windows: Bar, Panel, and Rule now use ASCII characters - show_cursor is now a no-op on legacy windows -### Added +### Added - Added Console.input @@ -1651,142 +1655,142 @@ Major version bump for a breaking change to `Text.stylize signature`, which corr - First official release, API still to be stabilized +[Unreleased]: https://github.com/willmcgugan/rich/compare/v11.0.0...HEAD [11.2.0]: https://github.com/willmcgugan/rich/compare/v11.1.0...v11.2.0 [11.1.0]: https://github.com/willmcgugan/rich/compare/v11.0.0...v11.1.0 [11.0.0]: https://github.com/willmcgugan/rich/compare/v10.16.1...v11.0.0 +[10.16.2]: https://github.com/willmcgugan/rich/compare/v10.16.1...v10.16.2 [10.16.1]: https://github.com/willmcgugan/rich/compare/v10.16.0...v10.16.1 [10.16.0]: https://github.com/willmcgugan/rich/compare/v10.15.2...v10.16.0 [10.15.2]: https://github.com/willmcgugan/rich/compare/v10.15.1...v10.15.2 [10.15.1]: https://github.com/willmcgugan/rich/compare/v10.15.0...v10.15.1 -[10.14.0]: https://github.com/willmcgugan/rich/compare/v10.14.0...v10.15.0 -[10.13.0]: https://github.com/willmcgugan/rich/compare/v10.13.0...v10.14.0 -[10.12.0]: https://github.com/willmcgugan/rich/compare/v10.12.0...v10.13.0 -[10.11.0]: https://github.com/willmcgugan/rich/compare/v10.11.0...v10.12.0 -[10.10.0]: https://github.com/willmcgugan/rich/compare/v10.10.0...v10.11.0 -[10.9.0]: https://github.com/willmcgugan/rich/compare/v10.9.0...v10.10.0 -[10.8.0]: https://github.com/willmcgugan/rich/compare/v10.8.0...v10.9.0 -[10.7.0]: https://github.com/willmcgugan/rich/compare/v10.7.0...v10.8.0 -[10.6.0]: https://github.com/willmcgugan/rich/compare/v10.6.0...v10.7.0 -[10.5.0]: https://github.com/willmcgugan/rich/compare/v10.5.0...v10.6.0 -[10.4.0]: https://github.com/willmcgugan/rich/compare/v10.4.0...v10.5.0 -[10.3.0]: https://github.com/willmcgugan/rich/compare/v10.3.0...v10.4.0 -[10.2.2]: https://github.com/willmcgugan/rich/compare/v10.2.2...v10.3.0 -[10.2.1]: https://github.com/willmcgugan/rich/compare/v10.2.1...v10.2.2 -[10.2.0]: https://github.com/willmcgugan/rich/compare/v10.2.0...v10.2.1 -[10.1.0]: https://github.com/willmcgugan/rich/compare/v10.1.0...v10.2.0 -[10.0.1]: https://github.com/willmcgugan/rich/compare/v10.0.1...v10.1.0 -[10.0.0]: https://github.com/willmcgugan/rich/compare/v10.0.0...v10.0.1 -[9.13.0]: https://github.com/willmcgugan/rich/compare/v9.13.0...v10.0.0 -[9.12.4]: https://github.com/willmcgugan/rich/compare/v9.12.4...v9.13.0 -[9.12.3]: https://github.com/willmcgugan/rich/compare/v9.12.3...v9.12.4 -[9.12.2]: https://github.com/willmcgugan/rich/compare/v9.12.2...v9.12.3 -[9.12.1]: https://github.com/willmcgugan/rich/compare/v9.12.1...v9.12.2 -[9.12.0]: https://github.com/willmcgugan/rich/compare/v9.12.0...v9.12.1 -[9.11.1]: https://github.com/willmcgugan/rich/compare/v9.11.1...v9.12.0 -[9.11.0]: https://github.com/willmcgugan/rich/compare/v9.11.0...v9.11.1 -[9.10.0]: https://github.com/willmcgugan/rich/compare/v9.10.0...v9.11.0 -[9.9.0]: https://github.com/willmcgugan/rich/compare/v9.9.0...v9.10.0 -[9.8.2]: https://github.com/willmcgugan/rich/compare/v9.8.2...v9.9.0 -[9.8.1]: https://github.com/willmcgugan/rich/compare/v9.8.1...v9.8.2 -[9.8.0]: https://github.com/willmcgugan/rich/compare/v9.8.0...v9.8.1 -[9.7.0]: https://github.com/willmcgugan/rich/compare/v9.7.0...v9.8.0 -[9.6.2]: https://github.com/willmcgugan/rich/compare/v9.6.2...v9.7.0 -[9.6.1]: https://github.com/willmcgugan/rich/compare/v9.6.1...v9.6.2 -[9.6.0]: https://github.com/willmcgugan/rich/compare/v9.6.0...v9.6.1 -[9.5.1]: https://github.com/willmcgugan/rich/compare/v9.5.1...v9.6.0 -[9.5.0]: https://github.com/willmcgugan/rich/compare/v9.5.0...v9.5.1 -[9.4.0]: https://github.com/willmcgugan/rich/compare/v9.4.0...v9.5.0 -[9.3.0]: https://github.com/willmcgugan/rich/compare/v9.3.0...v9.4.0 -[9.2.0]: https://github.com/willmcgugan/rich/compare/v9.2.0...v9.3.0 -[9.1.0]: https://github.com/willmcgugan/rich/compare/v9.1.0...v9.2.0 -[9.0.1]: https://github.com/willmcgugan/rich/compare/v9.0.1...v9.1.0 -[9.0.0]: https://github.com/willmcgugan/rich/compare/v9.0.0...v9.0.1 -[8.0.0]: https://github.com/willmcgugan/rich/compare/v8.0.0...v9.0.0 -[7.1.0]: https://github.com/willmcgugan/rich/compare/v7.1.0...v8.0.0 -[7.0.0]: https://github.com/willmcgugan/rich/compare/v7.0.0...v7.1.0 -[6.2.0]: https://github.com/willmcgugan/rich/compare/v6.2.0...v7.0.0 -[6.1.2]: https://github.com/willmcgugan/rich/compare/v6.1.2...v6.2.0 -[6.1.1]: https://github.com/willmcgugan/rich/compare/v6.1.1...v6.1.2 -[6.1.0]: https://github.com/willmcgugan/rich/compare/v6.1.0...v6.1.1 -[6.0.0]: https://github.com/willmcgugan/rich/compare/v6.0.0...v6.1.0 -[5.2.1]: https://github.com/willmcgugan/rich/compare/v5.2.1...v6.0.0 -[5.2.0]: https://github.com/willmcgugan/rich/compare/v5.2.0...v5.2.1 -[5.1.2]: https://github.com/willmcgugan/rich/compare/v5.1.2...v5.2.0 -[5.1.1]: https://github.com/willmcgugan/rich/compare/v5.1.1...v5.1.2 -[5.1.0]: https://github.com/willmcgugan/rich/compare/v5.1.0...v5.1.1 -[5.0.0]: https://github.com/willmcgugan/rich/compare/v5.0.0...v5.1.0 -[4.2.2]: https://github.com/willmcgugan/rich/compare/v4.2.2...v5.0.0 -[4.2.1]: https://github.com/willmcgugan/rich/compare/v4.2.1...v4.2.2 -[4.2.0]: https://github.com/willmcgugan/rich/compare/v4.2.0...v4.2.1 -[4.1.0]: https://github.com/willmcgugan/rich/compare/v4.1.0...v4.2.0 -[4.0.0]: https://github.com/willmcgugan/rich/compare/v4.0.0...v4.1.0 -[3.4.1]: https://github.com/willmcgugan/rich/compare/v3.4.1...v4.0.0 -[3.4.0]: https://github.com/willmcgugan/rich/compare/v3.4.0...v3.4.1 -[3.3.2]: https://github.com/willmcgugan/rich/compare/v3.3.2...v3.4.0 -[3.3.1]: https://github.com/willmcgugan/rich/compare/v3.3.1...v3.3.2 -[3.3.0]: https://github.com/willmcgugan/rich/compare/v3.3.0...v3.3.1 -[3.2.0]: https://github.com/willmcgugan/rich/compare/v3.2.0...v3.3.0 -[3.1.0]: https://github.com/willmcgugan/rich/compare/v3.1.0...v3.2.0 -[3.0.5]: https://github.com/willmcgugan/rich/compare/v3.0.5...v3.1.0 -[3.0.4]: https://github.com/willmcgugan/rich/compare/v3.0.4...v3.0.5 -[3.0.3]: https://github.com/willmcgugan/rich/compare/v3.0.3...v3.0.4 -[3.0.2]: https://github.com/willmcgugan/rich/compare/v3.0.2...v3.0.3 -[3.0.1]: https://github.com/willmcgugan/rich/compare/v3.0.1...v3.0.2 -[3.0.0]: https://github.com/willmcgugan/rich/compare/v3.0.0...v3.0.1 -[2.3.1]: https://github.com/willmcgugan/rich/compare/v2.3.1...v3.0.0 -[2.3.0]: https://github.com/willmcgugan/rich/compare/v2.3.0...v2.3.1 -[2.2.6]: https://github.com/willmcgugan/rich/compare/v2.2.6...v2.3.0 -[2.2.5]: https://github.com/willmcgugan/rich/compare/v2.2.5...v2.2.6 -[2.2.4]: https://github.com/willmcgugan/rich/compare/v2.2.4...v2.2.5 -[2.2.3]: https://github.com/willmcgugan/rich/compare/v2.2.3...v2.2.4 -[2.2.2]: https://github.com/willmcgugan/rich/compare/v2.2.2...v2.2.3 -[2.2.1]: https://github.com/willmcgugan/rich/compare/v2.2.1...v2.2.2 -[2.2.0]: https://github.com/willmcgugan/rich/compare/v2.2.0...v2.2.1 -[2.1.0]: https://github.com/willmcgugan/rich/compare/v2.1.0...v2.2.0 -[2.0.1]: https://github.com/willmcgugan/rich/compare/v2.0.1...v2.1.0 -[2.0.0]: https://github.com/willmcgugan/rich/compare/v2.0.0...v2.0.1 -[1.3.1]: https://github.com/willmcgugan/rich/compare/v1.3.1...v2.0.0 -[1.3.0]: https://github.com/willmcgugan/rich/compare/v1.3.0...v1.3.1 -[1.2.3]: https://github.com/willmcgugan/rich/compare/v1.2.3...v1.3.0 -[1.2.2]: https://github.com/willmcgugan/rich/compare/v1.2.2...v1.2.3 -[1.2.1]: https://github.com/willmcgugan/rich/compare/v1.2.1...v1.2.2 -[1.2.0]: https://github.com/willmcgugan/rich/compare/v1.2.0...v1.2.1 -[1.1.9]: https://github.com/willmcgugan/rich/compare/v1.1.9...v1.2.0 -[1.1.8]: https://github.com/willmcgugan/rich/compare/v1.1.8...v1.1.9 -[1.1.7]: https://github.com/willmcgugan/rich/compare/v1.1.7...v1.1.8 -[1.1.6]: https://github.com/willmcgugan/rich/compare/v1.1.6...v1.1.7 -[1.1.5]: https://github.com/willmcgugan/rich/compare/v1.1.5...v1.1.6 -[1.1.4]: https://github.com/willmcgugan/rich/compare/v1.1.4...v1.1.5 -[1.1.3]: https://github.com/willmcgugan/rich/compare/v1.1.3...v1.1.4 -[1.1.2]: https://github.com/willmcgugan/rich/compare/v1.1.2...v1.1.3 -[1.1.1]: https://github.com/willmcgugan/rich/compare/v1.1.1...v1.1.2 -[1.1.0]: https://github.com/willmcgugan/rich/compare/v1.1.0...v1.1.1 -[1.0.3]: https://github.com/willmcgugan/rich/compare/v1.0.3...v1.1.0 -[1.0.2]: https://github.com/willmcgugan/rich/compare/v1.0.2...v1.0.3 -[1.0.1]: https://github.com/willmcgugan/rich/compare/v1.0.1...v1.0.2 -[1.0.0]: https://github.com/willmcgugan/rich/compare/v1.0.0...v1.0.1 -[0.8.13]: https://github.com/willmcgugan/rich/compare/v0.8.13...v1.0.0 -[0.8.12]: https://github.com/willmcgugan/rich/compare/v0.8.12...v0.8.13 -[0.8.11]: https://github.com/willmcgugan/rich/compare/v0.8.11...v0.8.12 -[0.8.10]: https://github.com/willmcgugan/rich/compare/v0.8.10...v0.8.11 -[0.8.9]: https://github.com/willmcgugan/rich/compare/v0.8.9...v0.8.10 -[0.8.8]: https://github.com/willmcgugan/rich/compare/v0.8.8...v0.8.9 -[0.8.7]: https://github.com/willmcgugan/rich/compare/v0.8.7...v0.8.8 -[0.8.6]: https://github.com/willmcgugan/rich/compare/v0.8.6...v0.8.7 -[0.8.5]: https://github.com/willmcgugan/rich/compare/v0.8.5...v0.8.6 -[0.8.4]: https://github.com/willmcgugan/rich/compare/v0.8.4...v0.8.5 -[0.8.3]: https://github.com/willmcgugan/rich/compare/v0.8.3...v0.8.4 -[0.8.2]: https://github.com/willmcgugan/rich/compare/v0.8.2...v0.8.3 -[0.8.1]: https://github.com/willmcgugan/rich/compare/v0.8.1...v0.8.2 -[0.8.0]: https://github.com/willmcgugan/rich/compare/v0.8.0...v0.8.1 -[0.7.2]: https://github.com/willmcgugan/rich/compare/v0.7.2...v0.8.0 -[0.7.1]: https://github.com/willmcgugan/rich/compare/v0.7.1...v0.7.2 -[0.7.0]: https://github.com/willmcgugan/rich/compare/v0.7.0...v0.7.1 -[0.6.0]: https://github.com/willmcgugan/rich/compare/v0.6.0...v0.7.0 -[0.5.0]: https://github.com/willmcgugan/rich/compare/v0.5.0...v0.6.0 -[0.4.1]: https://github.com/willmcgugan/rich/compare/v0.4.1...v0.5.0 -[0.4.0]: https://github.com/willmcgugan/rich/compare/v0.4.0...v0.4.1 -[0.3.3]: https://github.com/willmcgugan/rich/compare/v0.3.3...v0.4.0 -[0.3.2]: https://github.com/willmcgugan/rich/compare/v0.3.2...v0.3.3 -[0.3.1]: https://github.com/willmcgugan/rich/compare/v0.3.1...v0.3.2 -[0.3.0]: https://github.com/willmcgugan/rich/compare/v0.3.0...v0.3.1 +[10.15.0]: https://github.com/willmcgugan/rich/compare/v10.14.0...v10.15.0 +[10.14.0]: https://github.com/willmcgugan/rich/compare/v10.13.0...v10.14.0 +[10.13.0]: https://github.com/willmcgugan/rich/compare/v10.12.0...v10.13.0 +[10.12.0]: https://github.com/willmcgugan/rich/compare/v10.11.0...v10.12.0 +[10.11.0]: https://github.com/willmcgugan/rich/compare/v10.10.0...v10.11.0 +[10.10.0]: https://github.com/willmcgugan/rich/compare/v10.9.0...v10.10.0 +[10.9.0]: https://github.com/willmcgugan/rich/compare/v10.8.0...v10.9.0 +[10.8.0]: https://github.com/willmcgugan/rich/compare/v10.7.0...v10.8.0 +[10.7.0]: https://github.com/willmcgugan/rich/compare/v10.6.0...v10.7.0 +[10.6.0]: https://github.com/willmcgugan/rich/compare/v10.5.0...v10.6.0 +[10.5.0]: https://github.com/willmcgugan/rich/compare/v10.4.0...v10.5.0 +[10.4.0]: https://github.com/willmcgugan/rich/compare/v10.3.0...v10.4.0 +[10.3.0]: https://github.com/willmcgugan/rich/compare/v10.2.2...v10.3.0 +[10.2.2]: https://github.com/willmcgugan/rich/compare/v10.2.1...v10.2.2 +[10.2.1]: https://github.com/willmcgugan/rich/compare/v10.2.0...v10.2.1 +[10.2.0]: https://github.com/willmcgugan/rich/compare/v10.1.0...v10.2.0 +[10.1.0]: https://github.com/willmcgugan/rich/compare/v10.0.1...v10.1.0 +[10.0.1]: https://github.com/willmcgugan/rich/compare/v10.0.0...v10.0.1 +[10.0.0]: https://github.com/willmcgugan/rich/compare/v9.13.0...v10.0.0 +[9.13.0]: https://github.com/willmcgugan/rich/compare/v9.12.4...v9.13.0 +[9.12.4]: https://github.com/willmcgugan/rich/compare/v9.12.3...v9.12.4 +[9.12.3]: https://github.com/willmcgugan/rich/compare/v9.12.2...v9.12.3 +[9.12.2]: https://github.com/willmcgugan/rich/compare/v9.12.1...v9.12.2 +[9.12.1]: https://github.com/willmcgugan/rich/compare/v9.12.0...v9.12.1 +[9.12.0]: https://github.com/willmcgugan/rich/compare/v9.11.1...v9.12.0 +[9.11.1]: https://github.com/willmcgugan/rich/compare/v9.11.0...v9.11.1 +[9.11.0]: https://github.com/willmcgugan/rich/compare/v9.10.0...v9.11.0 +[9.10.0]: https://github.com/willmcgugan/rich/compare/v9.9.0...v9.10.0 +[9.9.0]: https://github.com/willmcgugan/rich/compare/v9.8.2...v9.9.0 +[9.8.2]: https://github.com/willmcgugan/rich/compare/v9.8.1...v9.8.2 +[9.8.1]: https://github.com/willmcgugan/rich/compare/v9.8.0...v9.8.1 +[9.8.0]: https://github.com/willmcgugan/rich/compare/v9.7.0...v9.8.0 +[9.7.0]: https://github.com/willmcgugan/rich/compare/v9.6.2...v9.7.0 +[9.6.2]: https://github.com/willmcgugan/rich/compare/v9.6.1...v9.6.2 +[9.6.1]: https://github.com/willmcgugan/rich/compare/v9.6.0...v9.6.1 +[9.6.0]: https://github.com/willmcgugan/rich/compare/v9.5.1...v9.6.0 +[9.5.1]: https://github.com/willmcgugan/rich/compare/v9.5.0...v9.5.1 +[9.5.0]: https://github.com/willmcgugan/rich/compare/v9.4.0...v9.5.0 +[9.4.0]: https://github.com/willmcgugan/rich/compare/v9.3.0...v9.4.0 +[9.3.0]: https://github.com/willmcgugan/rich/compare/v9.2.0...v9.3.0 +[9.2.0]: https://github.com/willmcgugan/rich/compare/v9.1.0...v9.2.0 +[9.1.0]: https://github.com/willmcgugan/rich/compare/v9.0.1...v9.1.0 +[9.0.1]: https://github.com/willmcgugan/rich/compare/v9.0.0...v9.0.1 +[9.0.0]: https://github.com/willmcgugan/rich/compare/v8.0.0...v9.0.0 +[8.0.0]: https://github.com/willmcgugan/rich/compare/v7.1.0...v8.0.0 +[7.1.0]: https://github.com/willmcgugan/rich/compare/v7.0.0...v7.1.0 +[7.0.0]: https://github.com/willmcgugan/rich/compare/v6.2.0...v7.0.0 +[6.2.0]: https://github.com/willmcgugan/rich/compare/v6.1.2...v6.2.0 +[6.1.2]: https://github.com/willmcgugan/rich/compare/v6.1.1...v6.1.2 +[6.1.1]: https://github.com/willmcgugan/rich/compare/v6.1.0...v6.1.1 +[6.1.0]: https://github.com/willmcgugan/rich/compare/v6.0.0...v6.1.0 +[6.0.0]: https://github.com/willmcgugan/rich/compare/v5.2.1...v6.0.0 +[5.2.1]: https://github.com/willmcgugan/rich/compare/v5.2.0...v5.2.1 +[5.2.0]: https://github.com/willmcgugan/rich/compare/v5.1.2...v5.2.0 +[5.1.2]: https://github.com/willmcgugan/rich/compare/v5.1.1...v5.1.2 +[5.1.1]: https://github.com/willmcgugan/rich/compare/v5.1.0...v5.1.1 +[5.1.0]: https://github.com/willmcgugan/rich/compare/v5.0.0...v5.1.0 +[5.0.0]: https://github.com/willmcgugan/rich/compare/v4.2.2...v5.0.0 +[4.2.2]: https://github.com/willmcgugan/rich/compare/v4.2.1...v4.2.2 +[4.2.1]: https://github.com/willmcgugan/rich/compare/v4.2.0...v4.2.1 +[4.2.0]: https://github.com/willmcgugan/rich/compare/v4.1.0...v4.2.0 +[4.1.0]: https://github.com/willmcgugan/rich/compare/v4.0.0...v4.1.0 +[4.0.0]: https://github.com/willmcgugan/rich/compare/v3.4.1...v4.0.0 +[3.4.1]: https://github.com/willmcgugan/rich/compare/v3.4.0...v3.4.1 +[3.4.0]: https://github.com/willmcgugan/rich/compare/v3.3.2...v3.4.0 +[3.3.2]: https://github.com/willmcgugan/rich/compare/v3.3.1...v3.3.2 +[3.3.1]: https://github.com/willmcgugan/rich/compare/v3.3.0...v3.3.1 +[3.3.0]: https://github.com/willmcgugan/rich/compare/v3.2.0...v3.3.0 +[3.2.0]: https://github.com/willmcgugan/rich/compare/v3.1.0...v3.2.0 +[3.1.0]: https://github.com/willmcgugan/rich/compare/v3.0.5...v3.1.0 +[3.0.5]: https://github.com/willmcgugan/rich/compare/v3.0.4...v3.0.5 +[3.0.4]: https://github.com/willmcgugan/rich/compare/v3.0.3...v3.0.4 +[3.0.3]: https://github.com/willmcgugan/rich/compare/v3.0.2...v3.0.3 +[3.0.2]: https://github.com/willmcgugan/rich/compare/v3.0.1...v3.0.2 +[3.0.1]: https://github.com/willmcgugan/rich/compare/v3.0.0...v3.0.1 +[3.0.0]: https://github.com/willmcgugan/rich/compare/v2.3.1...v3.0.0 +[2.3.1]: https://github.com/willmcgugan/rich/compare/v2.3.0...v2.3.1 +[2.3.0]: https://github.com/willmcgugan/rich/compare/v2.2.6...v2.3.0 +[2.2.6]: https://github.com/willmcgugan/rich/compare/v2.2.5...v2.2.6 +[2.2.5]: https://github.com/willmcgugan/rich/compare/v2.2.4...v2.2.5 +[2.2.4]: https://github.com/willmcgugan/rich/compare/v2.2.3...v2.2.4 +[2.2.3]: https://github.com/willmcgugan/rich/compare/v2.2.2...v2.2.3 +[2.2.2]: https://github.com/willmcgugan/rich/compare/v2.2.1...v2.2.2 +[2.2.1]: https://github.com/willmcgugan/rich/compare/v2.2.0...v2.2.1 +[2.2.0]: https://github.com/willmcgugan/rich/compare/v2.1.0...v2.2.0 +[2.1.0]: https://github.com/willmcgugan/rich/compare/v2.0.1...v2.1.0 +[2.0.1]: https://github.com/willmcgugan/rich/compare/v2.0.0...v2.0.1 +[2.0.0]: https://github.com/willmcgugan/rich/compare/v1.3.1...v2.0.0 +[1.3.1]: https://github.com/willmcgugan/rich/compare/v1.3.0...v1.3.1 +[1.3.0]: https://github.com/willmcgugan/rich/compare/v1.2.3...v1.3.0 +[1.2.3]: https://github.com/willmcgugan/rich/compare/v1.2.2...v1.2.3 +[1.2.2]: https://github.com/willmcgugan/rich/compare/v1.2.1...v1.2.2 +[1.2.1]: https://github.com/willmcgugan/rich/compare/v1.2.0...v1.2.1 +[1.2.0]: https://github.com/willmcgugan/rich/compare/v1.1.9...v1.2.0 +[1.1.9]: https://github.com/willmcgugan/rich/compare/v1.1.8...v1.1.9 +[1.1.8]: https://github.com/willmcgugan/rich/compare/v1.1.7...v1.1.8 +[1.1.7]: https://github.com/willmcgugan/rich/compare/v1.1.6...v1.1.7 +[1.1.6]: https://github.com/willmcgugan/rich/compare/v1.1.5...v1.1.6 +[1.1.5]: https://github.com/willmcgugan/rich/compare/v1.1.4...v1.1.5 +[1.1.4]: https://github.com/willmcgugan/rich/compare/v1.1.3...v1.1.4 +[1.1.3]: https://github.com/willmcgugan/rich/compare/v1.1.2...v1.1.3 +[1.1.2]: https://github.com/willmcgugan/rich/compare/v1.1.1...v1.1.2 +[1.1.1]: https://github.com/willmcgugan/rich/compare/v1.1.0...v1.1.1 +[1.1.0]: https://github.com/willmcgugan/rich/compare/v1.0.3...v1.1.0 +[1.0.3]: https://github.com/willmcgugan/rich/compare/v1.0.2...v1.0.3 +[1.0.2]: https://github.com/willmcgugan/rich/compare/v1.0.1...v1.0.2 +[1.0.1]: https://github.com/willmcgugan/rich/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/willmcgugan/rich/compare/v0.8.13...v1.0.0 +[0.8.13]: https://github.com/willmcgugan/rich/compare/v0.8.12...v0.8.13 +[0.8.12]: https://github.com/willmcgugan/rich/compare/v0.8.11...v0.8.12 +[0.8.11]: https://github.com/willmcgugan/rich/compare/v0.8.10...v0.8.11 +[0.8.10]: https://github.com/willmcgugan/rich/compare/v0.8.9...v0.8.10 +[0.8.9]: https://github.com/willmcgugan/rich/compare/v0.8.8...v0.8.9 +[0.8.8]: https://github.com/willmcgugan/rich/compare/v0.8.7...v0.8.8 +[0.8.7]: https://github.com/willmcgugan/rich/compare/v0.8.6...v0.8.7 +[0.8.6]: https://github.com/willmcgugan/rich/compare/v0.8.5...v0.8.6 +[0.8.5]: https://github.com/willmcgugan/rich/compare/v0.8.4...v0.8.5 +[0.8.4]: https://github.com/willmcgugan/rich/compare/v0.8.3...v0.8.4 +[0.8.3]: https://github.com/willmcgugan/rich/compare/v0.8.2...v0.8.3 +[0.8.2]: https://github.com/willmcgugan/rich/compare/v0.8.1...v0.8.2 +[0.8.1]: https://github.com/willmcgugan/rich/compare/v0.8.0...v0.8.1 +[0.8.0]: https://github.com/willmcgugan/rich/compare/v0.7.2...v0.8.0 +[0.7.2]: https://github.com/willmcgugan/rich/compare/v0.7.1...v0.7.2 +[0.7.1]: https://github.com/willmcgugan/rich/compare/v0.7.0...v0.7.1 +[0.7.0]: https://github.com/willmcgugan/rich/compare/v0.6.0...v0.7.0 +[0.6.0]: https://github.com/willmcgugan/rich/compare/v0.5.0...v0.6.0 +[0.5.0]: https://github.com/willmcgugan/rich/compare/v0.4.1...v0.5.0 +[0.4.1]: https://github.com/willmcgugan/rich/compare/v0.4.0...v0.4.1 +[0.4.0]: https://github.com/willmcgugan/rich/compare/v0.3.3...v0.4.0 +[0.3.3]: https://github.com/willmcgugan/rich/compare/v0.3.2...v0.3.3 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e30a331fd..3e809c609 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -7,6 +7,7 @@ The following people have contributed to the development of Rich: - [Patrick Arminio](https://github.com/patrick91) - [Gregory Beauregard](https://github.com/GBeauregard/pyffstream) - [Darren Burns](https://github.com/darrenburns) +- [Ed Davis](https://github.com/davised) - [Pete Davison](https://github.com/pd93) - [James Estevez](https://github.com/jstvz) - [Oleksis Fraga](https://github.com/oleksis) @@ -28,7 +29,9 @@ The following people have contributed to the development of Rich: - [Tushar Sadhwani](https://github.com/tusharsadhwani) - [Tim Savage](https://github.com/timsavage) - [Nicolas Simonds](https://github.com/0xDEC0DE) +- [Aaron Stephens](https://github.com/aaronst) - [Gabriele N. Tornetta](https://github.com/p403n1x87) - [Dennis Brakhane](https://github.com/brakhane) - [Michał Górny](https://github.com/mgorny) - [Arian Mollik Wasi](https://github.com/wasi-master) +- [Brian Rutledge](https://github.com/bhrutledge) diff --git a/docs/source/highlighting.rst b/docs/source/highlighting.rst index 03993190c..34274d977 100644 --- a/docs/source/highlighting.rst +++ b/docs/source/highlighting.rst @@ -1,3 +1,5 @@ +.. _highlighting: + Highlighting ============ diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 57d19154b..3576c6ac8 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -1,7 +1,7 @@ Introduction ============ -Rich is a Python library for writing *rich* text (with color and style) to the terminal, and for displaying advanced content such as tables, markdown, and syntax highlighted code. +Rich is a Python library for writing *rich* text (with color and style) to the terminal, and for displaying advanced content such as tables, markdown, and syntax highlighted code. Use Rich to make your command line applications visually appealing and present data in a more readable way. Rich can also be a useful debugging aid by pretty printing and syntax highlighting data structures. @@ -38,7 +38,7 @@ The quickest way to get up and running with Rich is to import the alternative `` from rich import print -You can then print strings or objects to the terminal in the usual way. Rich will do some basic syntax highlighting and format data structures to make them easier to read. +You can then print strings or objects to the terminal in the usual way. Rich will do some basic syntax :ref:`highlighting` and format data structures to make them easier to read. Strings may contain :ref:`console_markup` which can be used to insert color and styles in to the output. @@ -50,7 +50,7 @@ This writes the following output to the terminal (including all the colors and s .. raw:: html -
Hello World!                                                 
+    
Hello World!
     {
         '__annotations__': {},
         '__builtins__': <module 'builtins' (built-in)>,
@@ -75,7 +75,7 @@ Rich in the REPL
 Rich may be installed in the REPL so that Python data structures are automatically pretty printed with syntax highlighting. Here's how::
 
     >>> from rich import pretty
-    >>> pretty.install() 
+    >>> pretty.install()
     >>> ["Rich and pretty", True]
 
 You can also use this feature to try out Rich *renderables*. Here's an example::
@@ -91,8 +91,8 @@ IPython Extension
 Rich also includes an IPython extension that will do this same pretty install + pretty tracebacks. Here's how to load it::
 
     In [1]: %load_ext rich
-    
-You can also have it load by default by adding `"rich"` to the ``c.InteractiveShellApp.extension`` variable in 
+
+You can also have it load by default by adding `"rich"` to the ``c.InteractiveShellApp.extension`` variable in
 `IPython Configuration `_.
 
 Rich Inspect
diff --git a/imgs/downloader.gif b/imgs/downloader.gif
index 2033d7b98..dad59f258 100644
Binary files a/imgs/downloader.gif and b/imgs/downloader.gif differ
diff --git a/imgs/logo.svg b/imgs/logo.svg
index 34c2a11ea..4842c4a8e 100644
--- a/imgs/logo.svg
+++ b/imgs/logo.svg
@@ -1,69 +1 @@
-
-
-  
-    
-      
-      
-    
-    
-      
-      
-      
-      
-        
-        
-      
-    
-  
-  
-    
-    
-    
-    
-    
-    
-    
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-    
-  
-  
-    
-      
-      
-      
-      
-      
-    
-  
-  
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/imgs/progress.gif b/imgs/progress.gif
index e145478fa..b4ccfa2f4 100644
Binary files a/imgs/progress.gif and b/imgs/progress.gif differ
diff --git a/imgs/spinners.gif b/imgs/spinners.gif
index b98685c20..7d3445e10 100644
Binary files a/imgs/spinners.gif and b/imgs/spinners.gif differ
diff --git a/imgs/status.gif b/imgs/status.gif
index ccb7ceb8e..c930fc76e 100644
Binary files a/imgs/status.gif and b/imgs/status.gif differ
diff --git a/imgs/traceback.png b/imgs/traceback.png
index 55b2e79a0..07a4a5007 100644
Binary files a/imgs/traceback.png and b/imgs/traceback.png differ
diff --git a/poetry.lock b/poetry.lock
index afa58c32f..e3f64e3c6 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -135,7 +135,7 @@ python-versions = ">=3.6.1"
 
 [[package]]
 name = "click"
-version = "8.0.3"
+version = "8.0.4"
 description = "Composable command line interface toolkit"
 category = "dev"
 optional = false
@@ -429,7 +429,7 @@ test = ["codecov", "coverage", "ipykernel", "ipython", "mock", "mypy", "pre-comm
 
 [[package]]
 name = "jupyter-core"
-version = "4.9.1"
+version = "4.9.2"
 description = "Jupyter core package. A base package on which Jupyter projects rely."
 category = "main"
 optional = true
@@ -476,7 +476,7 @@ python-versions = "*"
 
 [[package]]
 name = "mypy"
-version = "0.930"
+version = "0.931"
 description = "Optional static typing for Python"
 category = "dev"
 optional = false
@@ -924,14 +924,14 @@ test = ["pytest"]
 
 [[package]]
 name = "testpath"
-version = "0.5.0"
+version = "0.6.0"
 description = "Test utilities for code working with files and commands"
 category = "main"
 optional = true
 python-versions = ">= 3.5"
 
 [package.extras]
-test = ["pytest", "pathlib2"]
+test = ["pytest"]
 
 [[package]]
 name = "toml"
@@ -999,7 +999,7 @@ python-versions = ">=3.6"
 
 [[package]]
 name = "virtualenv"
-version = "20.13.1"
+version = "20.13.2"
 description = "Virtual Python Environment builder"
 category = "dev"
 optional = false
@@ -1062,7 +1062,7 @@ jupyter = ["ipywidgets"]
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.6.2"
-content-hash = "bd4a37ddd750fbf742ea1a5e7427cb2c94298e48168b518bf078ce00b1a588db"
+content-hash = "037fa9d7b0d26a13fb1fe08220d8b1afd33508e5d30111335bcfcc2958a04477"
 
 [metadata.files]
 appnope = [
@@ -1198,8 +1198,8 @@ cfgv = [
     {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
 ]
 click = [
-    {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
-    {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"},
+    {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"},
+    {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"},
 ]
 colorama = [
     {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
@@ -1331,8 +1331,8 @@ jupyter-client = [
     {file = "jupyter_client-7.1.2.tar.gz", hash = "sha256:4ea61033726c8e579edb55626d8ee2e6bf0a83158ddf3751b8dd46b2c5cd1e96"},
 ]
 jupyter-core = [
-    {file = "jupyter_core-4.9.1-py3-none-any.whl", hash = "sha256:1c091f3bbefd6f2a8782f2c1db662ca8478ac240e962ae2c66f0b87c818154ea"},
-    {file = "jupyter_core-4.9.1.tar.gz", hash = "sha256:dce8a7499da5a53ae3afd5a9f4b02e5df1d57250cf48f3ad79da23b4778cd6fa"},
+    {file = "jupyter_core-4.9.2-py3-none-any.whl", hash = "sha256:f875e4d27e202590311d468fa55f90c575f201490bd0c18acabe4e318db4a46d"},
+    {file = "jupyter_core-4.9.2.tar.gz", hash = "sha256:d69baeb9ffb128b8cd2657fcf2703f89c769d1673c851812119e3a2a0e93ad9a"},
 ]
 jupyterlab-pygments = [
     {file = "jupyterlab_pygments-0.1.2-py2.py3-none-any.whl", hash = "sha256:abfb880fd1561987efaefcb2d2ac75145d2a5d0139b1876d5be806e32f630008"},
@@ -1418,26 +1418,26 @@ mistune = [
     {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"},
 ]
 mypy = [
-    {file = "mypy-0.930-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:221cc94dc6a801ccc2be7c0c9fd791c5e08d1fa2c5e1c12dec4eab15b2469871"},
-    {file = "mypy-0.930-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db3a87376a1380f396d465bed462e76ea89f838f4c5e967d68ff6ee34b785c31"},
-    {file = "mypy-0.930-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1d2296f35aae9802eeb1327058b550371ee382d71374b3e7d2804035ef0b830b"},
-    {file = "mypy-0.930-cp310-cp310-win_amd64.whl", hash = "sha256:959319b9a3cafc33a8185f440a433ba520239c72e733bf91f9efd67b0a8e9b30"},
-    {file = "mypy-0.930-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:45a4dc21c789cfd09b8ccafe114d6de66f0b341ad761338de717192f19397a8c"},
-    {file = "mypy-0.930-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1e689e92cdebd87607a041585f1dc7339aa2e8a9f9bad9ba7e6ece619431b20c"},
-    {file = "mypy-0.930-cp36-cp36m-win_amd64.whl", hash = "sha256:ed4e0ea066bb12f56b2812a15ff223c57c0a44eca817ceb96b214bb055c7051f"},
-    {file = "mypy-0.930-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a9d8dffefba634b27d650e0de2564379a1a367e2e08d6617d8f89261a3bf63b2"},
-    {file = "mypy-0.930-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b419e9721260161e70d054a15abbd50603c16f159860cfd0daeab647d828fc29"},
-    {file = "mypy-0.930-cp37-cp37m-win_amd64.whl", hash = "sha256:601f46593f627f8a9b944f74fd387c9b5f4266b39abad77471947069c2fc7651"},
-    {file = "mypy-0.930-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ea7199780c1d7940b82dbc0a4e37722b4e3851264dbba81e01abecc9052d8a7"},
-    {file = "mypy-0.930-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:70b197dd8c78fc5d2daf84bd093e8466a2b2e007eedaa85e792e513a820adbf7"},
-    {file = "mypy-0.930-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5feb56f8bb280468fe5fc8e6f56f48f99aa0df9eed3c507a11505ee4657b5380"},
-    {file = "mypy-0.930-cp38-cp38-win_amd64.whl", hash = "sha256:2e9c5409e9cb81049bb03fa1009b573dea87976713e3898561567a86c4eaee01"},
-    {file = "mypy-0.930-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:554873e45c1ca20f31ddf873deb67fa5d2e87b76b97db50669f0468ccded8fae"},
-    {file = "mypy-0.930-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0feb82e9fa849affca7edd24713dbe809dce780ced9f3feca5ed3d80e40b777f"},
-    {file = "mypy-0.930-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bc1a0607ea03c30225347334af66b0af12eefba018a89a88c209e02b7065ea95"},
-    {file = "mypy-0.930-cp39-cp39-win_amd64.whl", hash = "sha256:f9f665d69034b1fcfdbcd4197480d26298bbfb5d2dfe206245b6498addb34999"},
-    {file = "mypy-0.930-py3-none-any.whl", hash = "sha256:bf4a44e03040206f7c058d1f5ba02ef2d1820720c88bc4285c7d9a4269f54173"},
-    {file = "mypy-0.930.tar.gz", hash = "sha256:51426262ae4714cc7dd5439814676e0992b55bcc0f6514eccb4cf8e0678962c2"},
+    {file = "mypy-0.931-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a"},
+    {file = "mypy-0.931-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00"},
+    {file = "mypy-0.931-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:300717a07ad09525401a508ef5d105e6b56646f7942eb92715a1c8d610149714"},
+    {file = "mypy-0.931-cp310-cp310-win_amd64.whl", hash = "sha256:7b3f6f557ba4afc7f2ce6d3215d5db279bcf120b3cfd0add20a5d4f4abdae5bc"},
+    {file = "mypy-0.931-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1bf752559797c897cdd2c65f7b60c2b6969ffe458417b8d947b8340cc9cec08d"},
+    {file = "mypy-0.931-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4365c60266b95a3f216a3047f1d8e3f895da6c7402e9e1ddfab96393122cc58d"},
+    {file = "mypy-0.931-cp36-cp36m-win_amd64.whl", hash = "sha256:1b65714dc296a7991000b6ee59a35b3f550e0073411ac9d3202f6516621ba66c"},
+    {file = "mypy-0.931-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e839191b8da5b4e5d805f940537efcaa13ea5dd98418f06dc585d2891d228cf0"},
+    {file = "mypy-0.931-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:50c7346a46dc76a4ed88f3277d4959de8a2bd0a0fa47fa87a4cde36fe247ac05"},
+    {file = "mypy-0.931-cp37-cp37m-win_amd64.whl", hash = "sha256:d8f1ff62f7a879c9fe5917b3f9eb93a79b78aad47b533911b853a757223f72e7"},
+    {file = "mypy-0.931-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9fe20d0872b26c4bba1c1be02c5340de1019530302cf2dcc85c7f9fc3252ae0"},
+    {file = "mypy-0.931-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1b06268df7eb53a8feea99cbfff77a6e2b205e70bf31743e786678ef87ee8069"},
+    {file = "mypy-0.931-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8c11003aaeaf7cc2d0f1bc101c1cc9454ec4cc9cb825aef3cafff8a5fdf4c799"},
+    {file = "mypy-0.931-cp38-cp38-win_amd64.whl", hash = "sha256:d9d2b84b2007cea426e327d2483238f040c49405a6bf4074f605f0156c91a47a"},
+    {file = "mypy-0.931-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ff3bf387c14c805ab1388185dd22d6b210824e164d4bb324b195ff34e322d166"},
+    {file = "mypy-0.931-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b56154f8c09427bae082b32275a21f500b24d93c88d69a5e82f3978018a0266"},
+    {file = "mypy-0.931-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ca7f8c4b1584d63c9a0f827c37ba7a47226c19a23a753d52e5b5eddb201afcd"},
+    {file = "mypy-0.931-cp39-cp39-win_amd64.whl", hash = "sha256:74f7eccbfd436abe9c352ad9fb65872cc0f1f0a868e9d9c44db0893440f0c697"},
+    {file = "mypy-0.931-py3-none-any.whl", hash = "sha256:1171f2e0859cfff2d366da2c7092b06130f232c636a3f7301e3feb8b41f6377d"},
+    {file = "mypy-0.931.tar.gz", hash = "sha256:0038b21890867793581e4cb0d810829f5fd4441aa75796b53033af3aa30430ce"},
 ]
 mypy-extensions = [
     {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
@@ -1688,8 +1688,8 @@ terminado = [
     {file = "terminado-0.13.0.tar.gz", hash = "sha256:713531ccb5db7d4f544651f14050da79809030f00d1afa21462088cf32fb143a"},
 ]
 testpath = [
-    {file = "testpath-0.5.0-py3-none-any.whl", hash = "sha256:8044f9a0bab6567fc644a3593164e872543bb44225b0e24846e2c89237937589"},
-    {file = "testpath-0.5.0.tar.gz", hash = "sha256:1acf7a0bcd3004ae8357409fc33751e16d37ccc650921da1094a86581ad1e417"},
+    {file = "testpath-0.6.0-py3-none-any.whl", hash = "sha256:8ada9f80a2ac6fb0391aa7cdb1a7d11cfa8429f693eda83f74dde570fe6fa639"},
+    {file = "testpath-0.6.0.tar.gz", hash = "sha256:2f1b97e6442c02681ebe01bd84f531028a7caea1af3825000f52345c30285e0f"},
 ]
 toml = [
     {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
@@ -1781,8 +1781,8 @@ typing-extensions = [
     {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
 ]
 virtualenv = [
-    {file = "virtualenv-20.13.1-py2.py3-none-any.whl", hash = "sha256:45e1d053cad4cd453181ae877c4ffc053546ae99e7dd049b9ff1d9be7491abf7"},
-    {file = "virtualenv-20.13.1.tar.gz", hash = "sha256:e0621bcbf4160e4e1030f05065c8834b4e93f4fcc223255db2a823440aca9c14"},
+    {file = "virtualenv-20.13.2-py2.py3-none-any.whl", hash = "sha256:e7b34c9474e6476ee208c43a4d9ac1510b041c68347eabfe9a9ea0c86aa0a46b"},
+    {file = "virtualenv-20.13.2.tar.gz", hash = "sha256:01f5f80744d24a3743ce61858123488e91cb2dd1d3bdf92adaf1bba39ffdedf0"},
 ]
 wcwidth = [
     {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
diff --git a/pyproject.toml b/pyproject.toml
index 4faf29818..feee94c8c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -41,7 +41,7 @@ jupyter = ["ipywidgets"]
 [tool.poetry.dev-dependencies]
 pytest = "^7.0.0"
 black = "^22.1"
-mypy = "^0.930"
+mypy = "^0.931"
 pytest-cov = "^3.0.0"
 attrs = "^21.4.0"
 types-dataclasses = "^0.6.4"
diff --git a/rich/_spinners.py b/rich/_spinners.py
index dc1db0777..d0bb1fe75 100644
--- a/rich/_spinners.py
+++ b/rich/_spinners.py
@@ -22,149 +22,36 @@
 SPINNERS = {
     "dots": {
         "interval": 80,
-        "frames": ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
+        "frames": "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏",
     },
-    "dots2": {"interval": 80, "frames": ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"]},
+    "dots2": {"interval": 80, "frames": "⣾⣽⣻⢿⡿⣟⣯⣷"},
     "dots3": {
         "interval": 80,
-        "frames": ["⠋", "⠙", "⠚", "⠞", "⠖", "⠦", "⠴", "⠲", "⠳", "⠓"],
+        "frames": "⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓",
     },
     "dots4": {
         "interval": 80,
-        "frames": [
-            "⠄",
-            "⠆",
-            "⠇",
-            "⠋",
-            "⠙",
-            "⠸",
-            "⠰",
-            "⠠",
-            "⠰",
-            "⠸",
-            "⠙",
-            "⠋",
-            "⠇",
-            "⠆",
-        ],
+        "frames": "⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆",
     },
     "dots5": {
         "interval": 80,
-        "frames": [
-            "⠋",
-            "⠙",
-            "⠚",
-            "⠒",
-            "⠂",
-            "⠂",
-            "⠒",
-            "⠲",
-            "⠴",
-            "⠦",
-            "⠖",
-            "⠒",
-            "⠐",
-            "⠐",
-            "⠒",
-            "⠓",
-            "⠋",
-        ],
+        "frames": "⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋",
     },
     "dots6": {
         "interval": 80,
-        "frames": [
-            "⠁",
-            "⠉",
-            "⠙",
-            "⠚",
-            "⠒",
-            "⠂",
-            "⠂",
-            "⠒",
-            "⠲",
-            "⠴",
-            "⠤",
-            "⠄",
-            "⠄",
-            "⠤",
-            "⠴",
-            "⠲",
-            "⠒",
-            "⠂",
-            "⠂",
-            "⠒",
-            "⠚",
-            "⠙",
-            "⠉",
-            "⠁",
-        ],
+        "frames": "⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉⠁",
     },
     "dots7": {
         "interval": 80,
-        "frames": [
-            "⠈",
-            "⠉",
-            "⠋",
-            "⠓",
-            "⠒",
-            "⠐",
-            "⠐",
-            "⠒",
-            "⠖",
-            "⠦",
-            "⠤",
-            "⠠",
-            "⠠",
-            "⠤",
-            "⠦",
-            "⠖",
-            "⠒",
-            "⠐",
-            "⠐",
-            "⠒",
-            "⠓",
-            "⠋",
-            "⠉",
-            "⠈",
-        ],
+        "frames": "⠈⠉⠋⠓⠒⠐⠐⠒⠖⠦⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈",
     },
     "dots8": {
         "interval": 80,
-        "frames": [
-            "⠁",
-            "⠁",
-            "⠉",
-            "⠙",
-            "⠚",
-            "⠒",
-            "⠂",
-            "⠂",
-            "⠒",
-            "⠲",
-            "⠴",
-            "⠤",
-            "⠄",
-            "⠄",
-            "⠤",
-            "⠠",
-            "⠠",
-            "⠤",
-            "⠦",
-            "⠖",
-            "⠒",
-            "⠐",
-            "⠐",
-            "⠒",
-            "⠓",
-            "⠋",
-            "⠉",
-            "⠈",
-            "⠈",
-        ],
+        "frames": "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈",
     },
-    "dots9": {"interval": 80, "frames": ["⢹", "⢺", "⢼", "⣸", "⣇", "⡧", "⡗", "⡏"]},
-    "dots10": {"interval": 80, "frames": ["⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"]},
-    "dots11": {"interval": 100, "frames": ["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"]},
+    "dots9": {"interval": 80, "frames": "⢹⢺⢼⣸⣇⡧⡗⡏"},
+    "dots10": {"interval": 80, "frames": "⢄⢂⢁⡁⡈⡐⡠"},
+    "dots11": {"interval": 100, "frames": "⠁⠂⠄⡀⢀⠠⠐⠈"},
     "dots12": {
         "interval": 80,
         "frames": [
@@ -228,315 +115,62 @@
     },
     "dots8Bit": {
         "interval": 80,
-        "frames": [
-            "⠀",
-            "⠁",
-            "⠂",
-            "⠃",
-            "⠄",
-            "⠅",
-            "⠆",
-            "⠇",
-            "⡀",
-            "⡁",
-            "⡂",
-            "⡃",
-            "⡄",
-            "⡅",
-            "⡆",
-            "⡇",
-            "⠈",
-            "⠉",
-            "⠊",
-            "⠋",
-            "⠌",
-            "⠍",
-            "⠎",
-            "⠏",
-            "⡈",
-            "⡉",
-            "⡊",
-            "⡋",
-            "⡌",
-            "⡍",
-            "⡎",
-            "⡏",
-            "⠐",
-            "⠑",
-            "⠒",
-            "⠓",
-            "⠔",
-            "⠕",
-            "⠖",
-            "⠗",
-            "⡐",
-            "⡑",
-            "⡒",
-            "⡓",
-            "⡔",
-            "⡕",
-            "⡖",
-            "⡗",
-            "⠘",
-            "⠙",
-            "⠚",
-            "⠛",
-            "⠜",
-            "⠝",
-            "⠞",
-            "⠟",
-            "⡘",
-            "⡙",
-            "⡚",
-            "⡛",
-            "⡜",
-            "⡝",
-            "⡞",
-            "⡟",
-            "⠠",
-            "⠡",
-            "⠢",
-            "⠣",
-            "⠤",
-            "⠥",
-            "⠦",
-            "⠧",
-            "⡠",
-            "⡡",
-            "⡢",
-            "⡣",
-            "⡤",
-            "⡥",
-            "⡦",
-            "⡧",
-            "⠨",
-            "⠩",
-            "⠪",
-            "⠫",
-            "⠬",
-            "⠭",
-            "⠮",
-            "⠯",
-            "⡨",
-            "⡩",
-            "⡪",
-            "⡫",
-            "⡬",
-            "⡭",
-            "⡮",
-            "⡯",
-            "⠰",
-            "⠱",
-            "⠲",
-            "⠳",
-            "⠴",
-            "⠵",
-            "⠶",
-            "⠷",
-            "⡰",
-            "⡱",
-            "⡲",
-            "⡳",
-            "⡴",
-            "⡵",
-            "⡶",
-            "⡷",
-            "⠸",
-            "⠹",
-            "⠺",
-            "⠻",
-            "⠼",
-            "⠽",
-            "⠾",
-            "⠿",
-            "⡸",
-            "⡹",
-            "⡺",
-            "⡻",
-            "⡼",
-            "⡽",
-            "⡾",
-            "⡿",
-            "⢀",
-            "⢁",
-            "⢂",
-            "⢃",
-            "⢄",
-            "⢅",
-            "⢆",
-            "⢇",
-            "⣀",
-            "⣁",
-            "⣂",
-            "⣃",
-            "⣄",
-            "⣅",
-            "⣆",
-            "⣇",
-            "⢈",
-            "⢉",
-            "⢊",
-            "⢋",
-            "⢌",
-            "⢍",
-            "⢎",
-            "⢏",
-            "⣈",
-            "⣉",
-            "⣊",
-            "⣋",
-            "⣌",
-            "⣍",
-            "⣎",
-            "⣏",
-            "⢐",
-            "⢑",
-            "⢒",
-            "⢓",
-            "⢔",
-            "⢕",
-            "⢖",
-            "⢗",
-            "⣐",
-            "⣑",
-            "⣒",
-            "⣓",
-            "⣔",
-            "⣕",
-            "⣖",
-            "⣗",
-            "⢘",
-            "⢙",
-            "⢚",
-            "⢛",
-            "⢜",
-            "⢝",
-            "⢞",
-            "⢟",
-            "⣘",
-            "⣙",
-            "⣚",
-            "⣛",
-            "⣜",
-            "⣝",
-            "⣞",
-            "⣟",
-            "⢠",
-            "⢡",
-            "⢢",
-            "⢣",
-            "⢤",
-            "⢥",
-            "⢦",
-            "⢧",
-            "⣠",
-            "⣡",
-            "⣢",
-            "⣣",
-            "⣤",
-            "⣥",
-            "⣦",
-            "⣧",
-            "⢨",
-            "⢩",
-            "⢪",
-            "⢫",
-            "⢬",
-            "⢭",
-            "⢮",
-            "⢯",
-            "⣨",
-            "⣩",
-            "⣪",
-            "⣫",
-            "⣬",
-            "⣭",
-            "⣮",
-            "⣯",
-            "⢰",
-            "⢱",
-            "⢲",
-            "⢳",
-            "⢴",
-            "⢵",
-            "⢶",
-            "⢷",
-            "⣰",
-            "⣱",
-            "⣲",
-            "⣳",
-            "⣴",
-            "⣵",
-            "⣶",
-            "⣷",
-            "⢸",
-            "⢹",
-            "⢺",
-            "⢻",
-            "⢼",
-            "⢽",
-            "⢾",
-            "⢿",
-            "⣸",
-            "⣹",
-            "⣺",
-            "⣻",
-            "⣼",
-            "⣽",
-            "⣾",
-            "⣿",
-        ],
+        "frames": "⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙"
+        "⡚⡛⡜⡝⡞⡟⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻"
+        "⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕"
+        "⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷"
+        "⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿",
     },
     "line": {"interval": 130, "frames": ["-", "\\", "|", "/"]},
-    "line2": {"interval": 100, "frames": ["⠂", "-", "–", "—", "–", "-"]},
-    "pipe": {"interval": 100, "frames": ["┤", "┘", "┴", "└", "├", "┌", "┬", "┐"]},
+    "line2": {"interval": 100, "frames": "⠂-–—–-"},
+    "pipe": {"interval": 100, "frames": "┤┘┴└├┌┬┐"},
     "simpleDots": {"interval": 400, "frames": [".  ", ".. ", "...", "   "]},
     "simpleDotsScrolling": {
         "interval": 200,
         "frames": [".  ", ".. ", "...", " ..", "  .", "   "],
     },
-    "star": {"interval": 70, "frames": ["✶", "✸", "✹", "✺", "✹", "✷"]},
-    "star2": {"interval": 80, "frames": ["+", "x", "*"]},
+    "star": {"interval": 70, "frames": "✶✸✹✺✹✷"},
+    "star2": {"interval": 80, "frames": "+x*"},
     "flip": {
         "interval": 70,
-        "frames": ["_", "_", "_", "-", "`", "`", "'", "´", "-", "_", "_", "_"],
+        "frames": "___-``'´-___",
     },
-    "hamburger": {"interval": 100, "frames": ["☱", "☲", "☴"]},
+    "hamburger": {"interval": 100, "frames": "☱☲☴"},
     "growVertical": {
         "interval": 120,
-        "frames": ["▁", "▃", "▄", "▅", "▆", "▇", "▆", "▅", "▄", "▃"],
+        "frames": "▁▃▄▅▆▇▆▅▄▃",
     },
     "growHorizontal": {
         "interval": 120,
-        "frames": ["▏", "▎", "▍", "▌", "▋", "▊", "▉", "▊", "▋", "▌", "▍", "▎"],
+        "frames": "▏▎▍▌▋▊▉▊▋▌▍▎",
     },
-    "balloon": {"interval": 140, "frames": [" ", ".", "o", "O", "@", "*", " "]},
-    "balloon2": {"interval": 120, "frames": [".", "o", "O", "°", "O", "o", "."]},
-    "noise": {"interval": 100, "frames": ["▓", "▒", "░"]},
-    "bounce": {"interval": 120, "frames": ["⠁", "⠂", "⠄", "⠂"]},
-    "boxBounce": {"interval": 120, "frames": ["▖", "▘", "▝", "▗"]},
-    "boxBounce2": {"interval": 100, "frames": ["▌", "▀", "▐", "▄"]},
-    "triangle": {"interval": 50, "frames": ["◢", "◣", "◤", "◥"]},
-    "arc": {"interval": 100, "frames": ["◜", "◠", "◝", "◞", "◡", "◟"]},
-    "circle": {"interval": 120, "frames": ["◡", "⊙", "◠"]},
-    "squareCorners": {"interval": 180, "frames": ["◰", "◳", "◲", "◱"]},
-    "circleQuarters": {"interval": 120, "frames": ["◴", "◷", "◶", "◵"]},
-    "circleHalves": {"interval": 50, "frames": ["◐", "◓", "◑", "◒"]},
-    "squish": {"interval": 100, "frames": ["╫", "╪"]},
-    "toggle": {"interval": 250, "frames": ["⊶", "⊷"]},
-    "toggle2": {"interval": 80, "frames": ["▫", "▪"]},
-    "toggle3": {"interval": 120, "frames": ["□", "■"]},
-    "toggle4": {"interval": 100, "frames": ["■", "□", "▪", "▫"]},
-    "toggle5": {"interval": 100, "frames": ["▮", "▯"]},
-    "toggle6": {"interval": 300, "frames": ["ဝ", "၀"]},
-    "toggle7": {"interval": 80, "frames": ["⦾", "⦿"]},
-    "toggle8": {"interval": 100, "frames": ["◍", "◌"]},
-    "toggle9": {"interval": 100, "frames": ["◉", "◎"]},
-    "toggle10": {"interval": 100, "frames": ["㊂", "㊀", "㊁"]},
-    "toggle11": {"interval": 50, "frames": ["⧇", "⧆"]},
-    "toggle12": {"interval": 120, "frames": ["☗", "☖"]},
-    "toggle13": {"interval": 80, "frames": ["=", "*", "-"]},
-    "arrow": {"interval": 100, "frames": ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"]},
+    "balloon": {"interval": 140, "frames": " .oO@* "},
+    "balloon2": {"interval": 120, "frames": ".oO°Oo."},
+    "noise": {"interval": 100, "frames": "▓▒░"},
+    "bounce": {"interval": 120, "frames": "⠁⠂⠄⠂"},
+    "boxBounce": {"interval": 120, "frames": "▖▘▝▗"},
+    "boxBounce2": {"interval": 100, "frames": "▌▀▐▄"},
+    "triangle": {"interval": 50, "frames": "◢◣◤◥"},
+    "arc": {"interval": 100, "frames": "◜◠◝◞◡◟"},
+    "circle": {"interval": 120, "frames": "◡⊙◠"},
+    "squareCorners": {"interval": 180, "frames": "◰◳◲◱"},
+    "circleQuarters": {"interval": 120, "frames": "◴◷◶◵"},
+    "circleHalves": {"interval": 50, "frames": "◐◓◑◒"},
+    "squish": {"interval": 100, "frames": "╫╪"},
+    "toggle": {"interval": 250, "frames": "⊶⊷"},
+    "toggle2": {"interval": 80, "frames": "▫▪"},
+    "toggle3": {"interval": 120, "frames": "□■"},
+    "toggle4": {"interval": 100, "frames": "■□▪▫"},
+    "toggle5": {"interval": 100, "frames": "▮▯"},
+    "toggle6": {"interval": 300, "frames": "ဝ၀"},
+    "toggle7": {"interval": 80, "frames": "⦾⦿"},
+    "toggle8": {"interval": 100, "frames": "◍◌"},
+    "toggle9": {"interval": 100, "frames": "◉◎"},
+    "toggle10": {"interval": 100, "frames": "㊂㊀㊁"},
+    "toggle11": {"interval": 50, "frames": "⧇⧆"},
+    "toggle12": {"interval": 120, "frames": "☗☖"},
+    "toggle13": {"interval": 80, "frames": "=*-"},
+    "arrow": {"interval": 100, "frames": "←↖↑↗→↘↓↙"},
     "arrow2": {
         "interval": 80,
         "frames": ["⬆️ ", "↗️ ", "➡️ ", "↘️ ", "⬇️ ", "↙️ ", "⬅️ ", "↖️ "],
@@ -769,7 +403,7 @@
             "▐/|____________▌",
         ],
     },
-    "dqpb": {"interval": 100, "frames": ["d", "q", "p", "b"]},
+    "dqpb": {"interval": 100, "frames": "dqpb"},
     "weather": {
         "interval": 100,
         "frames": [
@@ -798,7 +432,7 @@
             "☀️ ",
         ],
     },
-    "christmas": {"interval": 400, "frames": ["🌲", "🎄"]},
+    "christmas": {"interval": 400, "frames": "🌲🎄"},
     "grenade": {
         "interval": 80,
         "frames": [
@@ -819,7 +453,7 @@
         ],
     },
     "point": {"interval": 125, "frames": ["∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"]},
-    "layer": {"interval": 150, "frames": ["-", "=", "≡"]},
+    "layer": {"interval": 150, "frames": "-=≡"},
     "betaWave": {
         "interval": 80,
         "frames": [
diff --git a/rich/logging.py b/rich/logging.py
index 3da71e2dc..58188fd8a 100644
--- a/rich/logging.py
+++ b/rich/logging.py
@@ -43,6 +43,7 @@ class RichHandler(Handler):
             Defaults to 10.
         locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80.
         log_time_format (Union[str, TimeFormatterCallable], optional): If ``log_time`` is enabled, either string for strftime or callable that formats the time. Defaults to "[%x %X] ".
+        keywords (List[str], optional): List of words to highlight instead of ``RichHandler.KEYWORDS``.
     """
 
     KEYWORDS: ClassVar[Optional[List[str]]] = [
@@ -79,6 +80,7 @@ def __init__(
         locals_max_length: int = 10,
         locals_max_string: int = 80,
         log_time_format: Union[str, FormatTimeCallable] = "[%x %X]",
+        keywords: Optional[List[str]] = None,
     ) -> None:
         super().__init__(level=level)
         self.console = console or get_console()
@@ -102,6 +104,7 @@ def __init__(
         self.tracebacks_suppress = tracebacks_suppress
         self.locals_max_length = locals_max_length
         self.locals_max_string = locals_max_string
+        self.keywords = keywords
 
     def get_level_text(self, record: LogRecord) -> Text:
         """Get the level name from the record.
@@ -176,8 +179,12 @@ def render_message(self, record: LogRecord, message: str) -> "ConsoleRenderable"
         if highlighter:
             message_text = highlighter(message_text)
 
-        if self.KEYWORDS:
-            message_text.highlight_words(self.KEYWORDS, "logging.keyword")
+        if self.keywords is None:
+            self.keywords = self.KEYWORDS
+
+        if self.keywords:
+            message_text.highlight_words(self.keywords, "logging.keyword")
+
         return message_text
 
     def render(
diff --git a/rich/pretty.py b/rich/pretty.py
index f42434ef5..216075afd 100644
--- a/rich/pretty.py
+++ b/rich/pretty.py
@@ -323,6 +323,7 @@ def __rich_measure__(
             indent_size=self.indent_size,
             max_length=self.max_length,
             max_string=self.max_string,
+            expand_all=self.expand_all,
         )
         text_width = (
             max(cell_len(line) for line in pretty_str.splitlines()) if pretty_str else 0
diff --git a/rich/progress.py b/rich/progress.py
index bbbdf70ef..e4abbdb66 100644
--- a/rich/progress.py
+++ b/rich/progress.py
@@ -343,18 +343,48 @@ def render(self, task: "Task") -> Text:
 
 
 class TimeRemainingColumn(ProgressColumn):
-    """Renders estimated time remaining."""
+    """Renders estimated time remaining.
+
+    Args:
+        compact (bool, optional): Render MM:SS when time remaining is less than an hour. Defaults to False.
+        elapsed_when_finished (bool, optional): Render time elapsed when the task is finished. Defaults to False.
+    """
 
     # Only refresh twice a second to prevent jitter
     max_refresh = 0.5
 
+    def __init__(
+        self,
+        compact: bool = False,
+        elapsed_when_finished: bool = False,
+        table_column: Optional[Column] = None,
+    ):
+        self.compact = compact
+        self.elapsed_when_finished = elapsed_when_finished
+        super().__init__(table_column=table_column)
+
     def render(self, task: "Task") -> Text:
         """Show time remaining."""
-        remaining = task.time_remaining
-        if remaining is None:
-            return Text("-:--:--", style="progress.remaining")
-        remaining_delta = timedelta(seconds=int(remaining))
-        return Text(str(remaining_delta), style="progress.remaining")
+        if self.elapsed_when_finished and task.finished:
+            task_time = task.finished_time
+            style = "progress.elapsed"
+        else:
+            task_time = task.time_remaining
+            style = "progress.remaining"
+
+        if task_time is None:
+            return Text("--:--" if self.compact else "-:--:--", style=style)
+
+        # Based on https://github.com/tqdm/tqdm/blob/master/tqdm/std.py
+        minutes, seconds = divmod(int(task_time), 60)
+        hours, minutes = divmod(minutes, 60)
+
+        if self.compact and not hours:
+            formatted = f"{minutes:02d}:{seconds:02d}"
+        else:
+            formatted = f"{hours:d}:{minutes:02d}:{seconds:02d}"
+
+        return Text(formatted, style=style)
 
 
 class FileSizeColumn(ProgressColumn):
@@ -427,7 +457,9 @@ def render(self, task: "Task") -> Text:
             )
         else:
             unit, suffix = filesize.pick_unit_and_suffix(
-                total, ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], 1000
+                total,
+                ["bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
+                1000,
             )
         completed_ratio = completed / unit
         total_ratio = total / unit
diff --git a/rich/syntax.py b/rich/syntax.py
index 142f48f46..6a337e407 100644
--- a/rich/syntax.py
+++ b/rich/syntax.py
@@ -735,7 +735,7 @@ def __rich_console__(
     parser.add_argument(
         "-x",
         "--lexer",
-        default="default",
+        default=None,
         dest="lexer_name",
         help="Lexer name",
     )
diff --git a/rich/traceback.py b/rich/traceback.py
index 1d3b71ea3..bebf22f3e 100644
--- a/rich/traceback.py
+++ b/rich/traceback.py
@@ -390,9 +390,8 @@ def safe_str(_object: Any) -> str:
                 exc_type = cause.__class__
                 exc_value = cause
                 traceback = cause.__traceback__
-                if traceback:
-                    is_cause = True
-                    continue
+                is_cause = True
+                continue
 
             cause = exc_value.__context__
             if (
@@ -403,9 +402,8 @@ def safe_str(_object: Any) -> str:
                 exc_type = cause.__class__
                 exc_value = cause
                 traceback = cause.__traceback__
-                if traceback:
-                    is_cause = False
-                    continue
+                is_cause = False
+                continue
             # No cover, code is reached but coverage doesn't recognize it.
             break  # pragma: no cover
 
diff --git a/rich/tree.py b/rich/tree.py
index 66203e693..0beab7a9e 100644
--- a/rich/tree.py
+++ b/rich/tree.py
@@ -136,6 +136,7 @@ def make_guide(index: int, style: Style) -> Segment:
                     highlight=self.highlight,
                     height=None,
                 ),
+                pad=options.justify is not None,
             )
 
             if not (depth == 0 and self.hide_root):
@@ -214,9 +215,9 @@ def __rich_measure__(
 
     code = """\
 class Segment(NamedTuple):
-    text: str = ""    
-    style: Optional[Style] = None    
-    is_control: bool = False    
+    text: str = ""
+    style: Optional[Style] = None
+    is_control: bool = False
 """
     syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
 
@@ -224,7 +225,7 @@ class Segment(NamedTuple):
         """\
 ### example.md
 > Hello, World!
-> 
+>
 > Markdown _all_ the things
 """
     )
@@ -246,4 +247,5 @@ class Segment(NamedTuple):
     containers_node.add(Group("📄 [b magenta]Table", table))
 
     console = Console()
+
     console.print(root)
diff --git a/tests/test_layout.py b/tests/test_layout.py
index 61cc9b6b5..46f496b0c 100644
--- a/tests/test_layout.py
+++ b/tests/test_layout.py
@@ -1,4 +1,5 @@
 import sys
+
 import pytest
 
 from rich.console import Console
@@ -77,7 +78,7 @@ def test_tree():
         console.print(layout.tree, height=10)
     result = capture.get()
     print(repr(result))
-    expected = "⬍ Layout(name='root')                                       \n├── ⬍ Layout(size=2)                                        \n└── ⬌ Layout(name='bar')                                    \n    ├── ⬍ Layout()                                          \n    └── ⬍ Layout()                                          \n"
+    expected = "⬍ Layout(name='root')\n├── ⬍ Layout(size=2)\n└── ⬌ Layout(name='bar')\n    ├── ⬍ Layout()\n    └── ⬍ Layout()\n"
     print(result, "\n", expected)
     assert result == expected
 
diff --git a/tests/test_pretty.py b/tests/test_pretty.py
index 871f1397c..02488f464 100644
--- a/tests/test_pretty.py
+++ b/tests/test_pretty.py
@@ -1,15 +1,16 @@
 import io
 import sys
 from array import array
-from collections import defaultdict, UserDict
+from collections import UserDict, defaultdict
+from dataclasses import dataclass, field
 from typing import List
 
 import attr
 import pytest
-from dataclasses import dataclass, field
 
 from rich.console import Console
-from rich.pretty import install, Pretty, pprint, pretty_repr, Node, _ipy_display_hook
+from rich.measure import Measurement
+from rich.pretty import Node, Pretty, _ipy_display_hook, install, pprint, pretty_repr
 from rich.text import Text
 
 skip_py36 = pytest.mark.skipif(
@@ -464,3 +465,13 @@ def __getattr__(self, attr):
     foo = Foo()
     result = pretty_repr(foo)
     assert "Foo" in result
+
+
+def test_measure_pretty():
+    """Test measure respects expand_all"""
+    # https://github.com/Textualize/rich/issues/1998
+    console = Console()
+    pretty = Pretty(["alpha", "beta", "delta", "gamma"], expand_all=True)
+
+    measurement = console.measure(pretty)
+    assert measurement == Measurement(12, 12)
diff --git a/tests/test_progress.py b/tests/test_progress.py
index 2dd53ccd2..db2e825d3 100644
--- a/tests/test_progress.py
+++ b/tests/test_progress.py
@@ -2,6 +2,7 @@
 
 import io
 from time import sleep
+from types import SimpleNamespace
 
 import pytest
 
@@ -89,6 +90,33 @@ class FakeTask(Task):
     assert str(text) == "0:01:00"
 
 
+@pytest.mark.parametrize(
+    "task_time, formatted",
+    [
+        (None, "--:--"),
+        (0, "00:00"),
+        (59, "00:59"),
+        (71, "01:11"),
+        (4210, "1:10:10"),
+    ],
+)
+def test_compact_time_remaining_column(task_time, formatted):
+    task = SimpleNamespace(finished=False, time_remaining=task_time)
+    column = TimeRemainingColumn(compact=True)
+
+    assert str(column.render(task)) == formatted
+
+
+def test_time_remaining_column_elapsed_when_finished():
+    task_time = 71
+    formatted = "0:01:11"
+
+    task = SimpleNamespace(finished=True, finished_time=task_time)
+    column = TimeRemainingColumn(elapsed_when_finished=True)
+
+    assert str(column.render(task)) == formatted
+
+
 def test_renderable_column():
     column = RenderableColumn("foo")
     task = Task(1, "test", 100, 20, _get_time=lambda: 1.0)
@@ -123,7 +151,7 @@ def test_download_progress_uses_decimal_units() -> None:
     column = DownloadColumn()
     test_task = Task(1, "test", 1000, 500, _get_time=lambda: 1.0)
     rendered_progress = str(column.render(test_task))
-    expected = "0.5/1.0 KB"
+    expected = "0.5/1.0 kB"
     assert rendered_progress == expected
 
 
diff --git a/tests/test_tree.py b/tests/test_tree.py
index f5510aa53..c8465a97a 100644
--- a/tests/test_tree.py
+++ b/tests/test_tree.py
@@ -12,7 +12,7 @@ def test_render_single_node():
     console = Console(color_system=None, width=20)
     console.begin_capture()
     console.print(tree)
-    assert console.end_capture() == "foo                 \n"
+    assert console.end_capture() == "foo\n"
 
 
 def test_render_single_branch():
@@ -23,7 +23,7 @@ def test_render_single_branch():
     console.print(tree)
     result = console.end_capture()
     print(repr(result))
-    expected = "foo                 \n└── bar             \n"
+    expected = "foo\n└── bar\n"
     assert result == expected
 
 
@@ -36,7 +36,7 @@ def test_render_double_branch():
     console.print(tree)
     result = console.end_capture()
     print(repr(result))
-    expected = "foo                 \n├── bar             \n└── baz             \n"
+    expected = "foo\n├── bar\n└── baz\n"
     assert result == expected
 
 
@@ -54,7 +54,7 @@ def encoding(self):
     console.begin_capture()
     console.print(tree)
     result = console.end_capture()
-    expected = "foo                 \n+-- bar             \n`-- baz             \n"
+    expected = "foo\n+-- bar\n`-- baz\n"
     assert result == expected
 
 
@@ -74,7 +74,7 @@ def test_render_tree_non_win32():
     console.print(tree)
     result = console.end_capture()
     print(repr(result))
-    expected = "foo                 \n├── \x1b[3mbar\x1b[0m\x1b[3m             \x1b[0m\n\x1b[44m├── \x1b[0m\x1b[44mbaz\x1b[0m\x1b[44m             \x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m┣━━ \x1b[0m\x1b[44m1\x1b[0m\x1b[44m           \x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m┗━━ \x1b[0m\x1b[44m2\x1b[0m\x1b[44m           \x1b[0m\n└── egg             \n"
+    expected = "foo\n├── \x1b[3mbar\x1b[0m\n\x1b[44m├── \x1b[0m\x1b[44mbaz\x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m┣━━ \x1b[0m\x1b[44m1\x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m┗━━ \x1b[0m\x1b[44m2\x1b[0m\n└── egg\n"
     assert result == expected
 
 
@@ -87,12 +87,14 @@ def test_render_tree_win32():
     baz_tree.add("2")
     tree.add("egg")
 
-    console = Console(width=20, force_terminal=True, color_system="standard")
+    console = Console(
+        width=20, force_terminal=True, color_system="standard", legacy_windows=True
+    )
     console.begin_capture()
     console.print(tree)
     result = console.end_capture()
     print(repr(result))
-    expected = "foo                 \n├── \x1b[3mbar\x1b[0m\x1b[3m             \x1b[0m\n\x1b[44m├── \x1b[0m\x1b[44mbaz\x1b[0m\x1b[44m             \x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\x1b[44m           \x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\x1b[44m           \x1b[0m\n└── egg             \n"
+    expected = "foo\n├── \x1b[3mbar\x1b[0m\n\x1b[44m├── \x1b[0m\x1b[44mbaz\x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\n\x1b[44m│   \x1b[0m\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\n└── egg\n"
     assert result == expected
 
 
@@ -112,7 +114,7 @@ def test_render_tree_hide_root_non_win32():
     console.print(tree)
     result = console.end_capture()
     print(repr(result))
-    expected = "\x1b[3mbar\x1b[0m\x1b[3m                 \x1b[0m\n\x1b[44mbaz\x1b[0m\x1b[44m                 \x1b[0m\n\x1b[31;44m┣━━ \x1b[0m\x1b[44m1\x1b[0m\x1b[44m               \x1b[0m\n\x1b[31;44m┗━━ \x1b[0m\x1b[44m2\x1b[0m\x1b[44m               \x1b[0m\negg                 \n"
+    expected = "\x1b[3mbar\x1b[0m\n\x1b[44mbaz\x1b[0m\n\x1b[31;44m┣━━ \x1b[0m\x1b[44m1\x1b[0m\n\x1b[31;44m┗━━ \x1b[0m\x1b[44m2\x1b[0m\negg\n"
     assert result == expected
 
 
@@ -130,7 +132,7 @@ def test_render_tree_hide_root_win32():
     console.print(tree)
     result = console.end_capture()
     print(repr(result))
-    expected = "\x1b[3mbar\x1b[0m\x1b[3m                 \x1b[0m\n\x1b[44mbaz\x1b[0m\x1b[44m                 \x1b[0m\n\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\x1b[44m               \x1b[0m\n\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\x1b[44m               \x1b[0m\negg                 \n"
+    expected = "\x1b[3mbar\x1b[0m\n\x1b[44mbaz\x1b[0m\n\x1b[31;44m├── \x1b[0m\x1b[44m1\x1b[0m\n\x1b[31;44m└── \x1b[0m\x1b[44m2\x1b[0m\negg\n"
     assert result == expected