@@ -206,3 +206,121 @@ def get_license_header(self, comment_prefix: str = "//") -> str:
206206 return "\n " .join (
207207 f"{ comment_prefix } { line } " if line else comment_prefix for line in lines
208208 )
209+
210+ def wrap_line (
211+ self ,
212+ line : str ,
213+ max_width : int = 80 ,
214+ indent : str = "" ,
215+ continuation_indent : str = None ,
216+ ) -> List [str ]:
217+ """Wrap a long line into multiple lines with max_width characters.
218+
219+ Args:
220+ line: The line to wrap
221+ max_width: Maximum width per line (default 80)
222+ indent: The indentation to preserve for the first line
223+ continuation_indent: Extra indentation for continuation lines.
224+ If None, uses indent + 4 spaces.
225+
226+ Returns:
227+ List of wrapped lines
228+ """
229+ if continuation_indent is None :
230+ continuation_indent = indent + " "
231+
232+ # If line is already short enough, return as is
233+ if len (line ) <= max_width :
234+ return [line ]
235+
236+ # Don't wrap C++ preprocessor directives (macros)
237+ stripped = line .lstrip ()
238+ if stripped .startswith ("#" ):
239+ return [line ]
240+
241+ # Don't wrap comment lines (license headers, etc.)
242+ if stripped .startswith ("//" ) or stripped .startswith ("/*" ) or stripped .startswith ("*" ) or stripped .startswith ("#" ):
243+ return [line ]
244+
245+ # Extract the leading indent
246+ leading_spaces = line [: len (line ) - len (line .lstrip ())]
247+
248+ # Get the content without indent
249+ content = line [len (leading_spaces ) :]
250+
251+ # If it's still too short after considering indent, don't wrap
252+ if len (leading_spaces ) + len (content ) <= max_width :
253+ return [line ]
254+
255+ # Find good break points (prefer breaking at spaces, commas, operators)
256+ result = []
257+ current = content
258+ first_line = True
259+
260+ while len (leading_spaces ) + len (current ) > max_width :
261+ # Calculate available width
262+ if first_line :
263+ available = max_width - len (leading_spaces )
264+ else :
265+ available = max_width - len (continuation_indent )
266+
267+ if available <= 0 :
268+ # Can't wrap reasonably, return original
269+ return [line ]
270+
271+ # Find the best break point
272+ break_point = - 1
273+
274+ # Look for break points in order of preference
275+ search_text = current [:available ]
276+
277+ # Try to break at common delimiters (working backwards)
278+ for delimiter in [", " , " && " , " || " , " + " , " - " , " * " , " / " , " = " , " " , "," ]:
279+ idx = search_text .rfind (delimiter )
280+ if idx > 0 :
281+ break_point = idx + len (delimiter )
282+ break
283+
284+ # If no good break point found, just break at max width
285+ if break_point <= 0 :
286+ break_point = available
287+
288+ # Add the line segment
289+ if first_line :
290+ result .append (leading_spaces + current [:break_point ].rstrip ())
291+ first_line = False
292+ else :
293+ result .append (continuation_indent + current [:break_point ].rstrip ())
294+
295+ # Continue with the rest
296+ current = current [break_point :].lstrip ()
297+
298+ # Add the remaining content
299+ if current :
300+ if first_line :
301+ result .append (leading_spaces + current )
302+ else :
303+ result .append (continuation_indent + current )
304+
305+ return result if result else [line ]
306+
307+ def wrap_lines (
308+ self , lines : List [str ], max_width : int = 80 , preserve_blank : bool = True
309+ ) -> List [str ]:
310+ """Wrap multiple lines, handling each line's indentation.
311+
312+ Args:
313+ lines: List of lines to wrap
314+ max_width: Maximum width per line
315+ preserve_blank: If True, preserve blank lines as-is
316+
317+ Returns:
318+ List of wrapped lines
319+ """
320+ result = []
321+ for line in lines :
322+ if preserve_blank and not line .strip ():
323+ result .append (line )
324+ else :
325+ result .extend (self .wrap_line (line , max_width ))
326+ return result
0 commit comments