|
7 | 7 |
|
8 | 8 | import dataclasses |
9 | 9 | import logging |
| 10 | +import pathlib |
10 | 11 | import typing as t |
11 | 12 | import warnings |
12 | 13 | from typing import overload |
13 | 14 |
|
14 | | -from libtmux.common import has_gte_version, tmux_cmd |
| 15 | +from libtmux.common import has_gte_version, has_lt_version, tmux_cmd |
15 | 16 | from libtmux.constants import ( |
16 | 17 | RESIZE_ADJUSTMENT_DIRECTION_FLAG_MAP, |
17 | 18 | ResizeAdjustmentDirection, |
18 | 19 | ) |
| 20 | +from libtmux.formats import FORMAT_SEPARATOR |
19 | 21 | from libtmux.neo import Obj, fetch_obj |
20 | 22 |
|
21 | 23 | from . import exc |
@@ -483,47 +485,132 @@ def select_pane(self) -> "Pane": |
483 | 485 | raise exc.PaneNotFound(pane_id=self.pane_id) |
484 | 486 | return pane |
485 | 487 |
|
486 | | - def split_window( |
| 488 | + def split( |
487 | 489 | self, |
488 | | - attach: bool = False, |
489 | 490 | start_directory: t.Optional[str] = None, |
| 491 | + attach: bool = False, |
490 | 492 | vertical: bool = True, |
491 | 493 | shell: t.Optional[str] = None, |
492 | 494 | size: t.Optional[t.Union[str, int]] = None, |
493 | 495 | percent: t.Optional[int] = None, # deprecated |
494 | 496 | 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. |
497 | 501 |
|
498 | 502 | Parameters |
499 | 503 | ---------- |
500 | 504 | attach : bool, optional |
501 | | - Attach / select pane after creation. |
| 505 | + make new window the current window after creating it, default |
| 506 | + True. |
502 | 507 | 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. |
504 | 509 | vertical : bool, optional |
505 | 510 | 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. |
506 | 520 | 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. |
508 | 523 | environment: dict, optional |
509 | 524 | Environmental variables for new pane. tmux 3.0+ only. Passthrough to ``-e``. |
510 | 525 |
|
511 | 526 | Notes |
512 | 527 | ----- |
| 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 | +
|
513 | 541 | .. deprecated:: 0.28.0 |
514 | 542 |
|
515 | 543 | ``percent=25`` deprecated in favor of ``size="25%"``. |
516 | 544 | """ |
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"]) |
527 | 614 |
|
528 | 615 | """ |
529 | 616 | Commands (helpers) |
@@ -636,6 +723,52 @@ def width(self) -> t.Optional[str]: |
636 | 723 | # |
637 | 724 | # Legacy: Redundant stuff we want to remove |
638 | 725 | # |
| 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 | + |
639 | 772 | def get(self, key: str, default: t.Optional[t.Any] = None) -> t.Any: |
640 | 773 | """Return key-based lookup. Deprecated by attributes. |
641 | 774 |
|
|
0 commit comments