ENAML
ENAML: not a markup language


alpha := 'a'..'z' | 'A'..'Z'
digit := '0'..'9'
sp := *( char#32 )
hex-digit := digit | 'A'..'F'
quotable := all chars from #32 to #255, excluding quote (#34) and
    percent (#37) and del (#127)
    [you are allowed to quote any other chars you wish]
quoted-char := '%' hex-digit hex-digit

key := 1*( alpha | digit | '_' | '-')
    key is case-insensitive
    key is only valid up to 32 chars

inline-value := 1*( digit )
quoted-value := ( '"' *( quotable ) '"' ) |
    ( '\'' *( quotable ) '\'' )
hexified-value := '%' 1*( hex-digit hex-digit )
value := ( inline-value | quoted-value | hexified-value )
list := '[' *sp *( value *sp ) ']'

simple-pair := key [ ':' *sp ( value | list ) ]
complex-pair := simple-pair | ( key ':' *sp '{' *( complex-pair ) '}' )

command := complex-pair


age: 26 first-name: "Greg" url: "http://%20%34" image: %FF00337F7F7F



----- buffering -----

a single enaml message may be up to 8k before hitting a linefeed.  make sure your socket
buffering can handle that.



----- say2 protocol -----

(client)
login:{ nick email tagline? client? }
auth:{ key }
message:{ nick|id text }
message:{ nick|id stream: { type addr } }
message:{ nick|id file: { type filename size addr } }
whois:{ nick }
list-channels:{ grep }
list-people:{ grep }
say:{ text|act }
status:{ mode(active,away,busy) text }
change-nick:{ nick }
ping:{ }
prefs:{ tagline? notify?(on,off) password? }
server-info:{ }
server-cert
### add-user:{ id email password }
### boot-user: { nick|id text? }

(server)
hello
server-info:{ server version text }
server-cert:{ none|cert host }
challenge:{ key }
welcome:{ nick id }
bad-nick:{ nick text }
error:{ text }
message:{ id nick time text }
say:{ id nick time text|act }
members:{ type list id-list }
user-info:{ id nick host email type login-epoch idle tagline? mode status? status-time client? }
history-begin
history-end
signon:{ nick id time email }
signoff:{ nick id time }
status:{ nick id mode(active,away,busy) text? }
change-nick:{ old-nick id nick }
ping:{ }
prefs:{ tagline notify(on,off) password-changed? }
add-user:{ ok }
boot-user:{ nick id target-nick target-id text? }
motd:{ text }

(client)
<scrollname>: { key value }	<- state
<scrollname>: {...}		<- log

scroll: {
        new: { name type(log,state) }
        clear: { name }
        list
        dump-state: { name }
}

(server)
scroll: {
        list: { log:[] state:[] }
        dump-begin: { name }
        dump-end: { name }
        dump: { key value }
}

>>> login: { nick: "gandalf" email: "g@lag.net" }
bad-nick: { nick: "gandalf" msg: "Nickname is already in use." }
>>> login: { nick: "greg" email: "g@lag.net" }
welcome: { nick: "greg" id: "11" }
message: { id: "6" nick: "wizard" text: "have you finished with my copy
    of %22SNMP Illustrated Vol. 4%22?" }
>>> message: { id: "6" text: "not yet, i'm just getting to the good part" }
>>> message: { id: "6" text: "someone's using my normal nickname! :(" }
>>> message: { nick: "gandalf" text: "who are you?" }
message: { id: "9" nick: "gandalf" text: "huh?" }
>>> whois: { nick: "gandalf" }
info: { id: "9" nick: "gandalf" email: "hotnsoapy@yahoo.com"
    type: "person" login-epoch: "943788121" idle: "3"
    addr: "dsl-54-122-91.dialups.isp.com:5891"
    tagline: "by the power of greyskull!!" }
>>> list-people
members: { type: "person" list: [ "gandalf" "wizard" "smackdown"
    "greg" "legolas" ] id-list: [ 9 6 5 11 8 ] }
info: { id: "9" nick: "gandalf" ... }
info: { id: "6" nick: "wizard" ... }
  ...
info: { id: "12" nick: "legolas" ... }
