From 76dfb9654b1ea469ca957a0312ef9ab536dc0f3e Mon Sep 17 00:00:00 2001
From: Will McGugan <willmcgugan@gmail.com>
Date: Mon, 11 Jul 2022 12:49:56 +0100
Subject: [PATCH] optimized divide

---
 CHANGELOG.md        |  4 ++-
 pyproject.toml      |  2 +-
 rich/console.py     |  1 +
 rich/segment.py     | 62 +++++++++++++++++++++++++--------------------
 tests/test_panel.py |  3 ++-
 5 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 60204d2dd..767f3f8eb 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] - Unreleased
 
 ### 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/pyproject.toml b/pyproject.toml
index 7bb6bda18..3ebe0eac3 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 5b8eb751e..8c6049a49 100644
--- a/rich/console.py
+++ b/rich/console.py
@@ -1349,6 +1349,7 @@ def render_lines(
                         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 d825cfca4..75d13d052 100644
--- a/rich/segment.py
+++ b/rich/segment.py
@@ -18,6 +18,7 @@
 
 from .cells import (
     _is_single_cell_widths,
+    cached_cell_len,
     cell_len,
     get_character_cell_size,
     set_cell_size,
@@ -290,11 +291,11 @@ def split_and_crop_lines(
 
         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
@@ -611,41 +612,48 @@ def divide(
             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:
diff --git a/tests/test_panel.py b/tests/test_panel.py
index 040288cfe..5ae3babee 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()),