@@ 95,7 95,8 @@ namespace eval ::irc {
}
}
- proc ::irc::connect {hostname port {usetls 1}} {
+ # documented
+ proc ::irc::connect {hostname port {usetls 0}} {
variable chanmeta
if $usetls {
if {[info commands ::tls::socket] == ""} { package require tls }
@@ 110,15 111,19 @@ namespace eval ::irc {
proto $proto \
hostname $hostname \
port $port]
+
+ return $chan
}
- proc ::irc::enroll {chan {meta {}}}
+ # documented
+ proc ::irc::enroll {chan {meta {}}} {
fconfigure $chan -translation crlf -blocking 0
dict set meta chan $chan
dict set meta handlers {}
set chanmeta($chan) $meta
}
+ # documented
proc ::irc::listen {subcommand chan} {
switch -- $subcommand {
on {
@@ 134,16 139,21 @@ namespace eval ::irc {
}
}
+ # nodoc
proc ::irc::int-setaliases {interp} {
$interp alias irc::is
$interp alias irc::msg
$interp alias irc::listener
+ $interp alias irc::extern
+ $interp alias irc::handler
$interp alias irc::esc
$interp alias irc::unesc
$interp alias irc::src
$interp alias irc::tags
+ $interp alias irc::patlist
}
+ # nodoc
proc ::irc::int-onmsg {chan} {
set msg [gets $chan]
if {$msg == ""} { return }
@@ 151,7 161,10 @@ namespace eval ::irc {
variable chanmeta
irc::msg parse $msg tags src cmd params
- set srctype [irc::src parse $src srcparts]
+ set src ""
+ set srcparts ""
+ set srctype ""
+ if {$src != ""} { set srctype [irc::src parse $src srcparts] }
set dispatch [dict create rawmsg $msg \
chan $chan \
@@ 161,9 174,9 @@ namespace eval ::irc {
srcparts $srcparts \
cmd $cmd \
params $params \
- meta [dict remove [dict get chanmeta($chan)] handlers]]
+ meta [dict remove $chanmeta($chan) handlers]]
- foreach handler [dict get chanmeta($chan) handlers] {
+ foreach handler [dict get $chanmeta($chan) handlers] {
set patlist [lindex $handler 0]
set type [lindex $handler 1]
set id [lindex $handler 2]
@@ 208,18 221,19 @@ namespace eval ::irc {
irc::int-setaliases $interp
interp share {} $chan $interp
}
- $interp eval dict with $dispatch {}
- $interp eval after 0 $script
+ $interp eval [list set dispatch $dispatch]
+ $interp eval [list after idle $script]
}
}
}
}
+ # documented
proc ::irc::listener {subcommand chan args} {
variable chanmeta
switch -- $subcommand {
add {
- if {[llength args] != 2} { return -code error "wrong # args: should be \"irc::listener add chan patlist script\"" }
+ if {[llength $args] != 2} { return -code error "wrong # args: should be \"irc::listener add chan patlist script\"" }
set patlist [lindex $args 0]
set script [lindex $args 1]
set id [format "%016x" [expr {round(rand() * (2**64))}]]
@@ 231,15 245,15 @@ namespace eval ::irc {
set pipe [chan pipe]
set reader [lindex $pipe 0]
interp transfer {} $reader $interp
- $interp eval set chan $reader
- $interp eval after 0 $script
+ $interp eval [list set chan $reader]
+ $interp eval [list after idle $script]
dict lappend chanmeta($chan) handlers [list $patlist chan $id [lindex $pipe 1] $interp]
return $id
}
remove {
- if {[llength args] != 1} { return -code error "wrong # args: should be \"irc::listener remove chan id\"" }
+ if {[llength $args] != 1} { return -code error "wrong # args: should be \"irc::listener remove chan id\"" }
set newlist ""
foreach handler [dict get chanmeta($chan) handlers] {
if {[lindex $handler 2] != $args} {
@@ 251,33 265,111 @@ namespace eval ::irc {
}
dict set chanmeta($chan) handlers $newlist
}
- patlist {
- if {[llength $args] ni {1 2}} { return -code error "wrong # args: should be \"irc::listener patlist chan id ?patlist?\"" }
- set id [lindex $args 0]
-
- if {[llength $args] == 2}
- set newlist ""
- set patlist [lindex $args 1]
- foreach handler [dict get chanmeta($chan) handlers] {
- if {[lindex $handler 2] != $id} {
- lset handler 0 $patlist
- }
+ default { return -code error "unknown subcommand \"$subcommand\": must be add or remove" }
+ }
+ }
+
+ # documented
+ proc ::irc::handler {subcommand chan args} {
+ variable chanmeta
+ switch -- $subcommand {
+ add {
+ if {[llength $args] ni {2 3}} { return -code error "wrong # args: should be \"irc::handlers add chan patlist script ?interp?\"" }
+ set patlist [lindex $args 0]
+ set script [lindex $args 1]
+ set id [format "%016x" [expr {round(rand() * (2**64))}]]
+
+ set interp ""
+ if {[llength $args] == 3} {
+ set interp [lindex $args 2]
+ irc::int-setaliases $interp
+ interp share {} $chan $interp
+ set interp [list $interp]
+ }
+
+ dict lappend chanmeta($chan) handlers [concat [list $patlist script $id $script] $interp]
+
+ return $id
+ }
+ remove {
+ if {[llength args] != 1} { return -code error "wrong # args: should be \"irc::listener remove chan id\"" }
+ set newlist ""
+ foreach handler [dict get chanmeta($chan) handlers] {
+ if {[lindex $handler 2] != $args} {
lappend newlist $handler
+ } else {
+ interp delete [lindex $handler 4]
}
- dict set chanmeta($chan) handlers $newlist
- return $patlist
- } else {
- foreach handler [dict get chanmeta($chan) handlers] {
- if {[lindex $handler 2] != $id} {
- return [lindex $handler 0]
- }
+ }
+ dict set chanmeta($chan) handlers $newlist
+ }
+ default { return -code error "unknown subcommand \"$subcommand\": must be add or remove" }
+ }
+ }
+
+ # nodoc
+ proc ::irc::int-onextern {ichan chan} {
+ set msg [gets $ichan]
+ if [$msg == ""] return
+ puts $chan $msg
+ }
+ # documented
+ proc ::irc::extern {subcommand chan args} {
+ variable chanmeta
+ switch -- $subcommand {
+ add {
+ if {[llength $args] != 2} { return -code error "wrong # args: should be \"irc::extern add chan patlist ochan ichan\"" }
+ set patlist [lindex $args 0]
+ set ochan [lindex $args 1]
+ set ichan [lindex $args 2]
+ set id [format "%016x" [expr {round(rand() * (2**64))}]]
+
+ dict lappend chanmeta($chan) handlers [list $patlist extern $id $ochan $ichan]
+
+ fileevent $chan readable [list ::irc::int-onextern $ichan $chan]
+
+ return $id
+ }
+ remove {
+ if {[llength $args] != 1} { return -code error "wrong # args: should be \"irc::extern remove chan id\"" }
+ set newlist ""
+ foreach handler [dict get chanmeta($chan) handlers] {
+ if {[lindex $handler 2] != $args} {
+ lappend newlist $handler
+ } else {
+ puts [lindex $handler 3] $chan
+ puts [lindex $handler 3] end
+ close [lindex $handler 4]
}
}
+ dict set chanmeta($chan) handlers $newlist
}
- default { return -code error "unknown subcommand \"$subcommand\": must be add, patlist, or remove" }
+ default { return -code error "unknown subcommand \"$subcommand\": must be add or remove" }
}
}
+ # documented
+ proc ::irc::patlist {chan id {patlist {}}} {
+ if {$patlist != ""} {
+ set newlist ""
+ foreach handler [dict get chanmeta($chan) handlers] {
+ if {[lindex $handler 2] != $id} {
+ lset handler 0 $patlist
+ }
+ lappend newlist $handler
+ }
+ dict set chanmeta($chan) handlers $newlist
+ return $patlist
+ } else {
+ foreach handler [dict get chanmeta($chan) handlers] {
+ if {[lindex $handler 2] != $id} {
+ return [lindex $handler 0]
+ }
+ }
+ }
+ }
+
+
proc ::irc::src {subcommand args} {
switch -- $subcommand {
parse {
@@ 286,14 378,14 @@ namespace eval ::irc {
set partsVar ""
if {[llength $args] == 1} { set partsVar [lindex $args 1] }
- if [irc::is src::user] {
+ if [irc::is src::user $src] {
if [string length $partsVar] {
upvar $partsVar parts
regexp {^([^!@]+)(?:!([^@]+))?(?:@(.+))?$} $src _ nick username host
set parts [dict create nick $nick username $username host $host]
}
return user
- } elseif [irc::is src::servername] {
+ } elseif [irc::is src::servername $src] {
if [string length $partsVar] {
upvar $partsVar parts
set parts [dict create servername $src]
@@ 566,5 658,13 @@ namespace eval ::irc {
}
}
-irc::msg parse [gets stdin] tags src cmd params
-puts "tags: \"$tags\"\nsrc: \"$src\"\nparams: \"$cmd\"\nparams: \"$params\""
+set chan [irc::connect localhost 8000 0]
+puts $chan
+irc::listen on $chan
+irc::handler add $chan FOO {
+ puts $rawmsg
+ puts $chan "FOO2 BAR2"
+ flush $chan
+}
+
+vwait foo