def test_pane_differences(capsys): """ Test getting differences between panes """ panes1 = [Pane("pane1", "p", SPLIT_HORIZONTAL).set_number(0)] panes2 = [Pane("pane2", "p2", SPLIT_VERTICAL).set_number(1)] window1 = Window("win1", "window") window1.panes = panes1 window2 = Window("win2", "window2") window2.panes = panes2 expected = { "single": [ { "direction": {"expected": SPLIT_HORIZONTAL, "actual": SPLIT_VERTICAL,}, "split_from": {}, "start_dir": {}, } ] } actual = {"single": window1.get_pane_differences(window2.panes)} panes1.append(Pane("pane3", "p", SPLIT_HORIZONTAL)) panes2.append(Pane("pane4", "p", SPLIT_HORIZONTAL)) panes1[-1].set_target("pane1") panes2[-1].set_target("pane2") expected["multi"] = deepcopy(expected["single"]) expected["multi"].append( {"split_from": {"expected": "pane1", "actual": "pane2"}, "start_dir": {}} ) actual["multi"] = window1.get_pane_differences(window2.panes) assert_objects_equal(expected, actual, expected.keys(), capsys)
def test_get_split_command(capsys): """ Tests the command to generate the split works correctly """ pane = Pane("identity", type("Window", (object, ), {"number": 1}), SPLIT_VERTICAL) expected = {} actual = {} window = type("FakeWindow", (object, ), {"number": 1}) (Pane("pane1", window, SPLIT_HORIZONTAL).set_session_name("session").set_number(1)) expected["empty"] = "split-window -{0}".format(SPLIT_VERTICAL) actual["empty"] = pane.get_split_command() pane.set_start_dir('-c "home"') expected["with_dir"] = "split-window -{0} {1}".format( SPLIT_VERTICAL, '-c "home"') actual["with_dir"] = pane.get_split_command() pane.set_session_name("session").set_number(0).set_target("pane1") expected["all"] = "split-window -{0} -t {2} {1}".format( SPLIT_VERTICAL, '-c "home"', get_pane_syntax("session", 1, 1)) actual["all"] = pane.get_split_command() assert_objects_equal(expected, actual, expected.keys(), capsys)
def test_get_sets(capsys): """ Test setting and getting of attributes """ (Pane("target", "fake_window", None).set_session_name("session").set_number(0)) pane = Pane("identity", "fake_window", SPLIT_VERTICAL, True) pane.set_number(5).set_session_name("session").set_target( "target").set_start_dir("dir").set_size(30, 40) properties = { "identity": "identity", "number": 5, "window": "fake_window", "direction": SPLIT_VERTICAL, "split_from": "target", "session_name": "session", "start_dir": "dir", "command": "", "width": 30, "height": 40, "is_first": True, } assert_objects_equal(properties, pane, properties.keys(), capsys)
def add_pane(self, pane: Pane) -> "Window": """ Adds a pane to this window Parameters ---------- pane : Pane The pane to add to the window Returns ------- This instance """ self.panes.append(pane) if pane.split_from is not None: parent_pane_number = self.objects.get_pane_by_id( pane.split_from).number # Tmux numbers panes left-to-right & top-down, order dependent on initial split # Each time a pane is split, the number increases by one from where it was split # Thus, anything equal to or larger than the initial pane will increase by one # This emulates that logic in the cached panes here if pane.split_from is not None: for window_pane in self.panes: if window_pane.number >= parent_pane_number + 1: window_pane.number = window_pane.number + 1 pane.number = parent_pane_number + 1 return self
def test_add_pane(capsys): """ Test adding a pane """ window = Window("id", "name").set_number(1) expected = {"init": []} actual = {"init": deepcopy(window.panes)} pane = ( Pane("identity", window, SPLIT_HORIZONTAL) .set_session_name("session") .set_number(0) ) window.add_pane(pane) expected["single"] = 1 actual["single"] = window.get_pane_count() pane2 = ( Pane("identity2", window, SPLIT_HORIZONTAL) .set_session_name("session") .set_number(2) .set_target("identity") ) window.add_pane(pane2) expected["get"] = {"id": id(pane), "num": 1} actual["get"] = {"id": id(window.get_pane(0)), "num": pane2.number} pane3 = ( Pane("identity3", window, SPLIT_HORIZONTAL) .set_session_name("session") .set_number(2) .set_target("identity") ) window.add_pane(pane3) expected["inserted"] = 1 actual["inserted"] = pane3.number expected["previous"] = 2 actual["previous"] = pane2.number expected["middle"] = id(pane2) actual["middle"] = id(window.get_pane(1)) assert_objects_equal(expected, actual, expected.keys(), capsys)
def add_simple_pane(self, win_id: str, parent_id: str = None) -> None: """ Adds a pane to this window Parameters ---------- win_id : str The window ID to prefix this pane with parent_id = None : str Optionally, the ID of this pane's parent """ if parent_id: number = self.objects.get_pane_by_id(parent_id).number + 1 else: number = 0 debug("Window", "add_simple_pane", "Adding pane: " + str(number)) # The layout is a single pane pane = Pane(win_id + str(number), self, None, True) self.panes_added += 1 # All that's left after the comma is the pane number pane.set_number(number) self.panes.append(pane)
def test_get_target(capsys): """ Verify getting of target works as expected """ window = type("FakeWindow", (object, ), {"number": 1}) pane = (Pane("identity1", window, SPLIT_VERTICAL).set_session_name("session").set_number(1)) pane2 = (Pane("identity2", window, SPLIT_VERTICAL).set_session_name("session").set_number(2)) expected = {"none": None} actual = {"none": pane.get_target()} pane.set_target("identity2") expected["target"] = get_pane_syntax("session", 1, 2) actual["target"] = pane.get_target() pane2.set_number(3) expected[""] = get_pane_syntax("session", 1, 3) actual[""] = pane2.get_target(True) assert_objects_equal(expected, actual, expected.keys(), capsys)
def test_pane_creation(capsys): """ Test that a pane that is created has the proper attributes """ pane = Pane("identity", "fake_window", SPLIT_HORIZONTAL) properties = { "identity": "identity", "window": "fake_window", "direction": SPLIT_HORIZONTAL, "split_from": None, "command": "", "width": 0, "height": 0, "is_first": False, } assert_objects_equal(properties, pane, properties.keys(), capsys)
def test_get_command(capsys): """ Verify getting the command works """ pane = Pane("identity", "fake_window", SPLIT_VERTICAL) expected = {"none": ""} actual = {"none": pane.get_run_command()} pane.set_command("foo") expected["cmd"] = 'send-keys "foo" "C-m"' actual["cmd"] = pane.get_run_command() assert_objects_equal(expected, actual, expected.keys(), capsys)
def add_pane_by_layout(self, layout: str, pane_number: int, direction: str, parent_identity: str = None) -> None: """ Adds a new pane, using the layout to fill in details Parameters ---------- layout : string The layout string for the pane Will be in the following format: <size>,<offset_left>,<offset_top> pane_number : number The number of the pane, from the layout direction : string The direction this pane should be split from the previous one parent_identity : string The identity of the parent pane Used to re-order panes, if needed """ size = parse_size(layout.split(",")[0]) pane_id = "win{0}pane{1}".format(self.number, self.panes_added) pane = (Pane(pane_id, self, direction, self.panes_added == 0).set_session_name( self.session_name).set_size( 100 * size["width"] / self.base_width, 100 * size["height"] / self.base_height, )) parent = None try: parent = self.objects.get_pane_by_id(parent_identity) parent_number = parent.number except NameError: parent_number = None pane_number = (parent_number + 1 if parent_number is not None else self.panes_added) if parent_number is not None and self.panes_added > pane_number: debug( "Window", "add_pane", "Incrementing pane numbers above {0}".format(pane_number), ) for pane_to_check in self.panes: if pane_to_check.number >= pane_number: pane_to_check.set_number(pane_to_check.number + 1) pane.set_number(pane_number) if self.last_pane is not None and parent_number is None: pane.set_target(self.last_pane) elif parent: pane.set_target(parent.identity) self.last_pane = pane.identity self.panes_added += 1 self.panes.append(pane) debug( "Window", "add_pane", "Adding pane number {0} for parent {1} with size {2}".format( pane_number, parent_number, size), )
def test_command_quoting(capsys): """ Verify commands are escaped properly """ pane = Pane("identity", "fake_window", SPLIT_VERTICAL) pane.set_command("foo") expected = {} actual = {} expected["command1"] = '"foo" "C-m"' actual["command1"] = pane.command pane.set_command("foo", False) expected["command2"] = '"foo"' actual["command2"] = pane.command pane.set_command('echo "foo"') expected["command3"] = '"echo \\"foo\\"" "C-m"' actual["command3"] = pane.command pane.set_command("echo 'foo'") expected["command4"] = '"echo \'foo\'" "C-m"' actual["command4"] = pane.command pane.set_command('"echo \\"things\\"" "C-m"') expected["already_quoted"] = '"echo \\"things\\"" "C-m"' actual["already_quoted"] = pane.command assert_objects_equal(expected, actual, expected.keys(), capsys)
def test_differences(capsys): """ Test differences between panes """ pane1 = Pane("identity1", "fake_window", SPLIT_VERTICAL) pane2 = Pane("identity2", "fake_window", SPLIT_VERTICAL) expected = {"none": {}} actual = {"none": pane1.get_difference(pane2)} pane2 = Pane("identity3", "fake_window", SPLIT_HORIZONTAL) expected["dir"] = { "direction": { "expected": SPLIT_VERTICAL, "actual": SPLIT_HORIZONTAL } } actual["dir"] = pane1.get_difference(pane2) pane2 = Pane("identity4", "fake_window", SPLIT_VERTICAL) pane1.set_size(10, 20) pane2.set_size(30, 40) expected["size"] = { "width": { "expected": 10, "actual": 30 }, "height": { "expected": 20, "actual": 40 }, } actual["size"] = pane1.get_difference(pane2) assert_objects_equal(expected, actual, expected.keys(), capsys)
def test_size_command(capsys): """ Check the size command works appropriately """ window = type("FakeWindow", (object, ), {"number": 1}) target = get_pane_syntax("s", 1, 1) pane = Pane("identity1", window, SPLIT_VERTICAL).set_session_name("s").set_number(1) expected = {"none": ""} actual = {"none": pane.get_size_command()} pane.set_size(10) expected["width"] = "resize-pane -t {0} -x {1} ".format(target, 10) actual["width"] = pane.get_size_command() pane.set_size(10, 20) expected["both"] = "resize-pane -t {0} -x {1} -y {2}".format( target, 10, 20) actual["both"] = pane.get_size_command() pane = (Pane("identity2", window, SPLIT_VERTICAL).set_session_name("s").set_number(1).set_size( 0, 20)) expected["both"] = "resize-pane -t {0} -y {1}".format(target, 20) actual["both"] = pane.get_size_command() assert_objects_equal(expected, actual, expected.keys(), capsys)
def add_pane( self, identity: str, split_dir: str, window: str = None, split_from: str = None, working_directory: str = None, ) -> "TmuxBuilder": """ Adds a new pane to target or current window Parameters ---------- identity : string A unique ID for this pane split_dir : string The direction to split the window, either 'h' (horizontal) or 'v' (vertical) window : string|None The window ID to create the pane in, defaults to the current window split_from : string|None The pane ID to split this one from working_directory : string|None The working directory to set for this pane Returns ------- This instance """ if split_dir not in [None, "h", "v"]: raise ValueError( 'Invalid split direction specified: must be "v" or "h"!') if split_from: target = self.objects.get_pane_by_id(split_from) window = target.window else: window = self.__coalesce_window(window) target = None panes = window.get_pane_count() start_dir = None if working_directory: start_dir = format_working_directory(working_directory) elif window.start_dir: start_dir = window.start_dir else: start_dir = format_working_directory(self.start_dir) pane = (Pane(identity, window, split_dir, panes == 0).set_number(panes).set_session_name( self.session_name).set_start_dir(start_dir)) if split_from: pane.set_target(split_from) window.add_pane(pane) # The index of the current pane, not the number self.current_pane = window.get_pane_count() - 1 return self