Skip to content

Commit 9518777

Browse files
committed
Pane(feat[capture_frame]): Add capture_frame() method
why: Enable capturing pane content as TextFrame for visualization and snapshot testing. This bridges capture_pane() with the TextFrame dataclass for a more ergonomic testing workflow. what: - Add capture_frame() method that wraps capture_pane() - Default to pane dimensions when width/height not specified - Default to truncate mode for robustness in CI environments - Add comprehensive docstring with examples
1 parent 57939d6 commit 9518777

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

src/libtmux/pane.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import types
3232

3333
from libtmux._internal.types import StrPath
34+
from libtmux.textframe import TextFrame
35+
from libtmux.textframe.core import OverflowBehavior
3436

3537
from .server import Server
3638
from .session import Session
@@ -420,6 +422,93 @@ def capture_pane(
420422
)
421423
return self.cmd(*cmd).stdout
422424

425+
def capture_frame(
426+
self,
427+
start: t.Literal["-"] | int | None = None,
428+
end: t.Literal["-"] | int | None = None,
429+
*,
430+
content_width: int | None = None,
431+
content_height: int | None = None,
432+
overflow_behavior: OverflowBehavior = "truncate",
433+
) -> TextFrame:
434+
"""Capture pane content as a TextFrame.
435+
436+
Combines :meth:`capture_pane` with :class:`~libtmux.textframe.TextFrame`
437+
for visualization and snapshot testing.
438+
439+
Parameters
440+
----------
441+
start : str | int, optional
442+
Starting line number (same as :meth:`capture_pane`).
443+
Zero is the first line of the visible pane.
444+
Positive numbers are lines in the visible pane.
445+
Negative numbers are lines in the history.
446+
``-`` is the start of the history.
447+
Default: None
448+
end : str | int, optional
449+
Ending line number (same as :meth:`capture_pane`).
450+
Zero is the first line of the visible pane.
451+
Positive numbers are lines in the visible pane.
452+
Negative numbers are lines in the history.
453+
``-`` is the end of the visible pane.
454+
Default: None
455+
content_width : int, optional
456+
Frame width. Defaults to pane's current width.
457+
content_height : int, optional
458+
Frame height. Defaults to pane's current height.
459+
overflow_behavior : OverflowBehavior, optional
460+
How to handle content that exceeds frame dimensions.
461+
Defaults to ``"truncate"`` since pane content may exceed
462+
nominal dimensions during terminal transitions.
463+
464+
Returns
465+
-------
466+
:class:`~libtmux.textframe.TextFrame`
467+
Frame containing captured pane content.
468+
469+
Examples
470+
--------
471+
>>> pane.send_keys('echo "Hello"', enter=True)
472+
>>> import time; time.sleep(0.1)
473+
>>> frame = pane.capture_frame(content_width=20, content_height=5)
474+
>>> 'Hello' in frame.render()
475+
True
476+
477+
>>> print(frame.render()) # doctest: +SKIP
478+
+--------------------+
479+
|$ echo "Hello" |
480+
|Hello |
481+
|$ |
482+
| |
483+
| |
484+
+--------------------+
485+
"""
486+
from libtmux.textframe import TextFrame as TextFrameClass
487+
488+
# Capture content
489+
lines = self.capture_pane(start=start, end=end)
490+
491+
# Use pane dimensions if not specified
492+
self.refresh()
493+
width = (
494+
content_width if content_width is not None else int(self.pane_width or 80)
495+
)
496+
height = (
497+
content_height
498+
if content_height is not None
499+
else int(self.pane_height or 24)
500+
)
501+
502+
# Create and populate frame
503+
frame = TextFrameClass(
504+
content_width=width,
505+
content_height=height,
506+
overflow_behavior=overflow_behavior,
507+
)
508+
frame.set_content(lines)
509+
510+
return frame
511+
423512
def send_keys(
424513
self,
425514
cmd: str,

0 commit comments

Comments
 (0)