Repository: Textualize/rich
Pull request #2385 (2022-07-11 11:50:29)

optimized divide
## Type of changes

- [ ] Bug fix
- [ ] New feature
- [ ] Documentation / docstrings
- [ ] Tests
- [ ] Other

## Checklist

- [ ] I've run the latest [black](https://github.com/psf/black) with default args on new code.
- [ ] I've updated CHANGELOG.md and CONTRIBUTORS.md where appropriate.
- [ ] I've added tests for new code.
- [ ] I accept that @willmcgugan may be pedantic in the code review.

## Description

Please describe your changes here. If this fixes a bug, please link to the issue, if possible.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 60204d2d..d9555f07 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
-## [12.4.5] - Unreleased
+## [12.5.0] - 2022-07-11
 
 ### Added
 
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 
 - Default width of Jupyter console size is increased to 115
+- Optimized Segment.divide
 
 ### Fixed
 
@@ -26,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Fix edges used in first row of tables when `show_header=False` https://github.com/Textualize/rich/pull/2330
 - Fix interaction between `Capture` contexts and `Console(record=True)` https://github.com/Textualize/rich/pull/2343
 - Fixed hash issue in Styles class https://github.com/Textualize/rich/pull/2346
+- Fixed bug in `Segment.split_and_crop_lines`
 
 ### Changed
 
diff --git a/asvhashfile b/asvhashfile
index 88c591ed..8fdecd4d 100644
--- a/asvhashfile
+++ b/asvhashfile
@@ -17,6 +17,7 @@ v12.4.1
 v12.4.2
 v12.4.3
 v12.4.4
+v12.5.0
 v8.0.0
 v9.13.0
 v9.5.1
diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py
index 7a088f85..032eecf7 100644
--- a/benchmarks/benchmarks.py
+++ b/benchmarks/benchmarks.py
@@ -4,6 +4,7 @@ from benchmarks import snippets
 from rich.color import Color, ColorSystem
 from rich.console import Console
 from rich.pretty import Pretty
+from rich.segment import Segment
 from rich.style import Style
 from rich.syntax import Syntax
 from rich.table import Table
@@ -16,9 +17,10 @@ class TextSuite:
             file=StringIO(), color_system="truecolor", legacy_windows=False
         )
         self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)
+        self.text = Text.from_markup(snippets.MARKUP)
 
     def time_wrapping(self):
-        Text(snippets.LOREM_IPSUM).wrap(self.console, 12, overflow="fold")
+        self.text.wrap(self.console, 12, overflow="fold")
 
     def time_indent_guides(self):
         Text(snippets.PYTHON_SNIPPET).with_indent_guides()
@@ -27,7 +29,7 @@ class TextSuite:
         Text(snippets.LOREM_IPSUM).fit(12)
 
     def time_split(self):
-        Text(snippets.LOREM_IPSUM).split()
+        self.text.split()
 
     def time_divide(self):
         Text(snippets.LOREM_IPSUM).divide(range(20, 100, 4))
@@ -36,7 +38,7 @@ class TextSuite:
         Text(snippets.LOREM_IPSUM).align("center", width=self.len_lorem_ipsum * 3)
 
     def time_render(self):
-        Text(snippets.LOREM_IPSUM).render(self.console)
+        list(self.text.render(self.console))
 
     def time_wrapping_unicode_heavy(self):
         Text(snippets.UNICODE_HEAVY_TEXT).wrap(self.console, 12, overflow="fold")
@@ -48,7 +50,7 @@ class TextSuite:
         Text(snippets.UNICODE_HEAVY_TEXT).split()
 
     def time_divide_unicode_heavy(self):
-        Text(snippets.UNICODE_HEAVY_TEXT).divide(range(20, 100, 4))
+        self.text.divide(range(20, 100, 4))
 
     def time_align_center_unicode_heavy(self):
         Text(snippets.UNICODE_HEAVY_TEXT).align(
@@ -56,7 +58,7 @@ class TextSuite:
         )
 
     def time_render_unicode_heavy(self):
-        Text(snippets.UNICODE_HEAVY_TEXT).render(self.console)
+        list(Text(snippets.UNICODE_HEAVY_TEXT).render(self.console))
 
 
 class TextHotCacheSuite:
@@ -148,6 +150,8 @@ class StyleSuite:
         self.console = Console(
             file=StringIO(), color_system="truecolor", legacy_windows=False, width=100
         )
+        self.style1 = Style.parse("blue on red")
+        self.style2 = Style.parse("green italic bold")
 
     def time_parse_ansi(self):
         Style.parse("red on blue")
@@ -158,6 +162,9 @@ class StyleSuite:
     def time_parse_mixed_complex_style(self):
         Style.parse("dim bold reverse #00ee00 on rgb(123,12,50)")
 
+    def time_style_add(self):
+        self.style1 + self.style2
+
 
 class ColorSuite:
     def setup(self):
@@ -199,6 +206,13 @@ class ColorSuiteCached:
 
 class SegmentSuite:
     def setup(self):
-        self.console = Console(
-            file=StringIO(), color_system="truecolor", legacy_windows=False, width=100
-        )
+        self.line = [
+            Segment("foo"),
+            Segment("bar"),
+            Segment("egg"),
+            Segment("Where there is a Will"),
+            Segment("There is a way"),
+        ] * 2
+
+    def test_divide_complex(self):
+        list(Segment.divide(self.line, [5, 10, 20, 50, 108, 110, 118]))
diff --git a/benchmarks/results/benchmarks.json b/benchmarks/results/benchmarks.json
index c8e25962..3eda72de 100644
--- a/benchmarks/results/benchmarks.json
+++ b/benchmarks/results/benchmarks.json
@@ -144,7 +144,7 @@
         "warmup_time": -1
     },
     "benchmarks.StyleSuite.time_parse_ansi": {
-        "code": "class StyleSuite:\n    def time_parse_ansi(self):\n        Style.parse(\"red on blue\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False, width=100\n        )",
+        "code": "class StyleSuite:\n    def time_parse_ansi(self):\n        Style.parse(\"red on blue\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False, width=100\n        )\n        self.style1 = Style.parse(\"blue on red\")\n        self.style2 = Style.parse(\"green italic bold\")",
         "min_run_count": 2,
         "name": "benchmarks.StyleSuite.time_parse_ansi",
         "number": 0,
@@ -156,11 +156,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "30751ae63d82770f620ab5f807faf7437a5a7f2309db0c6403adb23ce9571ee5",
+        "version": "ef195062397e8505c3a84b44f8357e0bf4e659abc9a92ae1028707afade51f8a",
         "warmup_time": -1
     },
     "benchmarks.StyleSuite.time_parse_hex": {
-        "code": "class StyleSuite:\n    def time_parse_hex(self):\n        Style.parse(\"#f0f0f0 on #e2e28a\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False, width=100\n        )",
+        "code": "class StyleSuite:\n    def time_parse_hex(self):\n        Style.parse(\"#f0f0f0 on #e2e28a\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False, width=100\n        )\n        self.style1 = Style.parse(\"blue on red\")\n        self.style2 = Style.parse(\"green italic bold\")",
         "min_run_count": 2,
         "name": "benchmarks.StyleSuite.time_parse_hex",
         "number": 0,
@@ -172,11 +172,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "4d64f24e35306bc59f161cfd8e9542f1f76521ac58951af3841fba1722a9917b",
+        "version": "9077fcf6d594cd70a2eaeb984a0af1d8086f9ee865a4edffc0e00e7cec66963d",
         "warmup_time": -1
     },
     "benchmarks.StyleSuite.time_parse_mixed_complex_style": {
-        "code": "class StyleSuite:\n    def time_parse_mixed_complex_style(self):\n        Style.parse(\"dim bold reverse #00ee00 on rgb(123,12,50)\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False, width=100\n        )",
+        "code": "class StyleSuite:\n    def time_parse_mixed_complex_style(self):\n        Style.parse(\"dim bold reverse #00ee00 on rgb(123,12,50)\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False, width=100\n        )\n        self.style1 = Style.parse(\"blue on red\")\n        self.style2 = Style.parse(\"green italic bold\")",
         "min_run_count": 2,
         "name": "benchmarks.StyleSuite.time_parse_mixed_complex_style",
         "number": 0,
@@ -188,7 +188,23 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "9a9eff6e02c4c05312809b98da8d740a48c93f8718ff7ba74cfec9e3f956dbd8",
+        "version": "1494bc2364e167cce5ae6752fa198ce43b323d4955b6944b5640d33988cdcabc",
+        "warmup_time": -1
+    },
+    "benchmarks.StyleSuite.time_style_add": {
+        "code": "class StyleSuite:\n    def time_style_add(self):\n        self.style1 + self.style2\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False, width=100\n        )\n        self.style1 = Style.parse(\"blue on red\")\n        self.style2 = Style.parse(\"green italic bold\")",
+        "min_run_count": 2,
+        "name": "benchmarks.StyleSuite.time_style_add",
+        "number": 0,
+        "param_names": [],
+        "params": [],
+        "repeat": 0,
+        "rounds": 2,
+        "sample_time": 0.01,
+        "timeout": 60.0,
+        "type": "time",
+        "unit": "seconds",
+        "version": "c5f2383878cc982ab31d2624f4de284dcc12c3c299c94c3b1fc1d698dd8d8260",
         "warmup_time": -1
     },
     "benchmarks.SyntaxWrappingSuite.time_text_thin_terminal_heavy_wrapping": {
@@ -288,7 +304,7 @@
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_align_center": {
-        "code": "class TextSuite:\n    def time_align_center(self):\n        Text(snippets.LOREM_IPSUM).align(\"center\", width=self.len_lorem_ipsum * 3)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_align_center(self):\n        Text(snippets.LOREM_IPSUM).align(\"center\", width=self.len_lorem_ipsum * 3)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_align_center",
         "number": 0,
@@ -300,11 +316,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "f51eebb0dd72719da589ba30bbd85be25adf556231f15da3b8694499bb5b124f",
+        "version": "a8b6e02d49879810e61cd70701e4a41a61682871ba4a4b2f4273ace0bdb1250b",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_align_center_unicode_heavy": {
-        "code": "class TextSuite:\n    def time_align_center_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).align(\n            \"center\", width=self.len_lorem_ipsum * 3\n        )\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_align_center_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).align(\n            \"center\", width=self.len_lorem_ipsum * 3\n        )\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_align_center_unicode_heavy",
         "number": 0,
@@ -316,11 +332,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "6f157a0bd86b9db1c709c8fa9716458f797106b55ecd35afab408bd281b27e40",
+        "version": "c65e269d15b432f2add210392f1126e0759c869fca2ae08729cf6baba45f3a15",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_divide": {
-        "code": "class TextSuite:\n    def time_divide(self):\n        Text(snippets.LOREM_IPSUM).divide(range(20, 100, 4))\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_divide(self):\n        Text(snippets.LOREM_IPSUM).divide(range(20, 100, 4))\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_divide",
         "number": 0,
@@ -332,11 +348,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "64851da7a4fff5f7eedf5d6f18883aeb59a43decf556c31e627b6973bd1cc34e",
+        "version": "11caa260e10d0b561700f4457776c1548091694f5939e1cb201f494c44988c67",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_divide_unicode_heavy": {
-        "code": "class TextSuite:\n    def time_divide_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).divide(range(20, 100, 4))\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_divide_unicode_heavy(self):\n        self.text.divide(range(20, 100, 4))\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_divide_unicode_heavy",
         "number": 0,
@@ -348,11 +364,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "703b70a87fe0aa1599bb2e397e436f2387baf8cf7dcf349952df217899b97097",
+        "version": "44af19dfa643c363c09525d54342353925b59b3701794c06f5b056cd4cf85a72",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_fit": {
-        "code": "class TextSuite:\n    def time_fit(self):\n        Text(snippets.LOREM_IPSUM).fit(12)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_fit(self):\n        Text(snippets.LOREM_IPSUM).fit(12)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_fit",
         "number": 0,
@@ -364,11 +380,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "8eab5a31717088de197d2d9f60d4e1658dbf3941e1afc4a378134fc8683c8bef",
+        "version": "58c2358185e76c28a0552ba5bee2b9184fbaf918b9f34485b8940a971f166b38",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_fit_unicode_heavy": {
-        "code": "class TextSuite:\n    def time_fit_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).fit(12)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_fit_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).fit(12)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_fit_unicode_heavy",
         "number": 0,
@@ -380,11 +396,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "7154022579acd99d94691787cdf31162b15e38998dbc46d85250baacfdb339ef",
+        "version": "55d075d8f450b944e46b02814deedab2f4b05cb5550a2b4e0dcbb04dea51246b",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_indent_guides": {
-        "code": "class TextSuite:\n    def time_indent_guides(self):\n        Text(snippets.PYTHON_SNIPPET).with_indent_guides()\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_indent_guides(self):\n        Text(snippets.PYTHON_SNIPPET).with_indent_guides()\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_indent_guides",
         "number": 0,
@@ -396,11 +412,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "5a3722c26c96d1ef013e493ae4d2f99aa04f989ae6a8229123afd9d80f38a384",
+        "version": "a90fc2f17dbf830377011b10d0b9d263b6c7fc06215b9e47e264cd129851f421",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_render": {
-        "code": "class TextSuite:\n    def time_render(self):\n        Text(snippets.LOREM_IPSUM).render(self.console)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_render(self):\n        list(self.text.render(self.console))\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_render",
         "number": 0,
@@ -412,11 +428,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "28f30de133a59a0ae0c7e34075766a5a7e492acb6401c8ceb24b6d0c4002db53",
+        "version": "4d859e28c2f3d6fd67f25a1d92b2b865110be2ad42b26faa6549816824f1d06b",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_render_unicode_heavy": {
-        "code": "class TextSuite:\n    def time_render_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).render(self.console)\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_render_unicode_heavy(self):\n        list(Text(snippets.UNICODE_HEAVY_TEXT).render(self.console))\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_render_unicode_heavy",
         "number": 0,
@@ -428,11 +444,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "71f96ca5c6fe650b498a68a82f7268a1cd3d4b003a01d620fa0456b0827311e2",
+        "version": "4c10b25361392c9889c32587b68541e3dff0a4fe069405d7f5e5763deb07e3c1",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_split": {
-        "code": "class TextSuite:\n    def time_split(self):\n        Text(snippets.LOREM_IPSUM).split()\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_split(self):\n        self.text.split()\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_split",
         "number": 0,
@@ -444,11 +460,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "8ced6624e81ea79c121959a499bd08a83578f32be271fce55bad42196ba221b7",
+        "version": "cf8cd074f1b4bbd424d0cad4548c43a9cd19f7b5a8da2a1598bfa1cbaac5223c",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_split_unicode_heavy": {
-        "code": "class TextSuite:\n    def time_split_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).split()\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_split_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).split()\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_split_unicode_heavy",
         "number": 0,
@@ -460,11 +476,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "edcdec63428ba276875d287976df2ef6ea68e66a44dfe252a80eecd7705aa47d",
+        "version": "33cad3b4a38b0ed37ade46bda66bc9e84e0f73e3519cc77ac02d7da5123a9137",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_wrapping": {
-        "code": "class TextSuite:\n    def time_wrapping(self):\n        Text(snippets.LOREM_IPSUM).wrap(self.console, 12, overflow=\"fold\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_wrapping(self):\n        self.text.wrap(self.console, 12, overflow=\"fold\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_wrapping",
         "number": 0,
@@ -476,11 +492,11 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "7ee504db351412170e9e040a3c5f76a06ceb92b020dfd04c3d0ce3f2b7f5bc58",
+        "version": "961df5c6a57de40e2a07182136f3644f42f1dcab1017b571383e5cb2b3dcbf46",
         "warmup_time": -1
     },
     "benchmarks.TextSuite.time_wrapping_unicode_heavy": {
-        "code": "class TextSuite:\n    def time_wrapping_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).wrap(self.console, 12, overflow=\"fold\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)",
+        "code": "class TextSuite:\n    def time_wrapping_unicode_heavy(self):\n        Text(snippets.UNICODE_HEAVY_TEXT).wrap(self.console, 12, overflow=\"fold\")\n\n    def setup(self):\n        self.console = Console(\n            file=StringIO(), color_system=\"truecolor\", legacy_windows=False\n        )\n        self.len_lorem_ipsum = len(snippets.LOREM_IPSUM)\n        self.text = Text.from_markup(snippets.MARKUP)",
         "min_run_count": 2,
         "name": "benchmarks.TextSuite.time_wrapping_unicode_heavy",
         "number": 0,
@@ -492,7 +508,7 @@
         "timeout": 60.0,
         "type": "time",
         "unit": "seconds",
-        "version": "4db4b38f51b05f4dc11b5a2908c118fe556a7d36b9e1d85fd18e28885a384db0",
+        "version": "0c9e448fb577a673d91bfd3d0da5ade88ee11474cf9113869e669cbc6cf4c444",
         "warmup_time": -1
     },
     "version": 2
diff --git a/benchmarks/snippets.py b/benchmarks/snippets.py
index ef72dbcf..f8d177aa 100644
--- a/benchmarks/snippets.py
+++ b/benchmarks/snippets.py
@@ -171,3 +171,9 @@ Console オブジェクトには `print` メソッドがあり、これは組み
 
 出力結果に色やスタイルを追加する方法はいくつかあります。キーワード引数に `style` を追加することで、出力結果全体のスタイルを設定することができます。以下に例を示します:
 """
+
+
+MARKUP = "\n".join(
+    """[bold]Hello [i]World[/i] [bold magenta]foo [i]bar[/i] baz[/] [blue u]https://textualize.io[/]"""
+    for _ in range(20)
+)
diff --git a/pyproject.toml b/pyproject.toml
index 7bb6bda1..3ebe0eac 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -2,7 +2,7 @@
 name = "rich"
 homepage = "https://github.com/willmcgugan/rich"
 documentation = "https://rich.readthedocs.io/en/latest/"
-version = "12.4.4"
+version = "12.5.0"
 description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
 authors = ["Will McGugan <willmcgugan@gmail.com>"]
 license = "MIT"
diff --git a/rich/console.py b/rich/console.py
index 5b8eb751..8c6049a4 100644
--- a/rich/console.py
+++ b/rich/console.py
@@ -1349,6 +1349,7 @@ class Console:
                         render_options.max_width,
                         include_new_lines=new_lines,
                         pad=pad,
+                        style=style,
                     ),
                     None,
                     render_height,
diff --git a/rich/segment.py b/rich/segment.py
index d825cfca..20ccedf8 100644
--- a/rich/segment.py
+++ b/rich/segment.py
@@ -18,6 +18,7 @@ from typing import (
 
 from .cells import (
     _is_single_cell_widths,
+    cached_cell_len,
     cell_len,
     get_character_cell_size,
     set_cell_size,
@@ -290,11 +291,11 @@ class Segment(NamedTuple):
 
         for segment in segments:
             if "\n" in segment.text and not segment.control:
-                text, style, _ = segment
+                text, segment_style, _ = segment
                 while text:
                     _text, new_line, text = text.partition("\n")
                     if _text:
-                        append(cls(_text, style))
+                        append(cls(_text, segment_style))
                     if new_line:
                         cropped_line = adjust_line_length(
                             line, length, style=style, pad=pad
@@ -602,50 +603,56 @@ class Segment(NamedTuple):
         iter_cuts = iter(cuts)
 
         while True:
-            try:
-                cut = next(iter_cuts)
-            except StopIteration:
+            cut = next(iter_cuts, -1)
+            if cut == -1:
                 return []
             if cut != 0:
                 break
             yield []
         pos = 0
 
-        _cell_len = cell_len
+        segments_clear = split_segments.clear
+        segments_copy = split_segments.copy
+
+        _cell_len = cached_cell_len
         for segment in segments:
             text, _style, control = segment
             while text:
-                if control:
-                    end_pos = pos
-                else:
-                    end_pos = pos + _cell_len(text)
+                end_pos = pos if control else pos + _cell_len(text)
                 if end_pos < cut:
                     add_segment(segment)
                     pos = end_pos
                     break
 
-                try:
-                    if end_pos == cut:
-                        add_segment(segment)
-                        yield split_segments[:]
-                        del split_segments[:]
-                        pos = end_pos
-                        break
-                    else:
-                        before, segment = segment.split_cells(cut - pos)
-                        text, _style, control = segment
-                        add_segment(before)
-                        yield split_segments[:]
-                        del split_segments[:]
-                        pos = cut
-                finally:
-                    try:
-                        cut = next(iter_cuts)
-                    except StopIteration:
+                if end_pos == cut:
+                    add_segment(segment)
+                    yield segments_copy()
+                    segments_clear()
+                    pos = end_pos
+
+                    cut = next(iter_cuts, -1)
+                    if cut == -1:
                         if split_segments:
-                            yield split_segments[:]
+                            yield segments_copy()
                         return
-        yield split_segments[:]
+
+                    break
+
+                else:
+                    before, segment = segment.split_cells(cut - pos)
+                    text, _style, control = segment
+                    add_segment(before)
+                    yield segments_copy()
+                    segments_clear()
+                    pos = cut
+
+                cut = next(iter_cuts, -1)
+                if cut == -1:
+                    if split_segments:
+                        yield segments_copy()
+                    return
+
+        yield segments_copy()
 
 
 class Segments:


Test patch:
diff --git a/tests/test_panel.py b/tests/test_panel.py
index 040288cf..5ae3babe 100644
--- a/tests/test_panel.py
+++ b/tests/test_panel.py
@@ -73,7 +73,8 @@ def test_render_size():
             Segment(" ", Style()),
             Segment("foo"),
             Segment(
-                "                                                                         "
+                "                                                                         ",
+                Style(),
             ),
             Segment(" ", Style()),
             Segment("│", Style()),