Skip to content

Commit 86297ec

Browse files
committed
Server(feat[buffers]): add save_buffer, load_buffer, list_buffers for buffer I/O
why: Buffer file I/O and listing are needed for exporting pane content, importing data, and querying available buffers programmatically. what: - Add Server.save_buffer() wrapping save-buffer with append (-a), buffer_name (-b), and file path - Add Server.load_buffer() wrapping load-buffer with buffer_name (-b) and file path - Add Server.list_buffers() wrapping list-buffers returning raw output - Add tests for save/load cycle, append mode, and buffer listing
1 parent a4e5b92 commit 86297ec

2 files changed

Lines changed: 140 additions & 0 deletions

File tree

src/libtmux/server.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,102 @@ def delete_buffer(self, *, buffer_name: str | None = None) -> None:
622622
if proc.stderr:
623623
raise exc.LibTmuxException(proc.stderr)
624624

625+
def save_buffer(
626+
self,
627+
path: StrPath,
628+
*,
629+
buffer_name: str | None = None,
630+
append: bool | None = None,
631+
) -> None:
632+
"""Save a paste buffer to a file via ``$ tmux save-buffer``.
633+
634+
Parameters
635+
----------
636+
path : str or PathLike
637+
File path to save the buffer to.
638+
buffer_name : str, optional
639+
Name of the buffer (``-b`` flag). Defaults to the most recent.
640+
append : bool, optional
641+
Append to the file instead of overwriting (``-a`` flag).
642+
643+
Examples
644+
--------
645+
>>> import pathlib
646+
>>> server.set_buffer('save_me')
647+
>>> path = pathlib.Path(request.config.rootdir) / '..' / 'tmp_save.txt'
648+
>>> server.save_buffer(str(path))
649+
"""
650+
tmux_args: tuple[str, ...] = ()
651+
652+
if append:
653+
tmux_args += ("-a",)
654+
655+
if buffer_name is not None:
656+
tmux_args += ("-b", buffer_name)
657+
658+
tmux_args += (str(pathlib.Path(path).expanduser()),)
659+
660+
proc = self.cmd("save-buffer", *tmux_args)
661+
662+
if proc.stderr:
663+
raise exc.LibTmuxException(proc.stderr)
664+
665+
def load_buffer(
666+
self,
667+
path: StrPath,
668+
*,
669+
buffer_name: str | None = None,
670+
) -> None:
671+
"""Load a file into a paste buffer via ``$ tmux load-buffer``.
672+
673+
Parameters
674+
----------
675+
path : str or PathLike
676+
File path to load into the buffer.
677+
buffer_name : str, optional
678+
Name of the buffer (``-b`` flag).
679+
680+
Examples
681+
--------
682+
>>> import pathlib
683+
>>> path = pathlib.Path(request.config.rootdir) / '..' / 'tmp_load.txt'
684+
>>> _ = path.write_text('loaded')
685+
>>> server.load_buffer(str(path), buffer_name='loaded_buf')
686+
"""
687+
tmux_args: tuple[str, ...] = ()
688+
689+
if buffer_name is not None:
690+
tmux_args += ("-b", buffer_name)
691+
692+
tmux_args += (str(pathlib.Path(path).expanduser()),)
693+
694+
proc = self.cmd("load-buffer", *tmux_args)
695+
696+
if proc.stderr:
697+
raise exc.LibTmuxException(proc.stderr)
698+
699+
def list_buffers(self) -> list[str]:
700+
"""List paste buffers via ``$ tmux list-buffers``.
701+
702+
Returns
703+
-------
704+
list[str]
705+
Raw output lines from list-buffers.
706+
707+
Examples
708+
--------
709+
>>> server.set_buffer('buf_data')
710+
>>> result = server.list_buffers()
711+
>>> len(result) >= 1
712+
True
713+
"""
714+
proc = self.cmd("list-buffers")
715+
716+
if proc.stderr:
717+
raise exc.LibTmuxException(proc.stderr)
718+
719+
return proc.stdout
720+
625721
def switch_client(self, target_session: str) -> None:
626722
"""Switch tmux client.
627723

tests/test_server.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,50 @@ def test_buffer_delete(server: Server) -> None:
561561
server.show_buffer(buffer_name="del_buf")
562562

563563

564+
def test_buffer_save_load(server: Server, tmp_path: pathlib.Path) -> None:
565+
"""Test Server.save_buffer() and load_buffer() cycle."""
566+
server.new_session(session_name="buf_saveload")
567+
568+
# Set and save
569+
server.set_buffer("save_test_data")
570+
buf_file = tmp_path / "saved_buf.txt"
571+
server.save_buffer(buf_file)
572+
573+
# Verify file content
574+
assert buf_file.read_text() == "save_test_data"
575+
576+
# Load into a named buffer
577+
server.load_buffer(buf_file, buffer_name="loaded_buf")
578+
assert server.show_buffer(buffer_name="loaded_buf") == "save_test_data"
579+
580+
581+
def test_buffer_save_append(server: Server, tmp_path: pathlib.Path) -> None:
582+
"""Test Server.save_buffer() with append flag."""
583+
server.new_session(session_name="buf_saveappend")
584+
585+
buf_file = tmp_path / "append_buf.txt"
586+
587+
server.set_buffer("first_line", buffer_name="app1")
588+
server.save_buffer(buf_file, buffer_name="app1")
589+
590+
server.set_buffer("second_line", buffer_name="app2")
591+
server.save_buffer(buf_file, buffer_name="app2", append=True)
592+
593+
content = buf_file.read_text()
594+
assert "first_line" in content
595+
assert "second_line" in content
596+
597+
598+
def test_list_buffers(server: Server) -> None:
599+
"""Test Server.list_buffers()."""
600+
server.new_session(session_name="buf_list")
601+
server.set_buffer("buf_a", buffer_name="list_a")
602+
server.set_buffer("buf_b", buffer_name="list_b")
603+
604+
result = server.list_buffers()
605+
assert len(result) >= 2
606+
607+
564608
def test_new_session_config_file(
565609
server: Server,
566610
tmp_path: pathlib.Path,

0 commit comments

Comments
 (0)