]> gitweb.factorcode.org Git - factor.git/commitdiff
irc: IRC messages reimplemented
authorBruno Deferrari <utizoc@gmail.com>
Fri, 6 Mar 2009 01:11:46 +0000 (23:11 -0200)
committerBruno Deferrari <utizoc@gmail.com>
Thu, 9 Apr 2009 02:13:17 +0000 (23:13 -0300)
12 files changed:
extra/irc/client/client-docs.factor
extra/irc/client/client-tests.factor
extra/irc/client/client.factor
extra/irc/messages/base/authors.txt [new file with mode: 0644]
extra/irc/messages/base/base.factor [new file with mode: 0644]
extra/irc/messages/base/summary.txt [new file with mode: 0644]
extra/irc/messages/messages-tests.factor
extra/irc/messages/messages.factor
extra/irc/messages/parser/authors.txt [new file with mode: 0644]
extra/irc/messages/parser/parser.factor [new file with mode: 0644]
extra/irc/messages/parser/summary.txt [new file with mode: 0644]
extra/irc/messages/summary.txt [new file with mode: 0644]

index 6d4fae9b83af233f49150165e804ffa56dbda61e..d95d2bc2c6c0d1d34feee136ad135850d702fc66 100644 (file)
@@ -1,4 +1,4 @@
-USING: help.markup help.syntax quotations kernel irc.messages ;
+USING: help.markup help.syntax quotations kernel irc.messages irc.messages.base irc.messages.parser ;
 IN: irc.client
 
 HELP: irc-client "IRC Client object" ;
@@ -56,15 +56,15 @@ ARTICLE: "irc.client" "IRC Client"
 "Some of the RFC defined irc messages as objects:"
 { $table
   { { $link irc-message } "base of all irc messages" }
-  { { $link logged-in } "logged in to server" }
+  { { $link rpl-welcome } "logged in to server" }
   { { $link ping } "ping message" }
   { { $link join } "channel join" }
   { { $link part } "channel part" }
   { { $link quit } "quit from irc" }
   { { $link privmsg } "private message (to client or channel)" }
   { { $link kick } "kick from channel" }
-  { { $link roomlist } "list of participants in channel" }
-  { { $link nick-in-use } "chosen nick is in use by another client" }
+  { { $link rpl-names } "list of participants in channel" }
+  { { $link rpl-nickname-in-use } "chosen nick is in use by another client" }
   { { $link notice } "notice message" }
   { { $link mode } "mode change" }
   { { $link unhandled } "uninmplemented/unhandled message" }
index c1cbdcf8b8e022dd57a001a4cc3a0cfcd9d83334..4f25531eeedeba866f8fa245291976ad36201943 100644 (file)
@@ -1,7 +1,7 @@
 USING: kernel tools.test accessors arrays sequences
        io io.streams.duplex namespaces threads destructors
-       calendar irc.client.private irc.client irc.messages.private
-       concurrency.mailboxes classes assocs combinators ;
+       calendar irc.client.private irc.client irc.messages
+       concurrency.mailboxes classes assocs combinators irc.messages.parser ;
 EXCLUDE: irc.messages => join ;
 RENAME: join irc.messages => join_
 IN: irc.client.tests
@@ -49,13 +49,13 @@ M: mb-writer dispose drop ;
 
   { "factorbot" } [ irc> nick>> ] unit-test
 
-  { "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
+!  { "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
 
   { "#factortest" } [ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
-                      parse-irc-line forward-name ] unit-test
+                      string>irc-message forward-name ] unit-test
 
   { "someuser" } [ ":someuser!n=user@some.where PRIVMSG factorbot :hi"
-                   parse-irc-line forward-name ] unit-test
+                   string>irc-message forward-name ] unit-test
 ] with-irc
 
 ! Test login and nickname set
@@ -102,7 +102,7 @@ M: mb-writer dispose drop ;
       "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
       ":somebody!n=somebody@some.where PRIVMSG #factortest :hello" %push-line
       [ privmsg? ] read-matching-message
-      [ class ] [ name>> ] [ trailing>> ] tri
+      [ class ] [ target>> ] [ trailing>> ] tri
   ] unit-test
 ] with-irc
 
@@ -110,7 +110,7 @@ M: mb-writer dispose drop ;
       "ircuser" <irc-nick-chat>  [ %add-named-chat ] keep
       ":ircuser!n=user@isp.net PRIVMSG factorbot :hello" %push-line
       [ privmsg? ] read-matching-message
-      [ class ] [ name>> ] [ trailing>> ] tri
+      [ class ] [ target>> ] [ trailing>> ] tri
   ] unit-test
 ] with-irc
 
index 97fa65920908c5494a119c35f4cc6edfd22d194b..7986a726ba4883412ab5504dd621304ba34aa179 100755 (executable)
@@ -3,7 +3,7 @@
 USING: concurrency.mailboxes kernel io.sockets io.encodings.8-bit calendar
        accessors destructors namespaces io assocs arrays fry
        continuations threads strings classes combinators splitting hashtables
-       ascii irc.messages ;
+       ascii irc.messages irc.messages.base irc.messages.parser call ;
 RENAME: join sequences => sjoin
 EXCLUDE: sequences => join ;
 IN: irc.client
@@ -74,12 +74,12 @@ SINGLETON: irc-disconnected ! sent when connection is lost
 SINGLETON: irc-connected    ! sent when connection is established
 
 : terminate-irc ( irc-client -- )
-    [ is-running>> ] keep and [
+    dup is-running>> [
         f >>is-running
         [ stream>> dispose ] keep
         [ in-messages>> ] [ out-messages>> ] bi 2array
         [ irc-end swap mailbox-put ] each
-    ] when* ;
+    ] [ drop ] if ;
 
 <PRIVATE
 
@@ -120,7 +120,7 @@ M: irc-chat to-chat in-messages>> mailbox-put ;
 
 : chats-with-participant ( nick -- seq )
     irc> chats>> values
-    [ [ irc-channel-chat? ] keep and [ participants>> key? ] [ drop f ] if* ]
+    [ dup irc-channel-chat? [ participants>> key? ] [ 2drop f ] if ]
     with filter ;
 
 : to-chats-with-participant ( message nickname -- )
@@ -165,11 +165,10 @@ M: irc-chat to-chat in-messages>> mailbox-put ;
     " hostname servername :irc.factor" irc-print ;
 
 : /CONNECT ( server port -- stream )
-    irc> connect>> call drop ; inline
+    irc> connect>> call( host port -- stream local ) drop ;
 
 : /JOIN ( channel password -- )
-    "JOIN " irc-write
-    [ [ " :" ] dip 3append ] when* irc-print ;
+    "JOIN " irc-write [ " :" swap 3append ] when* irc-print ;
 
 : /PONG ( text -- )
     "PONG " irc-write irc-print ;
@@ -187,7 +186,7 @@ M: join forward-name trailing>> ;
 M: part forward-name channel>> ;
 M: kick forward-name channel>> ;
 M: mode forward-name name>> ;
-M: privmsg forward-name dup name>> me? [ irc-message-sender ] [ name>> ] if ;
+M: privmsg forward-name dup target>> me? [ sender>> ] [ target>> ] if ;
 
 UNION: single-forward join part kick mode privmsg ;
 UNION: multiple-forward nick quit ;
@@ -200,48 +199,48 @@ M: irc-message forward-message
 M: single-forward forward-message dup forward-name to-chat ;
 
 M: multiple-forward forward-message
-    dup irc-message-sender to-chats-with-participant ;
+    dup sender>> to-chats-with-participant ;
   
 M: broadcast-forward forward-message
     irc> chats>> values [ to-chat ] with each ;
 
 GENERIC: process-message ( irc-message -- )
 M: object      process-message drop ; 
-M: logged-in   process-message
-    name>> t irc> [ (>>is-ready) ] [ (>>nick) ] [ chats>> ] tri
+M: rpl-welcome process-message
+    nickname>> t irc> [ (>>is-ready) ] [ (>>nick) ] [ chats>> ] tri
     values [ initialize-chat ] each ;
 M: ping        process-message trailing>> /PONG ;
-M: nick-in-use process-message name>> "_" append /NICK ;
+M: rpl-nickname-in-use process-message name>> "_" append /NICK ;
 
 M: join process-message
-    [ drop +normal+ ] [ irc-message-sender ] [ trailing>> ] tri
+    [ drop +normal+ ] [ sender>> ] [ trailing>> ] tri
     dup chat> [ add-participant ] [ 3drop ] if ;
 
 M: part process-message
-    [ irc-message-sender ] [ channel>> ] bi remove-participant ;
+    [ sender>> ] [ channel>> ] bi remove-participant ;
 
 M: kick process-message
-    [ [ who>> ] [ channel>> ] bi remove-participant ]
-    [ dup who>> me? [ unregister-chat ] [ drop ] if ]
+    [ [ user>> ] [ channel>> ] bi remove-participant ]
+    [ dup user>> me? [ unregister-chat ] [ drop ] if ]
     bi ;
 
 M: quit process-message
-    irc-message-sender remove-participant-from-all ;
+    sender>> remove-participant-from-all ;
 
 M: nick process-message
-    [ irc-message-sender ] [ trailing>> ] bi rename-participant-in-all ;
+    [ sender>> ] [ trailing>> ] bi rename-participant-in-all ;
 
 M: mode process-message ( mode -- )
-    [ channel-mode? ] keep and [
+    dup channel-mode? [
         [ name>> ] [ mode>> ] [ parameter>> ] tri
         [ change-participant-mode ] [ 2drop ] if*
-    ] when* ;
+    ] [ drop ] if ;
 
 : >nick/mode ( string -- nick mode )
     dup first "+@" member? [ unclip ] [ 0 ] if participant-mode ;
 
 : names-reply>participants ( names-reply -- participants )
-    trailing>> [ blank? ] trim " " split
+    nicks>> [ blank? ] trim " " split
     [ >nick/mode 2array ] map >hashtable ;
 
 : maybe-clean-participants ( channel-chat -- )
@@ -249,14 +248,14 @@ M: mode process-message ( mode -- )
         H{ } clone >>participants f >>clean-participants
     ] when drop ;
 
-M: names-reply process-message
+M: rpl-names process-message
     [ names-reply>participants ] [ channel>> chat> ] bi [
         [ maybe-clean-participants ] 
         [ participants>> 2array assoc-combine ]
         [ (>>participants) ] tri
     ] [ drop ] if* ;
 
-M: end-of-names process-message
+M: rpl-names-end process-message
     channel>> chat> [
         t >>clean-participants
         [ f f f <participant-changed> ] dip name>> to-chat
@@ -268,7 +267,7 @@ M: end-of-names process-message
 
 GENERIC: handle-outgoing-irc ( irc-message -- ? )
 M: irc-end     handle-outgoing-irc drop f ;
-M: irc-message handle-outgoing-irc irc-message>client-line irc-print t ;
+M: irc-message handle-outgoing-irc irc-message>string irc-print t ;
 
 ! ======================================
 ! Reader/Writer
@@ -293,9 +292,9 @@ DEFER: (connect-irc)
 : (reader-loop) ( -- ? )
     irc> stream>> [
         |dispose stream-readln [
-            parse-irc-line handle-reader-message t
+            string>irc-message handle-reader-message t
         ] [
-            handle-disconnect
+            handle-disconnect
         ] if*
     ] with-destructors ;
 
@@ -314,7 +313,7 @@ DEFER: (connect-irc)
     [ forward-message ] [ process-message ] [ irc-end? not ] tri ;
 
 : strings>privmsg ( name string -- privmsg )
-    privmsg new [ (>>trailing) ] keep [ (>>name) ] keep ;
+    privmsg new [ (>>trailing) ] keep [ (>>target) ] keep ;
 
 : maybe-annotate-with-name ( name obj -- obj )
     { { [ dup string? ] [ strings>privmsg ] }
@@ -325,7 +324,7 @@ DEFER: (connect-irc)
 GENERIC: annotate-message ( chat object -- object )
 M: object  annotate-message nip ;
 M: part    annotate-message swap name>> >>channel ;
-M: privmsg annotate-message swap name>> >>name ;
+M: privmsg annotate-message swap name>> >>target ;
 M: string  annotate-message [ name>> ] dip strings>privmsg ;
 
 : spawn-irc ( -- )
@@ -335,7 +334,7 @@ M: string  annotate-message [ name>> ] dip strings>privmsg ;
     3drop ;
 
 GENERIC: (attach-chat) ( irc-chat -- )
-USE: prettyprint
+
 M: irc-chat (attach-chat)
     [ [ irc> >>client ] [ name>> ] bi irc> chats>> set-at ]
     [ [ irc> is-ready>> ] dip and [ initialize-chat ] when* ]
diff --git a/extra/irc/messages/base/authors.txt b/extra/irc/messages/base/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/messages/base/base.factor b/extra/irc/messages/base/base.factor
new file mode 100644 (file)
index 0000000..7350ef9
--- /dev/null
@@ -0,0 +1,115 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs classes.parser classes.tuple
+       combinators fry generic.parser kernel lexer
+       mirrors namespaces parser sequences splitting strings words ;
+IN: irc.messages.base
+
+TUPLE: irc-message line prefix command parameters trailing timestamp sender ;
+TUPLE: unhandled < irc-message ;
+
+SYMBOL: string-irc-type-mapping
+string-irc-type-mapping [ H{ } clone ] initialize
+
+: register-irc-message-type ( type string -- )
+    string-irc-type-mapping get set-at ;
+
+: irc>type ( string -- irc-message-class )
+    string-irc-type-mapping get at unhandled or ;
+
+GENERIC: irc-trailing-slot ( irc-message -- string/f )
+M: irc-message irc-trailing-slot
+    drop f ;
+
+GENERIC: irc-parameter-slots ( irc-message -- seq )
+M: irc-message irc-parameter-slots
+    drop f ;
+
+GENERIC: process-irc-trailing ( irc-message -- )
+M: irc-message process-irc-trailing
+    dup irc-trailing-slot [
+        swap [ trailing>> swap ] [ <mirror> ] bi set-at
+    ] [ drop ] if* ;
+
+GENERIC: process-irc-prefix ( irc-message -- )
+M: irc-message process-irc-prefix
+    drop ;
+
+<PRIVATE
+: [slot-setter] ( mirror -- quot )
+    '[ [ _ set-at ] [ drop ] if* ] ; inline
+PRIVATE>
+
+GENERIC: process-irc-parameters ( irc-message -- )
+M: irc-message process-irc-parameters
+    dup irc-parameter-slots [
+        swap [ parameters>> swap ] [ <mirror> [slot-setter] ] bi 2each
+    ] [ drop ] if* ;
+
+GENERIC: post-process-irc-message ( irc-message -- )
+M: irc-message post-process-irc-message drop ;
+
+GENERIC: fill-irc-message-slots ( irc-message -- )
+M: irc-message fill-irc-message-slots
+    {
+        [ process-irc-trailing ]
+        [ process-irc-prefix ]
+        [ process-irc-parameters ]
+        [ post-process-irc-message ]
+    } cleave ;
+
+GENERIC: irc-command-string ( irc-message -- string )
+M: irc-message irc-command-string drop f ;
+
+! FIXME: inverse of post-process is missing
+GENERIC: set-irc-parameters ( irc-message -- )
+M: irc-message set-irc-parameters
+    dup irc-parameter-slots
+    [ over <mirror> '[ _ at ] map >>parameters ] when* drop ;
+
+GENERIC: set-irc-trailing ( irc-message -- )
+M: irc-message set-irc-trailing
+    dup irc-trailing-slot [ over <mirror> at >>trailing ] when* drop ;
+
+GENERIC: set-irc-command ( irc-message -- )
+M: irc-message set-irc-command
+    [ irc-command-string ] [ (>>command) ] bi ;
+
+: irc-message>string ( irc-message -- string )
+    {
+        [ prefix>> ]
+        [ command>> ]
+        [ parameters>> " " join ]
+        [ trailing>> dup [ CHAR: : prefix ] when ]
+    } cleave 4array sift " " join ;
+
+<PRIVATE
+: ?define-irc-parameters ( class slot-names -- )
+    dup empty? not [
+        [ \ irc-parameter-slots create-method-in ] dip
+        [ [ "_" = not ] keep and ] map '[ drop _ ] define
+    ] [ 2drop ] if ;
+
+: ?define-irc-trailing ( class slot-name -- )
+    [
+        [ \ irc-trailing-slot create-method-in ] dip
+        first '[ drop _ ] define
+    ] [ drop ] if* ;
+
+: define-irc-class ( class params -- )
+    [ { ":" "_" } member? not ] filter
+    [ irc-message ] dip define-tuple-class ;
+
+: define-irc-parameter-slots ( class params -- )
+    { ":" } split1 [ over ] dip
+    [ ?define-irc-parameters ] [ ?define-irc-trailing ] 2bi* ;
+PRIVATE>
+
+#! SYNTAX:
+#! IRC: type "COMMAND" slot1 ...;
+#! IRC: type "COMMAND" slot1 ... : trailing-slot;
+: IRC: ( name string parameters -- )
+    CREATE-CLASS
+    [ scan-object register-irc-message-type ] keep
+    ";" parse-tokens
+    [ define-irc-class ] [ define-irc-parameter-slots ] 2bi ; parsing
diff --git a/extra/irc/messages/base/summary.txt b/extra/irc/messages/base/summary.txt
new file mode 100644 (file)
index 0000000..1a05067
--- /dev/null
@@ -0,0 +1 @@
+IRC messages base implementation
index ac1d003b1b7f475b6316657a46d2dc3cfc6ec88a..abe94de8efd9ebdaa88d810a654863f6a75978f2 100644 (file)
@@ -1,19 +1,10 @@
 USING: kernel tools.test accessors arrays
-       irc.messages irc.messages.private ;
+       irc.messages.parser irc.messages ;
 EXCLUDE: sequences => join ;
 IN: irc.messages.tests
 
 
-{ "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
-
-{ T{ irc-message
-     { line ":someuser!n=user@some.where PRIVMSG #factortest :hi" }
-     { prefix "someuser!n=user@some.where" }
-     { command  "PRIVMSG" }
-     { parameters { "#factortest" } }
-     { trailing "hi" } } }
-[ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
-  string>irc-message f >>timestamp ] unit-test
+! { "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
 
 { T{ privmsg
      { line ":someuser!n=user@some.where PRIVMSG #factortest :hi" }
@@ -21,9 +12,10 @@ IN: irc.messages.tests
      { command "PRIVMSG" }
      { parameters { "#factortest" } }
      { trailing "hi" }
-     { name "#factortest" } } }
+     { target "#factortest" }
+     { text "hi" } } }
 [ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ join
      { line ":someuser!n=user@some.where JOIN :#factortest" }
@@ -32,7 +24,7 @@ IN: irc.messages.tests
      { parameters { } }
      { trailing "#factortest" } } }
 [ ":someuser!n=user@some.where JOIN :#factortest"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ mode
      { line ":ircserver.net MODE #factortest +ns" }
@@ -42,7 +34,7 @@ IN: irc.messages.tests
      { name "#factortest" }
      { mode "+ns" } } }
 [ ":ircserver.net MODE #factortest +ns"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ mode
      { line ":ircserver.net MODE #factortest +o someuser" }
@@ -53,7 +45,7 @@ IN: irc.messages.tests
      { mode "+o" }
      { parameter "someuser" } } }
 [ ":ircserver.net MODE #factortest +o someuser"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ nick
      { line ":someuser!n=user@some.where NICK :someuser2" }
@@ -62,9 +54,9 @@ IN: irc.messages.tests
      { parameters  { } }
      { trailing "someuser2" } } }
 [ ":someuser!n=user@some.where NICK :someuser2"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
-{ T{ nick-in-use
+{ T{ rpl-nickname-in-use
      { line ":ircserver.net 433 * nickname :Nickname is already in use" }
      { prefix "ircserver.net" }
      { command "433" }
@@ -72,4 +64,4 @@ IN: irc.messages.tests
      { name "nickname" }
      { trailing "Nickname is already in use" } } }
 [ ":ircserver.net 433 * nickname :Nickname is already in use"
-  parse-irc-line f >>timestamp ] unit-test
\ No newline at end of file
+  string>irc-message f >>timestamp ] unit-test
\ No newline at end of file
index c88bbc072ac3aa9c4c8b329ac1fa0614caa006f4..e0f9a15effe72b716321ff91338892fefe3efe5c 100755 (executable)
 ! Copyright (C) 2008 Bruno Deferrari
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel fry splitting ascii calendar accessors combinators
-       arrays classes.tuple math.order ;
-RENAME: join sequences => sjoin
+       arrays classes.tuple math.order words assocs strings
+       irc.messages.base ;
 EXCLUDE: sequences => join ;
 IN: irc.messages
 
-TUPLE: irc-message line prefix command parameters trailing timestamp ;
-TUPLE: logged-in < irc-message name ;
-TUPLE: ping < irc-message ;
-TUPLE: join < irc-message ;
-TUPLE: part < irc-message channel ;
-TUPLE: quit < irc-message ;
-TUPLE: nick < irc-message ;
-TUPLE: privmsg < irc-message name ;
-TUPLE: kick < irc-message channel who ;
-TUPLE: roomlist < irc-message channel names ;
-TUPLE: nick-in-use < irc-message name ;
-TUPLE: notice < irc-message type ;
-TUPLE: mode < irc-message name mode parameter ;
-TUPLE: names-reply < irc-message who channel ;
-TUPLE: end-of-names < irc-message who channel ;
-TUPLE: unhandled < irc-message ;
-
-: <irc-client-message> ( command parameters trailing -- irc-message )
-    irc-message new
-        now >>timestamp
-        swap >>trailing
-        swap >>parameters
-        swap >>command ;
-
-<PRIVATE
-
-GENERIC: command-string>> ( irc-message -- string )
-
-M: irc-message command-string>> ( irc-message -- string ) command>> ;
-M: ping        command-string>> ( ping -- string )    drop "PING" ;
-M: join        command-string>> ( join -- string )    drop "JOIN" ;
-M: part        command-string>> ( part -- string )    drop "PART" ;
-M: quit        command-string>> ( quit -- string )    drop "QUIT" ;
-M: nick        command-string>> ( nick -- string )    drop "NICK" ;
-M: privmsg     command-string>> ( privmsg -- string ) drop "PRIVMSG" ;
-M: notice      command-string>> ( notice -- string )  drop "NOTICE" ;
-M: mode        command-string>> ( mode -- string )    drop "MODE" ;
-M: kick        command-string>> ( kick -- string )    drop "KICK" ;
-
-GENERIC: command-parameters>> ( irc-message -- seq )
-
-M: irc-message command-parameters>> ( irc-message -- seq ) parameters>> ;
-M: ping        command-parameters>> ( ping -- seq )    drop { } ;
-M: join        command-parameters>> ( join -- seq )    drop { } ;
-M: part        command-parameters>> ( part -- seq )    channel>> 1array ;
-M: quit        command-parameters>> ( quit -- seq )    drop { } ;
-M: nick        command-parameters>> ( nick -- seq )    drop { } ;
-M: privmsg     command-parameters>> ( privmsg -- seq ) name>> 1array ;
-M: notice      command-parameters>> ( norice -- seq )  type>> 1array ;
-M: kick command-parameters>> ( kick -- seq )
-    [ channel>> ] [ who>> ] bi 2array ;
-M: mode command-parameters>> ( mode -- seq )
-    [ name>> ] [ channel>> ] [ mode>> ] tri 3array ;
-
-GENERIC# >>command-parameters 1 ( irc-message params -- irc-message )
-
-M: irc-message >>command-parameters ( irc-message params -- irc-message )
-    drop ;
-
-M: logged-in >>command-parameters ( part params -- part )
-    first >>name ;
-
-M: privmsg >>command-parameters ( privmsg params -- privmsg )
-    first >>name ;
-
-M: notice >>command-parameters ( notice params -- notice )
-    first >>type ;
-
-M: part >>command-parameters ( part params -- part )
-    first >>channel ;
-
-M: kick >>command-parameters ( kick params -- kick )
-    first2 [ >>channel ] [ >>who ] bi* ;
-
-M: nick-in-use >>command-parameters ( nick-in-use params -- nick-in-use )
-    second >>name ;
-
-M: names-reply >>command-parameters ( names-reply params -- names-reply )
-    first3 nip [ >>who ] [ >>channel ] bi* ;
-
-M: end-of-names >>command-parameters ( names-reply params -- names-reply )
-    first2 [ >>who ] [ >>channel ] bi* ;
-
-M: mode >>command-parameters ( mode params -- mode )
-    dup length {
-        { 3 [ first3 [ >>name ] [ >>mode ] [ >>parameter ] tri* ] }
-        { 2 [ first2 [ >>name ] [ >>mode ] bi* ] }
-        [ drop first >>name dup trailing>> >>mode ]
-    } case ;
-
-PRIVATE>
-
-GENERIC: irc-message>client-line ( irc-message -- string )
-
-M: irc-message irc-message>client-line ( irc-message -- string )
-    [ command-string>> ]
-    [ command-parameters>> " " sjoin ]
-    [ trailing>> [ CHAR: : prefix ] [ "" ] if* ]
-    tri 3array " " sjoin ;
-
-GENERIC: irc-message>server-line ( irc-message -- string )
-
-M: irc-message irc-message>server-line ( irc-message -- string )
-   drop "not implemented yet" ;
-
-<PRIVATE
-
-! ======================================
-! Message parsing
-! ======================================
-
-: split-at-first ( seq separators -- before after )
-    dupd '[ _ member? ] find [ cut 1 tail ] [ swap ] if ;
-
-: remove-heading-: ( seq -- seq )
-    ":" ?head drop ;
-
-: parse-name ( string -- string )
-    remove-heading-: "!" split-at-first drop ;
-
-: split-prefix ( string -- string/f string )
-    dup ":" head?
-    [ remove-heading-: " " split1 ] [ f swap ] if ;
-
-: split-trailing ( string -- string string/f )
-    ":" split1 ;
-
-: copy-message-in ( command irc-message -- command )
-    {
-        [ line>>      >>line ]
-        [ prefix>>    >>prefix ]
-        [ command>>   >>command ]
-        [ trailing>>  >>trailing ]
-        [ timestamp>> >>timestamp ]
-        [ parameters>> [ >>parameters ] [ >>command-parameters ] bi ]
-    } cleave ;
-
-PRIVATE>
-
-UNION: sender-in-prefix privmsg join part quit kick mode nick ;
-GENERIC: irc-message-sender ( irc-message -- sender )
-M: sender-in-prefix irc-message-sender ( sender-in-prefix -- sender )
-    prefix>> parse-name ;
-
-: string>irc-message ( string -- object )
-    dup split-prefix split-trailing
-    [ [ blank? ] trim " " split unclip swap ] dip
-    now irc-message boa ;
-
-: irc-message>command ( irc-message -- command )
-    [
-        command>> {
-            { "PING"    [ ping ] }
-            { "NOTICE"  [ notice ] }
-            { "001"     [ logged-in ] }
-            { "433"     [ nick-in-use ] }
-            { "353"     [ names-reply ] }
-            { "366"     [ end-of-names ] }
-            { "JOIN"    [ join ] }
-            { "PART"    [ part ] }
-            { "NICK"    [ nick ] }
-            { "PRIVMSG" [ privmsg ] }
-            { "QUIT"    [ quit ] }
-            { "MODE"    [ mode ] }
-            { "KICK"    [ kick ] }
-            [ drop unhandled ]
-        } case new
-    ] keep copy-message-in ;
-
-: parse-irc-line ( string -- message )
-    string>irc-message irc-message>command ;
+! connection
+IRC: pass        "PASS"    password ;
+IRC: nick        "NICK"    nickname ;
+IRC: user        "USER"    user mode _ : realname ;
+IRC: oper        "OPER"    name password ;
+IRC: mode        "MODE"    name mode parameter ;
+IRC: service     "SERVICE" nickname _ distribution type _ : info ;
+IRC: quit        "QUIT"    : comment ;
+IRC: squit       "SQUIT"   server : comment ;
+! channel operations
+IRC: join        "JOIN"    channel ;
+IRC: part        "PART"    channel : comment ;
+IRC: topic       "TOPIC"   channel : topic ;
+IRC: names       "NAMES"   channel ;
+IRC: list        "LIST"    channel ;
+IRC: invite      "INVITE"  nickname channel ;
+IRC: kick        "KICK"    channel user : comment ;
+! chating
+IRC: privmsg     "PRIVMSG" target : text ;
+IRC: notice      "NOTICE"  target : text ;
+! server queries
+IRC: motd        "MOTD"    target ;
+IRC: lusers      "LUSERS"  mask target ;
+IRC: version     "VERSION" target ;
+IRC: stats       "STATS"   query target ;
+IRC: links       "LINKS"   server mask ;
+IRC: time        "TIME"    target ;
+IRC: connect     "CONNECT" server port remote-server ;
+IRC: trace       "TRACE"   target ;
+IRC: admin       "ADMIN"   target ;
+IRC: info        "INFO"    target ;
+! service queries
+IRC: servlist    "SERVLIST" mask type ;
+IRC: squery      "SQUERY"  service-name : text ;
+! user queries
+IRC: who         "WHO"     mask operator ;
+IRC: whois       "WHOIS"   target mask ;
+IRC: whowas      "WHOWAS"  nickname count target ;
+! misc
+IRC: kill        "KILL"    nickname : comment ;
+IRC: ping        "PING"    server1 server2 ;
+IRC: pong        "PONG"    server1 server2 ;
+IRC: error       "ERROR"   : message ;
+! numeric replies
+IRC: rpl-welcome         "001" nickname : comment ;
+IRC: rpl-whois-user      "311" nicnamek user host _ : real-name ;
+IRC: rpl-channel-modes   "324" channel mode params ;
+IRC: rpl-notopic         "331" channel : topic ;
+IRC: rpl-topic           "332" channel : topic ;
+IRC: rpl-inviting        "341" channel nickname ;
+IRC: rpl-names           "353" nickname _ channel : nicks ;
+IRC: rpl-names-end       "366" nickname channel : comment ;
+! error replies
+IRC: rpl-nickname-in-use "433" _ name ;
+IRC: rpl-nick-collision  "436" nickname : comment ;
diff --git a/extra/irc/messages/parser/authors.txt b/extra/irc/messages/parser/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/messages/parser/parser.factor b/extra/irc/messages/parser/parser.factor
new file mode 100644 (file)
index 0000000..1fa07fc
--- /dev/null
@@ -0,0 +1,35 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel fry splitting ascii calendar accessors combinators
+       arrays classes.tuple math.order words assocs
+       irc.messages.base sequences ;
+IN: irc.messages.parser
+
+<PRIVATE
+: split-at-first ( seq separators -- before after )
+    dupd '[ _ member? ] find [ cut 1 tail ] [ swap ] if ;
+
+: split-trailing ( string -- string string/f ) ":" split1 ;
+: remove-heading-: ( seq -- seq ) ":" ?head drop ;
+
+: split-prefix ( string -- string/f string )
+    dup ":" head? [
+        remove-heading-: " " split1
+    ] [ f swap ] if ;
+
+: split-message ( string -- prefix command parameters trailing )
+    split-prefix split-trailing
+    [ [ blank? ] trim " " split unclip swap ] dip ;
+
+: sender ( irc-message -- sender )
+    prefix>> [ remove-heading-: "!" split-at-first drop ] [ f ] if* ;
+PRIVATE>
+
+: string>irc-message ( string -- irc-message )
+    dup split-message
+    [ [ irc>type new ] [ >>command ] bi ]
+    [ >>parameters ]
+    [ >>trailing ]
+    tri*
+    [ (>>prefix) ] [ fill-irc-message-slots ] [ swap >>line ] tri
+    now >>timestamp dup sender >>sender ;
diff --git a/extra/irc/messages/parser/summary.txt b/extra/irc/messages/parser/summary.txt
new file mode 100644 (file)
index 0000000..7ec732a
--- /dev/null
@@ -0,0 +1 @@
+Basic parser for irc messages
diff --git a/extra/irc/messages/summary.txt b/extra/irc/messages/summary.txt
new file mode 100644 (file)
index 0000000..cf3a8ae
--- /dev/null
@@ -0,0 +1 @@
+IRC message definitions