dzp 2 лет назад
Родитель
Сommit
2855335413
7 измененных файлов с 6031 добавлено и 0 удалено
  1. 257 0
      docs/chat_protocol.txt
  2. 63 0
      docs/mslp_protocol.txt
  3. 303 0
      docs/syntax.txt
  4. 345 0
      docs/tintin19.txt
  5. 23 0
      docs/web.tin
  6. 4353 0
      help.txt
  7. 687 0
      src/validate

+ 257 - 0
docs/chat_protocol.txt

@@ -0,0 +1,257 @@
+Mud Master Chat Protocol
+
+Establishing a Connection
+
+Caller: Once a connection is made the caller sends a connection string;
+which looks like: "CHAT:<chat name>\n<ip address><port>".   The sprintf
+syntax is: "CHAT:%s\n%s%-5u".  The port must be 5 characters, padded on the
+right side with spaces. Once this string has been sent it waits for a
+response from the other side.  If a "NO" is received the call is cancelled.
+If the call was accepted the string "YES:<chat name>\n" is received.
+
+Receiver
+
+When a socket call is detected it accepts the socket then waits
+for the "CHAT:" string to be send from the caller.  If the receiver wishes
+to deny the call, the string "NO" needs to be sent back to the caller.  To
+accept the call, the string "YES:<chat name>\n" is sent back.
+
+Chat Data Blocks
+
+A chat data block looks like this:  <block ID byte><data><end of data byte>.
+All data dealing with needs to follow this format with a couple exceptions.
+The connection process doesn't use the data blocks and the file transfer
+blocks are a fixed size and don't need the <end of data> byte.
+
+Default Port
+
+The default port should always be 4050.
+
+
+Below is a list of the <block ID> values:
+
+#define CHAT_NAME_CHANGE                      1
+#define CHAT_REQUEST_CONNECTIONS              2
+#define CHAT_CONNECTION_LIST                  3
+#define CHAT_TEXT_EVERYBODY                   4
+#define CHAT_TEXT_PERSONAL                    5
+#define CHAT_TEXT_GROUP                       6
+#define CHAT_MESSAGE                          7
+#define CHAT_DO_NOT_DISTURB                   8
+
+#define CHAT_VERSION                         19
+#define CHAT_FILE_START                      20
+#define CHAT_FILE_DENY                       21
+#define CHAT_FILE_BLOCK_REQUEST              22
+#define CHAT_FILE_BLOCK                      23
+#define CHAT_FILE_END                        24
+#define CHAT_FILE_CANCEL                     25
+#define CHAT_PING_REQUEST                    26
+#define CHAT_PING_RESPONSE                   27
+
+#define CHAT_PEEK_CONNECTIONS                28
+#define CHAT_PEEK_LIST                       29
+#define CHAT_SNOOP_START                     30
+#define CHAT_SNOOP_DATA                      31
+
+#define CHAT_END_OF_COMMAND                 255
+
+The <end of data> byte is 255:
+
+
+
+<CHAT_NAME_CHANGE><new name><CHAT_END_OF_COMMAND>
+
+When a user changes their chat name the new name needs to be broadcast to
+all of their connections.
+
+
+
+<CHAT_REQUEST_CONNECTIONS><CHAT_END_OF_COMMAND>
+
+The sender requests connections from another connection asking to see all the
+people that person has marked as public, then try to connect to all of those
+yourself.
+
+
+
+<CHAT_CONNECTION_LIST><address>,<port>,<address>,<port><CHAT_END_OF_COMMAND>
+
+The receiver needs to put all the ip addresses and port numbers in a comma
+delimited string and send them back as a connection list.
+
+
+
+<CHAT_TEXT_EVERYBODY><text to send><CHAT_END_OF_COMMAND>
+
+Used to send some chat text to everybody.  All the text you want to be
+displayed needs to be generated on the sender's side, including the line
+feeds and the "<chat name> chats to everybody" string.
+
+Receiver:
+
+If the chat connection isn't being ignored, you simply print the
+string.  If you have any connections marked as being served you need to echo
+this string to those connections.  Or if this is coming from a connection
+being served, you need to echo to all your other connections.  This allows
+people who cannot connect directly to each other to connect with a 3rd
+person who *can* connect to both and be a server for them.
+
+
+
+<CHAT_TEXT_PERSONAL><text to send><CHAT_END_OF_COMMAND>
+
+This works the same way as CHAT_TEXT_EVERYBODY as far as what you need to
+send.  The text should obviously be changed so the person receiving knows
+this was a personal chat and not broadcast to everybody.  "\n%s chats to
+you, '%s'\n"
+
+Receiver:
+
+Just print the string that comes in if you aren't ignoring this connection.
+
+
+
+<CHAT_TEXT_GROUP><group><text to send><CHAT_END_OF_COMMAND>
+
+Used when you send text to a specific group of connections.  Works basically
+the same as the other text commands.  The group name is a 15 character
+string.  It *must* be 15 characters long, pad it on the right with spaces
+to fill it out.  "\n%s chats to the group, '%s'\n"
+
+Receiver:
+
+Just print the string that comes in if you aren't ignoring this
+connection.
+
+
+
+<CHAT_MESSAGE><message><CHAT_END_OF_COMMAND>
+
+This is used to send a message to another chat connection.  An example of
+this is when you try to send a command (action, alias, etc) to another chat
+connection and they don't have you flagged as accepting commands.  In that
+case a chat message is sent back to the sender telling them that command are
+not being accepted.  To let the other side know the message is generated
+from the chat program it is a good idea to make the string resemble
+something like: "\n<CHAT> %s is not allowing commands.\n"
+
+Receiver: Just print the message string.
+
+
+
+<CHAT_VERSION><version string><CHAT_END_OF_COMMAND>
+
+This is used to send your client's name and version.
+
+
+
+<CHAT_FILE_START><filename,length><CHAT_END_OF_COMMAND>
+
+This is sent to start sending a chat connection a file.  The filename should
+be just the filename and not a path.  Length is the size of the file in
+bytes.
+
+Receiver:
+
+First should check to make sure you are allowing files from this
+connection.  Make sure the filename is valid and that the length was
+trasnmitted.  MM by default won't allow you to overwrite files; which keeps
+people from messing with file already in your directory.  If for any reason
+the data isn't valid or you don't want to accept files from this person a
+CHAT_FILE_DENY should be sent back to abort the transfer.  If you want to
+continue with the transfer you need to start it off by requesting a block of
+data with CHAT_FILE_BLOCK_REQUEST.
+
+
+
+<CHAT_FILE_DENY><message><CHAT_END_OF_COMMAND>
+
+This is used when a CHAT_FILE_START has been received and you want to
+prevent the transfer from continuing.  <message> is a string telling the
+reason it was denied.  For example, if the file already existed you might
+deny it with: "File already exists."
+
+Receiver:
+
+Print the deny message.  Deal with cleaning up any files you
+opened when you tried to start the transfer.
+
+
+
+<CHAT_FILE_BLOCK_REQUEST><CHAT_END_OF_COMMAND>
+
+Sent to request the next block of data in a transfer.
+
+Receiver:
+
+Need to create a file block to be sent back.  File blocks are
+fixed length so they don't need the CHAT_END_OF_COMMAND byte.  If the end of
+file is reached need to send a CHAT_FILE_END close up the files and let the
+user know it is done sending.
+
+
+
+<CHAT_FILE_BLOCK><block of data>
+
+A file block is 500 bytes.  A file block is ALWAYS 500 bytes so no CHAT_END_OF_COMMAND should be added.
+
+Receiver:
+
+The receiver needs to keep track of the number of bytes written to
+properly write the last block of data.  If you keep track of the bytes
+written you know when to expect that last block that probably doesn't have a
+full 500 bytes to be saved.  File transfers are receiver driven, so for each
+block of data you accept, you need to send another CHAT_FILE_BLOCK_REQUEST
+back out to get more data.
+
+
+
+<CHAT_FILE_END><CHAT_END_OF_COMMAND>
+
+Close up your files and be done with it. This command isn't required for TinTin since it keeps track of the file transfer progress itself.
+
+
+
+<CHAT_FILE_CANCEL><CHAT_END_OF_COMMAND>
+Either side can send this command to abort a file transfer in progress.
+
+
+
+<CHAT_PING_REQUEST><timing data><CHAT_END_OF_COMMAND>
+
+The timing data is up to the ping requester. TinTin sends a 64 bit time stamp.
+
+
+
+<CHAT_PING_RESPONSE><timing data><CHAT_END_OF_COMMAND>
+
+Send back the timing data is the data that was sent with the CHAT_PING_REQUEST.
+
+
+
+<CHAT_PEEK_CONNECTIONS><CHAT_END_OF_COMMAND>
+
+The sender requests connections from another connection asking to see all the
+people that person has marked as public.
+
+
+
+<CHAT_PEEK_LIST><address>~<port>~<name>~<CHAT_END_OF_COMMAND>
+
+The receiver needs to put all the ip addresses, port numbers, and names in a
+tilda delimited string and send them back as a peek list.
+
+
+
+<CHAT_SNOOP_START><CHAT_END_OF_COMMAND>
+
+The sender requests to start or stop snooping data from a chat connection.
+The Receiver decides whether to allow snooping or not.
+
+
+
+<CHAT_SNOOP_DATA><message><CHAT_END_OF_COMMAND>
+
+Send by a client in snoop or forward mode. The message should be echoed by
+the receiver, but not be further forwarded to avoid infinite loops.

+ 63 - 0
docs/mslp_protocol.txt

@@ -0,0 +1,63 @@
+To create the most basic link insert text between \e[4m and \e[24m. These are
+the VT100 codes for underline on and underline off.
+
+#showme {Example: \e[4mlink1\e[24m ... \e[4mlink2\e[24m}
+
+------------------------------------------------------------------------------
+
+If you want to create a link without the underline use \e[4;24m instead of
+\e[4m.
+
+#showme {Example: \e[4;24mlink3 (no underline)\e[24m}
+
+------------------------------------------------------------------------------
+
+Links when clicked generate a LINK event, which are visible if you use
+#config mouse info. Example:
+
+#event {SHORT-CLICKED LINK MOUSE BUTTON ONE} {#showme {click!}}
+
+------------------------------------------------------------------------------
+
+If you want to create a complex link use an OSC code.
+
+\e]68;hello world\a\e[4mlink4\e[24m
+
+The link part remains the same, \e[4mlink4\e[24m, but since it is prefixed
+with the OSC code \e]68;hello world\a the %4 argument of the triggered LINK
+event will contain hello world.
+
+------------------------------------------------------------------------------
+
+\e]68;\001test\002hello world\a\e[4mlink5\e[24m
+
+The OSC code can contain MSDP. \001 indicates the start of a variable
+name, and \002 indicates the start of a variable value. In tintin
+this gets translated to {test}{hello world} which is available in the
+%4 argument of the event.
+
+------------------------------------------------------------------------------
+
+\e]68;\001name6a\002value6a\001name6b\002value6b\a\e[4mlink6\e[24m};
+
+In tintin this gets translated to {name6a}{value6a}{name6b}{value6b}
+
+------------------------------------------------------------------------------
+
+\e]68;0;command\a
+
+This is the most basic link.
+
+\e]68;0;
+\e]68;1;
+
+These three are identical and generate a standard link event.
+
+------------------------------------------------------------------------------
+
+\e]68;2;
+
+In tintin the ;2; option is used for internal help files.
+
+------------------------------------------------------------------------------
+

+ 303 - 0
docs/syntax.txt

@@ -0,0 +1,303 @@
+CHARACTERS
+----------
+          The following special characters are defined:
+
+#         The hashtag is the default character for starting a command and is
+          subsequently known as the command character or tintin character.
+
+          When loading a command file the command character is set to the
+          first character in the file. The character can also be redefined
+          using #config. It's adviced not to redefine the command character.
+
+;         The semi-colon is used as the command separator and can be used to
+          separate two commands. Multiple commands can be strung together as
+          well. Trailing semi-colons are ignored when reading a script file
+          as this is a common error.
+
+{ }       Curly brackets aka braces are used for seperating multi word command
+          arguments, nesting commands, and nesting variables. Braces cannot
+          be escaped using \{ \}, to escape { } use \x7B \x7D
+
+" "       Quote characters are used for strings in the #math, #if, #switch,
+          and #case commands. Instead of " " you can use an extra set of
+          braces { } to define strings, this is suggested if you are
+          expecting input to contain " characters.
+
+!         The exclamation sign is used to repeat commands, see #help history.
+          The character can be redefined using #config.
+
+\         An input line starting with a backslash is send verbatim if you are
+          connected to a server. This character can be configured with
+          #config.
+
+
+SUBSTITUTIONS
+-------------
+
+$&*@      All variable and function names must begin with an alphabetic
+          character, followed by any number of alphanumeric characters
+          and underscores.
+
+$         The dollar sign is used to retrieve the value of a variable.
+
+&         The ampersand sign is used to retrieve the index of a variable.
+
+*         The astrix sign is used to retrieve the name of a variable.
+
+@         The at sign followed by an alphanumeric string is used for functions.
+
+[ ]       Brackets are used for nested variables which function as an
+          associative array. Associative arrays are also known as tables and
+          maps. Regex can be used within brackets to match multiple variables.
+
+          Variables are ordered alphanumerically.
+
++ -       The plus and minus sign is used to access variables by their index,
+          with the first variable having index 1, and the last variable
+          having index -1.
+
+%0- %99   The percent sign followed by a number is used for arguments by the
+          following triggers:
+
+          alias, action, button, delay, event, function, substitute, and tick.
+
+&0- &99   The ampersand sign followed by a number is used for arguments in the
+          regex and replace commands.
+
+<000>     Three alphanumeric characters encapsulated by the less- and greater-
+          than signs are used for 4 and 8 bit color codes.
+
+<0000>    Either a B (background) or F (foreground) followed by three
+          hexadecimal characters encapsulated by < > signs are used for 12
+          bit color codes. Requires truecolor capable terminal.
+
+<0000000> Either a B (background) or F (foreground) followed by six
+          hexadecimal characters encapsulated by < > signs are used for 24
+          bit color codes. Requires truecolor capable terminal.
+
+          More information is available at #help color.
+
+\         The back slash is used to escape a character. All available options
+          are listed at #help escape. Escapes are typically escaped when text
+          leaves the client, by being send to a server, the shell, or being
+          displayed on the screen. Escapes try to mimic escapes in PCRE when
+          possible.
+
+\a        07  bell character.
+\t        08  horizontal tab character.
+\n        10  line feed character.
+\v        11  vertical tab character.
+\r        13  carriage return character.
+\e        27  escape character.
+\c            6 bit control character, \ca for ctrl-a.
+\x            8 bit character using 2 hexadecimal numbers.
+\u            16 bit unicode character, \uFFFD for example.
+\U            21 bit unicode character, \U02AF21 for example.
+
+          All variables and functions can be escaped by doubling the sign,
+          like $$variable_name or @@function_name. To escape a variable
+          twice use $$$var_name. One escape is removed each time tintin
+          needs to substitute a variable or function.
+
+          All trigger arguments can be escaped by double the ampersand,
+          like %%1. One escape is removed each time tintin substitutes
+          trigger arguments.
+
+          All command arguments can be escaped by doubling the ampersand,
+          like &&1. One escape is removed each time tintin substitutes
+          command arguments.
+
+
+COORDINATES
+-----------
+
+          When the 0,0 coordinate is in the upper left corner TinTin++ uses
+          a y,x / rows,cols notation, starting at 1,1. Subsequently -1,-1
+          will indicate the bottom right corner. This type of argument is
+          used by the #showme command.
+
+          When the 0,0 coordinate is in the bottom left corner tintin uses
+          a standard x,y notation. This type of argument is used by the
+          #map jump command.
+
+SQUARES
+-------
+
+          A square argument takes 2 coordinates. The first coordinate defines
+          the upper left corner, the last two coordinates define the bottom
+          right corner. The upper left corner of the terminal is defines as
+          1,1 and the bottom right corner as -1,-1. This type of argument is
+          used by #draw, #button and #map offset.
+
+PANES
+-----
+          A pane argument takes 4 size values, which are: top pane, bottom
+          pane, left pane, right pane. When a negative value is provided the
+          size is the maximum size, minus the value. This type of argument
+          is used by the #split command.
+
+
+MATH
+----
+          Operators       Priority     Function
+          ------------------------------------------------
+          !               0            logical not
+          ~               0            bitwise not
+          *               1            integer multiply
+          **              1            integer power
+          /               1            integer divide
+          //              1            integer root
+          %               1            integer modulo
+          d               1            integer random dice roll
+          +               2            integer addition
+          -               2            integer subtraction
+          <<              3            bitwise shift
+          >>              3            bitwise shift
+          >               4            logical greater than
+          >=              4            logical greater than or equal
+          <               4            logical less than
+          <=              4            logical less than or equal
+          ==              5            logical equal (can use regex)
+          !=              5            logical not equal (can use regex)
+          ===             5            string equal
+          !==             5            string not equal
+           &              6            bitwise and
+           ^              7            bitwise xor
+           |              8            bitwise or
+          &&              9            logical and
+          ^^             10            logical xor
+          ||             11            logical or
+
+? :       The ? : symbols can be used for simple ternary operations.
+
+M,K,m,u   These four metric suffixes are allowed for numbers.
+
+{ }       Braces can be used in #math to perform string operations.
+
+{a} > {b} This checks if the string "a" is greater than "b".
+
+,         Commas in numbers are ignored, as well as spaces and tabs.
+
+.         Dots can be used in #math to perform floating point calculations.
+          The precision is set to the highest precision number used in the
+          calculation.
+
+( )       Braces can be used in #math to prioritize a calculation.
+
+
+STATEMENTS
+----------
+
+         TT++ has the following commands which behave like statements.
+
+         #break
+         #case {value} {true}
+         #continue
+         #default {commands}
+         #else {commands}
+         #elseif {expression} {true}
+         #foreach {list} {variable} {commands}
+         #if {expression} {true}
+         #loop {min} {max} {variable} {commands}
+         #parse {string} {variable} {commands}
+         #return {value}
+         #switch {expression} {commands}
+         #while {expression} {commands}
+
+REGEX
+-----
+
+        ^ force match of start of line.
+        $ force match of end of line.
+        \ escape one character.
+   %1-%99 lazy match of any text, available at %1-%99.
+       %0 should be avoided in triggers, and if left alone lists all matches.
+      { } embed a raw regular expression, matches are stored to %1-%99.
+    %!{ } embed a raw regular expression, matches are not stored.
+          [ ] . + | ( ) ? * are treated as normal text unlessed used within
+          braces. Keep in mind that { } is replaced with ( ) automatically
+          unless %!{ } is used.
+
+          Of the following the (lazy) match is available at %1-%99
+
+       %w match zero to any number of word characters.
+       %W match zero to any number of non word characters.
+       %d match zero to any number of digits.
+       %D match zero to any number of non digits.
+       %s match zero to any number of spaces.
+       %S match zero to any number of non spaces.
+
+       %? match zero or one character.
+       %. match one character.
+       %+ match one to any number of characters.
+       %* match zero to any number of characters.
+
+       %i matching becomes case insensitive.
+       %I matching becomes case sensitive (default).
+
+ESCAPE
+------
+
+    \a    beep the terminal.
+    \c    send a control character, \ca for ctrl-a.
+    \e    start an escape sequence.
+    \n    send a line feed.
+    \r    send a carriage return.
+    \t    send a horizontal tab.
+    \x    print an 8 bit character using hexadecimal, \xFF for example.
+    \x7B  send the '{' character.
+    \x7D  send the '}' character.
+    \u    print a 16 bit unicode character, \uFFFD for example.
+    \U    print a 21 bit unicode character, \U02AF21 for example.
+    \v    send a vertical tab
+
+COLOR CODES
+-----------
+         <xyz>  with x, y, z being parameters
+
+         Parameter 'x': VT100 code
+
+         0 - Reset all colors and codes to default
+         1 - Bold
+         2 - Dim
+         4 - Underscore
+         5 - Blink
+         7 - Reverse
+         8 - Skip (use previous code)
+
+         Parameter 'y':  Foreground color
+         Parameter 'z':  Background color
+
+         0 - Black                5 - Magenta
+         1 - Red                  6 - Cyan
+         2 - Green                7 - White
+         3 - Yellow               8 - Skip
+         4 - Blue                 9 - Default
+
+         For xterm 256 colors support use <aaa> to <fff> for RGB foreground
+         colors and <AAA> to <FFF> for RGB background colors. For the grayscale
+         foreground colors use <g00> to <g23>, for grayscale background colors
+         use <G00> to <G23>.
+
+         The tertiary colors are as follows:
+
+         <acf> - Azure            <afc> - Jade
+         <caf> - Violet           <cfa> - Lime
+         <fac> - Pink             <fca> - Orange
+
+Example: #showme <acf>Azure    <afc>Jade     <caf>Violet
+Example: #showme <cfa>Lime     <fac>Pink     <fca>Orange
+
+         For 12 bit truecolor use <F000> to <FFFF> for foreground colors and
+         <B000> to <BFFF> for background colors.
+
+         For 24 bit truecolor use <F000000> to <FFFFFFF> for foreground
+         colors and <B000000> to <BFFFFFF> for background colors.
+
+HELP
+----
+    [ ]   Argument is optional.
+    < >   Argument is required.
+    { }   Argument is literal.
+     |    Used to separate arguments with multiple options.
+

+ 345 - 0
docs/tintin19.txt

@@ -0,0 +1,345 @@
+
+         ooooooooooo ooooo oooo   oooo ooooooooooo ooooo oooo   oooo
+         88  888  88  888   8888o  88  88  888  88  888   8888o  88
+             888      888   88 888o88      888      888   88 888o88
+             888      888   88   8888      888      888   88   8888
+            o888o    o888o o88o    88     o888o    o888o o88o    88
+
+
+                               ooo         ooo
+                               888         888
+                           oooo888oooo oooo888oooo
+                               888         888
+                               888         888
+
+
+                    Original documentation by Peter Unold
+
+
+                             Table of Contents
+                             -----------------
+
+     1)  What is TinTin++? .............................
+     2)  Giving Credit Where Credit is Due .............
+     3)  Starting TinTin++ .............................
+     3)  Basic Features ................................
+     4)  Connecting to a MUD ...........................
+     5)  Split Screen ..................................
+     6)  Aliases .......................................
+     7)  Actions .......................................
+     8)  Highlights ....................................
+     9)  Speedwalk .....................................
+    10)  Tickers .......................................
+    11)  Command Files .................................
+    12)  Command History ...............................
+    13)  Path Tracking .................................
+    14)  Advanced Features .............................
+    15)  Help ..........................................
+
+
+
+                               T I N T I N ++
+
+                 (T)he K(I)cki(N) (T)ick D(I)kumud Clie(N)t
+
+
+
+                   =========  What is TinTin++?  =========
+
+     TinTin++ is a client program specialized to help playing muds. This is a
+     souped up version of TINTIN III with many new features.
+
+
+
+            =========  Giving Credit Where Credit is Due ========
+
+     None of this work would be possible, without the work done by Peter Unold.
+     He was the author of TINTIN III, the base of TinTin++.  Hats off to ya
+     Peter, You started the ball rolling.
+
+
+
+                   =========  Starting TinTin++  =========
+
+     The syntax for starting tintin is: ./tt++ [command file]
+
+     Read more about the command file in the 'files' section below. Remember
+     one thing however. All actions, aliases, substitutions, etc, defined when
+     starting up TinTin++ are inherited by all sessions.
+
+     If you want to get out of tintin after starting it type: #end or press
+     ctrl-d. If you want to paste text use shift-insert, text is automatically
+     copied upon selection.
+
+
+
+                     ========  Basic Features  =========
+
+     I'll start by explaining some of the very basic and important features:
+
+     All TinTin++ commands starts with a '#'. (can be changed with #config)
+
+     Example: #help -- #help is a client command, and isn't send to the mud.
+
+     All TinTin++ commands can be abbreviated when typed.
+
+     Example: #he -- Typing #he is the same as typing #help
+
+     All commands can be separated with a ';'.
+
+     Example: n;l green;s;say Dan Dare is back! -- do these 4 commands
+
+     There are several ways ';'s can be overruled.
+
+     Example: \say Hello ;) -- Lines starting with a '\' aren't parsed by
+     tintin.
+
+     Example: say Hello \;) -- The escape character can esape 1 letter.
+
+
+
+                      ========  Connecting to a Mud  =========
+
+     Command: #session {session name} {mud address} {port} {filename}
+
+     Example: #session bob tintin.sf.net 4321
+
+     You can have more than one session, in which case you can switch between
+     sessions typing #<session name>.
+
+     You can get a list of all sessions by typing: #session.
+
+     Providing a filename is optional.
+
+
+
+                      ========  Split Screen  =========
+
+     Command: #split
+
+     The split command will create a separated input and output area. This
+     allows you to see the entire line that you are typing, without having
+     the mud scroll your text off the screen, or breaking up the line.
+
+     Using the #prompt command you can capture the prompt and place it on the
+     split line. To get rid of the split interface you can use #unsplit which
+     will restore the terminal settings to default.
+
+
+
+                        =========  Aliases  =========
+
+     Command: #alias
+
+     Usage: #alias {name} {commands}
+
+     Use this command to define aliases. The variables %0, %1.. %99 contain
+     the arguments to the aliases-command as follows:
+
+     the %0 variable contains ALL the arguments.
+     the %1 variable contains the 1st argument
+     the %2 variable contains the 2nd argument
+     ....
+     the %99 variable contains the 99th argument
+
+     Example: #alias nice say Hello Mr %1
+
+     If there are no variables on the right-side of the alias definition, any
+     arguments following the aliases-command will be appended to the command
+     string.
+
+     Example: #alias ff cast 'fireball' -- 'ff bob' equals: cast 'fireball' bob
+
+     If you want an alias to execute more commands, you must use braces.
+
+     Example: #alias ws {wake;stand}
+
+     To delete an alias use the #unalias command.
+
+     TinTin++ doesn't baby sit, and will not check for recursive aliases! You
+     can avoid recursion by escaping the entire line so it is send directly to
+     the mud.
+
+     Example: #alias put \put %1 in %2
+
+
+
+                        =========  Actions  =========
+
+     Command: #action
+
+     Usage: #action {action-text} {commands}
+
+     Actions, also known as triggers, are used to define an action to take
+     place when a particular text appears on your screen. There are 99
+     variables you can use as wildcards in the action-text. These variables
+     are %1, %2....%9, %10....%98, %99.
+
+     Examples:
+
+     #action {You are hungry} {get bread bag;eat bread}
+
+     #action {%1 has arrived.} shake %1 -- shake hands with people arriving.
+
+     #action {%1 tells you '%2'} {tell bob %1 told me '%2'} -- forward tells
+     to Bob.
+
+     #action {tells you} #bell -- beep the terminal when you get a tell.
+
+     You can have tintin ignore the actions if you type '#ignore action on'.
+
+     You can see what commands TINTIN executes when an action triggers, by
+     typing '#debug action on'.
+
+     You can remove actions with the #unaction command.
+
+
+
+                        =========  Highlights  =========
+
+     Command: #highlight (remember you can abbreviate commands)
+
+     Usage: #high {text} {color}
+
+     This command works a bit like #action. The purpose of this command is to
+     substitute text from the mud with color you provide. This command is a
+     simplified version of the #substitute command.
+
+     Examples:
+
+     #high {Snowy} {light yellow} -- colors the word Snowy.
+
+     #high {%1Snowy%2} {light yellow} -- colors a line containing Snowy
+
+     Use #unhigh to delete highlights.
+
+
+
+                       =========  Speedwalk  =========
+
+     If you type a command consisting ONLY of numbers and the letters n, e, s,
+     w, u, d - then this command can be interpreted as a serie of directions
+     you want to go to.
+
+     Example: ssw2n -- go south, south, west, north, north
+
+     If you have problems with typing some commands that actually ONLY consists
+     of these words, then type them in CAPS. For example when checking the NEWS
+     or when asked to enter NEW as your name.
+
+     You must enable speedwalking with: #config speedwalk on
+
+
+
+                        =========  Tickers  =========
+
+     Command: #ticker {name} {commands} {seconds}
+
+     Every 60 seconds on a standard dikumud a so called tick occures. You
+     regenerate faster hp/mana/mp if you're sleeping/resting during a tick. So
+     it's pretty nice to know when the next tick occurs. TinTin++ helps you
+     with that.
+
+     #ticker {tick} {#show TICK!!!;#delay 50 #show 10 SECONDS TO TICK!} {60}
+
+     This creates a ticker with the name {tick} which will print TICK!!!, as
+     well as print a warning when the next tick will occure.
+
+     Use #untick to delete tickers.
+
+
+
+                     =========  Command Files  =========
+
+     When you order TinTin++ to read a command file, tintin parses all the
+     text in the file. You can use command files to keep aliases/actions in,
+     login to a mud(name, password etc..) and basically all kinds of commands.
+
+     You can make the command files with either a text editor (strongly
+     suggested), or use the #write command to write out a file.
+
+     Commands for files:
+
+     #read filename -- read and execute the file.
+
+     #write filename -- write all actions/aliases/substitutes known for the
+     current session to a file.
+
+     When you use #session you can tell it to read a command file with the 4th
+     argument.
+
+     Example: #session bob tintin.sf.net 4321 bobthemage.tin
+
+
+
+                    =========  Command History  =========
+
+     If you want to use your command history you have 2 options. If you gave
+     Mashiranou a 4 lines long tell about the weather or something, but she
+     was AFK, and 15 minuts later she comes back to the keyboard and you want
+     to give her the exact same message you would type: !tell mashiran
+     TinTin++ will search through your command history for the command
+     starting with 'tell mashiran' and execute it.
+
+     Another slightly more flexible option is typing control-r which will
+     display the reverse search prompt. Simply type in a substring of a
+     command previously entered and it will keep showing matches till you
+     find the command you are looking for.
+
+
+
+                     =========  Path Tracking  =========
+
+     Tintin tries to keep track of your movement. That is whenever you type
+     either north/south/east/west/up/down, tintin will push the direction and
+     it's opposite direction into a queue (the path) if '#path new' has been
+     used.
+
+     Commands for path:
+
+     #path new -- start path mode, and resets queue.
+     #path end -- stop path mode.
+     #path map -- show the path
+     #path ins {forward} {backward} -- insert commands into the queue
+     #path del -- forget last move in the path
+     #path save {f|b} {alias} -- save the path to the given alias
+     #path load {alias} -- load a path alias into the map queue
+     #path walk {forward|backward} -- walk 1 step forward or backward of a queue.
+
+     #action {Alas, you cannot go that way.} {#path del}
+
+     real life example.. tatataaaa:
+
+     You want a fast run to the master mindflayer and back. You go to the dump
+     and type: #path new. Then you run down and kill the master. To go back you
+     just type: #path save backward tmp;$tmp
+
+     You could of course just as well have recalled out of there, but... Hell
+     it's just an example.
+
+
+
+                   =========  Advanced Features  =========
+
+     Command: #run {name} {shell command}
+
+     #run lets you run any console application interactively inside tintin.
+
+     Learning how to use tintin will not only allow you to customize and
+     automate a telnet connection, but any console application can be
+     enhanced with triggers.
+
+
+
+                         =========  Help  =========
+
+     Command: #help {subject}
+
+     The help command is your friend, and also contains the most up to date
+     information of all available tintin commands. If you type #help without
+     an argument you will see the various help subjects, most of which aren't
+     described in this manual since it only covers the basics to get you
+     started.
+
+
+     Enjoy

+ 23 - 0
docs/web.tin

@@ -0,0 +1,23 @@
+#function clink
+{
+    #format result {%+%1h} {%2};
+    #replace result {#} { };
+    #replace result {%2} {\c<a href='%3'\c>%2\c</a\c>}
+}
+
+#config log html
+#config charset utf-8
+#buffer clear
+#draw Yellow scroll top side 1 1 1 80
+#showme {<138>│@clink{78;Tutorial;tutorial.html}│}
+#draw Yellow scroll right bot side 1 1 1 80
+
+#showme {}
+
+#draw Yellow scroll top side 1 1 1 80
+#showme {<138>│@clink{78;Manual;help.html}│}
+#draw Yellow scroll right bot side 1 1 1 80
+
+#showme {}
+
+#buffer write index.html

+ 4353 - 0
help.txt

@@ -0,0 +1,4353 @@
+Command: #action {message} {commands} {priority}
+
+         The #action command can be used to respond with one or several
+         commands to a specific message send by the server. The %1-%99
+         variables are substituted from the message and can be used in the
+         command part of the action.
+
+         If the message starts with a ~ color codes must be matched. You can
+         enable #config {convert meta} on to display meta characters.
+
+         For more information on pattern matching see the section on PCRE.
+
+Example: #action {%1 tells you '%2'} {tell %1 I'm afk.}
+
+         Actions can be triggered by the #show command. If you don't want a
+         #show to get triggered use: #line ignore #show {text}
+
+         Actions are ordered alphabetically and only one action can trigger at
+         a time. To change the order you can assign a priority, which defaults
+         to 5, with a lower number indicating a higher priority. The priority
+         can be a floating point number and should be between 1 and 9.
+
+         To remove an action with %* as the message, use #unaction {%%*} or
+         #unaction {\%*}. Alternatively you could wrap the action inside a
+         class, and kill that class when you no longer need the action.
+
+Comment: You can remove an action with the #unaction command.
+
+Related: pcre, gag, highlight, prompt and substitute.
+
+Command: #alias {name} {commands} {priority}
+
+         The #alias command can be used to shorten up long or oftenly used
+         commands. The %1-99 variables are substituted from the arguments when
+         using an alias and represent the 1st till 99th word which can be used
+         in the commands part of the alias. If %0 is used it will contain all
+         arguments. The priority part is optional and determines the priority
+         of the alias, it defaults to 5.
+
+         If no % variable is used in the commands section any argument will be
+         appended to the end as if %0 was used. This feature might be removed
+         in the future, and shouldn't be used.
+
+Example: #alias {k} {kill %1;kick}
+
+         Typing 'k orc' would result in attacking the orc followed by a kick.
+
+         You can create multi-word aliases by using variables in the name
+         section.
+
+Example: #alias {k %1 with %2} {draw %2;attack %1;slash %1 with %2;
+           kick at %2;strike %1 with %2}
+
+         Using the above alias you could type k blue smurf with battle axe
+
+         To have an alias that matches all user input, use %* as the name.
+
+Example: #alias {%*} {#show You wrote: %0}
+
+         Aliases are ordered alphabetically and only one alias can trigger at
+         a time. To change the order you can assign a priority, which defaults
+         to 5, with a lower number indicating a higher priority. The priority
+         can be a floating point number.
+
+         To remove an alias with %* as the name, use #unalias {%%*} or #unalias
+         {\%*}. Alternatively you can wrap the alias inside a class, and kill
+         that class when you no longer need the alias.
+
+         For more information on pattern matching see the section on PCRE.
+
+Comment: You can remove an alias with the #unalias command.
+
+Related: cursor, history, keypad, macro, speedwalk and tab.
+
+Command: #all {string}
+
+         If you have multiple sessions in one terminal you can use #all to
+         execute the command with all sessions, excluding the startup session.
+
+Example: #all quit
+
+         Sends 'quit' to all sessions.
+
+Related: port, run, session, sessionname, snoop, ssl and zap.
+
+Command: #bell {flash|focus|margin|ring|volume} {argument}
+
+         The #bell command without an argument will ring the terminal bell.
+
+Example: #action {Bubba tells you} {#bell}
+
+         If you aren't watching the screen this could be useful if you don't
+         want to miss out on a conversation with Bubba. Alternatively you can
+         use #system to play a sound file.
+
+         Some terminals will allow you to use VT100 Operating System Commands
+         to change the terminal's bell behavior which can be used to flash the
+         taskbar icon and or focus the window on receival of a bell.
+
+Example: #action {Bubba tells you} {#screen save title;#screen set title Tell!;
+           #bell ring;#delay 10 #screen load title}
+
+         The above example will save your window title, change the title to
+         'Tell!', ring the bell, next reset the window title after 10 seconds.
+
+         It's possible to set the terminal to pop to the foreground upon
+         ringing of the alarm bell.
+
+Example: #bell focus on;#bell ring;#bell focus off
+
+         It's possible to adjust the alarm bell volume on some terminals.
+
+Example: #loop {1} {8} {cnt} {#line substitute variables
+           #delay {$cnt} {#show Volume $cnt: #bell volume $cnt;#bell}
+
+Related: screen
+
+Command: #break
+
+         The break command can be used inside the #else, #elseif, #if, #foreach,
+         #loop, #parse, #switch, and #while statements. When #break is found,
+         tintin will stop executing the statement it is currently in and move on
+         to the next.
+
+Example: #while {1} {#math cnt $cnt + 1;#if {$cnt == 20} {#break}}
+
+Related: statements
+
+Command: #buffer {option} {argument}
+
+         The buffer command has various options to manipulate your scrollback
+         buffer.
+
+         The size of the scrollback buffer can be configured using #config
+         buffer_size <size>. The size must be either 100, 1000, 10000, 100000
+         or 1000000 lines.
+
+         While scrolling through the scrollback buffer incoming text is not
+         displayed, this can be disabled using #config scroll_lock off. The
+         scroll lock is automatically disabled when manual input is received,
+         subsequently #buffer up and down only work properly when used in a
+         macro or mouse event.
+
+         #buffer {clear} {[lower bound]} {[upper bound]}
+
+         Without an argument this will clear the entire scrollback buffer.
+         Otherwise it will clear the given range.
+
+         Positive numbers are measured from the start of the scrollback buffer,
+         negative numbers from the end.
+
+         #buffer {down} [lines]
+
+         Moves your scrollback buffer down one page and displays the page. If
+         a line number is provided it will scroll down the given number of
+         lines.
+
+         #buffer {end}
+
+         Moves you to the end of your scrollback buffer and displays the page.
+         Disables scroll lock mode. Most useful when used in a #macro.
+
+         #buffer {find} {[number]} {<string>} {[variable]}
+
+         Moves the buffer to the given string which can contain a regular
+         expression. Optionally you can provide the number of matches to skip,
+         allowing you to jump further back in the buffer.
+
+         A positive number searches from the start of the buffer, a negative
+         number from the end. If you provide a variable the location will be
+         stored and no jump takes place.
+
+         #buffer {get} {<variable>} {<lower bound>} {[upper bound]}
+
+         Allows you to store one or several lines from your scrollback buffer
+         (including color codes) into a variable. The lower and upper bound
+         must be between 1 and the size of the buffer. If the upper bound is
+         omitted the given line is stored as a standard variable. If an upper
+         bound is given the lines between the two bounds are stored as a list.
+
+         Positive numbers are measured from the start of the scrollback buffer,
+         negative numbers from the end.
+
+         #buffer {home}
+
+         Moves you to the top of your scrollback buffer and displays the page.
+         Enables scroll lock mode. Most useful when used in a #macro.
+
+         #buffer {info} {[save]} {[variable]}
+
+         Display buffer info, optionally save the data to a variable.
+
+         #buffer {jump} {<location>}
+
+         Moves the buffer to the given location. A positive number jumps from
+         the start of the buffer, a negative number from the end.
+
+         #buffer {lock} {on|off}
+
+         Toggles the lock on the scrollback buffer. When locked, newly incoming
+         text won't be displayed, any command will disable the lock, though
+         several buffer commands will re-enable the lock. When unlocking it'll
+         move you to the end of your scrollback buffer and display the page.
+
+         #buffer {refresh}
+
+         Marks the buffer as needing to be refreshed, only useful while in
+         vertical split mode.
+
+         #buffer {up} [lines]
+
+         Moves your scrollback buffer up one page and displays the page.
+         Enables scroll lock mode. Most useful when used in a #macro. You
+         can use #buffer {up} {1} to move the scrollback buffer up 1 line.
+
+         #buffer {write} {<filename>}
+
+         Writes the scrollback buffer to the given file.
+
+Example: #macro {\e[F} {#buffer end}
+
+Related: echo, grep, macro, showme and screen.
+
+Command: #button {square} {commands} {priority}
+
+         The #button command can be used to respond with one or several
+         commands to a mouse click received within the specified square.
+         The click coordinates are stored in %0-%3 and can be used in the
+         command part of the button.
+
+         The square part should exists of two coordinates defining the
+         upper left and bottom right corner using row, col, row, col syntax.
+         The square arguments should be separated by spaces, semi-colons or
+         braces.
+
+         By default the button is set to respond to a mouse button press, to
+         respond to other button presses you must add a 5th argument to the
+         square that defines the button press type. You can enable #info
+         button on to see button events and their type as they happen.
+
+         The priority part is optional and determines the priority of the
+         button, it defaults to 5.
+
+         You must enable #config {mouse tracking} on for buttons to work.
+
+         This command draws no visible button, you'll have to do so separately
+         if needed.
+
+Example: #button {1;1;2;2} {#show You clicked the upper left corner.}
+
+         Buttons are ordered alphabetically and only one button can trigger at
+         a time. To change the order you can assign a priority, which defaults
+         to 5, with a lower number indicating a higher priority. The priority
+         can be a floating point number.
+
+Comment: To see button clicks trigger use #info button on.
+
+Comment: You can remove a button with the #unbutton command.
+
+Related: delay, event and ticker.
+
+Command: #case {conditional} {arguments}
+
+         The case command must be used within the #switch command. When the
+         conditional argument of the case command matches the conditional
+         argument of the switch command the body of the case is executed.
+
+         When comparing strings both the switch and case arguments must be
+         surrounded in quotes.
+
+Example:
+
+         #function {reverse_direction}
+         {
+             #switch {"%1"}
+             {
+                 #case {"north"} {#return south};
+                 #case {"east"}  {#return west};
+                 #case {"south"} {#return north};
+                 #case {"west"}  {#return east};
+                 #case {"up"}    {#return down};
+                 #case {"down"}  {#return up}
+             }
+         }
+
+         This function returns the reverse direction. @reverse_direction{north}
+         would return south.
+
+Related: default, statements and switch.
+
+Command: #cat {variable} {argument}
+
+         The cat command will concatenate the argument to the given variable.
+
+Related: format, function, local, math, replace, script and variable.
+
+
+         The following special characters are defined:
+
+#        The hashtag is the default character for starting a command and is
+         subsequently known as the command character or tintin character.
+         When loading a command file the command character is set to the
+         first character in the file. The character can also be redefined
+         using #config.
+
+;        The semi-colon is used as the command separator and can be used to
+         separate two commands. Multiple commands can be strung together as
+         well. Trailing semi-colons are ignored when reading a script file
+         as this is a common error.
+
+{ }      Curly brackets aka braces are used for separating multi word command
+         arguments, nesting commands, and nesting variables. Braces cannot
+         easily be escaped and must always be used in pairs.
+
+" "      Quote characters are used for strings in the #math, #if, #switch,
+         and #case commands. It is however suggested to use a set of braces
+         { } to define strings instead, particularly when checking strings
+         that may contain quotes.
+
+!        The exclamation sign is used to repeat commands, see #help history.
+         The character can be redefined using #config.
+
+\        An input line starting with a backslash is sent verbatim if you are
+         connected to a server. This character can be configured with
+         #config, and is itself sent verbatim when the verbatim config mode
+         is enabled.
+
+Related: colors, escape_codes, function, mathematics, pcre and variable.
+
+Command: #chat {option} {argument}
+
+         The #chat command is used to create peer to peer connections to other
+         clients, typically for the purpose of chatting and sending files.
+         This is a decentralized chat system, meaning you have to exchange ip
+         addresses and port numbers with other users in order to connect to
+         them.
+
+         #chat {init} {port}
+           #chat initialize launches your chat server. The port number is
+           optional, and by default 4050 is used as your port. After using
+           this command other people can connect to your chat server using
+           your ip address and port number, and in turn you can connect to
+           other people.
+         #chat {name} {name}
+           By default your name is set to TinTin, but most servers will
+           reject you if there is already someone with the name TinTin
+           connected, so one of the first things you'd want to do is
+           change your chat name. Your name can include color codes. Some
+           names aren't accepted by tt++ chat servers, like the name 'all'
+           and names longer than 20 characters.
+         #chat {message} {buddy|all} {text}
+           This is the main command used for communication. If you use
+           #chat message all, the message is marked as public and send to
+           everyone you are connected to.
+         #chat {accept} {buddy} {boost}
+           Accept a file transfer from a buddy. The boost is optional and
+           must be a value between 1 and 1000.
+         #chat {call}       {address} {port}
+           #chat call is used to connect to another chat server. If you
+           omit the port argument the default port (4050) is used.
+         #chat {cancel}     {buddy}            Cancel a file transfer
+         #chat {color}      {color names}      Set the default color
+         #chat {decline}    {buddy}            Decline a file transfer
+         #chat {dnd}                           Decline new connections
+         #chat {download}   {directory}        Set your download directory
+         #chat {emote}      {buddy|all} {text} Send an emote message
+         #chat {forward}    {buddy}            Forward all chat messages
+         #chat {forwardall} {buddy}            Forward all session output
+         #chat {filestat}   {buddy}            Show file transfer data
+         #chat {group}      {buddy} {name}     Assign a chat group
+         #chat {ignore}     {buddy}            Ignores someone
+         #chat {info}                          Displays your info
+         #chat {ip}         {address}          Changes your IP address
+         #chat {paste}      {buddy|all} {text} Pastes a block of text
+         #chat {peek}       {buddy}            Show one's public connections
+         #chat {ping}       {buddy}            Display response time
+         #chat {private}    {buddy|all}        Make a connection private
+         #chat {public}     {buddy|all}        Make a connection public
+         #chat {reply}      {text}             Reply to last private message
+         #chat {request}    {buddy}            Request one's public connections
+         #chat {send}       {buddy|all} {text} Sends a raw data string
+         #chat {sendfile}   {buddy} {filename} Start a file transfer
+         #chat {serve}      {buddy}            Forward all public chat messages
+         #chat {uninitialize}                  Uninitialize the chat port.
+         #chat {who}                           Show all connections
+           #chat who shows all people you are connected to. The first
+           column shows a reference number for the connection, which can be
+           used instead of the connection's name when sending someone a message
+           The second column shows the connection's name. The third column
+           shows flags set for the connection, (P)rivate, (I)gnore, (S)erve,
+           (F)orward to user, and (f)orward from user. The next columns show
+           ip, port, and client name.
+         #chat {zap}        {buddy}            Close a connection
+
+Related: port
+
+Command: #class {name} {option} {arg}
+
+         The class command is primarily used to assign groups of triggers and
+         variables a label so they can be easily removed.
+
+         #class {<name>} {assign} {<argument>}
+           Will open the class, execute argument, and close afterwards.
+         #class {<name>} {clear}
+           Will delete all triggers associated with the given class.
+         #class {<name>} {close}
+           Close the given class, opening the last open class, if any.
+         #class {<name>} {kill}
+           Will clear, close, and remove the class.
+         #class {<name>} {list}
+           List all triggers associated with the given class.
+         #class {<name>} {load}
+           Will load the saved copy of the class from memory.
+         #class {<name>} {open}
+           Open a class, closing a previously opened class. All triggers
+           added afterwards are assigned to this class.
+         #class {<name>} {read} {<filename>
+           Will open the class, read the file, and close afterwards.
+         #class {<name>} {save}
+           Will save all triggers of the given class to memory.
+         #class {<name>} {size} {<variable>}
+           Will store the size of the class in a variable.
+         #class {<name>} {write} {<filename>}
+           Will write all triggers of the given class to file.
+
+         Keep in mind that you need to use #class save before using
+         #class clear and #class load
+
+Example: #class rich kill;#class rich read poor.tin
+         Deletes all triggers of 'rich' class if any. Read 'poor.tin' file,
+         all triggers loaded will be assigned to the 'rich' class.
+
+Related: config, debug, ignore, info, kill, line and message.
+
+Syntax:  <xyz>  with x, y, z being parameters
+
+         Parameter 'x': VT100 code
+
+         0 - Reset all colors and codes to default
+         1 - Bold
+         2 - Dim
+         3 - Italic
+         4 - Underscore
+         5 - Blink
+         7 - Reverse
+         8 - Skip (use previous code)
+
+         Parameter 'y':  Foreground color
+         Parameter 'z':  Background color
+
+         0 - Black                5 - Magenta
+         1 - Red                  6 - Cyan
+         2 - Green                7 - White
+         3 - Yellow               8 - Skip
+         4 - Blue                 9 - Default
+
+         For xterm 256 colors support use <aaa> to <fff> for RGB foreground
+         colors and <AAA> to <FFF> for RGB background colors. For the grayscale
+         foreground colors use <g00> to <g23>, for grayscale background colors
+         use <G00> to <G23>.
+
+         The tertiary colors are as follows:
+
+         <acf> - Azure            <afc> - Jade
+         <caf> - Violet           <cfa> - Lime
+         <fac> - Pink             <fca> - Orange
+
+Example: #show <acf>Azure    <afc>Jade     <caf>Violet
+Example: #show <cfa>Lime     <fac>Pink     <fca>Orange
+
+         For 12 bit truecolor use <F000> to <FFFF> for foreground colors and
+         <B000> to <BFFF> for background colors.
+
+         For 24 bit truecolor use <F000000> to <FFFFFFF> for foreground
+         colors and <B000000> to <BFFFFFF> for background colors.
+
+         If the color code exceeds your configured color mode it will be
+         downgraded to the closest match.
+
+Related: characters, coordinates, escape_codes, mathematics and pcre.
+
+Command: #commands {abbreviation}
+
+         Shows all commands, or all commands starting with the given
+         abbreviation.
+
+Related: help, info and statements.
+
+Command: #config {option} {argument}
+
+         This allows you to configure various settings, the settings can be
+         written to file with the #write command.
+
+         If you configure the global session (the one you see as you start up
+         tintin) all sessions started will inherite these settings.
+
+         It's advised to make a configuration file to read on startup if you
+         do not like the default settings.
+
+         Use #config without an argument to see your current configuration as
+         well as a brief explanation of each config option.
+
+         The following config options are not listed by default:
+
+         #CONFIG {AUTO TAB}      {NUMBER} Buffer lines used for tab completion
+         #CONFIG {CHILD LOCK}    {ON|OFF} Enable or disable command input.
+         #CONFIG {CONNECT RETRY} {NUMBER} Seconds to try to connect on failure.
+         #CONFIG {CONVERT META}  {ON|OFF} Shows color codes and key bindings.
+         #CONFIG {DEBUG TELNET}  {ON|OFF} Shows telnet negotiations y/n.
+         #CONFIG {HYBERNATE}     {ON|OFF} Enable or disable low CPU usage mode.
+         #CONFIG {LOG LEVEL}   {LOW|HIGH} LOW logs server output before triggers.
+         #CONFIG {INHERITANCE}   {ON|OFF} Session trigger inheritance y/n.
+         #CONFIG {MCCP}          {ON|OFF} Enable or disable MCCP support.
+         #CONFIG {RANDOM SEED}   {NUMBER} Seed value used for random numbers.
+         #CONFIG {TAB WIDTH}     {NUMBER} Number of spaces used for a tab
+         #CONFIG {TINTIN CHAR}   {SYMBOL} Character used for TinTin++ commands.
+
+Related: class and line.
+
+Command: #continue
+
+         The continue command can be used inside the #FOREACH, #LOOP, #PARSE,
+         #WHILE and #SWITCH commands. When #CONTINUE is found, tintin will go
+         to the end of the command and proceed as normal, which may be to
+         reiterate the command.
+
+Example: #loop 1 10 cnt {#if {$cnt % 2 == 0} {#continue} {say $cnt}}
+
+Related: break, foreach, list, loop, parse, repeat, return and while.
+
+
+         When the 0,0 coordinate is in the upper left corner TinTin++ uses
+         a y,x / row,col notation, starting at 1,1. Subsequently -1,-1
+         will indicate the bottom right corner. This type of argument is
+         used by the #showme command.
+
+         When the 0,0 coordinate is in the bottom left corner tintin uses
+         a standard x,y notation. This type of argument is used by the
+         #map jump command.
+
+         The vast majority of tintin commands use y,x / row,col notation,
+         primarily because that is the notation used by the VT100 standard
+         used for terminal emulation.
+
+         Squares
+
+         A square argument takes 2 coordinates. The first coordinate defines
+         the upper left corner, the last coordinate defines the bottom
+         right corner. The upper left corner of the terminal is defined as
+         1,1 and the bottom right corner as -1,-1. This type of argument is
+         used by #draw, #button and #map offset.
+
+         Panes
+
+         A pane argument takes 4 size values, which are: top pane, bottom
+         pane, left pane, right pane. When a negative value is provided the
+         size is the maximum size, minus the value. This type of argument
+         is used by the #split command.
+
+         Ranges
+
+         A range argument takes 2 values known as the upper bound and lower
+         bound. The upper bound (first value) defines the start of the
+         range, the lower bound (second value) the end. The first index of
+         a range is defined as 1. When a negative value is provides the last
+         index is defined as -1. This type of argument is used by #buffer
+         and #variable.
+
+Related: characters, colors, escape_codes, mathematics and pcre.
+
+Command: #cr
+
+         Sends a carriage return to the session.  Useful for aliases that need
+         extra carriage returns.
+
+         This command is obsolete as you can accomplish the same using #send
+         without an argument or #send {}.
+
+Related: forall
+
+Command: #cursor {option} {argument}
+
+         Typing #cursor without an option will show all available cursor
+         options, their default binding, and an explanation of their function.
+
+         The cursor command's primarly goal is adding customizable input editing
+         with macros. Subsequently many cursor commands only work properly when
+         used within a macro or event.
+
+         #cursor flag
+
+         EOL         end of line character(s)
+         ECHO        local echo
+         OVERTYPE    overtype mode
+
+         #cursor macro
+
+         PRESERVE    do not erase the macro from the macro input buffer
+         RESET       erase the macro input buffer
+
+         #cursor tab
+
+         CASELESS    makes tab completion caseless
+         COMPLETE    makes tab completion work while editing
+
+         DICTIONARY  performs tab completion on the dictionary
+         LIST        performs tab completion on the tab completion list
+         SCROLLBACK  performs tab completion on the scrollback buffer
+
+         BACKWARD    specifies tab completion to go backward
+         FORWARD     specifies tab completion to go forward
+
+         Multiple options can/must be specified at once.
+
+Related: alias, history, keypad, macro, speedwalk and tab.
+
+Command: #daemon {attach|detach|kill|list} [name]
+
+         #daemon provides functionality similar to that of the screen and tmux
+         utilities.
+
+         #daemon attach [name]
+           The attach option will try to find a daemonized tintin instance and
+           take over control. The name argument is optional.
+
+         #daemon detach [name]
+           The detach option will daemonize tintin, turning it into a background
+           process. The name argument is optional and is useful if you have
+           several daemonized tt++ instances running so you can keep them apart.
+
+         #daemon kill [name]
+           Kills all daemons or daemons with matching name.
+
+         #daemon list [name]
+           List all daemons or daemons with matching name.
+
+         You can launch tintin and attach the first daemonized instance using
+         tt++ -R. To attach a named instance use tt++ -R<name>.
+
+Related: script, system and run.
+
+Command: #debug {listname} {on|off|log}
+
+         Toggles a list on or off. With no argument it shows your current
+         settings, as well as the list names that you can debug.
+
+         If you for example set ACTIONS to ON you will get debug information
+         whenever an action is triggered.
+
+         #debug {listname} {log} will silently write debugging information to
+         the log file, you must be logging in order for this to work.
+
+         Not every list has debug support yet.
+
+Related: class, ignore, info, kill and message.
+
+Command: #default {commands}
+
+         The default command can only be used within the switch command. When
+         the conditional argument of non of the case commands matches the switch
+         command's conditional statement the default command is executed.
+
+Related: case, default, else, elseif, if, switch and regexp.
+
+Command: #delay {seconds} {command}
+Command: #delay {name} {command} {seconds}
+
+         Delay allows you to have tintin wait the given amount of seconds
+         before executing the given command.
+
+         Nanosecond floating point precision is allowed. Delays will fire in
+         0.01 second intervals.
+
+         Named delays are treated as one-shot tickers, see #help tick.
+
+Example: #delay {1} {#show last};#show first
+         This will print 'first', and 'last' around one second later.
+
+Comment: If you want to remove a delay with the #undelay command you can add
+         a name as the first argument, be aware this changes the syntax. If
+         the name is a number keep in mind that delays with the same numeric
+         name will not be overwritten
+
+Related: event and ticker.
+
+Command: #draw [line color] [options] <type> <square> {text}
+
+         The draw commands allows you to draw various types of lines and shapes
+         on the screen. The types with a brief description are provided when you
+         type #draw without an argument.
+
+         The <square> arguments should exists of two coordinates defining the
+         upper left and bottom right corner using row, col, row, col syntax.
+
+         The square arguments can be negative, in which case the coordinates
+         are calculated from the opposite side of the screen. In the case the
+         screen is 80 columns wide using #draw box 1 60 10 70 will be the
+         equivalent of #draw box 1 -21 10 -11, but with different screen
+         widths the boxes would be drawn in different places.
+
+         You can prefix the option with a color code or color name to color the
+         lines and shapes.
+
+         You can further prefix the option as following:
+
+         ASCII       draw in ASCII mode.
+         BALIGN      bottom align text.
+         BLANKED     blank the lines and corners.
+         BOTTOM      draw on the bottom side if possible.
+         BOXED       draw a box along the square.
+         BUMPED      precede the draw with an enter.
+         CALIGN      center text.
+         CIRCLED     circle the corners.
+         CONVERT     draw text with meta conversion.
+         CROSSED     cross the corners.
+         CURSIVE     draw text with cursive letters.
+         FAT         draw text with fat letters.
+         FILLED      fill circles and jewels.
+         FOREGROUND  draw even if session is not active.
+         GRID        draw TABLE as a grid.
+         HORIZONTAL  draw horizontal if possible.
+         HUGE        draw text in huge letters.
+         JEWELED     diamond the corners.
+         JOINTED     draw corners.
+         LALIGN      left align text.
+         LEFT        draw on the left side if possible.
+         NUMBERED    draw numbers instead of lines.
+         PRUNED      prune the corners.
+         RALIGN      right align text.
+         RIGHT       draw on the right side if possible.
+         ROUNDED     round the corners.
+         SANSSERIF   draw text with sansserif letters.
+         SCALED      fit the square to the text size.
+         SCROLL      draw in the scrolling region.
+         SHADOWED    shadow HUGE text.
+         TALIGN      top align text too large to fit.
+         TEED        tee the corners.
+         TOP         draw on the top side if possible.
+         TRACED      trace HUGE text.
+         TUBED       draw tubes instead of lines.
+         UALIGN      unwrap and rewrap text.
+         UNICODE     draw in unicode mode.
+         VERTICAL    draw vertical if possible.
+
+         The following types are available.
+
+         [HORIZONTAL] BAR {<MIN>;<MAX>;[COLOR]}
+          will draw a bar, use two 256 color codes for a color gradient.
+         [ASCII|UNICODE|HUGE] BOX {[TEXT1]} {[TEXT2]}
+           will draw a box.
+         [BOXED|FOREGROUND] BUFFER
+           will draw the scrollback buffer.
+         [BLANKED|CIRCLED|CROSSED|JEWELED|ROUNDED|TEED|PRUNED] CORNER
+           will draw a corner.
+         [BLANKED|HORIZONTAL|NUMBERED|TUBED|VERTICAL] LINE {[TEXT]}
+           will draw a line.
+         [BOXED] MAP
+           will draw the map
+         RAIN {<VARIABLE>} {[SPAWN]} {[FADE]} {[LEGEND]}
+           will draw digital rain.
+         [JOINTED|TOP|LEFT|BOTTOM|RIGHT] SIDE
+           will draw one or more sides of a box.
+         [GRID] TABLE {[LIST1]} {[LIST2]}
+          will draw a table.
+         [CURSIVE|FAT|HUGE|SANSSERIF] TILE {[TEXT1]} {[TEXT2]}
+           will draw a tile
+
+         All draw types take an optional text argument as long as a valid
+         square with enough space has been defined. Text is automatically
+         word wrapped and text formatting can be customized with the
+         CALIGN, LALIGN, RALIGN, and UALIGN options.
+
+Example: #draw Blue box 1 1 3 20 {Hello world!}
+
+Related: buffer, echo, grep and showme.
+
+Command: #echo {format} {argument1} {argument2} {etc}
+
+         Echo command displays text on the screen with formatting options. See
+         the help file for the format command for more information.
+
+         The echo command does not trigger actions.
+
+         As with the #show command you can split the {format} argument up into
+         two braced arguments, in which case the 2nd argument is the row number.
+
+Example: #echo {The current date is %t.} {%Y-%m-%d %H:%M:%S}
+         #echo {[%38s][%-38s]} {Hello World} {Hello World}
+         #echo {{this is %s on the top row} {1}} {printed}
+
+Related: buffer, format, grep and showme.
+
+Command: #edit {option} [argument]
+
+         The edit command can be used to turn the default line editor into a
+         text editor.
+
+         #edit create <arguments>
+           Create an editor, initialize using the provided arguments.
+
+         #edit load <variable>
+           Create an editor, initialize using the provided list variable.
+
+         #edit read <filename>
+           Create an editor, initialize using the provided file.
+
+         #edit resume
+           Resume editing after a suspension.
+
+         #edit save <variable>
+           Save the editor to the provided variable.
+
+         #edit suspend
+           Suspend editing, similar to pressing enter except that no
+           events are triggered.
+
+         #edit write <filename
+           Write the editor content to file.
+
+Example: #edit create {bli}{bla}{blo}
+
+Related: cursor and macro.
+
+
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│alt b                    ││cursor backward word                        │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│alt f                    ││cursor forward word                         │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│ctrl a                   ││cursor home                                 │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl b                   ││cursor backward                             │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl c                   ││clear line                                  │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl d                   ││delete or exit                              │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl e                   ││cursor end                                  │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl f                   ││cursor forward                              │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl g                   ││                                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl h                   ││backspace                                   │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl i                   ││tab                                         │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl j                   ││enter                                       │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl k                   ││clear line right                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl l                   ││redraw input                                │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl m                   ││enter                                       │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl n                   ││input history next                          │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl o                   ││                                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl p                   ││input history prev                          │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl q                   ││                                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl r                   ││input history search                        │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl s                   ││                                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl t                   ││scroll buffer lock                          │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl u                   ││clear line left                             │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl v                   ││convert meta characters                     │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl w                   ││delete word left                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl x                   ││                                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl y                   ││paste                                       │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl z                   ││suspend                                     │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│arrow left               ││cursor left                                 │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│arrow right              ││cursor right                                │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│arrow up                 ││previous input line                         │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│arrow down               ││next input line                             │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│ctrl arrow left          ││cursor left word                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl arrow right         ││cursor right word                           │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│backspace                ││backspace                                   │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│alt backspace            ││clear line left                             │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl backspace           ││clear line                                  │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│delete                   ││delete                                      │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl delete              ││delete word right                           │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│end                      ││cursor end                                  │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl end                 ││scroll buffer end                           │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│enter                    ││enter                                       │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│shift-enter              ││soft enter                                  │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│home                     ││cursor home                                 │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│ctrl home                ││scroll buffer home                          │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│page up                  ││scroll buffer up                            │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│page down                ││scroll buffer down                          │
+└─────────────────────────┘└────────────────────────────────────────────┘
+┌─────────────────────────┐┌────────────────────────────────────────────┐
+│tab                      ││complete word forward                       │
+├─────────────────────────┤├────────────────────────────────────────────┤
+│shift-tab                ││complete word backward                      │
+└─────────────────────────┘└────────────────────────────────────────────┘
+
+Related: cursor, edit and macro.
+
+Command: #else {commands}
+
+         The else statement should follow an #IF or #ELSEIF statement and is
+         only called if the proceeding #IF or #ELSEIF is false.
+
+Example: #if {1d2 == 1} {smile};#else {grin}
+
+Related: case, default, elseif, if, switch and regexp.
+
+Command: #elseif {conditional} {commands}
+
+         The elseif statement should follow an #IF or #ELSEIF statement and is
+         only called when the statement is true and the proceeding #IF and
+         #ELSEIF statements are false.
+
+Example: #if {1d3 == 1} {smirk};#elseif {1d2 == 1} {snicker}
+
+Related: case, default, else, if, switch and regexp.
+
+Command: #end {<message>}
+
+         Terminates tintin and return to unix.  On most systems, ctrl-c has
+         the same result.
+
+         The message is optional and is printed before tintin exits. When
+         using #end {\} tintin will terminate silently.
+
+Related: zap
+
+         You may use the escape character \ for various special characters.
+
+         \a    beep the terminal.
+         \c    send a control character, \ca for ctrl-a.
+         \e    start an escape sequence.
+         \f    send a form feed.
+         \n    send a line feed.
+         \r    send a carriage return.
+         \t    send a horizontal tab.
+         \x    print an 8 bit character using hexadecimal, \xFF for example.
+         \x7B  send the '{' character.
+         \x7D  send the '}' character.
+         \u    print a 16 bit unicode character, \uFFFD for example.
+         \u{}  print a 8-21 bit unicode character, \u{2AF21} for example.
+         \U    print a 21 bit unicode character, \U02AF21 for example.
+         \v    send a vertical tab
+
+         Ending a line with \ will stop tintin from appending a line feed.
+         To escape arguments in an alias or action use %%0 %%1 %%2 etc.
+
+Related: characters, colors, coordinates, mathematics and pcre.
+
+Command: #event {event type} {commands}
+
+         Events allow you to create triggers for predetermined client events.
+
+         Use #event without an argument to see a list of possible events with
+         a brief description. Use #event %* to see the current list of defined
+         events. Use #info {events} {on} to see events get thrown.
+
+         Events, like triggers in general, are case sensitive and event names
+         must be defined using all upper case letters. Only one event can be
+         defined for each event type.
+
+         To enable mouse events use #config mouse_tracking on, to see mouse
+         events use #config mouse_tracking info.
+
+         CATCH EVENTS
+
+         CATCH <EVENT>
+           Some events can be prefixed with CATCH to interrupt default
+           behavior.
+
+         CLASS EVENTS
+
+         CLASS ACTIVATED [CLASS],  CLASS_CLEAR [CLASS],  CLASS CREATED [CLASS],
+         CLASS DEACTIVATED [CLASS],  CLASS DESTROYED [CLASS],
+         CLASS_LOAD [CLASS]
+           %0 class name
+
+         GAG EVENTS
+
+         GAG <EVENT>
+           Some events can be prefixed with GAG to gag default system
+           messages.
+
+         INPUT EVENTS
+
+         EDIT STARTED, EDIT FINISHED
+           %0 name  %1 lines %2 size %3 data
+
+         HISTORY UPDATE
+           %0 command
+
+         RECEIVED KEYPRESS, PROCESSED KEYPRESS
+           %0 character  %1 unicode index  %2 edit row  %3 edit column
+
+         RECEIVED INPUT [NAME]
+           %0 raw text
+
+         RECEIVED INPUT CHARACTER
+           %0 character  %1 unicode index  %2 size  %3 width
+
+         NO SESSION ACTIVE      %0 raw text %1 size
+         SEND OUTPUT            %0 raw text %1 size
+         SENT OUTPUT            %0 raw text %1 size
+
+         MAP EVENTS
+
+         END OF PATH,  END OF RUN, MAP UPDATED VTMAP
+           These events have no additional arguments.
+
+         MAP CREATE EXIT, MAP DELETE EXIT
+           %0 vnum  %1 exit name  %2 exit cmd  %3 exit vnum
+
+         MAP CREATE ROOM, MAP DELETE ROOM
+           %0 vnum  %1 name
+
+         MAP ENTER MAP, MAP EXIT MAP
+           %0 vnum
+
+         MAP ENTER ROOM [VNUM]
+           %0 new vnum  %1 old vnum %2 direction
+
+         MAP EXIT ROOM [VNUM]
+           %0 old vnum  %1 new vnum %2 direction
+
+         MAP FOLLOW MAP
+           %0 old vnum  %1 new vnum  %2 exit name
+
+         MAP REGION <MOUSE>, MAP ROOM <MOUSE>
+           %0 row  %1 col  %2 -row  %3 -col  %5 vnum  %6 info
+
+         MOUSE EVENTS
+
+         DOUBLE-CLICKED <MOUSE> %0 row %1 col %2 -row %3 -col %4 word %5 line
+         LONG-CLICKED <MOUSE>   %0 row %1 col %2 -row %3 -col %4 word %5 line
+         MOVED <MOUSE>          %0 row %1 col %2 -row %3 -col %4 word %5 line
+         PRESSED <MOUSE>        %0 row %1 col %2 -row %3 -col %4 word %5 line
+         SHORT-CLICKED <MOUSE>  %0 row %1 col %2 -row %3 -col %4 word %5 line
+         RELEASED <MOUSE>       %0 row %1 col %2 -row %3 -col %4 word %5 line
+         SCROLLED <MOUSE>       %0 row %1 col %2 -row %3 -col %4 word %5 line
+         TRIPLE-CLICKED <MOUSE> %0 row %1 col %2 -row %3 -col %4 word %5 line
+
+         MAP <MOUSE EVENT>
+           Mouse events can be prefixed with MAP to only trigger when the mouse
+           event occurs inside the VT100 map region.
+
+         SWIPED [DIR]
+           %0 dir  %1 button  %2 row  %3 col  %4 -row  %5 -col
+                              %6 row  %7 col  %8 -row  %9 -col %10 rows %11 cols
+
+         OUTPUT EVENTS
+
+         BUFFER UPDATE, DISPLAY UPDATE
+           These events have no additional arguments.
+
+         RECEIVED LINE          %0 raw text %1 plain text
+         RECEIVED OUTPUT        %0 raw text %1 plain text
+         RECEIVED PROMPT        %0 raw text %1 plain text
+
+         PORT EVENTS
+
+         CHAT MESSAGE, PORT MESSAGE
+           %0 raw text  %1 plain text
+
+         PORT CONNECTION        %0 name %1 ip %2 port
+         PORT DISCONNECTION     %0 name %1 ip %2 port
+         PORT LOG MESSAGE       %0 name %1 ip %2 port %3 data %4 plain data
+         PORT RECEIVED MESSAGE  %0 name %1 ip %2 port %3 data %4 plain data
+
+         SCAN EVENTS
+
+         SCAN CSV HEADER        %0 all args %1 arg1 %2 arg2 .. %99 arg99
+         SCAN CSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99
+         SCAN TSV HEADER        %0 all args %1 arg1 %2 arg3 .. %99 arg99
+         SCAN TSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99
+
+         SCREEN EVENTS
+
+         SCREEN DIMENSIONS      %0 height %1 width
+         SCREEN FOCUS           %0 focus (0 or 1)
+         SCREEN LOCATION        %0 rows %1 cols  %2 height %3 width
+
+         SCREEN MOUSE LOCATION
+           %0 row  %1 col  %2 -row  %3 -col  %4 pix row  %5 pix col
+           %6 -pix row  %7 -pix col  %8 location
+
+         SCREEN RESIZE          %0 rows %1 cols %2 height %3 width
+         SCREEN SIZE            %0 rows %1 cols
+         SCREEN SPLIT           %0 top row %1 top col %2 bot row %3 bot col
+         SCREEN UNSPLIT         %0 top row %1 top col %2 bot row %3 bot col
+
+         SESSION EVENTS
+
+         SESSION ACTIVATED      %0 name
+         SESSION CONNECTED      %0 name %1 host %2 ip %3 port %4 file
+         SESSION CREATED        %0 name %1 host %2 ip %3 port %4 file
+         SESSION DEACTIVATED    %0 name
+         SESSION DISCONNECTED   %0 name %1 host %2 ip %3 port
+         SESSION TIMED OUT      %0 name %1 host %2 ip %3 port
+
+         SYSTEM EVENTS
+
+         DAEMON ATTACH TIMEOUT  %0 file %1 pid
+         DAEMON ATTACHED        %0 file %1 pid
+         DAEMON DETACHED        %0 file %1 pid
+         PROGRAM START          %0 startup arguments
+         PROGRAM TERMINATION    %0 goodbye message
+
+         READ ERROR             %0 filename %1 error message
+         READ FILE              %0 filename
+         WRITE ERROR            %0 filename %1 error message
+         WRITE FILE             %0 filename
+
+         SYSTEM CRASH           %0 message
+         SYSTEM ERROR           %0 name %1 system msg %2 error %3 error msg
+         UNKNOWN COMMAND        %0 raw text
+         SIGUSR                 %0 signal
+
+         TELNET EVENTS
+
+         IAC <EVENT>
+           IAC TELNET events are made visible using #config telnet info.
+
+         IAC SB GMCP            %0 module    %1 data  %2 plain data
+         IAC SB GMCP <MODULE>                %1 data  %2 plain data
+         IAC SB MSSP            %0 variable  %1 data
+         IAC SB MSDP            %0 variable  %1 data  %2 plain data
+         IAC SB MSDP [VAR]      %0 variable  %1 data  %2 plain data
+         IAC SB NEW-ENVIRON     %0 variable  %1 data  %2 plain data
+         IAC SB ZMP <VAR>       %0 variable  %1 data
+         IAC SB <VAR>           %0 variable  %1 raw data  %2 plain data
+
+         TIME EVENTS
+
+         DATE <MONTH-DAY OF MONTH> [HOUR:MINUTE], DAY [DAY OF MONTH],
+         HOUR [HOUR], MONTH [DAY OF MONTH], TIME <HOUR:MINUTE>[:SECOND],
+         WEEK [DAY OF WEEK], YEAR [YEAR]
+           %0 year  %1 month  %2 day of week  %3 day of month  %4 hour
+           %5 minute  %6 second
+
+         VARIABLE EVENTS
+
+         VARIABLE UPDATE <VAR>  %0 name %1 new value %2 path
+         VARIABLE UPDATED <VAR> %0 name %1 new value %2 path
+
+         VT100 EVENTS
+
+         VT100 SCROLL REGION    %0 top row %1 bot row %2 rows %3 cols %4 wrap
+
+         To see all events trigger use #info event on. Since this can get
+         rather spammy it's possible to gag event info messages.
+
+Example: #event {SESSION CONNECTED} {#read mychar.tin}
+
+Comment: You can remove an event with the #unevent command.
+
+Related: button, delay and ticker.
+
+Command: #foreach {list} {variable} {commands}
+
+         For each item in the provided list the foreach statement will update
+         the given variable and execute the command part of the statement. List
+         elements must be separated by braces or semicolons.
+
+Example: #foreach {bob;tim;kim} {name} {tell $name Hello}
+Example: #foreach {{bob}{tim}{kim}} {name} {tell $name Hello}
+
+Related: break, continue, list, loop, parse, repeat, return and while.
+
+Command: #format {variable} {format} {argument1} {argument2} {etc}
+
+         Allows you to store a string into a variable in the exact same way
+         C's sprintf works with a few enhancements and limitations like a
+         maximum of 30 arguments.
+
+         If you use #format inside an alias or action you must escape %1s as
+         %+1s or %%1s or %\1s so the %1 isn't substituted by the trigger.
+
+         #format {test} {%+9s} {string}  pad string with up to 9 spaces
+         #format {test} {%-9s} {string}  post pad string with up to 9 spaces
+         #format {test} {%.8s} {string}  copy at most 8 characters
+         #format {test} {%a}   {number}  print corresponding charset character
+         #format {test} {%c}   {string}  use a highlight color name
+         #format {test} {%d}   {number}  print a number with integer formatting
+         #format {test} {%f}   {string}  perform floating point math
+         #format {test} {%g}   {number}  perform thousand grouping on {number}
+         #format {test} {%h}   {string}  turn text into a header line
+         #format {test} {%l}   {string}  lowercase text
+         #format {test} {%m}   {string}  perform mathematical calculation
+         #format {test} {%n}     {name}  capitalize the first letter
+         #format {test} {%p}   {string}  strip leading and trailing spaces
+         #format {test} {%r}   {string}  reverse text, hiya = ayih
+         #format {test} {%s}   {string}  print given string
+         #format {test} {%t}   {format}  display time with strftime format
+                                         optional {{format}{time}} syntax
+         #format {test} {%u}   {string}  uppercase text
+         #format {list} {%w}   {string}  store word wrapped text in {list}
+                                         optional {{string}{width}} syntax
+         #format {test} {%x}      {hex}  print corresponding charset character
+         #format {test} {%A}     {char}  store corresponding character value
+         #format {test} {%D}      {hex}  convert hex to decimal in {test}
+         #format {hash} {%H}   {string}  store a 64 bit string hash in {hash}
+         #format {test} {%L}   {string}  store the string length in {test}
+         #format {test} {%M}   {number}  convert number to metric in {test}
+         #format {test} {%S}   {string}  store the number of spelling errors
+         #format {time} {%T}         {}  store the epoch time in {time}
+         #format {time} {%U}         {}  store the micro epoch time in {time}
+         #format {test} {%X}      {dec}  convert dec to hexadecimal in {test}
+
+         #format {test} {%%}             a literal % character
+
+Comment: See #help TIME for help on the %t argument.
+
+Related: cat, echo, function, local, math, replace, script, time and variable.
+
+Command: #function {name} {operation}
+
+         Functions allow you to execute a script within a line of text, and
+         replace the function call with the line of text generated by the
+         function.
+
+         Be aware that each function should use the #return command at the
+         end of the function with the result, or set the {result} variable.
+
+         To use a function use the @ character before the function name.
+         The function arguments should be placed between braces behind the
+         function name with argument separated by semicolons.
+
+         Functions can be escaped by adding additional @ signs.
+
+Example: #function test #return 42;#showme @@test{}
+
+         The function itself can use the provided arguments which are stored
+         in %1 to %99, with %0 holding all arguments.
+
+Example: #function {rnd} {#math {result} {1 d (%2 - %1 + 1) + %1 - 1}}
+         #show A random number between 100 and 200: @rnd{100;200}
+
+Example: #function gettime {#format result %t %H:%M}
+         #show The current time is @gettime{}
+
+Comment: You can remove a function with the #unfunction command.
+
+Related: format, local, math, replace, script and variable.
+
+Command: #gag {string}
+
+         Removes any line that contains the string.
+
+Comment: See '#help action', for more information about triggers.
+
+         There are a system messages that can be gagged using gag events.
+
+Comment: You can remove a gag with the #ungag command.
+
+Related: action, highlight, prompt and substitute.
+
+      ####################################################################
+      #                                                                  #
+      #                    T I N T I N + +   2.02.31b                    #
+      #                                                                  #
+      #      Code by Peter Unold, Bill Reis, and Igor van den Hoven      #
+      #                                                                  #
+      ####################################################################
+
+Command: #grep [page] {search string}
+
+         This command allows you to search for matching lines in your scroll
+         back buffer. The amount of matches shown equals your screen size. If
+         you want to search back further use the optional page number. You can
+         use wildcards for better search results. Be aware the search string
+         is case sensitive, which can be disabled by using %i.
+
+         By default grep searches from the end of the scrollback buffer to the
+         beginning, this can be reversed by using a negative page number.
+
+Example: #grep Bubba tells you
+         This will show all occasions where bubba tells you something.
+
+Related: buffer, echo and showme.
+
+Command: #help {subject}
+
+         Without an argument #help will list all available help subjects.
+
+         Using #help %* will display all help entries.
+
+Related: commands, debug, ignore, info, message and statements.
+
+Command: #highlight {string} {color names} {priority}
+
+         The highlight command is used to change the color of incoming text.
+
+         Available color options are:
+
+         reset      - resets the color state to default
+         light      - turns the color light.
+         dark       - turns the color dark.
+         underscore - underscores the text.
+         blink      - makes the text blink.
+         reverse    - reverse foreground and background color.
+         b          - makes next color the background color.
+
+         Available color names are:
+
+         <abd> - azure                 <acf> - Azure
+         <aad> - blue                  <aaf> - Blue
+         <add> - cyan                  <aff> - Cyan
+         <aaa> - ebony                 <bbb> - Ebony
+         <ada> - green                 <afa> - Green
+         <adb> - jade                  <afc> - Jade
+         <bda> - lime                  <cfa> - Lime
+         <dad> - magenta               <faf> - Magenta
+         <dba> - orange                <fca> - Orange
+         <dab> - pink                  <fac> - Pink
+         <daa> - red                   <faa> - Red
+         <ccc> - silver                <eee> - Silver
+         <cba> - tan                   <eda> - Tan
+         <bad> - violet                <caf> - Violet
+         <ddd> - white                 <fff> - White
+         <dda> - yellow                <ffa> - Yellow
+
+         Colors can be provided as either a color code or one of the valid color
+         names. If the color name is in all lower case a dark color is printed.
+         If the first letter of the color name is capitalized a light color is
+         printed.
+
+         The %1-99 variables can be used as 'wildcards' that will match with any
+         text. They are useful for highlighting a complete line. The %0 variable
+         should never be used in highlights.
+
+         You may start the string to highlight with a ^ to only highlight text
+         if it begins the line.
+
+         Besides color names also <abc> color codes can be used.
+
+Example: #high {Valgar} {reverse underscore Jade}
+         Prints every occurrence of 'Valgar' in underscored reverse video Jade.
+
+Example: #high {^You{|r} %1} {light cyan}
+         Prints every line that starts with 'You' in light cyan.
+
+Example: #high {Bubba} {red underscore b Green}
+         Highlights the name Bubba as red underscored text on green background.
+
+Comment: See '#help action', for more information about triggers.
+
+Comment: See '#help substitute', for more advanced color substitution.
+
+Comment: This command only works with ANSI/VT100 terminals or emulators.
+
+Comment: You can remove a highlight with the #unhighlight command.
+
+Related: action, gag, prompt and substitute.
+
+Command: #history {delete}                 Delete the last command.
+         #history {insert}    {command}    Insert a command.
+         #history {list}                   Display the entire command history.
+         #history {read}      {filename}   Read a command history from file.
+         #history {write}     {filename}   Write a command history to file.
+
+         Without an argument all available options are shown.
+
+         By default all commands are saved to the history list and the history
+         list is saved between sessions in the ~/.tintin/history.txt file.
+
+         You can set the character to repeat a command in the history with the
+         #config {REPEAT CHAR} {<character>} configuration option, by default
+         this is set to the exclamation mark.
+
+         You can use ! by itself to repeat the last command, or !<text> to
+         repeat the last command starting with the given text.
+
+         You can use #config {REPEAT ENTER} {ON} to repeat the last command
+         when you press enter on an empty line.
+
+         You can press ctrl-r to enter an interactive regex enabled history
+         search mode, or by issuing #cursor {history search}.
+
+         TinTin++ tries to bind the arrow up and down keys to scroll through
+         the history list by default. You can bind these with a macro yourself
+         using #cursor {history next} and #cursor {history prev}. Many #cursor
+         commands only work properly when bound with a macro.
+
+Related: alias, cursor, keypad, macro, speedwalk and tab.
+
+Command: #if {conditional} {commands if true}
+
+         The #if command works similar to an if statement in other languages,
+         and is based on the way C handles its conditional statements.
+         When an #if command is encountered, the conditional statement is
+         evaluated, and if TRUE (any non-zero result) the commands are executed.
+
+         The conditional is evaluated exactly the same as in the #math command,
+         if the conditional evaluates as anything except 0 the commands are
+         executed. See the 'math' helpfile for more information.
+
+         To handle the case where an if statement is false it can be followed
+         by the #else command.
+
+Example: #action {%0 gives you %1 gold coins.} {#if {%1 > 5000} {thank %0}}
+         If someone gives you more than 5000 coins, thank them.
+
+Example: #alias {k} {#if {"%0" == ""} {kill $target};#else {kill %0}}
+
+Related: case, default, else, elseif, math, switch and regexp.
+
+Command: #ignore {listname} {on|off}
+
+         Toggles a list on or off. With no arguments it shows your current
+         settings, as well as the list names that you can ignore.
+
+         If you for example use #IGNORE ACTIONS ON actions will no longer
+         triger. Not every list can be ignored.
+
+Related: class, debug, info, kill and message.
+
+                   ████████┐██████┐███┐   ██┐████████┐██████┐███┐   ██┐
+                   └──██┌──┘└─██┌─┘████┐  ██│└──██┌──┘└─██┌─┘████┐  ██│
+                      ██│     ██│  ██┌██┐ ██│   ██│     ██│  ██┌██┐ ██│
+                      ██│     ██│  ██│└██┐██│   ██│     ██│  ██│└██┐██│
+                      ██│   ██████┐██│ └████│   ██│   ██████┐██│ └████│
+                      └─┘   └─────┘└─┘  └───┘   └─┘   └─────┘└─┘  └───┘
+                                       ██┐      ██┐
+                                       ██│      ██│
+                                    ████████┐████████┐
+                                    └──██┌──┘└──██┌──┘
+                                       ██│      ██│
+                                       └─┘      └─┘
+
+                       (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t
+
+
+         What is TinTin++?
+
+         TinTin++ is a client program specialized to help playing muds. This is
+         a souped up version of TINTIN III with many new features.
+
+         Giving Credit Where Credit is Due
+
+         None of this work would be possible, without the work done by Peter
+         Unold. He was the author of TINTIN III, the base of TinTin++. Hats off
+         to ya Peter. You started the ball rolling.
+
+         Introduction
+
+         If you're new to TinTin++ a good place to start is the introduction,
+         which should be linked below.
+
+Related: introduction
+
+Command: #info {listname} {LIST|ON|OFF|SAVE}
+
+         Without an argument info displays the settings of every tintin list.
+
+         By providing the name of a list and the LIST option it shows all
+         triggers/variables associated with that list. With the SAVE option
+         this data is written to the info variable.
+
+         #info arguments will show matched trigger arguments.
+         #info big5toutf will show the big5 to utf8 translation table.
+         #info cpu will show information about tintin's cpu usage.
+         #info environ will show the environment variables.
+         #info input will show information about the input line.
+         #info matches will show matched command arguments.
+         #info mccp will show information about data compression.
+         #info memory will show information about the memory stack.
+         #info stack will show the low level debugging stack.
+         #info session will show information on the session.
+         #info sessions will show information on all sessions.
+         #info system will show some system information.
+         #info tokenizer will show information about the script stack.
+         #info unicode will show information on the provided character.
+
+Related: class, debug, ignore, kill and message.
+
+         On this page you'll find an introduction to using TinTin++. Additional
+         information can be found in the individual help sections.
+
+         Starting and Ending
+
+         The syntax for starting TinTin++ is: ./tt++ [command file]
+
+         Read more about the command file in the files section below. Remember
+         one thing though. All actions, aliases, substitutions, etc, defined
+         when starting up TinTin++ are inherited by all sessions.
+
+         If you want to exit TinTin++ type '#end' or press ctrl-d on an empty
+         line.
+
+         For the WinTin++ users, if you want to paste text use shift-insert,
+         text is automatically copied upon selection. This is typical Linux
+         behavior, but it can take some getting used to.
+
+
+         Basic features
+
+         I'll start by explaining some of the very basic and important features:
+
+         All TinTin++ commands starts with a '#'.
+
+Example: #help -- #help is a client command, and isn't send to the server.
+
+         All TinTin++ commands can be abbreviated when typed.
+
+         #he -- Typing #he is the same as typing #help though it's suggested to
+         use at least 3 letter abbreviations just in case another command is
+         added that starts with 'he'.
+
+         All commands can be separated with a ';'.
+
+         n;l dragon;s;say Dan Dare is back! -- do these 4 commands
+         There are 3 ways ';'s can be overruled.
+
+         \say Hello ;) -- Lines starting with a '\' aren't parsed by TinTin++.
+         say Hello \;) -- The escape character can escape 1 letter.
+         #config verbatim on -- Everything is sent as is except '#' commands.
+
+         Connecting to a server
+
+Command: #session {session name} {server address} {port}
+
+Example: #session someone tintin.sourceforge.net 4321
+
+         You can have more than one session, in which case you can switch
+         between sessions typing #<session name>.
+
+         You can get a list of all sessions by typing: #session. The current
+         active session is marked with (active). Snooped sessions with
+         (snooped). MCCP sessions (compression) with (mccp 2) and (mccp 3).
+
+
+         Split
+
+Command: #split
+
+         The split command will create a separated input and output area.
+
+         Using the #prompt command you can capture the prompt and place it on
+         the split line. To get rid of the split interface you can use #unsplit
+         which will restore the terminal settings to default.
+
+
+         Alias
+
+Command: #alias {name} {commands}
+
+         The syntax of the #alias command is almost like alias in csh.
+         Use this command to define aliases. The variables %0, %1.. %9 contain
+         the arguments to the aliased command as follows:
+         the %0 variable contains all the arguments.
+         the %1 variable contains the 1st argument
+         ....
+         the %9 variable contains the 9th argument
+
+Example: #alias greet say Greetings, most honorable %1
+
+         If you want an alias to execute more commands, you must use braces.
+
+Example: #alias ws {wake;stand}
+
+         To delete an alias use the #unalias command.
+
+         WARNING! TinTin++ doesn't baby sit, and hence does not check for
+         recursive aliases! You can avoid recursion by escaping the entire
+         line.
+
+Example: #alias put \put %1 in %2
+
+         Or by using the send command.
+
+Example: #alias put #send put %1 in %2
+
+
+         Action
+
+Command: #action {action-text} {commands}
+
+         Use this command to define an action to take place when a particular
+         text appears on your screen. There are 99 variables you can use as
+         wildcards in the action-text.
+
+         These variables are %1, %2, %3 .... %9, %10, %11 ... %97, %98, %99.
+
+Example: #action {You are hungry} {get bread bag;eat bread}
+
+Example: #action {%1 has arrived.} shake %1 -- shake hands with people arriving.
+
+Example: #action {%1 tells you '%2'}
+                   {tell bob %1 told me '%2'} -- forward tells.
+
+Example: #action {tells you} #bell -- beep on tell.
+
+         You can have TinTin++ ignore actions if you type '#ignore actions on'.
+
+         You can see what commands TinTin++ executes when an action triggers
+         by typing '#debug actions on'.
+
+         You can remove actions with the #unaction command.
+
+
+         Command files
+
+         When you order TinTin++ to read a command file, it parses all the text
+         in the file. You can use command files to keep aliases/actions in,
+         login to a server (name, password etc..) and basically all kinds of
+         commands.
+
+         You can make the command files with either a text editor (suggested),
+         or use the #write command to write out a file.
+
+         Commands for files:
+
+         #read filename -- read and execute the file.
+
+         #write filename -- write all actions/aliases/substitutes/etc known for
+         the current session to a file.
+
+Example:
+         #session x mymud.com 1234
+         myname
+         mypassword
+         #split
+         #action {^You are hungry.} {eat bread}
+
+         If you save the above five lines to a file named 'mymud.tin' you can
+         use 'tt++ mymud.tin' to start tintin and execute the file, connecting
+         you to your mud, logging in, enabling split mode, and setting an action
+         to eat a bread whenever you go hungry.
+
+         Highlight
+
+Command: #highlight {text} {color}
+
+         This command works a bit like #action. The purpose of this command is
+         to substitute text from the server with color you provide. This command
+         is a simplified version of the #substitute command.
+
+Example: #high {Snowy} {light yellow}
+
+Example: #high {%*Snowy%*} {light yellow}
+
+         Use #unhigh to delete highlights.
+
+
+         Speedwalk
+
+         If you type a command consisting ONLY of letters and numbers n, e, s,
+         w, u, d - then this command can be interpreted as a serie of movement
+         commands.
+
+Example: ssw2n -- go south, south, west, north, north
+
+         If you have problems with typing some commands that actually ONLY
+         consists of these letters, then type them in CAPS. For example when
+         checking the NEWS or when asked to enter NEW as your name.
+
+         You must enable speedwalking with: #config speedwalk on.
+
+
+         Ticker
+
+Command: #ticker {name} {commands} {seconds}
+
+         The name can be whatever you want it to be, and is only required for
+         the unticker command. The commands will be executed every x amount of
+         seconds, which is specified in the interval part.
+
+Example: #tick {tick} {#delay 50 #show 10 SECONDS TO TICK!;#show TICK!!!} {60}
+
+         This creates a ticker with the name {tick} which will print TICK!!!,
+         as well as print a warning when the next tick will occure.
+
+         You can remove tickers with #untick
+
+
+         Repeating Commands
+
+         You can repeat a command, the syntax is: #number command
+
+Example: #5 cackle -- if you just killed bob the wizard.
+Example: #10 {buy bread;put bread bag} -- repeat these 2 commands 10 times.
+Example: #100 ooc w00t w00t!!!!! -- nochannel yourself.
+
+
+         History
+
+         TinTin++ has a limited subset of the csh history features.
+
+         ! -- repeat the last command
+         !cast -- repeat the last command starting with cast
+         ctrl-r -- enter the reverse history search mode.
+
+
+         Map commands
+
+         TinTin++ has a powerful highly configurable automapper. Whenever
+         you type n/ne/e/se/s/sw/w/nw/n/u/d tt++ tries to keep track of your
+         movement.
+
+         Commands for map:
+
+         #map create -- create a map.
+         #map goto 1 -- go to the first room in the map, created by default.
+         #map map -- display the map.
+         #map undo -- undo your last map alteration.
+         #map write <filename> -- save the map to file.
+         #map read <filename> -- load a map from file.
+
+         There are many other map options and it's beyond the scope of this
+         help section to explain everything there is to know, but I'll give
+         a set of commands that will get most people started.
+
+         #map create
+         #split 12 1
+         #map flag unicode on
+         #map flag vt on
+         #map goto 1
+
+         These commands will create a 12 row vt100 split section at the top of
+         your screen where a map drawn using unicode characters is displayed.
+
+Example: #action {There is no exit in that direction.} {#map undo}
+
+         The map will be automatically created as you move around.
+
+
+         Help
+
+Command: #help {subject}
+
+         The help command is your friend and contains the same helpfiles
+         inside TinTin++ as are available on the website. If you type #help
+         without an argument you will see the various available help subjects
+         which try to explain the TinTin++ commands and features in greater
+         detail. Entries in cyan describe commands, while entries in white
+         describe various features, often in greater detail.
+
+
+         That's all for the introduction, enjoy
+
+Related: characters, colors, coordinates, editing, escape_codes, greeting, keypad, lists, mapping, mathematics, screen_reader, sessionname, speedwalk, statements, suspend and time.
+
+         When TinTin++ starts up it sends \e= to the terminal to enable the
+         terminal's application keypad mode, which can be disabled using #show {\e>}
+
+      Configuration A           Configuration B           Configuration C
+ ╭─────┬─────┬─────┬─────╮ ╭─────┬─────┬─────┬─────╮ ╭─────┬─────┬─────┬─────╮
+ │num  │/    │*    │-    │ │num  │/    │*    │-    │ │Num  │nkp/ │nkp* │nkp- │
+ ├─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┤
+ │7    │8    │9    │+    │ │Home │Up   │PgUp │+    │ │nkp7 │nkp8 │nkp9 │nkp+ │
+ ├─────┼─────┼─────┤     │ ├─────┼─────┼─────┤     │ ├─────┼─────┼─────┤     │
+ │4    │5    │6    │     │ │Left │Cntr │Right│     │ │nkp4 │nkp5 │nkp6 │     │
+ ├─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┤
+ │1    │2    │3    │Enter│ │End  │Down │PgDn │Enter│ │nkp1 │nkp2 │nkp3 │nkpEn│
+ ├─────┴─────┼─────┤     │ ├─────┴─────┼─────┤     │ ├─────┴─────┼─────┤     │
+ │0          │.    │     │ │Ins        │Del  │     │ │nkp0       │nkp. │     │
+ ╰───────────┴─────┴─────╯ ╰───────────┴─────┴─────╯ ╰───────────┴─────┴─────╯
+
+         With keypad mode disabled numlock on will give you configuration A,
+         and numlock off will give you configuration B. With keypad mode
+         enabled you'll get configuration C.
+
+         Terminals that support keypad mode
+         Linux Console, PuTTY, MinTTY, Eterm, aterm.
+
+         Terminals that do not support keypad mode
+
+         RXVT on Cygwin, Windows Console, Gnome Terminal, Konsole.
+
+         Peculiar Terminals
+
+         RXVT requires turning off numlock to enable configuration C.
+
+         Xterm may require disabling Alt/NumLock Modifiers (num-lock) in the
+         ctrl left-click menu. Or edit ~/.Xresources and add
+         XTerm*VT100.numLock:false
+
+         Mac OS X Terminal requires enabling 'strict vt100 keypad behavior' in
+         Terminal -> Window Settings -> Emulation.
+
+Related: colors, coordinates, escape_codes, mathematics and pcre.
+
+Command: #kill {list} {pattern}
+
+         Without an argument, the kill command clears all lists.  Useful if
+         you don't want to exit tintin to reload your command files.
+
+         With one argument a specific list can be cleared.
+
+         With two arguments the triggers in the chosen list that match the
+         given pattern will be removed.
+
+Example: #kill alias %*test*
+
+Related: class, debug, ignore, info and message.
+
+Command: #line {option} {argument}
+
+         Line options that alter the argument.
+
+         #line json <variable> <argument>
+           The variable is translated to json and the argument is executed
+           with &0 holding the json data.
+
+         #line strip <argument>
+           Argument is executed with all color codes stripped.
+
+         #line substitute <options> <argument>
+           Argument is executed using the provided substitutions, available
+           options are: arguments, braces, colors, escapes, functions, secure,
+           and variables.
+
+         Line options that alter how the line is executed.
+
+         #line background <argument>
+           Prevent new session activation.
+
+         #line capture <variable> <argument.
+           Argument is executed and output stored in <variable>.
+
+         #line convert <argument>
+           Argument is executed with escaped meta characters.
+
+         #line debug <argument>
+           Argument is executed in debug mode.
+
+         #line gag [amount]
+           Gag the next line, or given lines. Use + or - to increase
+           or decrease the current amount.
+
+         #line ignore {argument}
+           Argument is executed without any triggers being checked.
+
+         #line local {argument}
+           Argument is executed with all newly and indirectly
+           created variables being local.
+
+         #line log <filename> [text]
+           Log the next line to file unless the [text] argument is
+           provided.
+
+         #line logmode <option> <argument>
+           Argument is executed using the provided logmode, available
+           modes are: html, plain, raw, and stamp.
+
+         #line msdp <argument>
+           Turn the argument into an msdp telnet sequence, starting at the
+           first opening brace. Will turn tintin tables into msdp tables,
+           with semicolons being used to create msdp arrays.
+
+         #line multishot <number> <argument>
+           Argument is executed in multishot mode, all triggers created
+           will only fire the given number of times.
+
+         #line oneshot <argument>
+           Argument is executed in oneshot mode, all triggers created will
+           only fire once.
+
+         #line quiet <argument>
+           Argument is executed with suppression of most system messages.
+
+         #line verbatim <argument>
+           Argument is executed verbatim, prohibiting variable and function
+           substitutions.
+
+         #line verbose <argument>
+           Argument is executed with most system messages enabled.
+
+         When using #line log and logging in html format use \c< \c> \c& \c" to
+         log a literal < > & and ".
+
+Related: class and config.
+
+Command: #list {variable} {option} {argument}
+
+         #list {var} {add} <items>              Add <items> to the list
+         #list {var} {clear}                    Empty the given list
+         #list {var} {collapse} <separator>     Turn list into a variable
+         #list {var} {create} <items>           Create a list using <items>
+         #list {var} {delete} <index> [amount]  Delete the item at <index>,
+                                                the [amount] is optional.
+         #list {var} {explode} <separator>      Turn variable into a list
+         #list {var} {indexate} [key]           Index a list table for sorting
+         #list {var} {insert} <index> <item>    Insert <item> at given index
+         #list {var} {filter} <keep> [remove]   Filter with keep / remove regex
+         #list {var} {find} <regex> <variable>  Return the found index
+         #list {var} {get} <index> <variable>   Copy an item to {variable}
+         #list {var} {numerate}                 Renumber a table or list
+         #list {var} {order} [items]            Sort list alphanumerically
+         #list {var} {refine} <keep> [remove]   Filter with keep / remove math
+                                                with &0 holding the value
+         #list {var} {reverse}                  Reverse the list
+         #list {var} {shuffle}                  Shuffle the list
+         #list {var} {set} <index> <item>       Change the item at {index}
+         #list {var} {simplify} [items]         Turn list into a simple list
+         #list {var} {size} <variable>          Copy list size to {variable}
+         #list {var} {sort} [items]             Sort list alphabetically, if
+                                                an item is given it's added.
+         #list {var} {tokenize} <string>        Create a character list
+
+         The index should be between +1 and the list's size. You can also give
+         a negative value, in which case -1 equals the last item in the list, -2
+         the second last, etc.
+
+         When inserting an item a positive index will prepend the item at the
+         given index, while a negative index will append the item.
+
+         The add and create options allow using multiple items, as well
+         as semicolon separated items.
+
+         The get option will return the item or the indexation. Use
+         $var[<index>] to retrieve the nested data of a list table.
+
+         The order, sort and simplify options will perform the operation on
+         the given list. Optional items can be provided which are added to
+         the new or existing list before the operation is executed. Sorting
+         and ordering are stable.
+
+         The indexate option prepares a table or list table for order, sort,
+         filter, refine, and find operations for the given key. It is similar
+         to the SELECT option in SQL.
+
+         A size of 0 is returned for an empty or non-existent list. You can
+         directly access the size of a list using &var[].
+
+         You can directly access elements in a list variable using $var[+1],
+         $var[+2], $var[-1], etc.
+
+Related: break, continue, foreach, loop, parse, repeat, return and while.
+
+         There are several different types of lists in tintin which behave in a
+         fairly universal manner. To properly explain lists it's easiest to
+         explain the most basic variable type first before discussing more
+         complex types.
+
+       - Basic variable: The standard key = value variable.
+
+       - Simple list: A string that contains semicolon delimited fields.
+         {a;b;c}. Can be saved as a variable.
+
+       - Brace list: A string in which fields are delimited with braces.
+         {a}{b}{c}. Brace lists cannot be stored as a variable because tables
+         use braces as well, they must be stored as a simple list instead.
+
+       - Table: Think of this as variables nested within another variable. Or
+          as variables contained within another variable.
+
+       - List: A table that uses integers for its indexes. Also known as an
+         array. The #list command is a utility command for using tables as
+         arrays.
+
+         Simple Variables
+
+Example:
+         #variable {simple} {Hello World!}
+         #show $simple
+
+         To see if the 'simple' variable exists you can use &{simple} which
+         will display 0 if the variable does not exist, or the variable's index
+         if it exists.
+
+         If you have multiple variables they are sorted alphabetically and
+         numerically. While it's not all that relevant for simple variables,
+         the first variable has index 1, the second variable index 2, and so
+         on.
+
+         Variable names need to start with a letter and only exist of letters,
+         numbers, and underscores. If you need to use a non standard variable
+         name this is possible using braces.
+
+Example: #variable {:)} {Happy Happy!};#show ${:)}
+
+         Variables can be accessed using their index. While primarily useful
+         for tables it is possible to do this for simple variables. Use +1 for
+         the first variable, +2 for the second variable, etc. Use -1 for the
+         last variable, -2 for the second last variable, etc.
+
+Example: #show The first variable is: *{+1} with value: ${+1}
+
+         Removing Variables
+
+         To remove a variable, use #unvariable or #unvar (every command can be
+         abbreviated). It's possible to remove multiple variables at once
+         using #unvar {var 1} {var 2} {etc}
+
+         Variables are unique to each session, so if you have multiple
+         sessions, removing a variable from one session won't remove it from
+         other sessions.
+
+         If you remove a table variable, all variables contained within that
+         table variable are removed as well.
+
+         Simple Lists
+
+         A simple list is a string that contains semicolon delimited fields.
+         Commands can be entered as simple lists, for example:
+         #show {a};#show {b} will execute a single line as two commands.
+
+         Several commands take a simple list as their input, these are:
+         #foreach, #line substitute, #path load, #list create, and #highlight.
+
+         Brace Lists
+
+         A brace list is a string in which fields are delimited with braces.
+         Most commands take a brace list for their arguments, for example:
+         #session {x} {mud.com} {1234} {mud.tin}. The session command takes
+         4 arguments, the 4th argument (command file) is optional.
+
+         Commands that take a simple list as their input will also accept a
+         brace list, keep in mind you'll have to embed the brace list in an
+         extra set of braces, for example: #path load {{n}{s}{w}{w}}, which is
+         identical to: #path load {n;s;w;w}.
+
+         Brace lists cannot be stored as variables because TinTin++ will
+         confuse them with tables. You can convert a brace list to a table
+         variable using: #list {bracelist} {create} {{a}{b}{c}} this will look
+         internally as: {{1}{a}{2}{b}{3}{c}}. You can then convert this table
+         back to a simple list using: #list {bracelist} {simplify} which will
+         change it to {a;b;c}.
+
+         Braces cannot easily be escaped in TinTin++. Using \{ or \} will not
+         work. The reason for this is due to several factors, but primarily
+         backward compatibility. To escape braces you must define them using
+         hexadecimal notation using \x7B and \x7D. See #help escape for a list
+         of escape options, and the help file will also remind you of how to
+         escape braces.
+
+         Tables
+
+         Tables are key/value pairs stored within a variable. Tables are also
+         known as associative arrays, dictionaries, maps, nested variables,
+         structures, and probably a couple of other names. There are several
+         ways to create and access tables.
+
+Example: #variable {friendlist} {{bob}{bob@mail.com} {bubba}{sunset@gmail.com}}
+
+         This will create a friendlist with two entries, the key is the name of
+         the friend, the value is the email address of the friend. You can see
+         the email address of bob using: #show {$friendlist[bob]}. You can
+         also define this table as following:
+
+Example:
+         #variable {friendlist[bob]} {bob@mail.com}
+         #variable {friendlist[bubba]} {sunset@gmail.com}
+
+         This would create the exact same table as the single line declaration
+         used previously. To see the first key in the table use:
+         *friendlist[+1], to see the first value in the table use:
+         $friendlist[+1]. To see the size of the table use &friendlist[]. To
+         print a bracelist of all friends use *friendlist[], to print a
+         bracelist of all friends whose name starts with the letter 'a' you
+         would use: *friendlist[a%*]. Similarly to see the number of friends
+         you have whose name ends with the letter 'b' you would use:
+         &friendlist[%*b].
+
+         See #help regexp for a brief overview of regular expression options.
+         While TinTin++ supports PCRE (perl-compatible regular expressions), it
+         embeds them within its own regular expression syntax that is simpler
+         and less invasive, while still allowing the full power of PCRE for
+         those who need it.
+
+Example: #unvariable {friendlist[bubba]}
+
+         This would remove {bubba} from the friendlist. To remove the entire
+         friendlist you would use: #unvariable {friendlist}.
+
+Example: #variable {friendlist} {{bob} {{email}{bob@ma.il} {phone}{123456789}}}
+
+         There is no limit to the number of nests, simply add more braces. To
+         see Bob's email in this example you would use:
+         #show {$friendlist[bob][email]}.
+
+         To merge two tables the #cat command can be used.
+Example:
+         #variable {bli} {{a}{1}{b}{2}}
+         #variable {blo} {{c}{3}{d}{4}}
+         #cat {blo} {$bli}
+
+         Lists
+
+         Tables are sorted alphabetically with the exception of numbers which
+         are sorted numerically. If you want to determine the sorting order
+         yourself you can use use the #list command which helps you to use
+         tables as arrays.
+
+Example: #action {%1 chats %2} {#list chats add {%0}}
+
+         Each time a chat is received it's added to the end of the 'chats' list
+         variable. If you type #variable chats this might look like:
+
+         #VARIABLE {chats}
+         {
+                 {1} {Bubba chats Hi}
+                 {2} {Bob chats Hi bub}
+                 {3} {Bubba chats Bye}
+                 {4} {Bob chats bub bye}
+         }
+
+         Parsing
+
+         There are various ways to parse lists and tables, using either #loop,
+         #foreach, #while, or #<number>.
+
+         #loop takes two numeric arguments, incrementing or decrementing the
+         first number until it matches the second number. The value of the loop
+         counter is stored in the provided variable.
+
+         #foreach takes either a simple list or a brace list as its first
+         argument. Foreach will go through each item in the list and store the
+         value in the provided variable.
+
+         #while will perform an if check on the first argument, if the result
+         is true it will execute the commands in the second argument. Then it
+         performs an if check on the first argument again. It will continue to
+         repeat until the if check returns 0 or the loop is interrupted with a
+         control flow command. It takes special care to avoid infinite loops.
+
+         #<number> will execute the provided argument 'number' times. For
+         example: #4 {#show beep! \a}
+
+         Here are some examples.
+
+Example: #list friends create {bob;bubba;zorro}
+
+         Internally this looks like {{1}{bob}{2}{bubba}{3}{zorro}} and the
+         list can be parsed in various ways.
+
+Example: #foreach {$friends[%*]} {name} {#show $name}
+
+Example: #foreach {*friends[%*]} {i} {#show $friends[$i]}
+
+Example: #loop {1} {&friends[]} {i} {#show $friends[+$i]}
+
+Example: #math i 1;#while {&friends[+$i]} {#show $friends[+$i];
+         #math i $i + 1}
+
+Example: #math i 1;#&friends[] {#show $friends[+$i];#math i $i + 1}
+
+         Each of the five examples above performs the same task; printing the
+         three names in the friends list.
+
+         If you want to get a better look at what goes on behind the scenes
+         while executing scripts you can use '#debug all on'. To stop seeing
+         debug information use '#debug all off'.
+
+         List Tables
+
+         List tables are also known as databases and the #list command has
+         several options to manipulate them.
+
+         For these options to work properly all tables need to have identical
+         keys. Here is an example list table.
+
+         #var {friendlist}
+         {
+             {1}{{name}{bob} {age}{54}}
+             {2}{{name}{bubba} {age}{21}}
+             {3}{{name}{pamela} {age}{36}}
+         }
+
+         To sort the list table by age you would use:
+
+         #list friendlist indexate age
+         #list friendlist order
+
+         To remove everyone whose name starts with a 'b' you would use:
+
+         #list friendlist indexate name
+         #list friendlist filter {} {b%*}
+
+         The filter option only supports regular expressions. To filter
+         using mathematics you would loop through the list backwards:
+
+         #loop &friendlist[] 1 index
+         {
+             #if {$friendlist[+$index][age] < 30}
+             {
+                 #list friendlist delete $index
+             }
+         }
+
+         Alternatively you can use the refine option.
+
+         #list friendlist indexate age
+         #list friendlist refine {&0 >= 30}
+
+         To add an item to a list table there are two options:
+
+         #list friendlist add {{{name}{hobo} {age}{42}}}
+         #list friendlist insert -1 {{name}{hobo} {age}{42}}
+
+         Optimization
+
+         TinTin++ tables are exceptionally fast while they remain under 100
+         items. Once a table grows beyond 10000 items there can be performance
+         issues when inserting and removing items in the beginning or middle of
+         the table.
+
+         The plan is to eventually implement an indexable and flexible data
+         structure for large tables.
+
+         If you load a large table from file it's important to make sure it's
+         sorted, when using #write to save a table it's automatically sorted.
+
+         If you notice performance issues on large tables it's relatively easy
+         to create a hash table.
+
+Example:
+
+         #alias {sethash}
+         {
+             #format hash %H %1;
+             #math hash1 $hash % 100;
+             #math hash2 $hash / 100 % 100;
+             #var hashtable[$hash1][$hash2][%1] %2
+         }
+
+         #function {gethash}
+         {
+             #format hash %H %1;
+             #math hash1 $hash % 100;
+             #math hash2 $hash / 100 % 100;
+             #return $hashtable[$hash1][$hash2][%1]
+         }
+
+         #alias {test}
+         {
+             sethash bli hey;
+             sethash bla hi;
+             sethash blo hello;
+             #show The value of bla is: @gethash{bla}
+         }
+
+         The above script will rapidly store and retrieve over 1 million items.
+         Looping through a hash table is relatively easy as well.
+
+Example:
+
+         #alias {showhash}
+         {
+             #foreach {*hashtable[%*]} {hash1}
+             {
+                 #foreach {*hashtable[$hash1][%*]} {hash2}
+                 {
+                     #echo {%-20s = %s}
+                                        {hashtable[$hash1][$hash2]}
+                                        {$hashtable[$hash1][$hash2]}
+                 }
+             }
+        }
+
+Related: break, continue, foreach, loop, parse, repeat, return and while.
+
+Command: #local {variable name} {text to fill variable}
+
+         The local command sets a local variable. Unlike a regular variable
+         a local variable will only stay in memory for the duration of the
+         event that created it. They are accessed in the same way as a
+         regular variable.
+
+         Commands that store information to a variable will use a local variable
+         if it exists.
+
+         Avoid setting the result variable as local in a function. Similarly,
+         it is best to avoid setting a local variable that is identical to an
+         existing regular variable.
+
+Example: #alias {swap} {#local x %0;#replace x {e} {u};#show $x}
+
+Comment: You can remove a local variable with the #unlocal command.
+
+Related: format, function, math, replace, script and variable.
+
+Command: #log {option} {argument}
+
+         The log command allows logging session output to file. You can set the
+         data type to either plain, raw, or html with the config command.
+
+         #log append <filename>
+           Start logging to the given file, if the file already exists it won't
+           be overwritten and data will be appended to the end.
+
+         #log move <filename_1> <filename_2>
+           Move filename_1 to filename_2. This can be any file and doesn't need
+           to be a log file.
+
+         #log overwrite <filename>
+           Start logging to the given file, if the file already exists it will
+           be overwritten.
+
+         #log off
+           Stop logging.
+
+         #log remove <filename>
+           Remove the file. This can be any file and doesn't need to be a log
+           file.
+
+         #log timestamp <format>
+           When set the timestamp will be prepended to each line logged to file.
+           The format will be formatted as a date using the strftime format
+           specifiers as described in #help time.
+
+Related: read, scan, textin, time and write.
+
+Command: #loop {<start>} {<finish>} {<variable>} {commands}
+
+         Like a for statement, loop will loop from start to finish incrementing
+         or decrementing by 1 each time through.  The value of the loop counter
+         is stored in the provided variable, which you can use in the commands.
+
+Example: #loop 1 3 loop {get all $loop.corpse}
+         This equals 'get all 1.corpse;get all 2.corpse;get all 3.corpse'.
+
+Example: #loop 3 1 cnt {drop $cnt\.key}
+         This equals 'drop 3.key;drop 2.key;drop 1.key'.
+
+Related: break, continue, foreach, list, parse, repeat, return and while.
+
+Command: #macro {key sequence} {commands}
+
+         Macros allow you to make tintin respond to function keys.
+
+         The key sequence send to the terminal when pressing a function key
+         differs for every OS and terminal. To find out what sequence is sent
+         you can enable the CONVERT META config option.
+
+         Another option is pressing ctrl-v, which will enable CONVERT META for
+         the next key pressed.
+
+         If you only want a key sequence to trigger at the start of an input
+         line prefix the key sequence with ^.
+
+Example: #macro {(press ctrl-v)(press F1)} {#show \e[2J;#buffer lock}
+         Clear the screen and lock the window when you press F1, useful when the
+         boss is near.
+
+Example: #macro {\eOM} {#cursor enter}
+         Makes the keypad's enter key work as an enter in keypad mode.
+
+Example: #macro {^nn} {n}
+         Makes pressing n twice on an empty line execute north.
+
+Comment: Not all terminals properly initialize the keypad key sequences.
+         If this is the case you can still use the keypad, but instead of the
+         arrow keys use ctrl b, f, p, and n.
+
+Comment: You can remove a macro with the #unmacro command.
+
+Related: alias, cursor, history, keypad, speedwalk and tab.
+
+Command: #map
+
+         The map command is the backbone of the auto mapping feature.
+
+         #map at <exit|vnum> <command>
+           Execute the command at the given exit or vnum.
+
+         #map center <x> <y> <z>
+           Sets displaying center of the map viewer, default is 0 0 0.
+
+         #map color <field> [value]
+           Sets the map color for the given color field. Use #map color reset
+           to restore colors to default.
+
+         #map create <size>
+           Creates a new map and room 1. The default size is 50000 rooms.
+
+         #map destroy {area|world} <name>
+           Deletes the map or given area.
+
+         #map delete <exit|vnum>
+           Deletes the room for the given exit or vnum.
+
+         #map dig <exit|vnum> [new|<vnum>]
+           Creates an exit for the given exit name. If no valid exit name
+           is given or no existing room is found a new room is created.
+           Useful for portal links and other alternative forms of
+           transportation. If the 'new' argument is provided all existing
+           rooms are ignored and a new room is created. If a room vnum is
+           given as the second argument an exit will be created leading
+           to the given room vnum. If the room vnum doesn't exist a new
+           room is created.
+
+         #map entrance <exit> <option> <arg> [both]
+           Set the entrance data for the given exit. You must specify a
+           valid two-way exit for this to work.
+
+         #map exit <exit> <option> <arg> [both]
+           Set the exit data. Useful with a closed door where you can
+           set the exit command: '#map exit e command {open east;e}'.
+           Use #map exit <exit> for a list of available options.
+           Use #map exit <exit> save to save all exit data.
+
+         #map exitflag <exit> <AVOID|BLOCK|HIDE|INVIS> [on|off]
+           Set exit flags. See #map roomflag for more info.
+
+         #map explore <exit>
+           Explores the given exit until a dead end or an
+           intersection is found. The route is stored in #path and can
+           subsequently be used with #walk. Useful for long roads.
+
+         #map find <name> <exits> <desc> <area> <note> <terrain> <flag>
+           searches for the given room name. If found the shortest path
+           from your current location to the destination is calculated.
+           The route is stored in #path and can subsequently be used with
+           the various #path commands. If #map flag nofollow is set it
+           will store the exit commands instead of the exit names.
+
+           If <exits> is provided all exits must be matched, if
+           <roomdesc>, <roomarea> or <roomnote> or <roomterrain> or
+           <roomflag> is provided these are matched as well against the
+           room to be found.
+
+           These search options are also available for the at, delete,
+           goto, link, list and run commands.
+
+         #map flag asciigraphics
+           Takes up more space but draws a more detailed
+           map that displays the ne se sw nw exits and room symbols.
+
+         #map flag asciivnums
+           Display room vnums if asciigraphics is enabled.
+
+         #map flag direction
+           Display an arrow on the map showing the direction of your
+           last movement command.
+
+         #map flag fast
+           Limit coordinate searches to a 50 room radius. Useful to
+           speed up map drawing and room creation on large maps.
+
+         #map flag nofollow
+           When you enter movement commands the map will no longer
+           automatically follow along. Useful for MSDP and GMCP
+           automapping scripts. When you use #map find in nofollow
+           mode it will store the exit command instead of the exit
+           name into the path.
+
+         #map flag pancake
+           Makes the map display rooms above or below you. You can use
+           #map color room  for a color gradient.
+
+         #map flag quiet
+           Silence map messages when creating new rooms through movement.
+
+         #map flag static
+           Will make the map static so new rooms are no longer
+           created when walking into an unmapped direction. Useful when
+           you're done mapping and regularly bump into walls accidentally
+           creating a new room. #map dig etc will still work.
+
+         #map flag symbolgraphics
+           Draw a 1x1 map using the defined room symbols.
+
+         #map flag terrain
+           Fill up empty space surrounding rooms with terrain symbols
+
+         #map flag vtgraphics
+           Enables vt line drawing on some terminals
+
+         #map flag vtmap
+           Will enable the vtmap which is shown in the top split
+           screen if you have one. You can create a 16 rows high top
+           screen by using '#split 16 1'.
+
+         #map get <option> <variable> [vnum]
+           Store a map value into a variable, if no vnum is given the
+           current room is used. Use 'all' as the option to store all
+           values as a table.
+
+         #map get roomexits <variable>
+           Store all room exits into variable.
+
+         #map global <room vnum>
+           Set the vnum of a room that contains global
+           exits, for example an exit named 'recall' that leads to the
+           recall location. The room can contain multiple exits, in case
+           there are multiple commands that are similar to recall.
+
+         #map goto <room vnum> [dig]
+           Takes you to the given room vnum, with the
+           dig argument a new room will be created if none exists.
+
+         #map goto <name> <exits> <desc> <area> <note> <terrain>
+           Takes you to the given room name, if you provide exits those
+           must match.
+
+         #map info [save]
+           Gives information about the map and room you are in. If the save
+           argument is given the map data is saved to the info[map] variable.
+
+         #map insert <direction> [roomflag]
+           Insert a room in the given direction. Most useful for inserting
+           void rooms.
+
+         #map jump <x> <y> <z>
+           Jump to the given coordinate, which is relative
+           to your current room.
+
+         #map landmark <name> <vnum> [description] [size]
+           Creates an alias to target the provided room vnum. The
+           description is optional and should be brief. The size
+           determines from how many rooms away the landmark can be
+           seen.
+
+         #map leave
+           Makes you leave the map. Useful when entering a maze. You
+           can return to your last known room using #map return.
+
+         #map legend <legend> [symbols|reset]
+         #map legend <legend> <index> [symbol]
+           There are several legends and sub-legends available for
+           drawing maps to suit personal preference and character sets.
+           Use #map legend all to see the legend as currently defined.
+           Use #map legend <legend> <reset> to set the default legend.
+           Use #map legend <legend> <character list> to create a custom
+           legend. Custom legends are stored in the map file and can be
+           saved and loaded using #map write and #map read.
+
+         #map link <direction> <room name> [both]
+           Links two rooms. If the both
+           argument and a valid direction is given the link is two ways.
+
+         #map list <name> <exits> <desc> <area> <note> <terrain>
+           Lists all matching rooms and their distance. The following
+           search keywords are supported.
+
+           {distance}    <arg> will list rooms within given distance.
+           {roomarea}    <arg> will list rooms with matching area name.
+           {roomdesc}    <arg> will list rooms with matching room desc.
+           {roomexits}   <arg> will list rooms with identical room exits.
+                               Use * as an exit to ignore non pathdir exits.
+           {roomflag}    <arg> will list rooms with matching room flags.
+           {roomid}      <arg> will list rooms with identical id name.
+           {roomname}    <arg> will list rooms with matching room name.
+           {roomnote}    <arg> will list rooms with matching room note.
+           {roomterrain} <arg> will list rooms with matching room terrain.
+           {variable}    <arg> will save the output to given variable.
+
+         #map map <rows> <cols> <append|overwrite|list|variable> <name>
+           Display a drawing of the map of the given height and width.
+           All arguments are optional. If {rows} or {cols} are set to {}
+           or {0} they will use the scrolling window size as the default.
+           If {rows} or {cols} are a negative number this number is
+           subtracted from the scrolling window size.
+
+         #map map <rows> <cols> draw <square>
+           Display a drawing of the map of the given height and width.
+           The square argument exists of 4 numbers formulating the top
+           left corner and bottom right corner of a square.
+
+           If you use {append|overwrite} the map is written to the specified
+           file name which must be given as the 4th argument.
+           If you use {list|variable} the map is saved to the specified
+           variable name.
+
+         #map move <direction>
+           This does the same as an actual movement command, updating your
+           location on the map and creating new rooms. Useful when you are
+           following someone and want the map to follow along. You will need
+           to create actions using '#map move', for this to work.
+
+         #map offset <row> <col> <row> <col>
+           Define the offset of the vtmap as a square. Without an argument
+           it defaults to the entire top split region.
+
+         #map read <filename>
+           Will load the given map file.
+
+         #map resize <size>
+           Resize the map, setting the maximum number of rooms.
+
+         #map return
+           Returns you to your last known room after leaving the map
+           or loading a map.
+
+         #map roomflag <flags> <get|on|off>
+         
+         #map roomflag avoid
+           When set, '#map find' will avoid a route leading
+           through that room. Useful for locked doors, etc.
+         #map roomflag block
+           When set the automapper will prevent movement into or through
+           the room. Useful for death traps.
+         #map roomflag hide
+           When set, '#map' will not display the map beyond
+           this room. When mapping overlapping areas or areas that aren't
+           build consistently you need this flag as well to stop
+           auto-linking, unless you use void rooms.
+         #map roomflag invis
+           When set the room will be colored with the INVIS color.
+         #map roomflag leave
+           When entering a room with this flag, you will
+           automatically leave the map. Useful when set at the entrance
+           of an unmappable maze.
+         #map roomflag noglobal
+           This marks a room as not allowing global
+           transportation, like norecall rooms that block recall.
+         #map roomflag void
+           When set the room becomes a spacing room that can
+           be used to connect otherwise overlapping areas. A void room
+           should only have two exits. When entering a void room you are
+           moved to the connecting room until you enter a non void room.
+         #map roomflag static
+           When set the room will no longer be autolinked
+           when walking around. Useful for mapping mazes.
+
+         #map run <room name> [delay]
+           Calculates the shortest path to the destination and walks you
+           there. The delay is optional and requires using braces. Besides
+           the room name a list of exits can be provided for more precise
+           matching.
+
+         #map set <option> <value> [vnum]
+           Set a map value for your current room, or given room if a room
+           vnum is provided.
+
+         #map sync <filename>
+           Similar to #map read except the current map won't be unloaded
+           or overwritten.
+
+         #map terrain <name> <symbol> [flag]
+           Set the terrain symbol and flag.
+
+         #map terrain <name> <symbol> [DENSE|SPARSE|SCANT]
+           Determine symbol density, omit for the default.
+
+         #map terrain <name> <symbol> [NARROW|WIDE|VAST]
+           Determine symbol spread range, omit for the default.
+
+         #map terrain <name> <symbol> [FADEIN|FADEOUT]
+           Determine symbol spread density, omit for the default.
+
+         #map terrain <name> <symbol> [DOUBLE]
+           You're using two characters for the symbol.
+
+         #map travel <direction> <delay>
+           Follows the direction until a dead end or an intersection is
+           found. Use braces around the direction if you use the delay,
+           which will add the given delay between movements.
+           Use #path stop to stop a delayed run.
+
+         #map undo
+           Will undo your last move. If this created a room or a link
+           they will be deleted, otherwise you'll simply move back a
+           room. Useful if you walked into a non-existent direction.
+
+         #map uninsert <direction>
+           Exact opposite of the insert command.
+
+         #map unlandmark <name>
+           Removes a landmark.
+
+         #map unlink <direction> [both]
+           Will remove the exit, this isn't two way so you can have the
+           properly display no exit rooms and mazes.
+           If you use the both argument the exit is removed two-ways.
+
+         #map unterrain <name>
+           Removes a terrain.
+
+         #map update [now]
+           Sets the vtmap to update within the next 0.1 seconds, or
+           instantly with the now argument.
+
+         #map vnum <low> [high]
+           Change the room vnum to the given number, if a range is
+           provided the first available room in that range is selected.
+
+         #map write <filename> [force]
+           Will save the map, if you want to save a map to a .tin file
+           you must provide the {force} argument.
+
+Related: path, pathdir and speedwalk.
+
+
+         TinTin++ has a powerful automapper that uses a room system similar to
+         Diku MUDs which means that odd map layouts and weird exit
+         configurations aren't a problem. The mapper provides tools to improve
+         the visual map display. For basic path tracking see #help PATH.
+
+         #map create [size]
+
+         This command creates the initial map. The size is 50,000 by default
+         and can be changed at any time with the #map resize command. If you
+         play a MUD that uses MSDP or GMCP to provide room numbers you'll have
+         to increase it to the highest reported room number. Increasing the
+         size of the map doesn't decrease performance.
+
+         #map goto <location>
+
+         When you create the map you are not automatically inside the map. By
+         default room number (vnum) 1 is created, so you can go to it using
+         #map goto 1. Once you are inside the map new rooms are automatically
+         created as you move around. Movement commands are defined with the
+         pathdir command. By default n, ne, e, se, s, sw, w, nw, u, d are
+         defined.
+
+         #map map <rows> <cols> <append|overwrite|list|variable> <name>
+
+         To see the map you can use #map map. It's annoying to have to
+         constantly type #map map however. Instead it's possible to use #split
+         to display a vt100 map. To do so execute:
+
+         #split 16 1
+         #map flag vtmap on
+
+         The first command sets the top split lines to 16 and the bottom split
+         line to 1. If you want a smaller or larger map display you can use a
+         different value than 16.
+
+         If you don't need to display diagonal exits and prefer a more compact
+         look you can use #map flag AsciiGraphics off. This will enable the
+         standard display which uses UTF-8 box drawing characters, results may
+         vary depending on the font used.
+
+         If your terminal supports UTF-8 you can also give #map flag unicode on
+         a try.
+
+         If you want to display the map in a different location of the screen
+         use something like:
+
+         #split 0 1 0 -80
+         #map offset 1 81 -4 -1
+
+         This will display the map on the right side of the screen, if the
+         width of the screen is wide enough.
+
+         #map undo
+
+         If you accidentally walk into the wall on your MUD the mapper will
+         still create a new room. You can easily fix this mistake by using
+         #map undo. If you want to move around on the map without moving around
+         on the MUD you can use: #map move {direction}. To delete a room
+         manually you can use: #map delete {direction}. To create a room
+         manually you can use: #map dig {direction}.
+
+         #map write <filename>
+
+         You can save your map using #map write, to load a map you can use
+         #map read <filename>.
+
+         #map set <option> <value>
+
+         You can set the room name using #map set roomname <name>. You either
+         have to do this manually or create triggers to set the room name
+         automatically. Once the room name is set you can use #map goto with
+         the room name to visit it. If there are two rooms with the same name
+         #map goto will go to the most nearby room. If you want to always go
+         to the same room you should memorize the room number or create a
+         landmark.
+
+         #map landmark firstroom 1
+
+         You can further narrow down the matches by providing additional
+         arguments, for example:
+
+         #map goto {dark alley} {roomexits} {n;e} {roomarea} {Haddock Ville}
+
+         You can set the room weight using #map set roomweight {value}. The
+         weight by default is set to 1.0 and it represents the difficulty of
+         traversing the room. If you have a lake as an alternative route, and
+         traversing water rooms is 4 times slower than regular rooms, then you
+         could set the weight of the lake rooms to 4.0. If the lake is 3 rooms
+         wide the total weight is 12. If walking around the lake has a weight
+         less than 12 the mapper will go around the lake, if the weight is
+         greater than 12 the mapper will take a route through the lake.
+
+         You can set the room symbol using #map set roomsymbol {value}. The
+         symbol should be one, two, or three characters, which can be
+         colorized. You can for example mark shops with an 'S' and colorize the
+         'S' depending on what type of shop it is.
+
+         #map run <location> <delay>
+
+         The run command will have tintin find the shortest path to the given
+         location and execute the movement commands to get there. You can
+         provide a delay in seconds with floating point precision, for example:
+
+         #map run {dark alley} {0.5}
+
+         This will make you walk towards the nearest dark alley with 0.5 second
+         intervals. Typical MUDs accept commands at 0.25 second intervals.
+
+         #map insert {direction} {flag}
+
+         The insert command is useful for adding spacer rooms called void rooms.
+         Often rooms overlap, and by adding void rooms you can stretch out
+         exits. For example: #map insert north void. You cannot enter void rooms
+         once they've been created, so you'll have to use #map info in an
+         adjacent room to find the room vnum, then use #map goto {vnum} to
+         visit.
+
+         It's also possible to align rooms using void rooms. This is easily
+         done using #map insert north void.
+
+Related: map, path and pathdir.
+
+Command: #math {variable} {expression}
+
+         Performs math operations and stores the result in a variable.  The math
+         follows a C-like precedence, as follows, with the top of the list
+         having the highest priority.
+
+         Operators       Priority     Function
+         ------------------------------------------------
+         !               0            logical not
+         ~               0            bitwise not
+         d               1            integer random dice
+         *               2            integer multiply
+         **              2            integer power
+         /               2            integer divide
+         //              2            integer sqrt // 2 or cbrt // 3
+         %               2            integer modulo
+         +               3            integer addition
+         -               3            integer subtraction
+         <<              4            bitwise shift
+         >>              4            bitwise shift
+         ..              4            integer range
+         >               5            logical greater than
+         >=              5            logical greater than or equal
+         <               5            logical less than
+         <=              5            logical less than or equal
+         ==              6            logical equal (can use regex)
+         ===             6            logical equal (never regex)
+         !=              6            logical not equal (can use regex)
+         !==             6            logical not equal (never regex)
+          &              7            bitwise and
+          ^              8            bitwise xor
+          |              9            bitwise or
+         &&             10            logical and
+         ^^             11            logical xor
+         ||             12            logical or
+         ?              13            logical ternary if (unfinished code)
+         :              14            logical ternary else 
+
+         True is any non-zero number, and False is zero.  Parentheses () have
+         highest precedence, so inside the () is always evaluated first.
+
+         Strings must be enclosed in " " or { } and in the case of an == or
+         != operation a regex is performed with the regular expression in the
+         right-hand string. In the case of a <= or >= operation the alphabetic
+         order is compared.
+
+         The #if and #switch commands use #math. Several commands accepting
+         numeric input allow math operations as well, such as #delay.
+
+         Floating point precision is added by using the decimal . operator or
+         using #format with the %f flag character.
+
+Example: #math {heals} {$mana / 40}
+         Assuming there is a variable $mana, divides its value by 40 and stores
+         the result in $heals.
+
+Example: #action {^You receive %0 experience} {updatexp %0}
+         #alias updatexp {#math {xpneed} {$xpneed - %0}
+         Let's say you have a variable which stores xp needed for your next
+         level.  The above will modify that variable after every kill, showing
+         the amount still needed.
+
+Example: #action {%0 tells %1}
+           {#if {{%0} == {Bubba} && $afk} {reply I'm away, my friend.}}
+         When you are away from keyboard, it will only reply to your friend.
+
+Related: cat, format, function, local, mathematics, replace, script and variable.
+
+         Number operations
+
+         Operators       Priority     Function
+         ------------------------------------------------
+         !               0            logical not
+         ~               0            bitwise not
+         *               1            integer multiply
+         **              1            integer power
+         /               1            integer divide
+         //              1            integer sqrt // 2 or cbrt // 3
+         %               1            integer modulo
+         d               1            integer random dice roll
+         +               2            integer addition
+         -               2            integer subtraction
+         <<              3            bitwise shift
+         >>              3            bitwise shift
+         >               4            logical greater than
+         >=              4            logical greater than or equal
+         <               4            logical less than
+         <=              4            logical less than or equal
+         ==              5            logical equal
+         !=              5            logical not equal
+          &              6            bitwise and
+          ^              7            bitwise xor
+          |              8            bitwise or
+         &&              9            logical and
+         ^^             10            logical xor
+         ||             11            logical or
+
+         Operator priority can be ignored by using parentheses, for example
+         (1 + 1) * 2 equals 4, while 1 + 1 * 2 equals 3.
+
+         String operations
+
+         Operators       Priority     Function
+         ------------------------------------------------
+         >               4            alphabetical greater than
+         >=              4            alphabetical greater than or equal
+         <               4            alphabetical less than
+         <=              4            alphabetical less than or equal
+         ==              5            alphabetical equal using regex
+         !=              5            alphabetical not equal using regex
+         ===             5            alphabetical equal
+         !==             5            alphabetical not equal
+
+         Strings must be encased in double quotes or braces. The > >= < <=
+         operators perform basic string comparisons. The == != operators perform
+         regular expressions, with the argument on the left being the string,
+         and the argument on the right being the regex. For example
+         {bla} == {%*a} would evaluate as 1.
+
+Related: math and regexp.
+
+Command: #message {listname} {on|off}
+
+         This will show the message status of all your lists if typed without an
+         argument. If you set for example VARIABLES to OFF you will no longer be
+         spammed when correctly using the #VARIABLE and #UNVARIABLE commands.
+
+Related: class, debug, ignore, info and kill.
+
+         The #math command supports using 1K, 1M, 1m, and 1u to make large and
+         small number handling a little easier. These are case sensitive. Only
+         four symbols are supported to keep false positives to a minimum.
+
+         ╭─────────┬────────┬─────────────────────────────────╮
+         │    Name │ Symbol │                           Factor│
+         ├─────────┼────────┼─────────────────────────────────┤
+         │    Mega │      M │                        1 000 000│
+         │    Kilo │      K │                            1 000│
+         │         │        │                                 │
+         │   milli │      m │                            0.001│
+         │   micro │      u │                        0.000 001│
+         ╰─────────┴────────┴─────────────────────────────────╯
+
+Related: echo, format and math.
+
+
+         To enable xterm mouse tracking use #CONFIG MOUSE ON.
+
+         To see mouse events as they happen use #CONFIG MOUSE INFO. This
+         information can then be used to create mouse events with the #event
+         command and buttons with the #button command.
+
+         Visual buttons and pop-ups can be drawn on the screen with the #draw
+         command.
+
+         The input field can be changed and renamed using #screen inputregion,
+         which allows creating named events for enter handling.
+
+         Links can be created using the MSLP protocol which will generate link
+         specific events when clicked.
+
+
+Related: button, draw, event and MSLP.
+
+
+         MSDP (Mud Server Data Protocol) is part of the #port functionality.
+         See #help event for additional documentation as all MSDP events are
+         available as regular events.
+
+         Available MSDP events can be queried using the MSDP protocol
+         as described in the specification.
+
+         https://tintin.sourceforge.io/protocols/msdp
+
+Related: event and port.
+
+
+         MSLP (Mud Server Link Protocol) requires enabling #config mouse on,
+         and creating the appropriate LINK events.
+
+         The simplest link can be created by surrounding a keyword with the
+         \e[4m and \e[24m tags.
+
+Example: #substitute {\b{n|e|s|w|u|d}\b} {\e[4m%1\e[24m}
+
+         This would display 'Exits: n, e, w.' as 'Exits: n, e, w.'.
+
+         When clicked this would trigger the PRESSED LINK MOUSE BUTTON ONE
+         event of which %4 will hold the link command and %6 holds the
+         link name, which in the case of a simple link will be empty.
+
+Example: #event {PRESSED LINK MOUSE BUTTON ONE} {#send {%4}}
+
+         Keep in mind that if you change PRESSED to DOUBLE-CLICKED the link
+         will only work if the text does not scroll in between clicks.
+
+         If you want to create a complex link use an OSC code.
+
+Example: #sub {\bsmurf\b} {\e]68;1;;say I hate smurfs!\a\e[4m%0\e[24m}
+
+         If you have the LINK event of the previous example set, the %4
+         argument will contain 'say I hate smurfs!'.
+
+Example: #sub {\bgoblin\b} {\e]68;1;SEND;kill goblin\a\e[4m%0\e[24m}
+
+         Notice the previous instance of ;; has been replaced with ;SEND;
+         which will name the link. This will generate a named event.
+
+Example: #event {PRESSED LINK SEND MOUSE BUTTON ONE} {#send {%4}}
+
+         By naming links you can organize things a little bit better instead
+         of tunneling everything through the same event.
+
+         Keep in mind that the server is allowed to use \e]68;1;\a as well,
+         subsequently various security measures are in place.
+
+         To create secure links, which are filtered out when send by a server,
+         you need to use \e]68;2;\a, and they instead trigger the SECURE LINK
+         event.
+
+Example: #sub {%* tells %*} {\e]68;2;EXEC;#cursor set tell %1 \a\e[4m%0\e[24m}
+         #event {PRESSED SECURE LINK EXEC MOUSE BUTTON ONE} {%4}
+
+         This would make you start a reply when clicking on a tell.
+
+Website: https://tintin.mudhalla.net/protocols/mslp
+
+Related: event and port.
+
+Command: #nop {whatever}
+
+         Short for 'no operation', and is ignored by the client.  It is useful
+         for commenting in your coms file, any text after the nop and before a
+         semicolon or end of line is ignored. You shouldn't put braces { } in it
+         though, unless you close them properly.
+
+         A valid alternative for #nop is #0.
+
+Comment: By using braces you can comment out multiple lines of code in a script
+         file.
+
+         For commenting out an entire trigger and especially large sections of
+         triggers you would want to use /* text */
+
+Example: #nop This is the start of my script file.
+
+Related: read
+
+Command: #parse {string} {variable} {commands}
+
+         Like the loop statement, parse will loop from start to finish through
+         the given string.  The value of the current character is stored in the
+         provided variable.
+
+Example: #parse {hello world} {char} {#show $char}
+
+Related: break, continue, foreach, list, loop, repeat, return and while.
+
+Command: #path {option} {argument}
+
+         create   Will clear the path and start path mapping.
+         delete   Will delete the last move of the path.
+         describe Describe the path and current position.
+         destroy  Will clear the path and stop path mapping.
+         get      Will get either the length or position.
+         goto     Go the the start, end, or given position index.
+         insert   Add the given argument to the path.
+         load     Load the given variable as the new path.
+         map      Display the map and the current position.
+         move     Move the position forward or backward. If a number is given
+                  the position is changed by the given number of steps.
+         run      Execute the current path, with an optional floating point
+                  delay in seconds as the second argument.
+         save     Save the path to a variable. You must specify whether you
+                  want to save the path 'forward' or 'backward'.
+         start    Start path mapping.
+         stop     Stop path mapping, can also abort #path run.
+         swap     Switch the forward and backward path.
+         unzip    Load the given speedwalk as the new path.
+         walk     Take one step forward or backward.
+         zip      Turn the path into a speedwalk.
+
+Example: #path ins {unlock n;open n} {unlock s;open s}
+
+Related: map, pathdir and speedwalk.
+
+Command: #pathdir {dir} {reversed dir} {coord}
+
+         By default tintin sets the most commonly used movement commands
+         meaning you generally don't really have to bother with pathdirs.
+         Pathdirs are used by the #path and #map commands.
+
+         The first argument is a direction, the second argument is the reversed
+         direction.  The reverse direction of north is south, etc.
+
+         The third argument is a spatial coordinate which is a power of two.
+         'n' is 1, 'e' is 2, 's' is 4, 'w' is '8', 'u' is 16, 'd' is 32. The
+         exception is for compound directions, whose value should be the sum
+         of the values of each cardinal direction it is composed of. For
+         example, 'nw' is the sum of 'n' and 'w' which is 1 + 8, so 'nw'
+         needs to be given the value of 9. This value is required for the
+         #map functionality to work properly.
+
+Example: #pathdir {ue} {dw} {18}
+         #pathdir {dw} {ue} {40}
+
+Comment: You can remove a pathdir with the #unpathdir command.
+
+Related: map and path.
+
+
+         A regular expression, regex or regexp is a sequence of characters that
+         defines a search pattern. Since the 1980s, different syntaxes for
+         writing regular expressions exist, the two most widely used ones being
+         the POSIX syntax and the similar but more advanced Perl standard.
+         TinTin++ supports the Perl standard known as PCRE (Perl Compatible
+         Regular Expressions).
+
+         Regular expressions are an integral part of TinTin++, but keep in mind
+         that tintin doesn't allow you to use regular expressions directly,
+         instead it uses a simpler intermediate syntax that still allows more
+         complex expressions when needed.
+
+         Commands that utilize regular expressions are: action, alias, elseif,
+         gag, grep, highlight, if, kill, local, math, prompt, regexp, replace,
+         substitute, switch, variable and while. Several other commands use
+         regular expressions in minor ways. Fortunately the basics are very
+         easy to learn.
+
+         TinTin++ Regular Expression
+
+         The following support is available for regular expressions.
+
+       ^ match start of line.
+       $ match of end of line.
+       \ escape one character.
+
+  %1-%99 match of any text, stored in the corresponding index.
+      %0 should be avoided in the regex, contains all matched text.
+     { } embed a perl compatible regular expression, matches are stored.
+   %!{ } embed a perl compatible regular expression, matches are not stored.
+
+         [ ] . + | ( ) ? * are treated as normal text unless used within braces.
+         Keep in mind that { } is replaced with ( ) automatically unless %!{ }
+         is used.
+
+TinTin++ Description                                      POSIX
+      %a Match zero or more characters including newlines ([^\n]*?)
+      %A Match zero or more newlines                      ([\n]*?)
+      %c Match zero or more ansi color codes              ((?:\e\[[0-9;]*m)*?)
+      %d Match zero or more digits                        ([0-9]*?)
+      %D Match zero or more non-digits                    ([^0-9]*?)
+      %i Matches become case insensitive                  (?i)
+      %I Matches become case sensitive (default)          (?-i)
+      %s Match zero or more spaces                        ([\r\n\t ]*?)
+      %w Match zero or more word characters               ([A-Za-z0-9_]*?)
+      %W Match zero or more non-word characters           ([^A-Za-z0-9_]*?)
+      %? Match zero or one character                      (.??)
+      %. Match one character                              (.)
+      %+ Match one or more characters                     (.+?)
+      %* Match zero or more characters excluding newlines (.*?)
+
+         Ranges
+
+         If you want to match 1 digit use %+1d, if you want to match between 3
+         and 5 spaces use %+3..5s, if you want to match 1 or more word
+         characters use %+1..w, etc.
+
+         Variables
+
+         If you use %1 in an action to perform a match the matched string is
+         stored in the %1 variable which can be used in the action body.
+
+Example: #act {%1 says 'Tickle me'} {tickle %1}
+
+         If you use %2 the match is stored in %2, etc. If you use an unnumbered
+         match like %* or %S the match is stored at the last used index
+         incremented by one.
+
+Example: #act {%3 says '%*'} {#if {"%4" == "Tickle me"} {tickle %3}}
+
+         The maximum variable index is 99. If you begin an action with %* the
+         match is stored in %1. You should never use %0 in the trigger part of
+         an action, when used in the body of an action %0 contains all the parts
+         of the string that were matched.
+
+         To prevent a match from being stored use %!*, %!w, etc.
+
+         Perl Compatible Regular Expressions
+
+         You can embed a PCRE (Perl Compatible Regular Expression) using curley
+         braces { }, these braces are replaced with parentheses ( ) unless you
+         use %!{ }.
+
+         Or
+
+         You can separate alternatives within a PCRE using the | character.
+
+Example: #act {%* raises {his|her|its} eyebrows.} {say 42..}
+
+         Brackets
+
+         You can group alternatives and ranges within a PCRE using brackets.
+
+Example: #act {%* says 'Who is number {[1-9]}?} {say $number[%2] is number %2}
+
+         The example only triggers if someone provides a number between 1 and
+         9. Any other character will cause the action to not trigger.
+
+Example: #act {%* says 'Set password to {[^0-9]*}$} {say The password must
+           contain at least one number, not for security reasons, but just to
+           annoy you.} {4}
+
+         When the ^ character is used within brackets it creates an inverse
+         search, [^0-9] matches every character except for a number between 0
+         and 9.
+
+         Quantification
+
+         A quantifier placed after a match specifies how often the match is
+         allowed to occur.
+
+       ? repeat zero or one time.
+       * repeat zero or multiple times.
+       + repeat once or multiple times.
+     {n} repeat exactly n times, n must be a number.
+    {n,} repeat at least n times, n must be a number.
+   {n,o} repeat between n and o times, n and o must be a number.
+
+Example: #act {%* says 'Who is number {[1-9][0-9]{0,2}}?} {Say $number[%2] is
+           number %2}
+
+         The example only triggers if someone provides a number between 1 and
+         999.
+
+         Parantheses
+
+         TinTin Regular Expressions automatically add parenthesis, for example
+         %* translates to (.*?) in PCRE unless the %* is found at the start or
+         end of the line, in which cases it translates to (.*). Paranthesis in
+         PCRE causes a change in execution priority similar to mathematical
+         expressions, but parentheses also causes the match to be stored to a
+         variable.
+
+         When nesting multiple sets of parentheses each nest is assigned its
+         numerical variable in order of appearance.
+
+Example: #act {%* chats '{Mu(ha)+}'} {chat %2ha!}
+
+         If someone chats Muha you will chat Muhaha! If someone chats Muhaha
+         you will chat Muhahaha!
+
+         Lazy vs Greedy
+
+         By default regex matches are greedy, meaning {.*} will capture as much
+         text as possible.
+
+Example: #regex {bli bla blo} {^{.*} {.*}$} {#show Arg1=(&1) Arg2=(&2)}
+
+         This will display: Arg1=(bli bla) Arg2=(blo)
+
+         By appending a ? behind a regex it becomes lazy, meaning {.*?} will
+         capture as little text as possible.
+
+Example: #regex {bli bla blo} {^{.*?} {.*?}$} {#show Arg1=(&1) Arg2=(&2)}
+
+         This will display: Arg1=(bli) Arg2=(bla blo).
+
+         Escape Codes
+
+         PCRE support the following escape codes.
+
+    PCRE Description                                    POSIX
+      \A Match start of string                          ^
+      \b Match word boundaries                          (^|\r|\n|\t| |$)
+      \B Match non-word boundaries                      [^\r\n\t ]
+      \c Insert control character                       \c
+      \d Match digits                                   [0-9]
+      \D Match non-digits                               [^0-9]
+      \e Insert escape character                        \e
+      \f Insert form feed character                     \f
+      \n Insert line feed character                     \n
+      \r Insert carriage return character               \r
+      \s Match spaces                                   [\r\n\t ]
+      \S Match non-spaces                               [^\r\n\t ]
+      \t Insert tab character                           \t
+      \w Match letters, numbers, and underscores        [A-Za-z0-9_]
+      \W Match non-letters, numbers, and underscores    [^A-Za-z0-9_]
+      \x Insert hex character                           \x
+      \Z Match end of string                            $
+
+         \s matches one space, \s+ matches one or multiple spaces, the use
+         of {\s+} is required for this sequence to work in tintin, \s by         itself will work outside of a set of braces.
+
+         Color triggers
+
+         To make matching easier text triggers (Actions, Gags, Highlights,
+         Prompts, and Substitutes) have their color codes stripped. If you
+         want to create a color trigger you must start the triggers with a ~
+         (tilde). To make escape codes visible use #config {convert meta} on.
+
+Example: #action {~\e[1;37m%1} {#var roomname %1}
+
+         If the room name is the only line on the server in bright white
+         white color trigger will save the roomname.
+
+
+         This covers the basics. PCRE has more options, most of which are
+         somewhat obscure, so you'll have to read a PCRE manual for additional
+         information.
+
+Related: map and path.
+
+Command: #port {option} {argument}
+
+         #port {init} {name} {port} {file}
+           Initilize a port session.
+
+         #port {call} {address} {port}
+           Connect to a remote socket.
+
+         #port {color} {color names}
+           Set the default color of port messages.
+
+         #port {dnd}
+           Do Not Disturb. Decline new connections
+
+         #port {group} {name} {group}
+           Assign a socket group.
+
+         #port {ignore} {name}
+           Ignore a socket
+
+         #port {info}
+           Display information about the port session.
+
+         #port {name} {name}
+           Change socket name.
+
+         #port {prefix} {text}
+           Set prefix before each message.
+
+         #port {send} {name|all} {text}
+           Send data to socket
+
+         #port {uninitialize}
+           Uninitialize the port session.
+
+         #port {who}
+           Show all connections
+
+         #port {zap} {name}
+           Close a connection
+
+         The port command is very similar to chat except that it creates a
+         new session dedicated to receiving socket connections at the given
+         port number without built-in support for a communication protocol.
+
+         You can init with 0 as the port number to create a dummy session.
+
+Related: all, chat, run, session, sessionname, snoop, ssl and zap.
+
+Command: #prompt {text} {new text} {row #} {col #}
+
+         Prompt is a feature for split window mode, which will capture a line
+         received from the server and display it on the status bar of your
+         split screen terminal. You would define <text> and <new text> the
+         same way as you would with #substitute.
+
+         The row number is optional and useful if you use a non standard split
+         mode. A positive row number draws #row lines from the top while a
+         negative number draws #row lines from the bottom. Without an argument
+         #prompt will write to the default split line, which is one row above
+         the input line, typically at row -2.
+
+         If the row number is set to 0, #prompt will behave like #substitute.
+         This is useful to let tintin know that a prompt was received so you
+         can use #config packet_patch with minimal interference.
+
+         The col number is optional and can be used to set the column index.
+         A positive col number draws the given number of columns from the left,
+         while a negative col number draws from the right. If you leave the
+         col number empty tintin will clear the row before printing at the
+         start of the row.
+
+         The #show command takes a row and col argument as well so it's also
+         possible to place text on your split lines using #show.
+
+Comment: See #help split for more information on split mode.
+
+Comment: See #help substitute for more information on text
+         substitutions.
+
+Comment: You can remove a prompt with the #unprompt command.
+
+Related: action, gag, highlight and substitute.
+
+Command: #read {filename}
+
+         Reads a commands file into memory.  The coms file is merged in with
+         the currently loaded commands.  Duplicate commands are overwritten.
+
+         If you uses braces, { and } you can use several lines for 1 commands.
+         This however means you must always match every { with a } for the read
+         command to work.
+
+         You can comment out triggers using /* text */
+
+Related: log, scan, textin and write.
+
+Command: #regexp {string} {expression} {true} {false}
+
+         Compares the string to the given regular expression.
+
+         The expression can contain escapes, and if you want to match a literal
+         \ character you'll have to use \\ to match a single backslash.
+
+         Variables are stored in &1 to &99 with &0 holding the matched
+         substring.
+
+         The #regex command is not a proper statement like #if, when using
+         #return or #break in the {true} argument it won't terminate any loop
+         the #regex command is nested within.
+
+       ^ force match of start of line.
+       $ force match of end of line.
+       \ escape one character.
+  %1-%99 lazy match of any text, available at %1-%99.
+      %0 should be avoided in triggers, and if left alone lists all matches.
+     { } embed a raw regular expression, matches are stored to %1-%99.
+   %!{ } embed a raw regular expression, matches are not stored.
+         [ ] . + | ( ) ? * are treated as normal text unlessed used within
+         braces. Keep in mind that { } is replaced with ( ) automatically
+         unless %!{ } is used.
+
+         Of the following the (lazy) match is available at %1-%99 + 1
+
+      %a match zero or more characters including newlines.
+      %A match zero or more newlines.
+      %c match zero or more ansi color codes.
+      %d match zero or more digits.
+      %D match zero or more non digits.
+      %s match zero or more spaces.
+      %S match zero or more non spaces.
+      %w match zero or more word characters.
+      %W match zero or more non word characters.
+
+      Experimental (subject to change) matches are:
+
+      %p match zero or more printable characters.
+      %P match zero or more non printable characters.
+      %u match zero or more unicode characters.
+      %U match zero or more non unicode characters.
+
+      If you want to match 1 digit use %+1d, if you want to match between 3
+      and 5 spaces use %+3..5s, if you want to match 0 or more word
+      characters use %+0..w, etc.
+
+      %+ match one or more characters.
+      %? match zero or one character.
+      %. match one character.
+      %* match zero or more characters.
+
+      %i matching becomes case insensitive.
+      %I matching becomes case sensitive (default).
+
+         The match is automatically stored to a value between %1 and %99
+         starting at %1 and incrementing by 1 for every regex. If you use
+         %15 as a regular expression, the next unnumbered regular expression
+         would be %16. To prevent a match from being stored use %!*, %!w, etc.
+
+Example: #regexp {bli bla blo} {bli {.*} blo} {#show &1}
+
+Comment: Like an alias or function #regex has its own scope.
+
+Related: pcre and replace.
+
+Command: #[number] {commands}
+
+        Sometimes you want to repeat the same command multiple times. This is
+        the easiest way to accomplish that.
+
+Example: #10 {buy bread}
+
+Related: mathematics and statements.
+
+Command: #replace {variable} {oldtext} {newtext}
+
+         Searches the given variable, replacing each occurrence of 'oldtext'
+         with 'newtext'. The 'oldtext' argument is a regular expression.
+
+         Variables are stored in &1 to &99 with &0 holding the entire matched
+         substring.
+
+Example: #function rnd #math result 1d9;#replace test {%.} {@rnd{}}
+
+Related: cat, format, function, local, math, script and variable.
+
+Command: #return {text}
+
+         This command can be used to break out of a command string being
+         executed.
+
+         If used inside a #function you can use #return with an argument to both
+         break out of the function and set the result variable.
+
+Related: break, continue, foreach, list, loop, parse, repeat and while.
+
+Command: #run {name} {shell command} {file}
+
+         The run command works much like the system command except that it
+         runs the command in a pseudo terminal. The run command also creates
+         a session that treats the given shell command as a server. This
+         allows you to run ssh, as well as any other shell application, with
+         full tintin scripting capabilities. If a file name is given the file
+         is loaded prior to execution.
+
+Example: #run {somewhere} {ssh someone@somewhere.com}
+Example: #run {something} {tail -f chats.log}
+
+Related: all, port, session, sessionname, snoop, ssl and zap.
+
+Command: #scan {abort|csv|tsv|txt} {filename}
+
+         The scan command is a file reading utility.
+
+         #scan {abort}
+           This command must be called from with a SCAN event and will
+           abort the scan if one is in progress.
+
+         #scan {csv} <filename>
+           The scan csv command reads in a comma separated value file
+           without printing the content to the screen. Instead it triggers one
+           of two events.
+
+           The SCAN CSV HEADER event is triggered on the first line of the csv
+           file. The SCAN CSV LINE event is triggered on the second and each
+           subsequent line of the csv file. The %0 argument contains the entire
+           line, with  %1 containing the first value, %2 the second value, etc,
+           all the way up to %99.
+
+           Values containing spaces must be surrounded with quotes, keep in mind
+           newlines within quotes are not supported. Use two quotes to print one
+           literal quote character.
+
+         #scan {dir} <filename> <variable>
+
+          The scan dir command will read the given filename or directory and
+          store any gathered information into the provided variable.
+
+         #scan {tsv} <filename>
+
+           The scan tsv <filename> command reads in a tab separated value file
+           without printing the content to the screen. Instead it triggers the
+           SCAN TSV HEADER event for the first line and SCAN TSV LINE for all
+           subsequent lines.
+
+         #scan {file} <filename> {commands}
+
+           The scan file command reads the given files and executes the
+            commands argument. &0 contains the raw content of the file and
+            &1 contains the plain content. &2 contains the raw byte size of the
+            file and &3 the plain byte size. &5 contains the line count.
+
+         #scan {txt} <filename>
+
+           The scan txt <filename> command reads in a file and sends its content
+           to the screen as if it was send by a server. After using scan you can
+           use page-up and down to view the file.
+
+           This command is useful to convert ansi color files to html or viewing
+           raw log files.
+
+           Actions, highlights, and substitutions will trigger as normal, and it
+           is possible to create an action to execute #scan abort to prematurely
+           stop the scan.
+
+Related: read and textin.
+
+Command: #screen {option} {argument}
+
+         The screen command offers a variety of screen manipulation
+         commands and utilities.
+
+         #screen blur
+           Move the terminal to the back of the stack.
+
+         #screen clear [all|scroll region|square] <args>
+           Provide 4 arguments defining the top left and bottom right corner
+           when erasing a square.
+
+         #screen focus
+           Move the terminal to the front of the stack.
+
+         #screen fullscreen [on|off]
+           Toggles fullscreen mode when used without an argument.
+
+         #screen get <option> <var>
+           Get various screen options and save them to <var>. Use #screen
+           get without an argument to see all available options.
+
+         #screen info
+           Debugging information.
+
+         #screen inputregion <square> [name]
+           Set the input region. The name argument is optional and can be
+           used to create named RECEIVED INPUT [NAME] events.
+
+         #screen load <both|label|title>
+           Reload the saved title, label, or both.
+
+         #screen minimize <on|off>
+           Minimize with on, restore with off.
+
+         #screen maximize [on|off]
+           Maximize with on, restore with off.
+
+         #screen move <height> <width>
+           Move the upper left corner of the terminal to pixel coordinate.
+
+         #screen raise <event>
+           This will raise several screen events with %1 and %2 arguments.
+
+         #screen refresh
+           Terminal dependant, may do nothing.
+
+         #screen rescale <height> <width>
+           Resize the screen to the given height and width in pixels.
+
+         #screen resize <rows> <cols>
+           Resize the screen to the given height and width in characters.
+
+         #screen save <both|label|title>
+           Save the title, label, or both.
+
+         #screen scroll <square>
+           Set the scrolling region, changes the split setting.
+
+         #screen set <both|label|title>
+           Set the title, label, or both. Only title works on Windows.
+
+         #screen swap
+           Swap the input and scroll region.
+
+Related: bell
+
+Command: #config {SCREEN READER} {ON|OFF}
+
+         Screen reader mode is enabled by using #config screen on. One purpose
+         of the screen reader mode is to report to servers that a screen reader
+         is being used by utilizing the MTTS standard. The MTTS specification
+         is available at:
+
+         http://tintin.sourceforge.net/protocols/mtts
+
+         With the screen reader mode enabled TinTin++ will try to remove or
+         alter visual elements where possible.
+
+Related: config
+
+Command: #script {variable} {shell command}
+
+         The script command works much like the system command except that it
+         treats the generated echos as commands if no variable is provided.
+
+         This is useful for running php, perl, ruby, and python scripts. You
+         can run these scripts either from file or from within tintin if the
+         scripting language allows this.
+
+         If you provide a variable the output of the script is stored as a list.
+
+Example: #script {ruby -e 'print "#show hello world"'}
+Example: #script {python -c 'print "#show hello world"'}
+Example: #script {php -r 'echo "#show hello world"'}
+Example: #script {path} {pwd};#show The path is $path[1].
+
+Related: format, function, local, math, replace and variable.
+
+Command: #send {text}
+
+         Sends the text directly to the server, useful if you want to start
+         with an escape code.
+
+Related: textin
+
+Command: #session {name} {host} {port} {file}
+
+         Starts a telnet session with the given name, host, port, and optional
+         file name. The name can be anything you want, except the name of an
+         already existing session, a number, or the keywords '+' and '-'.
+
+         If a file name is given the file is only read if the session
+         succesfully connects.
+
+         Without an argument #session shows the currently defined sessions.
+
+         If you have more than one session, you can use the following commands:
+
+         #session {-}        Switch to the previous session.
+         #session {+}        Switch to the next session.
+         #session {<number>} Switch to the given session. Session 0 is the
+                             startup session, +1 the first, +2 the second, and
+                             -1 is the last session. Sessions are (currently)
+                             sorted in order of creation.
+         #gts                Switch to the startup session. The name gts stands
+                             for global tintin session.
+         #ats                Switch to the active session. The name ats stands
+                             for active tintin session.
+                             not necessarily the calling session.
+         #{name}             Activates to the session with the given name.
+         #{name} {command}:  Executes a command with the given session without
+                             changing the active session.
+         @<name>{text}:      Parse text in the given session, substituting the
+                             variables and functions, and print the result in
+                             the current active session.
+
+         The startup session is named 'gts' and can be used for relog scripts.
+         Do keep in mind that tickers do not work in the startup session.
+
+Example: #event {SESSION DISCONNECTED} {#gts #delay 10 #ses %0 tintin.net 4321}
+
+Related: all, port, run, sessionname, snoop, ssl and zap.
+
+Syntax:  #[sessionname] {commands}
+
+         You can create multiple sessions with the #session command. By default
+         only one session is active, meaning commands you input are executed in
+         the active session. While all sessions receive output, only output sent
+         to the active session is displayed.
+
+         When you create a session with the #session command you must specify a
+         session name, the session name, prepended with a hashtag, can be used
+         to activate the session when used without an argument. If an argument
+         is given it will be executed by that session as a command, the session
+         will not be activated.
+
+Example: #ses one tintin.net 23;#ses two tintin.net 23;#one;#two grin
+
+         This will create two sessions, the session that was created last (two
+         in this case) will be automatically activated upon creation. Using
+         #one, session one is activated. Using #two grin, the grin social will
+         be executed by session two, session one will remain the active session.
+
+         If you send a variable to another session it will be substituted before
+         being passed. If you want the variable value of the receiving session
+         to be used you need to use '$${variable}' to properly escape it.
+
+Syntax:  @[sessionname]{substitution}
+
+         If you want to pull the value of a variable from another session you
+         can do so in a similar way as you would use a #function call. Using
+         #showme {@two{$test}} in session one would print the value of $test,
+         as defined by session two.
+
+Related: suspend
+
+Command: #show {string} {row} {col}
+
+         Display the string to the terminal, do not send to the server.  Useful
+         for status, warnings, etc.  The {row} and col number are optional and
+         work the same way as the row number of the #prompt trigger.
+
+         Actions can be triggered by the show command. If you want to avoid
+         this from happening use: #line ignore #show {<string>}.
+
+Example: #tick {TICK} {#delay 50 #show 10 SECONDS TO TICK!!!} {60}
+
+Comment: The #prompt helpfile contains more information on using the
+         option {row} and {col} arguments.
+
+Related: buffer, draw, echo, grep and prompt.
+
+Command: #snoop {session name} {on|off|scroll}
+
+         If there are multiple sessions active, this command allows you to
+         monitor what is going on in the sessions that are not currently active.
+         The line of text from other sessions will be prefixed by the session's
+         name.
+
+         You can toggle off snoop mode by executing #snoop a second time.
+
+         By using the scroll argument you will snoop the session's scroll
+         region which will overwrite the display of whichever session is active.
+         You can change the size and location of a session's scroll region by
+         using the #split and #screen scrollregion commands.
+
+Related: all, port, run, session, sessionname, ssl and zap.
+
+         SPEEDWALK V1
+
+         Speedwalking allows you to enter multiple directions without using
+         semicolons. Directions should be prefixed with a number and will be
+         executed the given number of times.
+
+         You can enable speedwalking with #CONFIG {SPEEDWALK} {ON}.
+
+Example: Without speedwalk, you have to type:
+         s;s;w;w;w;w;w;s;s;s;w;w;w;n;n;w
+         With speedwalk, you only have to type:
+         2s5w3s3w2nw
+
+         SPEEDWALK V2
+
+         Modern MUDs have increasingly adopted the use of diagonal exits, like
+         ne, nw, sw, and se. To make accomodations for this the #map and #path
+         command no longer interpret nesw as a speedwalk and require this to
+         be written as 1n1e1s1w, which then allows 2ne2e to execute ne;ne;e;e.
+
+         Speedwalks entered on the input line continue to use the v1 system.
+
+         The #path load command is backward compatible with v1 speedwalks and
+         to load v2 speedwalks the #path unzip command needs to be used, unless
+         the speedwalk was saved using #path save in which case a v2 compatible
+         format is used that can also contain timing data.
+
+Example: #path unzip 3n1e2nw
+Example: #map move 3ne1d
+
+Related: keypad, mapping and repeat.
+
+Command: #split {top bar} {bottom bar} {left bar} {right bar} {input bar}
+
+         This option requires for your terminal to support VT100 emulation.
+
+         #split allows the creation of a top status bar, a left and right status
+         bar, a scrolling region, a bottom status bar, and an input line.
+
+         ╭────────────────────────────────╮
+         │            top bar             │
+         ├──────┬──────────────────┬──────┤
+         │ left │    scrolling     │ right│
+         │ bar  │     region       │  bar │
+         ├──────┴──────────────────┴──────┤
+         │           bottom bar           │
+         ├────────────────────────────────┤
+         │           input bar            │
+         ╰────────────────────────────────╯
+
+         By default the bottom status bar is filled with dashes --- and
+         subsequently it is also known as the split line. The scrolling
+         region is also known as the main screen and this is where all
+         incoming text is displayed by default.
+
+         If you use #split without an argument it will set the height of the
+         top status bar to 0 lines and the bottom status bar to 1 line.
+
+         If you use #split with one argument it will set the height of the top
+         status bar to the given number of lines and the bottom status bar will
+         be set to 1 line.
+
+         If you use two arguments the first argument is the height of the top
+         status bar and the second argument the height of the bottom status bar.
+
+         The third and fourth argument are optional and default to 0.
+
+         The fifth argument is optional and sets the size of the input bar, it
+         defaults to 1.
+
+         It is possible to use negative arguments in which case the bar width
+         defines the minimum width of the scrolling region.
+
+Example: #split 0 0
+         This will create a split screen with just a scrolling region and an
+         input line. Great for the minimalist.
+
+Example: #split 1 1 0 -80
+         This will create a split screen with a single line top and bottom
+         bar. The left bar has a width of 0 while the right bar will be of
+         variable width. If for example the screen is 100 columns wide, 80
+         columns will be used for the scrolling region, leaving a right bar
+         with a width of 20 columns.
+
+         To avoid displaying problems it's suggesed to use #prompt to capture
+         the prompt sent by the MUD.
+
+Comment: You can display text on the split line(s) with the #prompt and
+         #show {line} {row} commands.
+
+Comment: You can remove split mode with the #unsplit command.
+
+Related: echo, prompt and showme.
+
+Command: #ssl {name} {host} {port} {file}
+
+         Starts a secure socket telnet session with the given name, host, port,
+         and optional file name.
+
+Related: all, port, run, sessionname, snoop, ssl and zap.
+
+
+         TinTin++ knows the following statements.
+
+         #break
+         #case {value} {true}
+         #continue
+         #default {commands}
+         #else {commands}
+         #elseif {expression} {true}
+         #foreach {list} {variable} {commands}
+         #if {expression} {true}
+         #loop {min} {max} {variable} {commands}
+         #parse {string} {variable} {commands}
+         #return {value}
+         #switch {expression} {commands}
+         #while {expression} {commands}
+
+Related: mathematics, pcre and repeat.
+
+Command: #substitute {text} {new text} {priority}
+
+         Allows you to replace text from the server with the new text.
+
+         The %1-%99 variables can be used to capture text and use it as part of
+         the new output.
+
+         Color codes can be used to color the new text, to restore the color to
+         that of the original line the <900> color code can be used.
+
+         If only one argument is given, all active substitutions that match the
+         argument are displayed.  Wildcards can be used, see '#help regex' for
+         additional information on that subject.
+
+         If no argument is given, all subs are displayed.
+
+Example: #sub {Zoe} {ZOE}
+         Any instance of Zoe will be replaced with ZOE.
+
+Example: #sub {~\e[0;34m} {\e[1;34m}
+         Replace generic dark blue color codes with bright blue ones.
+
+Example: #sub {%1massacres%2} {<018>%1<118>MASSACRES<018>%2}
+         Replaces all occurrences of 'massacres' with 'MASSACRES' in red.
+
+Comment: See '#help action', for more information about triggers.
+
+Comment: See '#help colors', for more information.
+
+Comment: You can remove a substitution with the #unsubstitute command.
+
+Related: action, gag, highlight and prompt.
+
+          TinTin++ will perform various types of substitions as detailed below.
+
+          Variables
+
+$ & * @   All variable and function names must begin with an alphabetic
+          character, followed by any combination of alphanumeric characters and
+          underscores.
+
+$         The dollar sign is used to retrieve the value of a variable.
+
+&         The ampersand sign is used to retrieve the index of a variable.
+
+*         The astrix sign is used to retrieve the name of a variable.
+
+@         The at sign is used for functions.
+
+[ ]       Brackets are used for nested variables which function as an
+          associative array. Associative arrays are also known as tables and
+          maps. Regex can be used within brackets to match multiple variables.
+
++ -       The plus and minus signs are used to access variables by their index,
+          with the first variable having index +1, and the last variable
+          having index -1. Variables are ordered alphanumerically.
+
+          All variables and functions can be escaped by doubling the sign,
+          like $$variable_name or @@function_name. To escape a variable
+          twice use $$$var_name. One escape is removed each time tintin
+          needs to substitute a variable or function.
+
+          Arguments
+
+%0 - %99  The percent sign followed by a number is used for arguments by the
+          following triggers:
+
+          alias, action, button, event, function, prompt, and substitute.
+
+&0 - &99  The ampersand sign followed by a number is used for arguments in the
+          regex and replace commands.
+
+          All trigger and command arguments can be escaped by doubling the
+          sign like %%1 or &&1. One escape is removed each time tintin
+          substitutes trigger or command arguments. To escape three times
+          triple the sign like %%%1, etc.
+
+          Colors
+
+<000>     Three alphanumeric characters encapsulated by the less- and greater-
+          than signs are used for 4 and 8 bit color codes.
+
+<0000>    Either a B (background) or F (foreground) followed by three
+          hexadecimal characters encapsulated by < > signs are used for 12
+          bit color codes. Requires truecolor capable terminal.
+
+<0000000> Either a B (background) or F (foreground) followed by six
+          hexadecimal characters encapsulated by < > signs are used for 24
+          bit color codes. Requires truecolor capable terminal.
+
+          More information is available at #help color.
+
+          Escapes
+
+\         The back slash is used to escape a character. All available options
+          are listed at #help escape. Escapes are typically escaped when text
+          leaves the client, by being send to a server, the shell, being
+          displayed on the screen, or being processed as part of a regex.
+          Escapes try to mimic escapes in PCRE when possible.
+
+Related: characters, colors, escape_codes and pcre.
+
+Command: #cursor suspend
+
+         Temporarily suspends tintin and returns you to your shell.  To
+         return to tintin, type 'fg' at the shell prompt.
+
+         While suspended your tintin sessions will freeze. To keep a
+         suspended session running use the #daemon command.
+
+Related: sessionname
+
+Command: #switch {conditional} {arguments}
+
+         The switch command works similar to the switch statement in other
+         languages. When the 'switch' command is encountered its body is parsed
+         and each 'case' command found will be compared to the conditional
+         argument of the switch and executed if there is a match.
+
+         When comparing strings both the switch and case arguments must be
+         enclosed in quote characters.
+
+         If the 'default' command is found and no 'case' statement has been
+         matched the default command's argument is executed.
+
+Example: #switch {1d4} {#case 1 cackle;#case 2 smile;#default giggle}
+
+Related: statements
+
+Command: #system {command}
+
+         Executes the command specified as a shell command.
+
+Related: detach, script and run.
+
+Command: #tab {word}
+
+         Adds a word to the tab completion list, alphabetically sorted.
+
+         If no tabs are defined tintin will use the scrollback buffer for auto
+         tab completion.
+
+         Tabbing behavior can be modified with the #cursor tab command which
+         by default is bound to the tab key.
+
+Example: #macro \t #cursor tab list scrollback caseless forward
+
+Comment: You can remove a tab with the #untab command.
+
+Related: alias, cursor, history, keypad, macro and speedwalk.
+
+Command: #textin {filename} {delay}
+
+         Textin allows the user to read in a file, and send its contents
+         directly to the server.  Useful for doing online creation, or message
+         writing.
+
+         The delay is in seconds and takes a floating point number which is
+         cumulatively applied to each outgoing line.
+
+Related: scan and send.
+
+Command: #ticker {name} {commands} {interval in seconds}
+
+         Executes given command every # of seconds. Floating point precision
+         for the interval is allowed. A ticker cannot fire more often than
+         10 times per second.
+
+Comment: Tickers don't work in the startup session.
+
+Comment: You can remove a ticker with the #unticker command.
+
+Related: delay and event.
+
+Command: #format {variable} {%t} {argument}
+
+         The %t format specifier of the #format command allows printing dates
+         using the strftime() format specifiers. By default the time stamp used
+         is the current time, if you want to print a past or future date use:
+
+Command: #format {variable} {%t} {{argument} {epoch time}}
+
+         The current epoch time value is obtained using #format {time} {%T}.
+
+         When using %t the argument should contain strftime format specifiers.
+         Below are some common specifiers, see man strftime for the full list.
+
+         %a  Abbreviated name of the day of the week (mon ... sun).
+         %A  Full name of the day of the week. (Monday ... Sunday)
+         %b  Abbreviated name of the month (Jan ... Dec)
+         %B  Full name of the month. (January ... December)
+         %C  2 digit numeric century. (19 ... 20)
+         %d  2 digit numeric day of the month (01 ... 31)
+         %H  2 digit numeric 24-hour clock hour. (00 ... 23)
+         %I  2 digit numeric 12-hour clock hour. (01 ... 12)
+         %j  3 digit numeric day of the year (001 ... 366)
+         %m  2 digit numeric month of the year (01 ... 12)
+         %M  2 digit numeric minute of the hour (00 ... 59)
+         %p  Abbreviated 12 hour clock period (AM ... PM)
+         %P  Abbreviated 12 hour clock period (am ... pm)
+         %S  2 digit numeric second of the minute (00 ...59
+         %u  1 digit numeric day of the week (1 ... 7)
+         %U  2 digit numeric Sunday week of the year (00 ... 53
+         %w  1 digit numeric day of the week (0 ... 6)
+         %W  2 digit numeric Monday week of the year (00 ... 53
+         %y  2 digit numeric year. (70 ... 38)
+         %Y  4 digit numeric year. (1970 ... 2038)
+         %z  5 digit timezone offset. (-1200 ... +1400)
+         %Z  Abbreviated name of the time zone. (CET, GMT, etc)
+
+Related: echo, event and format.
+
+         All available triggers in TinTin++ are displayed when you use the #info
+         command without an argument. All of them are written to file when you
+         use the #write command, except commands, histories, and paths.
+
+         Triggers can be disabled with the #ignore command. The #message
+         command can be used to disable messages generated or related to the
+         corresponding trigger, though this is generally not needed.
+
+         The #debug command will generate useful debugging information for the
+         corresponding trigger when enabled. The #info command can be used on
+         triggers to generate additional information that might be of use.
+
+Example: #info event on
+
+         When #info event is set to on you will see when most events are raised.
+         Since this can get rather spammy some of the events won't generate
+         messages, unless you have an event in the same category set already.
+
+         Text triggers
+
+         When a block of text arrives from the host it is split into individual
+         lines, and all action, prompt, gag, substitute, and highlight triggers
+         are checked for each line. Only one action can trigger per line, while
+         the other triggers can trigger multiple times.
+
+         Packet fragmentation
+
+         MUDs that send long blurbs of text, don't have MCCP support, have a bad
+         connection, or a combination of all three, will deliver broken packets.
+         This can cause triggers to not fire, as well as displaying problems if
+         #split is enabled.
+
+         To mitigate this you can use #config packet_patch 0.5.
+
+         TinTin++ will automatically enable packet patching if the IAC GA or IAC
+         EOR telnet sequences are used to mark the end of the prompt. A MUD can
+         negotiate the EOR option: https://tintin.mudhalla.net/protocols/eor
+
+         In addition #prompt can be used to make packet patching less noticable.
+
+         Color triggers
+
+         By default most color, control, and vt100 codes are stripped from
+         incoming text before being ran through the trigger engine. To create
+         a trigger that runs on the unstripped text, the regular expression in
+         the trigger should start with a ~.
+
+         To view control codes you can use #config convert_meta on which will
+         translate both input and output codes to PCRE escape sequences.
+
+         Multi-line triggers
+
+         If an action contains the \n sequence it will be turned into a
+         multi-line trigger. A multi-line action is executed on incoming blocks
+         of text from the MUD, and they will not trigger if the regular
+         expression spans more than one block. You can visualize incoming
+         blocks by using #event {RECEIVED OUTPUT} {#echo <058>%+80h BLOCK}
+
+         Since the %* expression does not capture the \n sequence it is required
+         to use %a to capture multiple lines. To capture the start of the block
+         use \A and for the end use \Z. You can use ^ and $ to capture the
+         start and end of a line.
+
+         Multi-line actions trigger before regular actions. Multiple
+         multi-line actions can trigger per block, and each multi-line action
+         can trigger multiple times per block. Packet fragmentation is not
+         currently handled.
+
+         Multi-line actions are experimental and subject to change.
+
+         Input triggers
+
+         The alias, history and pathdir triggers are checked for each line of
+         input. The macro and tab triggers are checked for key presses.
+
+         Time triggers
+
+         The delay, path, and ticker triggers will execute at a set timed
+         interval.
+
+         Substitution triggers
+
+         The function and variable triggers will generally execute right
+         before the final processing of a line of text.
+
+         Mouse triggers
+
+         The button trigger is checked for each mouse input. #config mouse
+         must be set to on to enable mouse tracking.
+
+         Event triggers
+
+         Events can be used for a wide variety of pre-defined triggers.
+
+Related: pcre, substitutions and escape_codes.
+
+Command: #variable {variable name} {text to fill variable}
+
+         Variables differ from the %0-99 arguments in the fact that you can
+         specify a full word as a variable, and they stay in memory for the
+         full session unless they are changed.  They can be saved in the
+         coms file, and can be set to different values if you have two or
+         more sessions running at the same time.  Variables are global for
+         each session and can be accessed by adding a $ before the variable
+         name.
+
+Example: #alias {target} {#var target %0}
+         #alias {x}      {kick $target}
+
+         The name of a variable must exist of only letters, numbers and
+         underscores in order to be substituted.  If you do not meet these
+         requirements do not panic, simply encapsulate the variable in braces:
+
+Example: #variable {cool website} {http://tintin.sourceforge.net}
+         #chat I was on ${cool website} yesterday!.
+
+         Variables can be escaped by adding additional $ signs.
+
+Example: #var test 42;#showme $$test
+
+         Variables can be nested using brackets:
+
+Example: #var hp[self] 34;#var hp[target] 46
+
+         You can see the first nest of a variable using $variable[+1] and the
+         last nest using $variable[-1]. Using $variable[-2] will report the
+         second last variable, and so on. To show all indices use *variable[].
+         To show all values use $variable[]. To show all values from index 2
+         through 4 use $variable[+2..4].
+
+         Nested variables are also known as tables, table generally being used
+         to refer to several variables nested within one specific variable.
+
+         It's possible to use regular expressions.
+
+Example: #show {Targets starting with the letter A: $targets[A%*]
+
+         To see the internal index of a variable use &<variable name>. To see
+         the size of a table you would use: &targets[] or &targets[%*]. A non
+         existent nested variable will report itself as 0.
+
+Example: #show {Number of targets starting with A: &targets[A%*]
+
+         In some scripts you need to know the name of a nested variable. This
+         is also known as the key, and you can get it using *variable. For
+         example *target[+1]. To get the first variable's name use *{+1}.
+
+         It's also possible to declare a table using brace notation. Using
+         #var hp[self] 34 is the equivalent of #var {hp} {{self}{34}}. This
+         also allows merging tables. #var hp[self] 34;#var hp[target] 46 is
+         the equivalent of #var {hp} {{self}{34} {target}{46}} as well as
+         #var {hp} {{self}{34}} {{target}{46}} or if you want to get creative
+         the equivalent of #var hp[self] 34;#var {hp} {$hp} {{target}{46}}.
+
+Comment: You can remove a variable with the #unvariable command.
+
+Related: cat, format, function, local, math, replace and script.
+
+Command: #while {conditional} {commands}
+
+         This command works similar to a 'while' statement in other languages.
+
+         When a 'while' command is encourated, the conditional is evaluated,
+         and if TRUE (any non-zero result) the commands are executed. The
+         'while' loop will be repeated indefinitely until the conditional is
+         FALSE or the #BREAK or #RETURN commands are found.
+
+         The 'while' statement is only evaluated if it is read, so you must
+         nest it inside a trigger, like an alias or action.
+
+         The conditional is evaluated exactly the same as in the 'math' command.
+
+Example: #math cnt 0;#while {$cnt < 20} {#math cnt $cnt + 1;say $cnt}
+
+Comment: See '#help math', for more information.
+
+Related: statements
+
+Command: #write {<filename>} {[FORCE]}
+
+         Writes all current actions, aliases, subs, highlights, and variables
+         to a command file, specified by filename.
+
+         By default you cannot write to .map files to prevent accidentally
+         overwriting a map file. Use the FORCE argument to ignore this
+         protection.
+
+Related: log, read, scan and textin.
+
+Command: #zap {[session]}
+
+         Kill your current session.  If there is no current session, it will
+         cause the program to terminate. If you provide an argument it'll zap
+         the given session instead.
+
+Related: all, port, run, session, sessionname, snoop and ssl.
+

+ 687 - 0
src/validate

@@ -0,0 +1,687 @@
+#!./tt++ -G
+
+#nop   1: #math
+#nop   2: #line
+#nop   3: #return
+#nop   4: #buffer
+#nop   5: #switch
+#nop   6: #class
+
+
+#line sub arg #var arg {%0}
+
+#if {"$arg" == "draw"}
+{
+	#screen clear all;
+	#draw convert scroll Red Blue box 1 1 5 40 convert\nx\ny;
+	#draw Red box 1 1 2 2;
+	#draw rounded Red box 3 1 4 2;
+	#draw tubed Red box 5 1 6 2;
+	#draw crossed Red box 8 1 9 2;
+
+	#draw Green line 1 4 1 14;
+	#draw Green teed line 2 4 2 14;
+	#draw Green jeweled line 3 4 3 14;
+	#draw Green circled line 4 4 4 14;
+	#draw Green left circled line 5 4 5 14;
+	#draw Green right circled line 6 4 6 14;
+	#draw Green bot vertical teed line 7 4 7 14;
+	#draw Green top vertical teed line 8 4 8 14;
+
+	#draw Yellow left horizontal teed line  1 16 10 16;
+	#draw Yellow right horizontal teed line 1 18 10 18;
+	#draw Yellow top circled line 1 20 10 20;
+	#draw Yellow bottom circled line 1 22 10 22;
+	#draw Yellow pruned circled line 1 24 10 24;
+	#draw Yellow filled circled line 1 26 10 26;
+	#draw Yellow filled jeweled line 1 28 10 28;
+
+	#draw Cyan box 1 40 10 60;
+	#draw Jade rounded box 2 41  9 59;
+	#draw Azure pruned box 2 41 9 59;
+	#draw Violet numbered box 3 42 8 58;
+	#draw White rounded tubed box 4 43 7 57;
+
+	#draw Magenta Green round table 12  1 20 38 {{a}{b}{c}{d}}{{e}{f}{g}{h}}{{i}{j}{k}{l}};
+	#draw Magenta Green grid table 12 42 21 78 {{a}{b}{c}{d}}{{e}{f}{g}{h}}{{i}{j}{k}{l}};
+
+	#draw White Red talign box 22  1 27 19 talign;
+	#draw White Red balign box 22 21 27 39 balign;
+	#draw White Red lalign box 22 41 27 59 lalign;
+	#draw White Red ralign box 22 61 27 79 ralign;
+	#draw White Red calign talign balign box 22 81 26 99 calign;
+
+	#draw Lime Azure cursive box 28  1 31 19 cursive;
+	#draw Lime Azure     fat box 28 21 31 39 fat;
+	#draw Lime Azure sansser box 28 41 31 59 sansserif;
+	#draw Lime Azure ualign  box 28 61 31 79 { u\na\nl\ni\ng\nn};
+	#draw Lime Azure scaled  box 28 81 31 99 scaled;
+
+
+
+	#end \
+}
+
+#draw Yellow Green scroll box 1 1 3 -1 Running Validator
+
+#format start %U
+
+#math error 0
+
+#alias error
+{
+	#math error $error + 1;
+	#line ignore #showme <118>Failed test %0
+}
+
+#0 )=-=( ERROR 1 )=-=( 0#
+
+#math tmp 1 + 1
+#if {$tmp != 2}{error 1: math failure}
+
+#math tmp 7 / 11 * 100.00
+#if {"$tmp" != "63.64"} {error 1.1: math failure}
+
+#math tmp (1 + 1) % 10
+#if {$tmp != 2} {error 1.2: math failure}
+
+#0 )=-=( ERROR 2 )=-=( 0#
+
+#alias {test} {#math tmp $tmp + 1}
+#line oneshot #alias {test%*} {#nop} {4}
+#math tmp 0
+#2 test
+#if {$tmp != 1}
+{
+	error 2: oneshot or math or alias failure
+}
+
+#0 )=-=( ERROR 3 )=-=( 0#
+
+#1 {#return;error 3: #return failure}
+
+#0 )=-=( ERROR 4 )=-=( 0#
+
+#buf get tmp -3 -1
+
+#if {&tmp[] != 3} error 4.1: buffer or variable or if failure (&&tmp[] != 3)
+#if {&tmp[%*] != 3} error 4.2: buffer or variable or if failure (&&tmp[%*] != 3)
+#if {&{tmp[]} != 3} error 4.3: buffer or variable or if failure (&&{tmp[]} != 3)
+#if {&{tmp[%*]} != 3} error 4.4: buffer or variable or if failure (&&{tmp[%*]} != 3)
+
+#showme $arg
+
+#0 )=-=( ERROR 5 )=-=( 0#
+
+#switch {3}     {#case 3 #return;#default error 5.0: switch failure}
+#switch {1+2}   {#case 3 #return;#default error 5.1: switch failure}
+#switch {"bla"} {#case "bla" #return;#default error 5.2: switch string failure}
+
+#0 )=-=( ERROR 6 )=-=( 0#
+
+#class tmp open
+#unvar tmp
+#var tmp 1
+#class tmp kill
+
+#if {&{tmp} != 0}
+{
+	error 6.1: class or variable failure
+}
+#class tmp assign #var tmp 2
+#if {$tmp != 2}
+{
+	error 6.2: class or variable failure
+}
+#class tmp save
+#class tmp clear
+#if {&{tmp} != 0}
+{
+	error 6.3: class or variable failure
+}
+#class tmp load
+#if {$tmp != 2}
+{
+	error 6.4: class or variable failure
+}
+#class tmp kill
+#if {&{tmp} != 0}
+{
+	error 6.5: class or variable failure
+}
+
+#0 )=-=( ERROR 7 )=-=( 0#
+
+#loop 1 2 tmp {#continue;error 7: continue failure}
+
+#0 )=-=( ERROR 8 )=-=( 0#
+
+#kill variable tmp
+
+#if {&{tmp} != 0}
+{
+	error 8: kill variable %* failure
+}
+
+#0 )=-=( ERROR 9 )=-=( 0#
+
+#line strip #if {{<128>} != {}}
+{
+	error 9: line strip failure
+}
+
+#0 )=-=( ERROR 10 )=-=( 0#
+
+#act {test} {error 10: line ignore failure}
+#line gag;
+#line ignore #showme <118>Failed test 10: line gag failure
+#unact {test}
+
+#0 )=-=( ERROR 11 )=-=( 0#
+
+#parse {abcd} {tmp} {#var tmp ($tmp)}
+#if {"$tmp" != "(d)"}
+{
+	error 11: parse failure
+}
+
+#0 )=-=( ERROR 12 )=-=( 0#
+
+#path load {#var tmp 1}
+#path walk
+#if {$tmp != 1}
+{
+	error 12: path load or walk failure
+}
+
+#0 )=-=( ERROR 13 )=-=( 0#
+
+#script tmp {echo 'test'}
+#if {{$tmp[1]} != {test}}
+{
+	error 13: script failure
+}
+
+#0 )=-=( ERROR 14 )=-=( 0#
+
+#regex {test} {te%?t} {#nop}
+{
+	error 14: regex failure
+}
+
+#0 )=-=( ERROR 15 )=-=( 0#
+
+#regex {bla} {bli}         {error 15.1: regex failure}
+#regex {$OK} {$OK}  {#nop} {error 15.2: regex failure}
+#regex {OK$} {OK$}         {error 15.3: regex failure}
+#regex {OK$} {OK$$}        {error 15.4: regex failure}
+#regex {OK$} {OK\$} {#nop} {error 15.5: regex failure}
+
+#0 )=-=( ERROR 16 )=-=( 0#
+
+#0 error 16: repeat failure
+
+#0 )=-=( ERROR 17 )=-=( 0#
+
+#unvar tmp
+
+#1
+{
+	#local tmp 1;
+	#if {$tmp != 1}
+	{
+		error 17: local failure
+	}
+}
+
+#0 )=-=( ERROR 18 )=-=( 0#
+
+#if {${tmp} == 1}
+{
+	error 18: local failure
+}
+
+#0 )=-=( ERROR 19 )=-=( 0#
+
+#1
+{
+	#local tmp 2;
+
+	#regex {a} {a}
+	{
+		#if {$tmp != 2}
+		{
+			error 19: local failure
+		}
+	}
+}
+
+#0 )=-=( ERROR 20 )=-=( 0#
+
+#if {"$arglebargle" != "\$arglebargle"}
+{
+	error 20: unassigned variable
+}
+
+#0 )=-=( ERROR 21 )=-=( 0#
+
+#alias {bla} {error 21: unalias malfunction}
+#alias {bla%*} {#nop}
+#unalias {bla}
+bla
+#unalias {bla%*}
+
+#0 )=-=( ERROR 22 )=-=( 0#
+
+#class bla open
+#var bla 2
+#var bli 2
+#alias haha hihi
+#fun bla blo
+#class bla close
+#class bla save
+#class bla clear
+#if {&{bla} != 0} {error 22: #class clear malfunction}
+#class bla load
+#if {&{bla} == 0} {error 23: #class load malfunction}
+#class bla clear
+#class bla load
+#class bla kill
+
+
+#0 )=-=( ERROR 24 )=-=( 0#
+
+#if {(513 & ~1) != 512} {error 24.01: #math error}
+#if {1 << 1 != 2}	   {error 24.02: #math error}
+#if {1 < 2} {#nop} {error 24.03: #math error}
+#if {2 > 1} {#nop} {error 24.04: #math error}
+#if {2 % 2} {error 24.05: #math error}
+
+#0 )=-=( ERROR 25 )=-=( 0#
+
+#var tmp 0;
+#var bla var
+#{$bla} tmp 1
+#if {$tmp != 1} {error 25.1: variable command}
+#$bla tmp 2
+#if {$tmp != 2} {error 25.2: variable command}
+
+#var bla gts
+#{$bla} #var tmp 3
+#if {$tmp != 3} {error 25.3: variable session}
+#$bla #var tmp 4
+#if {$tmp != 4} {error 25.4: variable session}
+
+#var bla #math tmp 5
+$bla
+#if {$tmp != 5} {error 25.5: variable input}
+$bla + 1
+#if {$tmp != 6} {error 25.6: variable input}
+
+#0 )=-=( ERROR 26 )=-=( 0#
+
+#format bla %X ─
+#if {$bla != 2500}     {error 26.1: format unicode handling}
+#format bla %x 2500
+#line sub esc #var bli \u2500
+#if {{$bla} != {$bli}} {error 26.2: unicode handling}
+#var {bla} {<128>A<138>BC<148>DE<158>FG}
+#format tmp %L {$bla}
+#if {$tmp != 7}        {error 26.6: format L handling}
+#format bli {%.5s} {$bla}
+#format tmp %L {$bli}
+#if {$tmp != 5}        {error 26.7: format .+s handling}
+#format bli {%.-5s} {$bla}
+#format tmp %L {$bli}
+#if {$tmp != 5}        {error 26.8: format .-s handling}
+#format bli {%-20s} {$bla}
+#format tmp %L {$bli}
+#if {$tmp != 20}       {error 26.9: format -s handling}
+#format bli {%+20s} {$bla}
+#format tmp %L {$bli}
+#if {$tmp != 20}       {error 26.10: format +s handling}
+#format bli {%+20.-3s} {$bla}
+#format tmp %L {$bli}
+#if {$tmp != 20}       {error 26.11: format +.-s handling}
+#format tmp %+10s {\e]68;1;SEND;bow\a\e[4mbow\e[24m}
+#format tmp %L {$tmp}
+#if {$tmp != 10} {error 26.12: format escape code handling}
+#line sub esc #format tmp %+10s {\e]68;1;SEND;bow\a\e[4mbow\e[24m}
+#format tmp %L {$tmp}
+#if {$tmp != 10} {error 26.13: format escape code handling}
+
+#0 )=-=( ERROR 27 )=-=( 0#
+
+#line sub esc #var bla {x\nx}
+#if {"$bla" === "x\nx"} {error 27.1: escape handling}
+#if {"$bla" != "x\nx"}  {error 27.2: escape handling}
+
+#0 )=-=( ERROR 28 )=-=( 0#
+
+#var bla[1] {{bli}{2}}
+#var bla[2] {{bli}{3}}
+
+#list bla index bli
+#list bla order
+#if {$bla[1][bli] != 2} {error 28.01: 2D list handling}
+#list bla reverse
+#if {$bla[1][bli] != 3} {error 28.02: 2D list handling}
+#var bla[1][blo] 4
+#list bla[1] get 1 tmp
+#if {$tmp != 3} {error 28.03: 2D list handling: $tmp}
+#list bla[1] get -1 tmp
+#if {$tmp != 4} {error 28.04: 2D list handling: $tmp}
+#list bla[1] find {4} tmp
+#if {$tmp != 2} {error 28.05: 2D list handling: $tmp}
+#list bla[1] set 2 5
+#list bla[1] find {5} tmp
+#if {$tmp != 2} {error 28.06: 2D list handling: $tmp}
+#list bla[1] insert 2 9
+#list bla[1] get 2 tmp
+#if {$tmp != 9} {error 28.07: 2D list handling: $tmp}
+
+#list bla tokenize 123456789
+#list bli create $bla[+2..+4]
+#if {&bli[] != 3} {error 28.08: list range handling: &bli[]}
+#list bli create $bla[-3..-1]
+#if {&bli[] != 3} {error 28.09: list range handling: &bli[]}
+
+#list bla tokenize abcdefghi
+#list bla filter {} {d}
+#if {"$bla[+4]" != "e"} {error 28.10: list filter handling: "$bla[+4]" != "e"}
+#list bla filter {f}
+#if {"$bla[+1]" != "f"} {error 28.11: list filter handling: "$bla[+1]" != "f"}
+
+#0 )=-=( ERROR 29 )=-=( 0#
+
+#alias {bla}
+{
+	#var bla 1;
+	#return;
+	#var bla 2
+}
+bla
+#if {$bla != 1} {error 29.1: return handling}
+
+#function {bla}
+{
+	#return 1;
+	#return 2;
+}
+#if {@bla{} != 1} {error 29.2: return handling}
+
+#function {bla}
+{
+	#if {1} #return 1;
+	#return 2
+}
+#if {@bla{} != 1} {error 29.3: return handling}
+
+#function {bla}
+{
+	#regex {1} {1} {#return 1};
+	#return 2
+}
+#if {@bla{} != 2} {error 29.4: regex return handling}
+
+#function {bla}
+{
+	#var blo 5;
+	#return $blo
+}
+
+#function {bli}
+{
+	#return @bla{}
+}
+
+#if {@bli{} != 5} {error 29.5: regex return handling (@bli{})}
+
+#0 )=-=( ERROR 30 )=-=( 0#
+
+#history insert {#var bla 33}
+!
+#if {$bla != 33} {error 30.1: history handling}
+
+#0 )=-=( ERROR 30 )=-=( 0#
+
+#var bla {{d}{4}{b}{2}{a}{1}{c}{3}}
+
+#if {$bla[+3] != 3} {error 30.1: table handling ($bla[+3] != 3)}
+#if {$bla[-2] != 3} {error 30.2: table handling ($bla[-2] != 3)}
+#if {&bla[0] != 0}  {error 30.3: table handling (&bla[0] != 0)}
+#unvar bla[=d]
+#if {&bla[] != 3}   {error 30.4: table handling (#unvar bla[=d])}
+#if {$bla[=d] != 4} {error 30.5: table handling (\$bla[=d])}
+
+#0 )=-=( ERROR 31 )=-=( 0#
+
+#tab bliblablo
+#cursor clear
+#cursor set bli
+#cursor tab list forward
+#cursor get bla
+#cursor clear
+#if {"$bla" != "bliblablo"} {error 31.1: tab list handling ("$bla" != "bliblablo")}
+#untab bliblablo
+#cursor set bli
+#cursor tab dict forward
+#cursor get bla
+#cursor clear
+#if {"$bla" != "bliaut"} {error 31.2: tab dict handling ("$bla" != "bliaut")}
+
+#0 )=-=( ERROR 32 )=-=( 0#
+#map create
+#map goto 1
+#map move {nw;ne;s;s}
+#map exit n weight 0.9
+#map find 3
+#path save forward bla
+#if {"$bla" != "n;n"} {error 32.1: #map find failing exit weight reduction}
+#map exit n weight 1.0
+#map find 3
+#path save forward bla
+#if {"$bla" != "nw;ne"} {error 32.2: #map find failing exit weight increase}
+
+#0 )=-=( ERROR 33 )=-=( 0#
+
+#alias {sethash}
+{
+       #format hash %H %1;
+       #math hash1 $hash % 100;
+       #math hash2 $hash / 100 % 100;
+       #var hashtable[$hash1][$hash2][%1] %2
+}
+
+#function {gethash}
+{
+       #format hash %H %1;
+       #math hash1 $hash % 100;
+       #math hash2 $hash / 100 % 100;
+       #return $hashtable[$hash1][$hash2][%1]
+}
+
+sethash bli hey
+sethash bla hi
+sethash blo hello
+#if {"@gethash{bla}" !== "hi"} {error 33.1: variable hashing support}
+
+#0 )=-=( ERROR 34 )=-=( 0#
+
+#regex {blibla} {%10bli%+3..3a} {#if {"&11" !== "bla"} {error 34.1: regex argument indexing (&11)}}
+#regex {blibla} {%.%+%.%*}      {#if {"&4" !== "bla"}  {error 34.2: regex argument indexing (&4)}}
+#regex {blibla} {%99bli%+3..3*}      {#if {"&99" !== "bla"} {error 34.3: regex argument indexing (&99)}}
+
+#0 )=-=( ERROR 35 )=-=( 0#
+
+#var bla {}
+#cat bla bli
+#if {{$bla} !== {bli}} {error 35.1: #cat simple}
+#cat bla bli
+#if {{$bla} !== {blibli}} {error 35.2: #cat simple ($bla) != (blibli)}
+#cat bla {{bli}{blo}}
+#if {{$bla[bli]} !== {blo}} {error 35.3: #cat table}
+#cat bla {{bla}{blu}}
+#if {{$bla[bla]} !== {blu}} {error 35.4: #cat table}
+#cat bla[bli] {{a}{b}}
+#if {{$bla[bli][a]} !== {b}} {error 35.5: #cat table}
+#var bla {}
+#foreach {bli;bla;blo} {add} #cat bla $add
+#if {"$bla" != "bliblablo"} {error 35.6: #foreach cat bliblablo}
+#var bla {}
+#while {&bla[] < 10}
+{
+	#cat bla {{&bla[]} {x}}
+}
+#if {&bla[] != 10} {error 35.7: #while bla (&bla[] != 10)}
+
+#0 )=-=( ERROR 36 )=-=( 0#
+
+#var match 0
+#line oneshot #act {^^^bla$$$} {#var match 1;#line gag}
+#showme bla
+#if {$match == 0} {error 36.1: regex ^^^$$$} {#var match 0}
+#line oneshot #act {^%.l%.$} {#var match 1;#line gag}
+#showme bla
+#if {$match == 0} {error 36.2: regex ^%.l%.$} {#var match 0}
+#line oneshot #act {^%+1Dl%+1S$} {#var match 1;#line gag}
+#showme bla
+#if {$match == 0} {error 36.3: regex ^%+1Dl%+1S$} {#var match 0}
+#line oneshot #act {^%iBLA$} {#var match 1;#line gag}
+#showme bla
+#if {$match == 0} {error 36.4: regex ^%iBLA$} {#var match 0}
+#line oneshot #act {^%+2wa$} {#var match 1}
+#line gag
+#showme bla
+#if {$match == 0} {error 36.5: regex ^%+2wa$} {#var match 0}
+#line oneshot #act {^%+2*a$} {#if {"%1" == "bl"} {#var match 1}}
+#line gag
+#showme bla
+#if {$match == 0} {error 36.6: regex ^%+2*a$} {#var match 0}
+
+#0 )=-=( ERROR 37 )=-=( 0#
+
+#var bla {{dzp}{{id}{dzp}{level}{18}}{xgg}{{id}{xgg}{level}{33}}}
+
+#if {{$bla[]} !== {$bla[%*]}} {error 37.1: {{$bla[] !== {$bla[%*]}}}}
+#if {{*bla[]} !== {*bla[%*]}} {error 37.2: {{*bla[] !== {*bla[%*]}}}}
+#if {{&bla[]} !== {&bla[%*]}} {error 37.3: {{&bla[] !== {&bla[%*]}}}}
+
+#0 ┌──────────────────────────────────────────────────────────────────────────────┐
+#0 │ ██████┐██████┐  █████┐ ███████┐██┐  ██┐   ████████┐███████┐███████┐████████┐ │
+#0 │██┌────┘██┌──██┐██┌──██┐██┌────┘██│  ██│   └──██┌──┘██┌────┘██┌────┘└──██┌──┘ │
+#0 │██│     ██████┌┘███████│███████┐███████│      ██│   █████┐  ███████┐   ██│    │
+#0 │██│     ██┌──██┐██┌──██│└────██│██┌──██│      ██│   ██┌──┘  └────██│   ██│    │
+#0 │└██████┐██│  ██│██│  ██│███████│██│  ██│      ██│   ███████┐███████│   ██│    │
+#0 │ └─────┘└─┘  └─┘└─┘  └─┘└──────┘└─┘  └─┘      └─┘   └──────┘└──────┘   └─┘    │
+#0 └──────────────────────────────────────────────────────────────────────────────┘
+
+#class bla open
+#var blabla x
+#class bla kill
+
+#action {bla} #nop
+#alias {bla} #nop
+#button {1;1;2;2} {#nop}
+#delay 1000 #nop
+#event {GAG SESSION DISCONNECTED} {#nop}
+#fun bla {#nop}
+#gag bla
+#high bla green
+#macro \e\e #nop
+#pathdir bla bli
+#prompt bla bli
+#sub bla bli
+#tab bla bli
+#tick bla {#nop} 1
+#var bla bli
+
+#line quiet
+{
+	#act;#alias;#button;#delay;#event;#event %*;#fun;#gag;#high;#macro;#pathdir;#prompt;#sub;#tab;#tick;#var
+}
+
+#nop #line quiet #line debug #1 {#if {0} {#nop};#elseif {0} {#nop};#else #switch {1} {#case 0 #nop;#case 1 #continue}}
+
+#unvar bla
+#untab bla
+#untick bla
+#unsub bla
+#unprompt bla
+#unpathdir bla
+#unmacro \e\e
+#ungag hrm
+#unfun bla
+#unhigh bla
+#unevent {GAG SESSION CONNECTED}
+#undelay %*
+#unbutton {1;1;2;2}
+#unact bla
+#unalias bla
+
+#bell volume 8
+#buffer get bla -1 -1;
+#cat bla bli
+#line quiet #chat init 0
+#chat uninit
+#cursor get bla
+#line quiet #daemon list
+#line quiet #dictionary bla
+#line quiet #dictionary hello
+#draw green tile 1 -1 1 -1
+#draw blue red scaled box 1 1 4 4 hello world
+#format bla {}
+#line quiet #help %*
+#history insert bla
+#history delete
+#info system save
+#list bla create {a;b;c}
+#kill variable bla
+#loop 0 1 bla #nop
+#line quiet
+{
+	#map create;
+	#map goto 1;
+	#map dig n;
+	#map destroy world
+}
+#math bla 2+2
+#message all on
+#parse {abc} {bla} {#nop}
+#path create
+#path destroy
+#line quiet #port init bla 0
+#snoop bla
+#bla #kill all
+#line quiet #port uninit
+#regex {bla} {bla} {#nop} {#nop}
+#var bla x
+#replace bla x y
+#screen get cols bla
+#line quiet #split
+#unsplit
+
+#format end %U;
+
+#0 )=-=( ERROR 19 )=-=( 0#
+
+#function time
+{
+	#math result ($end - $start) / 1000000.000
+}
+
+#if {$error}
+{
+	#draw White Red scroll box 1 1 3 80 End of validation with $error errors.;
+	#end \
+}
+{
+	#delay {0}
+	{
+		#info memory;
+		#info stack;
+		#draw Yellow Green scroll box 1 1 3 80 End of validation with 0 errors in @time{} seconds.;
+		#line benchmark {#10000 #math tmp (2 | 1) / 2 + 5};
+		#end \
+	}
+}