mailto:davygrvy@pobox.com (Just some Tcl hacker dude) ---- I have a Tcl enabled IRC client I'm working on. It does some fancy stuff and I'm near to a release. It is a faithful XiRCON clone regarding how user scripts operate. Here's some screenshots: * Doing Japanese: [http://tomasoft.sf.net/in_a_japanese_channel.gif] * Doing Chinese: [http://tomasoft.sf.net/263.gif] * Doing Klingon (in utf-8 over IRC and back using the CTCP/2 method of escaping): [http://tomasoft.sf.net/klingon.gif] * being normal (boring): [http://tomasoft.sf.net/in_an_english_channel.gif] ---- The client has been ''painfully'' designed to be 2 complimentary halves: * back-end (the irc_engine extension, 100% Tcl API only) * UI (whatever UI the user prefers according to the command control API) The irc_engine extension provides a single [Incr Tcl] class. The UI half (partialy undefined) also provides an [Incr Tcl] class. The two are brought together using inheritence like so: source irc_engine.itcl # =============================================================== # By selecting which IRC::ui class is sourced, we can switch # to what UI we want to use. # =============================================================== source irc_ui.itcl itcl::class IRC::connection { # =============================================== # Bring the 2 halves together using inheritence. # =============================================== inherit engine ui constructor {args} { eval engine::constructor $args } {} public method destroy {} {itcl::delete object $this} } ### Create a connection instance. set a [IRC::connection #auto someUserScript1.tcl someUserScript2.tcl] ### Connect to IRC. $a connect irc.qeast.net davygrvy DG {yo moma!} In the above, $a is now the connection object. All behavior of the engine is located in a script file called default.tcl . The behavior of irc_engine can be scripted by the user by loading scripts which are queried for event hooks prior to doing the default behavior. I do have a generic framework to the system, but only Tcl is supported. I have code started for perl, python, and java, but I'll have to get back to it later. Here's where it gets interesting for user scripts.. Each tcl user script is run in its own interpreter. It maintains some of its own commands such as [[IRC::on]], but aliases most up to the global interp by using aliasing. So from the script a call to '''IRC::echo ...''', will alias up to the global (the controlling or UI interp)as '''connection0 echo ...''' where connection0 is the [Incr Tcl] object. This allows us to have our scripts track with its connection. Where this gets more interesting is that from the aliasing, I can ''assume'' commands that will be in the top-most object that are provided by the UI. The echo method is located in the UI half, yet the user script is in a separate interp of the irc_engine extension half and always tracking to its parent object. irc_engine uses Tcl's event loop. This diagram show some of the code path: [http://tomasoft.sf.net/incoming_trail.gif] Tcl::Socket is just a wrapper for containing the socket API. When a line from the server is received, it is parsed into its protocol parts and is the container to the parts that will get passed around to the subsiquent modules. IRCSplitAndQ is responsible for any text mappings (or multiple mappings) that need to be decoded, any CTCP/2 encoding escapes, all CTCP quoting, and removing, and queueing, of all embedded CTCP commands prior to the original getting posted as a job to the event loop. [[more to come]] ---- [[ [Category Home Page] | [Category Person] ]]