Skip to content

Commit 2e1ac45

Browse files
committed
feat(Pane): Add Pane.split, deprecate Pane.split_window
1 parent 6ea527b commit 2e1ac45

File tree

1 file changed

+151
-18
lines changed

1 file changed

+151
-18
lines changed

src/libtmux/pane.py

Lines changed: 151 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77

88
import dataclasses
99
import logging
10+
import pathlib
1011
import typing as t
1112
import warnings
1213
from typing import overload
1314

14-
from libtmux.common import has_gte_version, tmux_cmd
15+
from libtmux.common import has_gte_version, has_lt_version, tmux_cmd
1516
from libtmux.constants import (
1617
RESIZE_ADJUSTMENT_DIRECTION_FLAG_MAP,
1718
ResizeAdjustmentDirection,
1819
)
20+
from libtmux.formats import FORMAT_SEPARATOR
1921
from libtmux.neo import Obj, fetch_obj
2022

2123
from . import exc
@@ -483,47 +485,132 @@ def select_pane(self) -> "Pane":
483485
raise exc.PaneNotFound(pane_id=self.pane_id)
484486
return pane
485487

486-
def split_window(
488+
def split(
487489
self,
488-
attach: bool = False,
489490
start_directory: t.Optional[str] = None,
491+
attach: bool = False,
490492
vertical: bool = True,
491493
shell: t.Optional[str] = None,
492494
size: t.Optional[t.Union[str, int]] = None,
493495
percent: t.Optional[int] = None, # deprecated
494496
environment: t.Optional[t.Dict[str, str]] = None,
495-
) -> "Pane": # New Pane, not self
496-
"""Split window at pane and return newly created :class:`Pane`.
497+
) -> "Pane":
498+
"""Split window and return the created :class:`Pane`.
499+
500+
Used for splitting window and holding in a python object.
497501
498502
Parameters
499503
----------
500504
attach : bool, optional
501-
Attach / select pane after creation.
505+
make new window the current window after creating it, default
506+
True.
502507
start_directory : str, optional
503-
specifies the working directory in which the new pane is created.
508+
specifies the working directory in which the new window is created.
504509
vertical : bool, optional
505510
split vertically
511+
shell : str, optional
512+
execute a command on splitting the window. The pane will close
513+
when the command exits.
514+
515+
NOTE: When this command exits the pane will close. This feature
516+
is useful for long-running processes where the closing of the
517+
window upon completion is desired.
518+
size: int, optional
519+
Cell/row or percentage to occupy with respect to current window.
506520
percent: int, optional
507-
percentage to occupy with respect to current pane
521+
Deprecated in favor of size. Percentage to occupy with respect to current
522+
window.
508523
environment: dict, optional
509524
Environmental variables for new pane. tmux 3.0+ only. Passthrough to ``-e``.
510525
511526
Notes
512527
-----
528+
:term:`tmux(1)` will move window to the new pane if the
529+
``split-window`` target is off screen. tmux handles the ``-d`` the
530+
same way as ``new-window`` and ``attach`` in
531+
:class:`Session.new_window`.
532+
533+
By default, this will make the window the pane is created in
534+
active. To remain on the same window and split the pane in another
535+
target window, pass in ``attach=False``.
536+
537+
.. versionchanged:: 0.28.0
538+
539+
``attach`` default changed from ``True`` to ``False``.
540+
513541
.. deprecated:: 0.28.0
514542
515543
``percent=25`` deprecated in favor of ``size="25%"``.
516544
"""
517-
return self.window.split_window(
518-
target=self.pane_id,
519-
attach=attach,
520-
start_directory=start_directory,
521-
vertical=vertical,
522-
shell=shell,
523-
size=size,
524-
percent=percent,
525-
environment=environment,
526-
)
545+
tmux_formats = ["#{pane_id}" + FORMAT_SEPARATOR]
546+
547+
tmux_args: t.Tuple[str, ...] = ()
548+
549+
if vertical:
550+
tmux_args += ("-v",)
551+
else:
552+
tmux_args += ("-h",)
553+
554+
if size is not None:
555+
if has_lt_version("3.1"):
556+
if isinstance(size, str) and size.endswith("%"):
557+
tmux_args += (f'-p{str(size).rstrip("%")}',)
558+
else:
559+
warnings.warn(
560+
'Ignored size. Use percent in tmux < 3.1, e.g. "size=50%"',
561+
stacklevel=2,
562+
)
563+
else:
564+
tmux_args += (f"-l{size}",)
565+
566+
if percent is not None:
567+
# Deprecated in 3.1 in favor of -l
568+
warnings.warn(
569+
f'Deprecated in favor of size="{str(percent).rstrip("%")}%" '
570+
+ ' ("-l" flag) in tmux 3.1+.',
571+
category=DeprecationWarning,
572+
stacklevel=2,
573+
)
574+
tmux_args += (f"-p{percent}",)
575+
576+
tmux_args += ("-P", "-F%s" % "".join(tmux_formats)) # output
577+
578+
if start_directory is not None:
579+
# as of 2014-02-08 tmux 1.9-dev doesn't expand ~ in new-window -c.
580+
start_path = pathlib.Path(start_directory).expanduser()
581+
tmux_args += (f"-c{start_path}",)
582+
583+
if not attach:
584+
tmux_args += ("-d",)
585+
586+
if environment:
587+
if has_gte_version("3.0"):
588+
for k, v in environment.items():
589+
tmux_args += (f"-e{k}={v}",)
590+
else:
591+
logger.warning(
592+
"Environment flag ignored, tmux 3.0 or newer required.",
593+
)
594+
595+
if shell:
596+
tmux_args += (shell,)
597+
598+
pane_cmd = self.cmd("split-window", *tmux_args)
599+
600+
# tmux < 1.7. This is added in 1.7.
601+
if pane_cmd.stderr:
602+
if "pane too small" in pane_cmd.stderr:
603+
raise exc.LibTmuxException(pane_cmd.stderr)
604+
605+
raise exc.LibTmuxException(
606+
pane_cmd.stderr, self.__dict__, self.window.panes
607+
)
608+
609+
pane_output = pane_cmd.stdout[0]
610+
611+
pane_formatters = dict(zip(["pane_id"], pane_output.split(FORMAT_SEPARATOR)))
612+
613+
return self.from_pane_id(server=self.server, pane_id=pane_formatters["pane_id"])
527614

528615
"""
529616
Commands (helpers)
@@ -636,6 +723,52 @@ def width(self) -> t.Optional[str]:
636723
#
637724
# Legacy: Redundant stuff we want to remove
638725
#
726+
def split_window(
727+
self,
728+
attach: bool = False,
729+
start_directory: t.Optional[str] = None,
730+
vertical: bool = True,
731+
shell: t.Optional[str] = None,
732+
size: t.Optional[t.Union[str, int]] = None,
733+
percent: t.Optional[int] = None, # deprecated
734+
environment: t.Optional[t.Dict[str, str]] = None,
735+
) -> "Pane": # New Pane, not self
736+
"""Split window at pane and return newly created :class:`Pane`.
737+
738+
Parameters
739+
----------
740+
attach : bool, optional
741+
Attach / select pane after creation.
742+
start_directory : str, optional
743+
specifies the working directory in which the new pane is created.
744+
vertical : bool, optional
745+
split vertically
746+
percent: int, optional
747+
percentage to occupy with respect to current pane
748+
environment: dict, optional
749+
Environmental variables for new pane. tmux 3.0+ only. Passthrough to ``-e``.
750+
751+
Notes
752+
-----
753+
.. deprecated:: 0.33
754+
755+
Deprecated in favor of :meth:`.split`.
756+
"""
757+
warnings.warn(
758+
"Pane.split_window() is deprecated in favor of Pane.split()",
759+
category=DeprecationWarning,
760+
stacklevel=2,
761+
)
762+
return self.split(
763+
attach=attach,
764+
start_directory=start_directory,
765+
vertical=vertical,
766+
shell=shell,
767+
size=size,
768+
percent=percent,
769+
environment=environment,
770+
)
771+
639772
def get(self, key: str, default: t.Optional[t.Any] = None) -> t.Any:
640773
"""Return key-based lookup. Deprecated by attributes.
641774

0 commit comments

Comments
 (0)