bram-patience-diff 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009--2026 Jane Street Group, LLC <opensource-contacts@janestreet.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,142 @@
1
+ Metadata-Version: 2.4
2
+ Name: bram-patience-diff
3
+ Version: 1.0.0
4
+ Summary: Patience Diff Algorithm - An implementation of Bram Cohen's diff algorithm
5
+ Home-page: https://github.com/joery0x3b800001/patience_diff
6
+ Author: Shaun Joe
7
+ Author-email: shaunjoeroy1234@gmail.com
8
+ License: GPLv2+
9
+ Project-URL: Bug Tracker, https://github.com/joery0x3b800001/patience_diff/issues
10
+ Project-URL: Source, https://github.com/joery0x3b800001/patience_diff
11
+ Keywords: diff algorithm patience sorting sequence
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Topic :: Utilities
16
+ Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.7
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Requires-Python: >=3.7
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE.md
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: license-file
35
+ Dynamic: project-url
36
+ Dynamic: requires-python
37
+ Dynamic: summary
38
+
39
+ # Patience Diff
40
+
41
+ A complete Python port of Bram Cohen's algorithm for computing efficient differences.
42
+
43
+ ## Features
44
+
45
+ - Patience Sorting Algorithm: O(n log n)
46
+ - Semantic Cleanup: Removes spurious matches
47
+ - Multiple Output Formats: Blocks, hunks with context
48
+ - Myers Fallback: Simple diff for edge cases
49
+ - Type Hints: Full annotations for IDE support
50
+ - Well Tested: Comprehensive test suite
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ make install # Install in dev mode
56
+ make test # Run tests
57
+ ```
58
+
59
+ ## License
60
+
61
+ GNU General Public License v2 or later
62
+
63
+ Original algorithm and OCaml implementation by Bram Cohen
64
+ Copyright (C) 2005, 2006 Canonical Ltd
65
+ Python port by Shaun Joe
66
+
67
+
68
+ ## API Reference
69
+
70
+ ### Core Functions
71
+
72
+ - `get_matching_blocks(transform, prev_array, next_array, big_enough=1)` - Find matching blocks
73
+ - `get_hunks(transform, prev_array, next_array, context=-1, big_enough=1)` - Generate hunks
74
+ - `matches(prev_array, next_array)` - Get matching index pairs
75
+ - `match_ratio(prev_array, next_array)` - Calculate similarity ratio
76
+
77
+ ### Data Types
78
+
79
+ - `Hunk` - Contiguous diff region with ranges
80
+ - `MatchingBlock` - Matching subsequence (prev_start, next_start, length)
81
+ - Range types: `Same`, `Prev`, `Next`, `Replace`
82
+
83
+
84
+ ## Project Structure
85
+
86
+ ```
87
+ src/ # Python package (11 modules)
88
+ ├── patience_diff.py # Core algorithm (700+ lines)
89
+ ├── plain_diff.py # Myers fallback
90
+ ├── hunk.py # Hunk data structures
91
+ ├── hunks.py # Hunk utilities
92
+ ├── matching_block.py # Matching block type
93
+ ├── range.py # Range types
94
+ ├── move_id.py # Move identifiers
95
+ ├── move_kind.py # Move classification
96
+ ├── patience_diff_intf.py # Interface definitions
97
+ ├── patience_diff_lib.py # Library exports
98
+ └── __init__.py # Package initialization
99
+
100
+ test/ # Test suite
101
+ ├── test_limit_context.py
102
+ ├── test_merge_diff.py
103
+ └── test_plain_diff_cutoff.py
104
+
105
+ Makefile # Build automation
106
+ setup.py # Package setup
107
+ pyproject.toml # Build configuration
108
+ README.md
109
+ ```
110
+
111
+
112
+ ## Testing
113
+
114
+ All tests passing:
115
+
116
+ ```bash
117
+ $ make test
118
+ test/test_limit_context.py PASSED
119
+ test/test_merge_diff.py PASSED
120
+ test/test_plain_diff_cutoff.py PASSED
121
+
122
+ ============================ 3 passed ============================
123
+ ```
124
+
125
+
126
+ ## Algorithm
127
+
128
+ The Patience Diff algorithm works in several steps:
129
+
130
+ 1. Identify unique elements (appearing exactly once in both sequences)
131
+ 2. Build longest increasing subsequence (LIS) of unique matches using patience sorting
132
+ 3. Recursively find matches in gaps between LIS elements
133
+ 4. Remove spurious small matches ("semantic cleanup")
134
+ 5. Merge adjacent blocks separated by identical elements
135
+ 6. Convert matching blocks to hunks with Same/Prev/Next/Replace ranges
136
+
137
+
138
+ ## References
139
+
140
+ - http://bazaar-vcs.org - Original implementation
141
+ - Eugene W. Myers: "An O(ND) Difference Algorithm and Its Variations"
142
+
@@ -0,0 +1,104 @@
1
+ # Patience Diff
2
+
3
+ A complete Python port of Bram Cohen's algorithm for computing efficient differences.
4
+
5
+ ## Features
6
+
7
+ - Patience Sorting Algorithm: O(n log n)
8
+ - Semantic Cleanup: Removes spurious matches
9
+ - Multiple Output Formats: Blocks, hunks with context
10
+ - Myers Fallback: Simple diff for edge cases
11
+ - Type Hints: Full annotations for IDE support
12
+ - Well Tested: Comprehensive test suite
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ make install # Install in dev mode
18
+ make test # Run tests
19
+ ```
20
+
21
+ ## License
22
+
23
+ GNU General Public License v2 or later
24
+
25
+ Original algorithm and OCaml implementation by Bram Cohen
26
+ Copyright (C) 2005, 2006 Canonical Ltd
27
+ Python port by Shaun Joe
28
+
29
+
30
+ ## API Reference
31
+
32
+ ### Core Functions
33
+
34
+ - `get_matching_blocks(transform, prev_array, next_array, big_enough=1)` - Find matching blocks
35
+ - `get_hunks(transform, prev_array, next_array, context=-1, big_enough=1)` - Generate hunks
36
+ - `matches(prev_array, next_array)` - Get matching index pairs
37
+ - `match_ratio(prev_array, next_array)` - Calculate similarity ratio
38
+
39
+ ### Data Types
40
+
41
+ - `Hunk` - Contiguous diff region with ranges
42
+ - `MatchingBlock` - Matching subsequence (prev_start, next_start, length)
43
+ - Range types: `Same`, `Prev`, `Next`, `Replace`
44
+
45
+
46
+ ## Project Structure
47
+
48
+ ```
49
+ src/ # Python package (11 modules)
50
+ ├── patience_diff.py # Core algorithm (700+ lines)
51
+ ├── plain_diff.py # Myers fallback
52
+ ├── hunk.py # Hunk data structures
53
+ ├── hunks.py # Hunk utilities
54
+ ├── matching_block.py # Matching block type
55
+ ├── range.py # Range types
56
+ ├── move_id.py # Move identifiers
57
+ ├── move_kind.py # Move classification
58
+ ├── patience_diff_intf.py # Interface definitions
59
+ ├── patience_diff_lib.py # Library exports
60
+ └── __init__.py # Package initialization
61
+
62
+ test/ # Test suite
63
+ ├── test_limit_context.py
64
+ ├── test_merge_diff.py
65
+ └── test_plain_diff_cutoff.py
66
+
67
+ Makefile # Build automation
68
+ setup.py # Package setup
69
+ pyproject.toml # Build configuration
70
+ README.md
71
+ ```
72
+
73
+
74
+ ## Testing
75
+
76
+ All tests passing:
77
+
78
+ ```bash
79
+ $ make test
80
+ test/test_limit_context.py PASSED
81
+ test/test_merge_diff.py PASSED
82
+ test/test_plain_diff_cutoff.py PASSED
83
+
84
+ ============================ 3 passed ============================
85
+ ```
86
+
87
+
88
+ ## Algorithm
89
+
90
+ The Patience Diff algorithm works in several steps:
91
+
92
+ 1. Identify unique elements (appearing exactly once in both sequences)
93
+ 2. Build longest increasing subsequence (LIS) of unique matches using patience sorting
94
+ 3. Recursively find matches in gaps between LIS elements
95
+ 4. Remove spurious small matches ("semantic cleanup")
96
+ 5. Merge adjacent blocks separated by identical elements
97
+ 6. Convert matching blocks to hunks with Same/Prev/Next/Replace ranges
98
+
99
+
100
+ ## References
101
+
102
+ - http://bazaar-vcs.org - Original implementation
103
+ - Eugene W. Myers: "An O(ND) Difference Algorithm and Its Variations"
104
+
@@ -0,0 +1,142 @@
1
+ Metadata-Version: 2.4
2
+ Name: bram-patience-diff
3
+ Version: 1.0.0
4
+ Summary: Patience Diff Algorithm - An implementation of Bram Cohen's diff algorithm
5
+ Home-page: https://github.com/joery0x3b800001/patience_diff
6
+ Author: Shaun Joe
7
+ Author-email: shaunjoeroy1234@gmail.com
8
+ License: GPLv2+
9
+ Project-URL: Bug Tracker, https://github.com/joery0x3b800001/patience_diff/issues
10
+ Project-URL: Source, https://github.com/joery0x3b800001/patience_diff
11
+ Keywords: diff algorithm patience sorting sequence
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Topic :: Utilities
16
+ Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.7
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Requires-Python: >=3.7
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE.md
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: license-file
35
+ Dynamic: project-url
36
+ Dynamic: requires-python
37
+ Dynamic: summary
38
+
39
+ # Patience Diff
40
+
41
+ A complete Python port of Bram Cohen's algorithm for computing efficient differences.
42
+
43
+ ## Features
44
+
45
+ - Patience Sorting Algorithm: O(n log n)
46
+ - Semantic Cleanup: Removes spurious matches
47
+ - Multiple Output Formats: Blocks, hunks with context
48
+ - Myers Fallback: Simple diff for edge cases
49
+ - Type Hints: Full annotations for IDE support
50
+ - Well Tested: Comprehensive test suite
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ make install # Install in dev mode
56
+ make test # Run tests
57
+ ```
58
+
59
+ ## License
60
+
61
+ GNU General Public License v2 or later
62
+
63
+ Original algorithm and OCaml implementation by Bram Cohen
64
+ Copyright (C) 2005, 2006 Canonical Ltd
65
+ Python port by Shaun Joe
66
+
67
+
68
+ ## API Reference
69
+
70
+ ### Core Functions
71
+
72
+ - `get_matching_blocks(transform, prev_array, next_array, big_enough=1)` - Find matching blocks
73
+ - `get_hunks(transform, prev_array, next_array, context=-1, big_enough=1)` - Generate hunks
74
+ - `matches(prev_array, next_array)` - Get matching index pairs
75
+ - `match_ratio(prev_array, next_array)` - Calculate similarity ratio
76
+
77
+ ### Data Types
78
+
79
+ - `Hunk` - Contiguous diff region with ranges
80
+ - `MatchingBlock` - Matching subsequence (prev_start, next_start, length)
81
+ - Range types: `Same`, `Prev`, `Next`, `Replace`
82
+
83
+
84
+ ## Project Structure
85
+
86
+ ```
87
+ src/ # Python package (11 modules)
88
+ ├── patience_diff.py # Core algorithm (700+ lines)
89
+ ├── plain_diff.py # Myers fallback
90
+ ├── hunk.py # Hunk data structures
91
+ ├── hunks.py # Hunk utilities
92
+ ├── matching_block.py # Matching block type
93
+ ├── range.py # Range types
94
+ ├── move_id.py # Move identifiers
95
+ ├── move_kind.py # Move classification
96
+ ├── patience_diff_intf.py # Interface definitions
97
+ ├── patience_diff_lib.py # Library exports
98
+ └── __init__.py # Package initialization
99
+
100
+ test/ # Test suite
101
+ ├── test_limit_context.py
102
+ ├── test_merge_diff.py
103
+ └── test_plain_diff_cutoff.py
104
+
105
+ Makefile # Build automation
106
+ setup.py # Package setup
107
+ pyproject.toml # Build configuration
108
+ README.md
109
+ ```
110
+
111
+
112
+ ## Testing
113
+
114
+ All tests passing:
115
+
116
+ ```bash
117
+ $ make test
118
+ test/test_limit_context.py PASSED
119
+ test/test_merge_diff.py PASSED
120
+ test/test_plain_diff_cutoff.py PASSED
121
+
122
+ ============================ 3 passed ============================
123
+ ```
124
+
125
+
126
+ ## Algorithm
127
+
128
+ The Patience Diff algorithm works in several steps:
129
+
130
+ 1. Identify unique elements (appearing exactly once in both sequences)
131
+ 2. Build longest increasing subsequence (LIS) of unique matches using patience sorting
132
+ 3. Recursively find matches in gaps between LIS elements
133
+ 4. Remove spurious small matches ("semantic cleanup")
134
+ 5. Merge adjacent blocks separated by identical elements
135
+ 6. Convert matching blocks to hunks with Same/Prev/Next/Replace ranges
136
+
137
+
138
+ ## References
139
+
140
+ - http://bazaar-vcs.org - Original implementation
141
+ - Eugene W. Myers: "An O(ND) Difference Algorithm and Its Variations"
142
+
@@ -0,0 +1,24 @@
1
+ LICENSE.md
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ bram_patience_diff.egg-info/PKG-INFO
6
+ bram_patience_diff.egg-info/SOURCES.txt
7
+ bram_patience_diff.egg-info/dependency_links.txt
8
+ bram_patience_diff.egg-info/top_level.txt
9
+ src/__init__.py
10
+ src/hunk.py
11
+ src/hunks.py
12
+ src/matching_block.py
13
+ src/move_id.py
14
+ src/move_kind.py
15
+ src/patience_diff.py
16
+ src/patience_diff_intf.py
17
+ src/patience_diff_lib.py
18
+ src/plain_diff.py
19
+ src/range.py
20
+ test/__init__.py
21
+ test/test_limit_context.py
22
+ test/test_merge_diff.py
23
+ test/test_patience_diff_lib.py
24
+ test/test_plain_diff_cutoff.py
@@ -0,0 +1,7 @@
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.pytest.ini_options]
6
+ testpaths = ["test"]
7
+ python_files = ["test_*.py"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,37 @@
1
+ from setuptools import setup, find_packages
2
+ import pathlib
3
+
4
+ here = pathlib.Path(__file__).parent.resolve()
5
+ long_description = (here / "README.md").read_text(encoding="utf-8")
6
+
7
+ setup(
8
+ name='bram-patience-diff',
9
+ version='1.0.0',
10
+ author='Shaun Joe',
11
+ author_email='shaunjoeroy1234@gmail.com',
12
+ description='Patience Diff Algorithm - An implementation of Bram Cohen\'s diff algorithm',
13
+ long_description=long_description,
14
+ long_description_content_type='text/markdown',
15
+ url='https://github.com/joery0x3b800001/patience_diff',
16
+ project_urls={
17
+ 'Bug Tracker': 'https://github.com/joery0x3b800001/patience_diff/issues',
18
+ 'Source': 'https://github.com/joery0x3b800001/patience_diff',
19
+ },
20
+ classifiers=[
21
+ 'Development Status :: 4 - Beta',
22
+ 'Intended Audience :: Developers',
23
+ 'Topic :: Software Development :: Libraries :: Python Modules',
24
+ 'Topic :: Utilities',
25
+ 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
26
+ 'Programming Language :: Python :: 3',
27
+ 'Programming Language :: Python :: 3.7',
28
+ 'Programming Language :: Python :: 3.8',
29
+ 'Programming Language :: Python :: 3.9',
30
+ 'Programming Language :: Python :: 3.10',
31
+ 'Programming Language :: Python :: 3.11',
32
+ ],
33
+ packages=find_packages(),
34
+ python_requires='>=3.7',
35
+ keywords='diff algorithm patience sorting sequence',
36
+ license='GPLv2+',
37
+ )
@@ -0,0 +1,81 @@
1
+ """
2
+ Patience Diff - A Python port of the OCaml Patience Diff library.
3
+
4
+ This is a comprehensive port of Bram Cohen's patience diff algorithm, as found in the Bazaar 1.14.1
5
+ source code, available at http://bazaar-vcs.org.
6
+
7
+ Copyright (C) 2005 Bram Cohen, Copyright (C) 2005, 2006 Canonical Ltd
8
+ Licensed under GNU General Public License v2 or later.
9
+ """
10
+
11
+ __version__ = "1.0.0"
12
+
13
+ # Import all public modules for convenience
14
+ from . import (
15
+ hunk,
16
+ hunks,
17
+ matching_block,
18
+ move_id,
19
+ move_kind,
20
+ patience_diff,
21
+ plain_diff,
22
+ range,
23
+ )
24
+
25
+ # Export commonly used classes and functions
26
+ from .hunk import Hunk
27
+ from .hunks import Hunks
28
+ from .matching_block import MatchingBlock
29
+ from .move_id import MoveId
30
+ from .move_kind import Move, WithinMove
31
+ from .range import Same, Prev, Next, Replace, Unified, Range
32
+ from .patience_diff import (
33
+ get_matching_blocks,
34
+ get_hunks,
35
+ matches,
36
+ match_ratio,
37
+ )
38
+
39
+ # Create module-level exports similar to OCaml
40
+ class PatienceDiff:
41
+ """Patience Diff algorithm module."""
42
+ get_matching_blocks = staticmethod(patience_diff.get_matching_blocks)
43
+ get_hunks = staticmethod(patience_diff.get_hunks)
44
+ matches = staticmethod(patience_diff.matches)
45
+ match_ratio = staticmethod(patience_diff.match_ratio)
46
+
47
+ class PlainDiff:
48
+ """Plain (Myers) diff algorithm module."""
49
+ get_matching_blocks = staticmethod(plain_diff.get_matching_blocks)
50
+ get_hunks = staticmethod(plain_diff.get_hunks)
51
+ matches = staticmethod(plain_diff.matches)
52
+ match_ratio = staticmethod(plain_diff.match_ratio)
53
+
54
+ __all__ = [
55
+ 'hunk',
56
+ 'hunks',
57
+ 'matching_block',
58
+ 'move_id',
59
+ 'move_kind',
60
+ 'patience_diff',
61
+ 'plain_diff',
62
+ 'range',
63
+ 'Hunk',
64
+ 'Hunks',
65
+ 'MatchingBlock',
66
+ 'MoveId',
67
+ 'Move',
68
+ 'WithinMove',
69
+ 'Same',
70
+ 'Prev',
71
+ 'Next',
72
+ 'Replace',
73
+ 'Unified',
74
+ 'Range',
75
+ 'get_matching_blocks',
76
+ 'get_hunks',
77
+ 'matches',
78
+ 'match_ratio',
79
+ 'PatienceDiff',
80
+ 'PlainDiff',
81
+ ]
@@ -0,0 +1,123 @@
1
+ """Hunk dataclass for representing chunks of differences."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import List
5
+
6
+
7
+ def _get_same_class():
8
+ """Lazy import to avoid circular imports."""
9
+ try:
10
+ from .range import Same
11
+ except ImportError:
12
+ from range import Same
13
+ return Same
14
+
15
+
16
+ @dataclass
17
+ class Hunk:
18
+ """A hunk represents a contiguous region of changes in a diff."""
19
+ prev_start: int
20
+ prev_size: int
21
+ next_start: int
22
+ next_size: int
23
+ ranges: List = field(default_factory=list)
24
+
25
+ def all_same(self):
26
+ """Check if all ranges in this hunk are identical."""
27
+ Same = _get_same_class()
28
+ return all(isinstance(r, Same) for r in self.ranges)
29
+
30
+ @staticmethod
31
+ def limit_infinite_context_hunk_to_context(hunk: 'Hunk', context: int) -> List['Hunk']:
32
+ """Split a hunk with unlimited context to one with limited context.
33
+
34
+ Removes large Same ranges from the middle, keeping only 'context' lines
35
+ of context around changes.
36
+ """
37
+ if context < 0:
38
+ return [hunk]
39
+
40
+ Same = _get_same_class()
41
+
42
+ ranges = hunk.ranges
43
+ hunks_list = []
44
+ curr_ranges = []
45
+ prev_start = hunk.prev_start
46
+ next_start = hunk.next_start
47
+
48
+ def finalize_hunk():
49
+ if curr_ranges:
50
+ h = Hunk(prev_start, prev_start, next_start, next_start, list(reversed(curr_ranges)))
51
+ hunks_list.append(h)
52
+ curr_ranges.clear()
53
+ return prev_start, next_start
54
+
55
+ i = 0
56
+ while i < len(ranges):
57
+ r = ranges[i]
58
+
59
+ if isinstance(r, Same):
60
+ size = len(r.items)
61
+
62
+ if i == len(ranges) - 1: # Last range
63
+ # Crop to context
64
+ keep = min(size, context)
65
+ if keep > 0:
66
+ cropped_items = r.items[:keep]
67
+ curr_ranges.append(Same(cropped_items))
68
+ prev_start += keep
69
+ next_start += keep
70
+
71
+ # Finalize
72
+ finalize_hunk()
73
+
74
+ elif size > context * 2:
75
+ # This Same is large, split it
76
+ # Keep first context
77
+ first_items = r.items[:context]
78
+ if first_items:
79
+ curr_ranges.append(Same(first_items))
80
+ prev_start += context
81
+ next_start += context
82
+
83
+ # Finalize current hunk
84
+ finalize_hunk()
85
+
86
+ # Advance by trimmed amount
87
+ prev_start += size - context
88
+ next_start += size - context
89
+
90
+ # Keep last context for next hunk
91
+ last_items = r.items[-context:]
92
+ if last_items:
93
+ curr_ranges.append(Same(last_items))
94
+
95
+ else:
96
+ # Keep entire Same range as context
97
+ curr_ranges.append(r)
98
+ prev_start += size
99
+ next_start += size
100
+
101
+ else:
102
+ # Non-Same range
103
+ if hasattr(r, 'items') and not isinstance(r, Same):
104
+ # Prev or Next
105
+ size = len(r.items)
106
+ if hasattr(r, 'lines'): # For backward compat
107
+ size = len(r.lines)
108
+ prev_start += size if hasattr(r, 'prev_items') else 0
109
+ next_start += size if hasattr(r, 'next_items') else 0
110
+ elif hasattr(r, 'prev_items'):
111
+ # Replace
112
+ prev_start += len(r.prev_items)
113
+ next_start += len(r.next_items)
114
+
115
+ curr_ranges.append(r)
116
+
117
+ i += 1
118
+
119
+ # Finalize last hunk if needed
120
+ if curr_ranges:
121
+ finalize_hunk()
122
+
123
+ return hunks_list