Skip to content

Commit 3654a36

Browse files
committed
Window(fix[move_window]): refresh moved window state
why: move-window can land on an index different from the requested target and can also change the owning session, leaving the returned Window stale. what: - refresh Window state after every successful move-window command - add regressions for relative move freshness - add a cross-session move regression with an explicit destination
1 parent 79331a1 commit 3654a36

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

src/libtmux/window.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,10 +1013,7 @@ def move_window(
10131013
if proc.stderr:
10141014
raise exc.LibTmuxException(proc.stderr)
10151015

1016-
if destination != "" and session is not None:
1017-
self.window_index = destination
1018-
else:
1019-
self.refresh()
1016+
self.refresh()
10201017

10211018
return self
10221019

tests/test_window.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,54 @@ def test_move_window_to_other_session(server: Server, session: Session) -> None:
400400
assert new_session.windows.get(window_id=window_id) == window
401401

402402

403+
@pytest.mark.parametrize(
404+
("flag_name", "destination_offset"), [("after", 0), ("before", 1)]
405+
)
406+
def test_move_window_relative_returns_fresh_window(
407+
flag_name: str,
408+
destination_offset: int,
409+
session: Session,
410+
) -> None:
411+
"""Window.move_window() returns fresh state for relative moves."""
412+
destination_window = session.active_window
413+
session.new_window(window_name="move_middle")
414+
moving_window = session.new_window(window_name="move_relative")
415+
assert destination_window.window_index is not None
416+
assert moving_window.window_id is not None
417+
418+
destination = str(int(destination_window.window_index) + destination_offset)
419+
if flag_name == "after":
420+
moving_window.move_window(destination, after=True)
421+
else:
422+
moving_window.move_window(destination, before=True)
423+
424+
fresh_window = Window.from_window_id(
425+
server=session.server,
426+
window_id=moving_window.window_id,
427+
)
428+
assert moving_window.window_index == fresh_window.window_index
429+
assert moving_window.session_id == fresh_window.session_id
430+
431+
432+
def test_move_window_to_other_session_with_destination(
433+
server: Server,
434+
session: Session,
435+
) -> None:
436+
"""Window.move_window() returns fresh state for cross-session moves."""
437+
window = session.new_window(window_name="move_cross_session")
438+
assert window.window_id is not None
439+
new_session = server.new_session("test_move_window_destination")
440+
destination = "99"
441+
442+
window.move_window(destination=destination, session=new_session.session_id)
443+
444+
fresh_window = Window.from_window_id(server=server, window_id=window.window_id)
445+
assert fresh_window.session_id == new_session.session_id
446+
assert fresh_window.window_index == destination
447+
assert window.session_id == fresh_window.session_id
448+
assert window.window_index == fresh_window.window_index
449+
450+
403451
def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None:
404452
"""Tmux allows select-layout with no arguments, so let's allow it here."""
405453
window = session.new_window(window_name="test_window")

0 commit comments

Comments
 (0)