picoIRC 0.2

if 0 {Richard Suchenwirth 2004-12-05 - Here's a slight rewrite of SS' minimal IRC client (see that page) - adding

  • indentation
  • user names in bold
  • other messages in italic
  • own posts are marked in blue as a rudimentary color scheme

WikiDbImage irc.gif

Still, it was only 38 LOC, last time I looked :) }

 package require Tk
 set ::server irc.freenode.org
 set ::chan   #tcl
 set ::me     $tcl_platform(user)
 text .t -height 30 -wrap word -font {Arial 9}
 .t tag config bold   -font [linsert [.t cget -font] end bold]
 .t tag config italic -font [linsert [.t cget -font] end italic]
 .t tag config blue   -foreground blue
 entry .cmd
 pack .cmd -side bottom -fill x
 pack .t -fill both -expand 1
 bind .cmd <Return> post
 proc recv {} {
     gets $::fd line
     # handle PING messages from server
     if {[lindex [split $line] 0] eq "PING"} {
        send "PONG [info hostname] [lindex [split $line] 1]"
        return
     }
     if {[regexp {:([^!]*)![^ ].* +PRIVMSG ([^ :]+) +:(.*)} $line -> \
         nick target msg]} {
         set tag ""
         if [regexp {\001ACTION(.+)\001} $msg -> msg] {set tag italic}
         if [in {azbridge ijchain} $nick] {regexp {<([^>]+)>(.+)} $msg -> nick msg}
        .t insert end $nick\t bold $msg\n $tag
     } else {.t insert end $line\n italic}
     .t yview end
 }
 proc in {list element} {expr {[lsearch -exact $list $element]>=0}}
 proc post {} {
     set msg [.cmd get]
     if [regexp {^/me (.+)} $msg -> action] {set msg "\001ACTION $action\001"}
     foreach line [split $msg \n] {send "PRIVMSG $::chan :$line"}
     .cmd delete 0 end
     set tag ""
     if [regexp {\001ACTION(.+)\001} $msg -> msg] {set tag italic}
     .t insert end $::me\t {bold blue} $msg\n [list blue $tag]
     .t yview end
 }
 proc send str {puts $::fd $str; flush $::fd}
 set ::fd [socket $::server 6667]
 send "NICK $::me"
 send "USER $::me 0 * :PicoIRC user"
 send "JOIN $::chan"
 fileevent $::fd readable recv 

 bind . <Escape> {exec wish $argv0 &; exit}

escargo 8 Mar 2006 - If lines of code is really an important metric to you, the three set commands could be replaced with the foreach idiom to do multiple assignments:

 if 0 {
   foreach {::server ::chan ::me} {irc.freenode.org #tcl $tcl_platform(user)} break
 }

That would cut the number of lines by two. - RS: Well, yes, but no... and you'd need a list anyway, since you refer to tcl_platform... My major metrics is not lines of code, but of course I try to remove all redundancies - KISS. But I do prefer scripts with <72 lines, just because in printout they fit on a single page :-)

I also noticed the expressions in the if commands were unbraced. Is that right? Is that good style? - RS: I have the rule for myself that an if condition that consists of a single function call (typically returning 0 or 1) can be unbraced - I consider the time needed to parse the strings "0" resp. "1" small enough that I rather spare myself the visual clutter of {[...]}. Matter of taste, of course.


vote on reddit at [L1 ] - that forum promped a rewrite of the above in Ruby at http://whytheluckystiff.net/ruby/smircer.rb


Could someone provide this code with verbose comments for those of us that are just learning? There are a few things about this code that I dont understand. For one, I dont see how this snippet deals with IRC's ping/pong behaviour (is it hardcoded into the socket command?). But thats not at all the extent of the confusion, hence the request for verbosity. - RS: Your wish is my command :^) See PicoIRC 0.2 explained.

Forgive this post if it breaks the wiki's ettiquite, its my first.


picoIRC 0.3 is a more elaborate version by SS.


MJ - added handling of the PING request.

Perhaps its just me, but that ping handler is sending some nastyness into the running of the script

 syntax error in expression "[lindex [split $line] 0] eq "PING""
    ("if" test expression)
    while compiling
 "if {[lindex [split $line] 0] eq "PING"} {
        send "PONG [info hostname] [lindex [split $line] 1]"
        return
     }"
    (compiling body of proc "recv", line 4)
    invoked from within
 "recv"

RS: I suppose it's the "eq" operator. You seem to be running an old Tcl from before 8.4 (which came out 2002...) - just replace eq with == for a quick fix.


Category Application - Category Internet