Compare commits
3 commits
05c9a48bb3
...
108091bfae
| Author | SHA1 | Date | |
|---|---|---|---|
| 108091bfae | |||
| f8e9ae0acc | |||
| 54cd0f6656 |
4 changed files with 28 additions and 12 deletions
2
justfile
2
justfile
|
|
@ -6,7 +6,7 @@ typecheck:
|
||||||
uvx ty check
|
uvx ty check
|
||||||
|
|
||||||
test:
|
test:
|
||||||
uv run pytest -n auto --testmon
|
uv run pytest -n auto --no-testmon
|
||||||
|
|
||||||
check: lint typecheck test
|
check: lint typecheck test
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -203,20 +203,34 @@ class IFSession:
|
||||||
buf += chunk
|
buf += chunk
|
||||||
|
|
||||||
# Check for prompt at end of buffer
|
# Check for prompt at end of buffer
|
||||||
# dfrotz prompt is "\n> " (with trailing space)
|
# dfrotz prompt is always "> " (with trailing space/newline)
|
||||||
text = buf.decode("latin-1").rstrip()
|
raw = buf.decode("latin-1")
|
||||||
|
has_prompt = (
|
||||||
|
raw.endswith("> ") or raw.endswith(">\n") or raw.endswith(">\r\n")
|
||||||
|
)
|
||||||
|
text = raw.rstrip()
|
||||||
|
# \n> is always the dfrotz prompt — strip unconditionally
|
||||||
if text.endswith("\n>"):
|
if text.endswith("\n>"):
|
||||||
return text[:-2].rstrip()
|
return text[:-2].rstrip()
|
||||||
if text == ">":
|
if text == ">":
|
||||||
return ""
|
return ""
|
||||||
|
# bare > (no preceding newline) — only strip when raw confirms prompt
|
||||||
|
if has_prompt and text.endswith(">"):
|
||||||
|
return text[:-1].rstrip()
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
text = buf.decode("latin-1").rstrip()
|
raw = buf.decode("latin-1")
|
||||||
|
has_prompt = raw.endswith("> ") or raw.endswith(">\n") or raw.endswith(">\r\n")
|
||||||
|
text = raw.rstrip()
|
||||||
|
# \n> is always the dfrotz prompt — strip unconditionally
|
||||||
if text.endswith("\n>"):
|
if text.endswith("\n>"):
|
||||||
return text[:-2].rstrip()
|
return text[:-2].rstrip()
|
||||||
if text == ">":
|
if text == ">":
|
||||||
return ""
|
return ""
|
||||||
|
# bare > (no preceding newline) — only strip when raw confirms prompt
|
||||||
|
if has_prompt and text.endswith(">"):
|
||||||
|
return text[:-1].rstrip()
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -315,7 +315,7 @@ async def shell(
|
||||||
if player.mode == "editor" and player.editor:
|
if player.mode == "editor" and player.editor:
|
||||||
_writer.write(f" {player.editor.cursor + 1}> ")
|
_writer.write(f" {player.editor.cursor + 1}> ")
|
||||||
elif player.mode == "if" and player.if_session:
|
elif player.mode == "if" and player.if_session:
|
||||||
_writer.write("> ")
|
_writer.write("\r\n> ")
|
||||||
else:
|
else:
|
||||||
_writer.write("mud> ")
|
_writer.write("mud> ")
|
||||||
await _writer.drain()
|
await _writer.drain()
|
||||||
|
|
@ -340,20 +340,22 @@ async def shell(
|
||||||
elif player.mode == "if" and player.if_session:
|
elif player.mode == "if" and player.if_session:
|
||||||
response = await player.if_session.handle_input(command)
|
response = await player.if_session.handle_input(command)
|
||||||
if response.output:
|
if response.output:
|
||||||
await player.send(response.output)
|
# Ensure output ends with newline
|
||||||
|
output = response.output
|
||||||
|
if not output.endswith("\r\n"):
|
||||||
|
output += "\r\n"
|
||||||
|
await player.send(output)
|
||||||
# Broadcast to spectators unless it's an escape command
|
# Broadcast to spectators unless it's an escape command
|
||||||
if not command.startswith("::"):
|
if not command.startswith("::"):
|
||||||
spectator_msg = (
|
spectator_msg = (
|
||||||
f"[{player.name}'s terminal]\r\n"
|
f"[{player.name}'s terminal]\r\n> {command}\r\n{output}"
|
||||||
f"> {command}\r\n"
|
|
||||||
f"{response.output}"
|
|
||||||
)
|
)
|
||||||
await broadcast_to_spectators(player, spectator_msg)
|
await broadcast_to_spectators(player, spectator_msg)
|
||||||
if response.done:
|
if response.done:
|
||||||
await player.if_session.stop()
|
await player.if_session.stop()
|
||||||
player.if_session = None
|
player.if_session = None
|
||||||
player.mode_stack.pop()
|
player.mode_stack.pop()
|
||||||
await player.send("you leave the terminal.\r\n")
|
await player.send("\r\nyou leave the terminal.\r\n")
|
||||||
# Notify spectators
|
# Notify spectators
|
||||||
leave_msg = f"{player.name} steps away from the terminal.\r\n"
|
leave_msg = f"{player.name} steps away from the terminal.\r\n"
|
||||||
await broadcast_to_spectators(player, leave_msg)
|
await broadcast_to_spectators(player, leave_msg)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ async def test_start_spawns_subprocess_and_returns_intro():
|
||||||
mock_process.stdout = AsyncMock()
|
mock_process.stdout = AsyncMock()
|
||||||
mock_process.stdin = AsyncMock()
|
mock_process.stdin = AsyncMock()
|
||||||
|
|
||||||
# Simulate dfrotz output: intro text followed by ">" prompt
|
# Simulate dfrotz output: intro text followed by "\n>" prompt
|
||||||
intro_bytes = b"Welcome to the story!\nYou are in a room.\n>"
|
intro_bytes = b"Welcome to the story!\nYou are in a room.\n>"
|
||||||
|
|
||||||
async def read_side_effect(n):
|
async def read_side_effect(n):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue