Command System - edgeof8/tIRC GitHub Wiki

Dynamic & Modular: The command system allows new commands to be added easily without modifying core client logic.

Command Structure

/command_name [arguments] [--option=value]

Commands are discovered dynamically from the tirc_core/commands/ directory.

Core Command Categories

  • Channel Ops: /join, /part, /topic
  • Server: /connect, /server, /quit
  • User: /msg, /query, /nick
  • UI: /window, /next, /clear
  • DCC: /dcc send, /dcc get
  • Scripting: /script, /trigger

Command Features

  • Tab completion for commands and arguments
  • Multiple command aliases
  • Context-aware execution
  • Async command handlers
  • Built-in help system
  • Scriptable command registration

Command Execution Flow

  1. Input Capture: User types command in input line (or command received via IPC).
  2. Parsing: CommandHandler splits command and arguments.
  3. Resolution: Finds matching command handler (Checks both core commands and script-registered commands).
  4. Execution: Runs handler in appropriate context:
    • Async handlers run directly in event loop.
    • Sync handlers run in thread pool.
  5. Response: Updates UI or sends IRC messages (All UI updates are thread-safe).

Note: tIRC's command system is fully async-capable. Commands can be implemented as either synchronous or asynchronous functions.

Command Module Structure

# Example command module (tirc_core/commands/channel/join_command.py)
from typing import Optional
from tirc_core.commands.command_handler import CommandDefinition

COMMAND_DEFINITIONS = [
    CommandDefinition(
        name="join",
        handler="handle_join_command",
        help={
            "usage": "/join <channel> [key]",
            "description": "Joins an IRC channel",
            "examples": [
                "/join #python",
                "/join #secret secretpass"
            ]
        },
        aliases=["j"]
    )
]

async def handle_join_command(client, args_str: str):
    args = args_str.split()
    if not args:
        await client.add_message("Error: Channel name required")
        return

    channel = args[0]
    key = args[1] if len(args) > 1 else None
    await client.network_handler.send(f"JOIN {channel} {key or ''}")

Help System Examples

/help         # List all commands
/help join    # Show help for /join
/help script  # Show scripting commands
/help dcc     # Show DCC commands

Scripting Integration

Scripts can register new commands using the ScriptAPI:

# In a script's on_load() method:
self.api.register_command(
    name="greet",
    handler=self.handle_greet,
    help={
        "usage": "/greet [name]",
        "description": "Sends a greeting message",
        "examples": ["/greet Alice", "/greet"]
    }
)

async def handle_greet(self, args_str: str):
    name = args_str.strip() or "everyone"
    await self.api.send_message(
        self.api.get_active_context(),
        f"Hello, {name}!"
    )

Command Registration Best Practices

  • Always provide complete help text with examples
  • Use async handlers for I/O operations
  • Validate arguments before processing
  • Handle errors gracefully with user feedback

Error Handling Example

async def handle_complex_command(self, args_str: str):
    try:
        # Parse and validate arguments
        args = self._parse_args(args_str)
        if not args.valid:
            await self.show_usage_error()
            return

        # Perform operation
        result = await self._perform_operation(args)
        await self.show_success(result)

    except ValueError as e:
        await self.show_error(f"Invalid input: {e}")
    except ConnectionError as e:
        await self.show_error(f"Network error: {e}")
    except Exception as e:
        logger.error(f"Unexpected error in command: {e}")
        await self.show_error("An unexpected error occurred")

Performance Considerations

  • Use async for network/disk operations
  • Keep sync handlers fast and non-blocking
  • Cache expensive operations where possible
  • Limit UI updates during batch operations

Advanced Usage

Command Chaining

# Example of chaining commands in a script
async def handle_chain(self, args_str: str):
    await self.api.execute_command("/connect irc.example.net")
    await asyncio.sleep(1)  # Brief delay
    await self.api.execute_command("/join #test")
    await self.api.execute_command("/msg #test Hello from script!")

Complex Command Example

import os # Added import for os.path.exists
import asyncio # Added import for asyncio.sleep

async def handle_file_upload(self, args_str: str):
    """Example complex command with multiple steps"""
    # Parse arguments
    parts = args_str.split(maxsplit=1)
    if len(parts) < 2:
        await self.show_usage_error()
        return

    nick, filepath = parts

    # Validate file
    if not os.path.exists(filepath):
        await self.show_error(f"File not found: {filepath}")
        return

    # Initiate DCC transfer
    transfer_id = await self.api.dcc_send_file(nick, filepath)

    # Monitor progress
    while True:
        status = await self.api.get_dcc_status(transfer_id)
        if status in ['COMPLETED', 'FAILED', 'CANCELLED']:
            break
        await asyncio.sleep(0.5)

    # Report final status
    if status == 'COMPLETED':
        await self.show_success(f"File sent to nick}")
    else:
        await self.show_error(f"Transfer failed: {status}")

</file_content>

IMPORTANT: For any future changes to this file, use the final_file_content shown above as your reference. This content reflects the current state of the file, including any auto-formatting (e.g., if you used single quotes but the formatter converted them to double quotes). Always base your SEARCH/REPLACE operations on this final version to ensure accuracy.<environment_details>

VSCode Visible Files

PyRC.wiki/Command-System.md

VSCode Open Tabs

logs/pyrc_core.log PyRC.wiki/Home.md PyRC.wiki/style-guide.md PyRC.wiki/_Sidebar.md PyRC.wiki/Advanced-Usage.md PyRC.wiki/API-Documentation.md PyRC.wiki/Architecture-Supplement.md PyRC.wiki/Getting-Started.md PyRC.wiki/Development-Setup.md PyRC.wiki/Building-From-Source.md PyRC.wiki/Core-Components.md PyRC.wiki/UI-System.md PyRC.wiki/Scripting.md PyRC.wiki/Script-API-Reference.md PyRC.wiki/State-Management.md PyRC.wiki/Debugging-And-Logging.md PyRC.wiki/Troubleshooting.md PyRC.wiki/Support.md PyRC.wiki/License.md PyRC.wiki/Acknowledgments.md PyRC.wiki/Quick-Start.md PyRC.wiki/Contributing.md PyRC.wiki/Command-System.md

Current Time

6/11/2025, 1:56:41 AM (Europe/London, UTC+1:00)

Context Window Usage

421,015 / 1,048.576K tokens used (40%)

Current Mode

ACT MODE </environment_details>

⚠️ **GitHub.com Fallback** ⚠️