mud/src/mudlib/commands/alias.py
Jared Miller 3f042de360
Add player alias system with persistence and dispatch
Implements a complete alias system allowing players to create command shortcuts.
Aliases are expanded during dispatch with a recursion guard (max 10 levels).

Changes:
- Add aliases field to Player dataclass (dict[str, str])
- Add player_aliases table to database schema
- Add save_aliases() and load_aliases() persistence functions
- Add alias/unalias commands with built-in command protection
- Integrate alias expansion into dispatch() before command resolution
- Add comprehensive test coverage for all features
2026-02-14 01:39:45 -05:00

74 lines
2 KiB
Python

"""Player alias commands."""
from mudlib.commands import CommandDefinition, _registry, register
from mudlib.player import Player
async def cmd_alias(player: Player, args: str) -> None:
"""Create or list aliases.
Usage:
alias - List all aliases
alias <name> - Show a specific alias
alias <name> <exp> - Create an alias
"""
args = args.strip()
# No args: list all aliases
if not args:
if not player.aliases:
await player.send("No aliases defined.\r\n")
else:
lines = [
f"{alias} -> {expansion}"
for alias, expansion in sorted(player.aliases.items())
]
await player.send("\r\n".join(lines) + "\r\n")
return
# Check if this is a single-word lookup or a definition
parts = args.split(None, 1)
alias_name = parts[0]
if len(parts) == 1:
# Show single alias
if alias_name in player.aliases:
await player.send(f"{alias_name} -> {player.aliases[alias_name]}\r\n")
else:
await player.send(f"No such alias: {alias_name}\r\n")
return
# Create alias
expansion = parts[1]
# Cannot alias over built-in commands
if alias_name in _registry:
await player.send(f"Cannot alias over built-in command: {alias_name}\r\n")
return
player.aliases[alias_name] = expansion
await player.send(f"Alias set: {alias_name} -> {expansion}\r\n")
async def cmd_unalias(player: Player, args: str) -> None:
"""Remove an alias.
Usage:
unalias <name>
"""
alias_name = args.strip()
if not alias_name:
await player.send("Usage: unalias <name>\r\n")
return
if alias_name in player.aliases:
del player.aliases[alias_name]
await player.send(f"Alias removed: {alias_name}\r\n")
else:
await player.send(f"No such alias: {alias_name}\r\n")
# Register commands
register(CommandDefinition("alias", cmd_alias))
register(CommandDefinition("unalias", cmd_unalias))