==================
TinTin++ Reference
==================


Comprehensive reference for TinTin++ (tt++) extracted from source code.
Generated from version 2.02.61, master branch.

.. contents:: Table of Contents
   :depth: 3
   :local:


Overview
========


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 sent 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


Commands
========


All TinTin++ commands. Commands start with the tintin character (default #).
Commands can be abbreviated: ``#he`` is the same as ``#help``.

action
------


Command: #action {message} {commands} {priority}

The #action command can be used to respond with one or several
commands to a specific message sent 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.

See also: pcre gag highlight prompt substitute


alias
-----


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.

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.

See also: cursor history keypad macro speedwalk tab


all
---


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.

See also: port run session sessionname snoop ssl zap


bell
----


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}

See also: screen


buffer
------


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}

See also: echo grep macro showme screen


button
------


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.

See also: delay event ticker


cat
---


Command: #cat {variable} {argument}

The cat command will concatenate the argument to the given variable.

See also: format function local math replace script variable


chat
----


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 events are triggered in the startup session.

::

   #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 sent 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}
     #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,
     Forward(A)ll to user, (F)orward to user, and (f)orward from user.
     The next columns show ip, port, and client name.
   #chat {zap}        {buddy}            Close a connection

See also: port


class
-----


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>} {debug} {on|off}
  Toggle debug mode for given class.
#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.

See also: config debug ignore info kill line message


commands
--------


Command: #commands {abbreviation}

Shows all commands, or all commands starting with the given
abbreviation.

See also: help info statements


config
------


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 {HIBERNATE}     {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.

See also: class line


cr
--


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 {}.

See also: forall


cursor
------


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
KEYPAD      keypad 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
INPUT       performs tab completion on the input history
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.

See also: alias history keypad macro speedwalk tab


daemon
------


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>.

See also: script system run


debug
-----


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.

See also: class ignore info kill message


delay
-----


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

See also: event ticker


draw
----


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      both LALIGN and RALIGN to 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 SPAWN (0.01-100) FADE (1-100).
[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
BALIGN, TALIGN, LALIGN, RALIGN, and UALIGN options.

Example: #draw Blue box 1 1 3 20 {Hello world!}

See also: buffer echo grep showme


echo
----


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}

See also: buffer format grep showme


edit
----


Command: #edit {option} [argument]

The edit command can be used to turn the default line editor into a
text editor.

#edit create [filename] [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 {bla.txt} {line 1} {line 2}

See also: cursor macro


end
---


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.

See also: zap


event
-----


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

FORMAT EVENTS

REFORMAT <MESSAGE>     Use #return to change MESSAGE

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

EDIT RESUMED, EDIT SUSPENDED
  %0 name

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, MAP FOLLOW GLOBAL
  %0 old vnum  %1 new vnum  %2 exit name

MAP REGION <MOUSE>, MAP ROOM <MOUSE>
  %0 row  %1 col  %2 -row  %3 -col  %4 vnum  %5 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.

PROCESSED LINE         %0 raw text %1 plain text %2 prompt (0 or 1)

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           %0 raw text  %1 plain text
CHAT SNOOP REQUEST     %0 name %1 ip %2 port

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 MESSAGE           %0 raw text %1 plain text
PORT RECEIVED MESSAGE  %0 name %1 ip %2 port %3 data %4 plain data
PORT RECEIVED DATA     %0 name %1 ip %2 port %3 data %4 size

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

CONFIG                 %0 name %1 value

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

RECEIVED ERROR         %0 message
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.

See also: button delay ticker


format
------


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.

See also: cat echo function local math replace script time variable


function
--------


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.

See also: format local math replace script variable


gag
---


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.

See also: action highlight prompt substitute


grep
----


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.

See also: buffer echo showme


help
----


Command: #help {subject}

Without an argument #help will list all available help subjects.

Using #help %* will display all help entries.

See also: commands debug ignore info message statements


highlight
---------


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.

See also: action gag prompt substitute


history
-------


Command: #history {delete}                    Delete the last command.
#history {get}    {variable} {range} Store list in variable.
#history {insert} {command}          Insert a command.
#history {list}                      Display the 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.

See also: alias cursor keypad macro speedwalk tab


if
--


Command: #if {conditional} {commands if true} {commands if false}

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. Alternatively, the else can be provided as the
third argument.

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}}

Example: #if {"%0" == "{bli|bla}"} {#showme %0 is either bli or bla.}

See also: case default else elseif math switch regexp


ignore
------


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
trigger. Not every list can be ignored.

See also: class debug info kill message


info
----


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 output will show information about the mud output buffers.
#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.

See also: class debug ignore kill message


kill
----


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*

See also: class debug ignore info message


line
----


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 benchmark <argument>
  Argument is executed and the elapsed time is reported after.

#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 ".

See also: class config


list
----


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} {copy} <variable>          Copy variable to the list
   #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} {swap} <index> <index>     Swap two items
   #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. All entries must contain the given key.

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.

See also: break continue foreach loop parse repeat return while


local
-----


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.

See also: format function math replace script variable


log
---


Command: #log {option} {argument}

The log command allows logging session output to file.

#config log_level <low|high>
  Default is high. Low, logs server output before triggers.

#config log_mode <html|plain|raw>
  Set the log's data type to either html, plain, or raw.

#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 make <directory>
  Create the given directory.

#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.

See also: read scan textin time write


macro
-----


Command: #macro {key sequence} {commands}

Macros allow you to make tintin respond to function keys.

The key sequence sent 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.

See also: alias cursor history keypad speedwalk tab


map
---


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.

See also: path pathdir speedwalk


math
----


::

    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.

See also: cat format function local mathematics replace script variable


message
-------


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.

See also: class debug ignore info kill


nop
---


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.

See also: read


path
----


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}

See also: map pathdir speedwalk


pathdir
-------


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.

See also: map path


port
----


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.

See also: all chat run session sessionname snoop ssl zap


prompt
------


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.

Example: #prompt {[%*] %* (%*) > } {[%1] %2 (%3)}
Example: #prompt {[%*] %* (%*) > } {} {-2}
If the <new text> argument is left empty the original text is used,
including colors. Use {\} for a blank line.

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.

See also: action gag highlight substitute


read
----


Command: #read {filename}

Reads a commands file into memory.  The commands are merged with the
currently loaded commands.  Duplicate commands are overwritten.

If you uses braces you can use several lines for each command.  You
must match every { with a } for the read command to work.

You can comment out triggers using /\* text \*/

See also: log scan textin write


regexp
------


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.

See also: pcre replace


replace
-------


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{}}

See also: cat format function local math script variable


run
---


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}

See also: all port session sessionname snoop ssl zap


scan
----


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 {json} <filename> <variable>
  The scan json command will read the given filename and store the data
  in the provided tintin 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 sent 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.

See also: read textin


screen
------


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.

See also: bell


script
------


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].

See also: format function local math replace variable


send
----


Command: #send {text}

Sends the text directly to the server, useful if you want to start
with an escape code.

See also: textin


session
-------


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}

See also: all port run sessionname snoop ssl zap


showme
------


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.

See also: buffer draw echo grep prompt


snoop
-----


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.

See also: all port run session sessionname ssl zap


split
-----


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.

See also: echo prompt showme


ssl
---


Command: #ssl {name} {host} {port} {file}

Starts a secure socket telnet session with the given name, host, port,
and optional file name.

See also: all port run sessionname snoop ssl zap


substitute
----------


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}
Replace a line containing '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.

See also: action gag highlight prompt


system
------


Command: #system {command}

Executes the command specified as a shell command.

See also: detach script run


tab
---


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 \	 #cursor tab list scrollback caseless forward

Comment: You can remove a tab with the #untab command.

See also: alias cursor history keypad macro speedwalk


textin
------


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.

See also: scan send


ticker
------


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.

See also: delay event


variable
--------


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} {https://tintin.mudhalla.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 disable using regular expressions start the match with '='.

Example: #show {A target literally defined as 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.

See also: cat format function local math replace script


write
-----


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.

See also: log read scan textin


zap
---


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.

See also: all port run session sessionname snoop ssl


Statements
==========


Flow control statements used within TinTin++ scripts.

break
-----


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}}

See also: statements


case
----


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.

See also: default statements switch


continue
--------


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}}

See also: break foreach list loop parse repeat return while


default
-------


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.

See also: case default else elseif if switch regexp


else
----


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}

See also: case default elseif if switch regexp


elseif
------


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}

See also: case default else if switch regexp


foreach
-------


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}

See also: break continue list loop parse repeat return while


loop
----


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'.

See also: break continue foreach list parse repeat return while


parse
-----


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}

See also: break continue foreach list loop repeat return while


return
------


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.

See also: break continue foreach list loop parse repeat while


switch
------


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}

See also: statements


while
-----


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.

See also: statements


Topics
======


Reference topics covering TinTin++ features and concepts.

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.

;        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.

See also: colors escape_codes function mathematics pcre variable


colors
------


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

Example: #show <125>Bold green on a magenta background.

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.

See also: characters coordinates escape_codes mathematics pcre


coordinates
-----------


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.

See also: characters colors escape_codes mathematics pcre


editing
-------


┌─────────────────────────┐┌────────────────────────────────────────────┐
│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                      │
└─────────────────────────┘└────────────────────────────────────────────┘

See also: cursor edit macro


escape codes
------------


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.

See also: characters colors coordinates mathematics pcre


keypad
------


When TinTin++ starts up it sends \e= to the terminal to enable the
terminal's application keypad mode, which can be disabled using
#cursor flag keypad off.

::

         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.

See also: colors coordinates escape_codes mathematics pcre


lists
-----


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]}
           }
       }
   }

See also: break continue foreach loop parse repeat return while


mapping
-------


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>. You can return to the room you were in when
the map was last saved by using #map return. You can use #event to
automatically read and write the map on session start and end.

#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.

See also: map path pathdir


mathematics
-----------


::

    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.

See also: math regexp


metric system
-------------


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│
╰─────────┴────────┴─────────────────────────────────╯

See also: echo format math


mouse
-----


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.

In order to copy/paste, most terminals require that you press the shift
key during selection.

See also: button draw event mslp


msdp
----


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.mudhalla.net/protocols/msdp

See also: event port


mslp
----


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: \e[4mn\e[24m, \e[4me\e[24m, \e[4mw\e[24m.'.

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 sent by a server,
you need to use \e]68;2;\a, and they instead trigger the SECURE LINK
event.

To create a link that is not underlined, use \e]4;24m text \e]24m.

Example: #sub {%* tells %*} {\e]68;2;EXEC;#cursor set tell %1 \a\e[4;24m%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

See also: event port


pcre
----


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 ([^\0]*?)
         %A Match zero or more newlines                      ([\
   ]*?)
         %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\
   \	 ]*?)
         %S Match zero or more non-spaces                    ([^\r\
   \	 ]*?)
         %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                            $
      \\ Match a backslash                              \\

\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.

Use \% to forcibly match a literal % character.

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.

See also: map path


repeat
------


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}
Example: #2 {buy bread} {buy apple}

See also: mathematics statements


screen reader
-------------


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:

https://tintin.mudhalla.net/protocols/mtts

With the screen reader mode enabled TinTin++ will try to remove or
alter visual elements where possible.

See also: config


sessionname
-----------


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.

See also: suspend


speedwalk
---------


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

See also: keypad mapping repeat


statements
----------


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}

See also: mathematics pcre repeat


substitutions
-------------


 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 sent 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.

See also: characters colors escape_codes pcre


suspend
-------


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.

See also: sessionname


time
----


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)

See also: echo event format


triggers
--------


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 or substitution contains the \\n sequence it will be
turned into a multi-line trigger. A multi-line trigger 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 the following event:

#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 triggers trigger before regular triggers. 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 triggers 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.

See also: pcre substitutions escape_codes


Events
======


Events allow you to create triggers for predetermined client events.
Use ``#event {EVENT NAME} {commands}`` to register an event handler.
Use ``#event`` without arguments to see all available events.
Use ``#info events on`` to watch events fire in real time.

Events are case sensitive and must be defined in ALL UPPER CASE.
Only one handler can be defined per event type.

Detailed event documentation
----------------------------

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

FORMAT EVENTS

REFORMAT <MESSAGE>     Use #return to change MESSAGE

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

EDIT RESUMED, EDIT SUSPENDED
  %0 name

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, MAP FOLLOW GLOBAL
  %0 old vnum  %1 new vnum  %2 exit name

MAP REGION <MOUSE>, MAP ROOM <MOUSE>
  %0 row  %1 col  %2 -row  %3 -col  %4 vnum  %5 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.

PROCESSED LINE         %0 raw text %1 plain text %2 prompt (0 or 1)

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           %0 raw text  %1 plain text
CHAT SNOOP REQUEST     %0 name %1 ip %2 port

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 MESSAGE           %0 raw text %1 plain text
PORT RECEIVED MESSAGE  %0 name %1 ip %2 port %3 data %4 plain data
PORT RECEIVED DATA     %0 name %1 ip %2 port %3 data %4 size

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

CONFIG                 %0 name %1 value

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

RECEIVED ERROR         %0 message
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.


Event list by category
----------------------

CATCH events
~~~~~~~~~~~~


``CATCH`` -- prefix for catch events


CLASS events
~~~~~~~~~~~~


``CLASS ACTIVATED`` -- class activations

``CLASS CREATED`` -- class creation

``CLASS DEACTIVATED`` -- class deactivations

``CLASS DESTROYED`` -- class destruction


GAG events
~~~~~~~~~~


``GAG`` -- prefix for gag events


INPUT events
~~~~~~~~~~~~


``EDIT FINISHED`` -- when editing is finished

``EDIT RESUMED`` -- when editing is resumed

``EDIT STARTED`` -- when editing is started

``EDIT SUSPENDED`` -- when editing is suspended

``HISTORY UPDATE`` -- command history update

``MODIFIED INPUT`` -- input line was modified

``NO SESSION ACTIVE`` -- input on startup session

``PROCESSED KEYPRESS`` -- after a regular keypress

``RECEIVED INPUT`` -- keyboard input is received

``RECEIVED INPUT CHARACTER`` -- keyboard input character

``RECEIVED KEYPRESS`` -- a keypress is received

``SEND OUTPUT`` -- before sending output

``SENT OUTPUT`` -- after sending output


MAP events
~~~~~~~~~~


``END OF PATH`` -- walking the last room

``END OF RUN`` -- running the last room

``MAP CREATE EXIT`` -- an exit is created

``MAP CREATE ROOM`` -- a room is created

``MAP DELETE EXIT`` -- an exit is deleted

``MAP DELETE ROOM`` -- a room is deleted

``MAP ENTER MAP`` -- entering the map

``MAP ENTER ROOM`` -- entering a map room

``MAP EXIT MAP`` -- exiting the map

``MAP EXIT ROOM`` -- exiting a map room

``MAP FOLLOW GLOBAL`` -- global move to a map room

``MAP FOLLOW MAP`` -- moving to a map room

``MAP UPDATED VTMAP`` -- vt map update


MOUSE events
~~~~~~~~~~~~


``DOUBLE-CLICKED`` -- mouse is double-clicked

``LONG-CLICKED`` -- mouse is long-clicked

``MAP DOUBLE-CLICKED`` -- vt map click

``MAP LOCATION`` -- vt map click

``MAP LONG-CLICKED`` -- vt map click

``MAP MOUSE LOCATION`` -- called by #screen raise

``MAP MOVED`` -- vt map mouse move

``MAP PRESSED`` -- vt map click

``MAP REGION`` -- vt map mouse events

``MAP RELEASED`` -- vt map click

``MAP ROOM`` -- vt map room mouse events

``MAP SCROLLED`` -- vt map scroll

``MAP SHORT-CLICKED`` -- vt map click

``MAP TRIPLE-CLICKED`` -- vt map click

``MOVED`` -- mouse is moved

``PRESSED`` -- mouse button is pressed

``RELEASED`` -- mouse button is released

``SCREEN MOUSE LOCATION`` -- called by #screen raise

``SCROLLED`` -- mouse wheel is scrolled

``SHORT-CLICKED`` -- mouse is short-clicked

``SWIPED`` -- mouse swipe

``TRIPLE-CLICKED`` -- mouse is triple-clicked


OUTPUT events
~~~~~~~~~~~~~


``PACKET PATCH`` -- broken packet detected

``PROCESSED LINE`` -- after triggers have fired

``RECEIVED LINE`` -- a new line is received

``RECEIVED OUTPUT`` -- bulk output is received

``RECEIVED PROMPT`` -- a prompt is received


PORT events
~~~~~~~~~~~


``CHAT MESSAGE`` -- any chat related message

``PORT CONNECTION`` -- socket connects

``PORT DISCONNECTION`` -- socket disconnects

``PORT INITIALIZED`` -- port is initialized

``PORT LOG MESSAGE`` -- local port log messages

``PORT MESSAGE`` -- local port messages

``PORT RECEIVED DATA`` -- bulk data is received

``PORT RECEIVED MESSAGE`` -- line data is received

``PORT UNINITIALIZED`` -- port is uninitialized


REFORMAT events
~~~~~~~~~~~~~~~


``REFORMAT`` -- system format message


SCAN events
~~~~~~~~~~~


``SCAN CSV HEADER`` -- scanning a csv file

``SCAN CSV LINE`` -- scanning a csv file

``SCAN TSV HEADER`` -- scanning a tsv file

``SCAN TSV LINE`` -- scanning a tsv file


SCREEN events
~~~~~~~~~~~~~


``SCREEN DESKTOP DIMENSIONS`` -- called by #screen raise

``SCREEN DESKTOP SIZE`` -- called by #screen raise

``SCREEN DIMENSIONS`` -- called by #screen raise

``SCREEN FILL`` -- split bars are filled

``SCREEN FOCUS`` -- focus changes

``SCREEN LOCATION`` -- called by #screen raise

``SCREEN MINIMIZED`` -- called by #screen raise

``SCREEN REFRESH`` -- the screen is refreshed

``SCREEN RESIZE`` -- the screen is resized

``SCREEN ROTATE LANDSCAPE`` -- the screen is rotated

``SCREEN ROTATE PORTRAIT`` -- the screen is rotated

``SCREEN SIZE`` -- called by #screen raise

``SCREEN SPLIT`` -- the screen is split

``SCREEN SPLIT FILL`` -- split region is filled

``SCREEN UNSPLIT`` -- the screen is unsplit

``SCROLLBAR MOVE`` -- scrollbar movement

``SCROLLBAR POSITION`` -- scrollbar position


SESSION events
~~~~~~~~~~~~~~


``SESSION ACTIVATED`` -- a session is activated

``SESSION CONNECTED`` -- a new session connects

``SESSION CREATED`` -- a new session is created

``SESSION DEACTIVATED`` -- a session is deactivated

``SESSION DESTROYED`` -- a session is destroyed

``SESSION DISCONNECTED`` -- a session disconnects

``SESSION TIMED OUT`` -- a session doesn't connect


SYSTEM events
~~~~~~~~~~~~~


``CONFIG`` -- config change

``DAEMON ATTACH TIMEOUT`` -- daemon attachment timeout

``DAEMON ATTACHED`` -- daemon attachment

``DAEMON DETACHED`` -- daemon detachment

``PROGRAM START`` -- main session starts

``PROGRAM TERMINATION`` -- main session exits

``READ ERROR`` -- the read command fails

``READ FILE`` -- the read command finished

``RECEIVED ERROR`` -- an error is received

``SIGHUB`` -- Terminal has closed

``SIGUSR`` -- Raised SIGUSR1 or SIGUSR2

``SYSTEM CRASH`` -- system crash

``SYSTEM ERROR`` -- system errors

``UNKNOWN COMMAND`` -- unknown tintin command

``WRITE ERROR`` -- the write command fails


TELNET events
~~~~~~~~~~~~~


``IAC`` -- prefix for telnet events


TIME events
~~~~~~~~~~~


``DATE`` -- the given date

``DAY`` -- each day or given day

``HOUR`` -- every hour or given hour

``MINUTE`` -- minute or given minute

``MONTH`` -- month or given month

``SECOND`` -- second or given second

``TIME`` -- the given time

``WEEK`` -- each week or given week

``YEAR`` -- each year or given year


UPDATE events
~~~~~~~~~~~~~


``BUFFER UPDATE`` -- scrollback buffer update

``DISPLAY UPDATE`` -- when display is updated

``SCROLLBAR UPDATE`` -- scrollbar update


VARIABLE events
~~~~~~~~~~~~~~~


``VARIABLE UPDATE`` -- before a variable updates

``VARIABLE UPDATED`` -- after a variable updates


VT100 events
~~~~~~~~~~~~


``VT100 CPR`` -- an ESC [ 6 n call

``VT100 DA`` -- an ESC [ c call

``VT100 DECID`` -- an ESC Z call

``VT100 DSR`` -- an ESC [ 5 n call

``VT100 ENQ`` -- an \\x05 call

``VT100 SCROLL REGION`` -- vt100 scroll region change


Telnet Protocol
===============


TinTin++ has built-in telnet protocol support. This section documents
the IAC commands, telnet options, and sub-negotiation protocols.

Use ``#config debug_telnet on`` to see telnet negotiations.
Use ``#event {IAC ...}`` to intercept and handle telnet events.
Use ``#event {CATCH IAC ...}`` to override default telnet behavior.

IAC Commands
------------

Interpret As Command (IAC) byte sequences used in the telnet protocol.

.. list-table::
   :header-rows: 1
   :widths: 10 10 10 70

   * - Name
     - Dec
     - Hex
     - Description
   * - IAC
     - 255
     - 0xFF
     - Interpret As Command escape byte
   * - DONT
     - 254
     - 0xFE
     - Refuse to perform option
   * - DO
     - 253
     - 0xFD
     - Request the other side perform option
   * - WONT
     - 252
     - 0xFC
     - Refuse to perform option
   * - WILL
     - 251
     - 0xFB
     - Agree to perform option
   * - SB
     - 250
     - 0xFA
     - Sub-negotiation begin
   * - GA
     - 249
     - 0xF9
     - Go Ahead -- used for prompt marking
   * - EL
     - 248
     - 0xF8
     - Erase Line
   * - EC
     - 247
     - 0xF7
     - Erase Character
   * - AYT
     - 246
     - 0xF6
     - Are You There
   * - AO
     - 245
     - 0xF5
     - Abort Output
   * - IP
     - 244
     - 0xF4
     - Interrupt Process
   * - BREAK
     - 243
     - 0xF3
     - Break
   * - DM
     - 242
     - 0xF2
     - Data Mark
   * - NOP
     - 241
     - 0xF1
     - No Operation
   * - SE
     - 240
     - 0xF0
     - Sub-negotiation End
   * - EOR
     - 239
     - 0xEF
     - End of Record -- used for prompt marking
   * - ABORT
     - 238
     - 0xEE
     - Abort
   * - SUSP
     - 237
     - 0xED
     - Suspend
   * - EOF
     - 236
     - 0xEC
     - End of File

Telnet Options
--------------

Negotiable telnet options. Options marked Yes are supported by TinTin++.
The Announce column indicates how TinTin++ announces support (WILL or DO).

.. list-table::
   :header-rows: 1
   :widths: 8 25 12 15 40

   * - Code
     - Name
     - Supported
     - Announce
     - Notes
   * - 0
     - BINARY
     - No
     - --
     - Binary transmission
   * - 1
     - ECHO
     - Yes
     - --
     - Echo -- server-side echo control
   * - 2
     - RCP
     - No
     - --
     -
   * - 3
     - SGA
     - Yes
     - --
     - Suppress Go Ahead
   * - 4
     - NAME
     - No
     - --
     -
   * - 5
     - STATUS
     - No
     - --
     -
   * - 6
     - TIMING MARK
     - No
     - --
     -
   * - 7
     - RCTE
     - No
     - --
     -
   * - 8
     - NAOL
     - No
     - --
     -
   * - 9
     - NAOP
     - No
     - --
     -
   * - 10
     - NAORCD
     - No
     - --
     -
   * - 11
     - NAOHTS
     - No
     - --
     -
   * - 12
     - NAOHTD
     - No
     - --
     -
   * - 13
     - NAOFFD
     - No
     - --
     -
   * - 14
     - NAOVTS
     - No
     - --
     -
   * - 15
     - NAOVTD
     - No
     - --
     -
   * - 16
     - NAOLFD
     - No
     - --
     -
   * - 17
     - EXTEND ASCII
     - No
     - --
     -
   * - 18
     - LOGOUT
     - No
     - --
     -
   * - 19
     - BYTE MACRO
     - No
     - --
     -
   * - 20
     - DATA ENTRY TERML
     - No
     - --
     -
   * - 21
     - SUPDUP
     - No
     - --
     -
   * - 22
     - SUPDUP OUTPUT
     - No
     - --
     -
   * - 23
     - SEND LOCATION
     - No
     - --
     -
   * - 24
     - TERMINAL TYPE
     - Yes
     - DO
     - Terminal Type negotiation
   * - 25
     - EOR
     - Yes
     - --
     - End of Record negotiation
   * - 26
     - TACACS UID
     - No
     - --
     -
   * - 27
     - OUTPUT MARKING
     - No
     - --
     -
   * - 28
     - TTYLOC
     - No
     - --
     -
   * - 29
     - 3270 REGIME
     - No
     - --
     -
   * - 30
     - X.3 PAD
     - No
     - --
     -
   * - 31
     - NAWS
     - Yes
     - DO
     - Negotiate About Window Size
   * - 32
     - TSPEED
     - Yes
     - --
     - Terminal Speed
   * - 33
     - LFLOW
     - No
     - --
     -
   * - 34
     - LINEMODE
     - No
     - --
     -
   * - 35
     - XDISPLOC
     - No
     - --
     -
   * - 36
     - OLD-ENVIRON
     - No
     - --
     -
   * - 37
     - AUTH
     - No
     - --
     -
   * - 38
     - ENCRYPT
     - No
     - --
     -
   * - 39
     - NEW-ENVIRON
     - Yes
     - DO
     - New Environment variables
   * - 40
     - TN3270E
     - No
     - --
     -
   * - 41
     - XAUTH
     - No
     - --
     -
   * - 42
     - CHARSET
     - Yes
     - WILL
     - Character Set negotiation
   * - 43
     - RSP
     - No
     - --
     -
   * - 44
     - COM PORT
     - No
     - --
     -
   * - 45
     - SLE
     - No
     - --
     -
   * - 46
     - STARTTLS
     - No
     - --
     - Start TLS encryption
   * - 47
     - KERMIT
     - No
     - --
     -
   * - 48
     - SEND-URL
     - No
     - --
     -
   * - 49
     - FORWARD_X
     - No
     - --
     -
   * - 69
     - MSDP
     - No
     - WILL
     - Mud Server Data Protocol
   * - 70
     - MSSP
     - No
     - WILL
     - Mud Server Status Protocol
   * - 85
     - MCCP1
     - No
     - --
     - MCCP v1 (obsolete)
   * - 86
     - MCCP2
     - Yes
     - WILL
     - Mud Client Compression Protocol v2
   * - 87
     - MCCP3
     - No
     - WILL
     - Mud Client Compression Protocol v3
   * - 90
     - MSP
     - No
     - --
     - Mud Sound Protocol
   * - 91
     - MXP
     - No
     - --
     - Mud eXtension Protocol
   * - 93
     - ZMP
     - No
     - --
     - Zenith Mud Protocol (unadopted)
   * - 200
     - ATCP
     - No
     - --
     - Achaea Telnet Communication Protocol (obsolete)
   * - 201
     - GMCP
     - No
     - WILL
     - Generic Mud Communication Protocol (MSDP over GMCP)
   * - 241
     - NOP
     - No
     - --
     -

Sub-Negotiation Protocols
-------------------------

Sub-negotiation sequences are framed by IAC SB ... IAC SE.

MSDP (Mud Server Data Protocol, option 69)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sub-negotiation codes::

    MSDP_VAR          1    Variable name
    MSDP_VAL          2    Variable value
    MSDP_TABLE_OPEN   3    Start of table
    MSDP_TABLE_CLOSE  4    End of table
    MSDP_ARRAY_OPEN   5    Start of array
    MSDP_ARRAY_CLOSE  6    End of array

Sequence: ``IAC SB MSDP MSDP_VAR <name> MSDP_VAL <value> IAC SE``

TinTin++ events::

    #event {IAC SB MSDP}            %0 variable  %1 data  %2 plain data
    #event {IAC SB MSDP <VARNAME>}  %0 variable  %1 data  %2 plain data

Use ``#line msdp`` to construct MSDP telnet sequences from TinTin++ tables.

Example::

    #event {SESSION CONNECTED} {
        #send {\xFF\xFA\x45\x01LIST\x02REPORTABLE_VARIABLES\xFF\xF0\}
    }

MSSP (Mud Server Status Protocol, option 70)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sub-negotiation codes::

    MSSP_VAR    1    Variable name
    MSSP_VAL    2    Variable value

TinTin++ events::

    #event {IAC SB MSSP}    %0 variable  %1 data

GMCP (Generic Mud Communication Protocol, option 201)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GMCP transmits data as JSON-encoded strings in sub-negotiation.

TinTin++ events::

    #event {IAC SB GMCP}             %0 module    %1 data  %2 plain data
    #event {IAC SB GMCP <MODULE>}                 %1 data  %2 plain data

Example::

    #event {IAC SB GMCP char.vitals} {
        #var vitals {%1}
    }

NEW-ENVIRON (option 39)
~~~~~~~~~~~~~~~~~~~~~~~

Sub-negotiation codes::

    ENV_IS      0    IS response
    ENV_SEND    1    SEND request
    ENV_INFO    2    INFO
    ENV_VAR     0    Well-known variable
    ENV_VAL     1    Variable value
    ENV_ESC     2    Escape (not implemented in tintin)
    ENV_USR     3    User-defined variable

TinTin++ events::

    #event {IAC SB NEW-ENVIRON}    %0 variable  %1 data  %2 plain data

CHARSET (option 42)
~~~~~~~~~~~~~~~~~~~

Sub-negotiation codes::

    CHARSET_REQUEST    1
    CHARSET_ACCEPTED   2
    CHARSET_REJECTED   3

NAWS (Negotiate About Window Size, option 31)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sends window dimensions as::

    IAC SB NAWS <width-hi> <width-lo> <height-hi> <height-lo> IAC SE

TinTin++ events::

    #event {CATCH IAC DO NAWS}    Override NAWS response

Example -- force 80 columns::

    #event {CATCH IAC DO NAWS} {
        #screen get rows ROWS;
        #format ROWS %a $ROWS;
        #send {\xFF\xFB\x1F\xFF\xFA\x1F\x50\x00${ROWS}\x00\xFF\xF0\}
    }

TTYPE (Terminal Type, option 24)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Terminal type negotiation. TinTin++ responds with terminal type on request.
Announced with DO (client requests server to send).

MCCP2 / MCCP3 (options 86, 87)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Mud Client Compression Protocol. MCCP2 uses zlib compression on the data
stream. MCCP3 is negotiated but less widely supported.

Use ``#config mccp on/off`` to enable/disable compression support.

MXP (Mud eXtension Protocol, option 91)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Example -- basic MXP link handling::

    #event {IAC DO MXP} {
        #send {\xFF\xFB\x5B\}
    }

Format Codes
============


Used with ``#format`` and ``#echo``. Similar to C's sprintf with extensions.

Syntax: ``#format {variable} {format-string} {arg1} {arg2} ...``

Within aliases/actions, escape %1 as %+1s or %%1s or %\\1s.
Maximum 30 arguments.

.. list-table::
   :header-rows: 1
   :widths: 10 15 75

   * - Code
     - Argument
     - Description
   * - ``%s``
     - string
     - Print a string
   * - ``%d``
     - number
     - Print with integer formatting
   * - ``%f``
     - number
     - Floating point math
   * - ``%a``
     - number
     - Print corresponding charset character
   * - ``%c``
     - string
     - Use a highlight color name
   * - ``%g``
     - number
     - Thousand grouping (e.g. 1,000,000)
   * - ``%h``
     - string
     - Turn text into a header line
   * - ``%l``
     - string
     - Lowercase text
   * - ``%m``
     - string
     - Perform mathematical calculation
   * - ``%n``
     - name
     - Capitalize the first letter
   * - ``%p``
     - string
     - Strip leading and trailing spaces
   * - ``%r``
     - string
     - Reverse text (hiya -> ayih)
   * - ``%t``
     - format
     - Display time with strftime format. Optional {{format}{time}} syntax
   * - ``%u``
     - string
     - Uppercase text
   * - ``%w``
     - string
     - Word wrap text into a list. Optional {{string}{width}} syntax
   * - ``%x``
     - hex
     - Print corresponding charset character from hex
   * - ``%A``
     - char
     - Store the numeric value of a character
   * - ``%b``
     - number
     - Convert number to given base (base in width specifier)
   * - ``%B``
     - string
     - Convert base string back to number (base in width specifier)
   * - ``%C``
     - (empty or col)
     - Screen columns, or column index of argument
   * - ``%D``
     - hex
     - Convert hexadecimal to decimal
   * - ``%G``
     - number
     - Thousand grouping (same as %g)
   * - ``%H``
     - string
     - Generate a 64-bit hash of the string
   * - ``%L``
     - string
     - String length (visual, not bytes)
   * - ``%M``
     - number
     - Convert number to metric notation
   * - ``%R``
     - (empty or row)
     - Screen rows, or row index of argument
   * - ``%S``
     - string
     - Count spelling errors in string
   * - ``%T``
     - (empty)
     - Current epoch time (seconds since 1970)
   * - ``%U``
     - (empty)
     - Current micro epoch time (microseconds)
   * - ``%X``
     - decimal
     - Convert decimal to hexadecimal
   * - ``%z``
     - number
     - Convert number to given base (variant, base in width specifier)
   * - ``%Z``
     - string
     - Convert base string back to number (variant)
   * - ``%%``
     -
     - Literal % character

Width and precision specifiers work like C printf::

    #format {test} {%+9s} {string}   -- pad with up to 9 spaces
    #format {test} {%-9s} {string}   -- right-pad with up to 9 spaces
    #format {test} {%.8s} {string}   -- copy at most 8 characters


Configuration
=============


Use ``#config {option} {value}`` to change settings.
Use ``#config`` without arguments to see current settings.
Settings can be saved with ``#write``.

.. list-table::
   :header-rows: 1
   :widths: 20 40 40

   * - Option
     - ON / Description
     - OFF / Description
   * - AUTO TAB
     - Buffer lines used for tab completion
     - --
   * - BUFFER SIZE
     - The size of the scrollback buffer
     - --
   * - CHARSET
     - The character set encoding used
     - --
   * - CHILD LOCK
     - TinTin++ is child locked.
     - TinTin++ is not child locked.
   * - COLOR MODE
     - The color code encoding used
     - --
   * - COLOR PATCH
     - Color the start of each line
     - Leave color handling up to the server
   * - COMMAND COLOR
     - The color of echoed commands
     - --
   * - COMMAND ECHO
     - Commands are echoed in split mode
     - Commands are not echoed in split mode
   * - COMPACT
     - Remove blank prompt lines
     - Do not remove blank prompt lines
   * - CONNECT RETRY
     - Seconds sessions try to connect on failure
     - --
   * - CONVERT META
     - TinTin++ converts meta characters
     - TinTin++ doesn't convert meta characters
   * - DEBUG TELNET
     - You see telnet negotiations
     - You do not see telnet negotatiations
   * - HIBERNATE
     - Go into low CPU usage mode
     - --
   * - HISTORY SIZE
     - The size of the command history
     - --
   * - INHERITANCE
     - The startup session is inherited
     - The startup session is not inherited
   * - LOG MODE
     - The data type mode of log files
     - --
   * - LOG LEVEL
     - TinTin++ only logs low level server data
     - TinTin++ only logs high level server data
   * - MCCP
     - MCCP is enabled.
     - MCCP is disabled.
   * - MOUSE
     - Generate mouse tracking events.
     - Do not generate mouse events.
   * - PACKET PATCH
     - Seconds to try to patch broken packets
     - --
   * - RANDOM SEED
     - Seed value used for random numbers
     - --
   * - REPEAT CHAR
     - Character used for repeating commands
     - --
   * - REPEAT ENTER
     - You send the last command on an enter
     - You send a carriage return on an enter
   * - SCREEN READER
     - You are using a screen reader
     - You are not using a screen reader
   * - SCROLL LOCK
     - You do not see server output while scrolling
     - You see server output while scrolling
   * - SPEEDWALK
     - Your input is scanned for speedwalks
     - Your input is not scanned for speedwalks
   * - TAB WIDTH
     - Number of spaces used for a tab
     - --
   * - TELNET
     - TELNET support is enabled.
     - TELNET support is disabled.
   * - TINTIN CHAR
     - Character used for TinTin++ commands
     - --
   * - VERBATIM
     - Keyboard input is send as is
     - Keyboard input is parsed by TinTin++
   * - VERBATIM CHAR
     - Character used for verbatim lines
     - --
   * - VERBOSE
     - Read script files verbosely
     - Read script files quietly
   * - WORDWRAP
     - Server output is word wrapped
     - Server output is line wrapped


Character Sets
==============


Use ``#config charset <name>`` to set the character encoding.

.. list-table::
   :header-rows: 1
   :widths: 20 20 60

   * - Name
     - Encoding
     - Description
   * - ASCII
     - iso-8859-1
     - ASCII
   * - UTF-8
     - utf-8
     - UTF-8
   * - BIG5
     - big5
     - BIG5
   * - BIG-5
     - big5
     - BIG5 (alias)
   * - CP949
     - cp949
     - CP949
   * - EUC-KR
     - cp949
     - CP949 (alias)
   * - GBK-1
     - gb18030
     - GB18030
   * - GB18030
     - gb18030
     - GB18030 (alias)
   * - BIG5TOUTF8
     - utf-8
     - Convert BIG5 to UTF-8
   * - CP437TOUTF8
     - utf-8
     - Convert CP437 to UTF-8
   * - FANSITOUTF8
     - utf-8
     - Convert CP437 to UTF-8 (fansite alias)
   * - CP1251TOUTF8
     - utf-8
     - Convert CP1251 to UTF-8
   * - CP949TOUTF8
     - utf-8
     - Convert CP949 to UTF-8
   * - EUCKRTOUTF8
     - utf-8
     - Convert EUC-KR/CP949 to UTF-8
   * - GBK1TOUTF8
     - utf-8
     - Convert GBK1/GB18030 to UTF-8
   * - ISO1TOUTF8
     - utf-8
     - Convert ISO-8859-1 to UTF-8
   * - ISO2TOUTF8
     - utf-8
     - Convert ISO-8859-2 to UTF-8
   * - KOI8TOUTF8
     - utf-8
     - Convert KOI8-R to UTF-8


List Types
==========


TinTin++ organizes triggers and data into typed lists.
Use ``#info`` to inspect lists, ``#kill`` to clear them, ``#ignore`` to disable.

**ACTION** -- Pattern-triggered responses to server output

**ALIAS** -- Command shortcuts and expansions

**BUTTON** -- Mouse click handlers for screen regions

**CLASS** -- Named groups of triggers for organization

**COMMAND** -- Internal command list

**CONFIG** -- Configuration settings

**DELAY** -- Timed delayed commands

**EVENT** -- Handlers for client events

**FUNCTION** -- Named functions callable with @name{}

**GAG** -- Patterns to suppress from display

**HIGHLIGHT** -- Color highlighting patterns

**HISTORY** -- Command history

**LANDMARK** -- Map landmarks

**MACRO** -- Key binding handlers

**PATH** -- Path recording and playback

**PATHDIR** -- Path direction mappings

**PROMPT** -- Prompt capture patterns

**SUBSTITUTE** -- Text replacement patterns

**TAB** -- Tab completion entries

**TERRAIN** -- Map terrain types

**TICKER** -- Repeating timed commands

**VARIABLE** -- User variables and data


Substitution Types
==================


Used with ``#line substitute <type> <argument>`` to control text processing.

**ARGUMENTS** -- Substitute %0-%99 argument variables

**BRACES** -- Process brace expressions

**COLORS** -- Process color codes

**EOL** -- Process end-of-line handling

**ESCAPES** -- Process escape sequences (\n, \e, etc)

**FUNCTIONS** -- Substitute @function{} calls

**LITERAL** -- Literal mode

**LNF** -- Line feed handling

**SECURE** -- Secure mode

**VARIABLES** -- Substitute $variable references


Examples and Recipes
====================


Example scripts from the TinTin++ SCRIPTS file.

::

    #nop -------------------------------------------------------------------------
    #nop Learn by example
    #nop -------------------------------------------------------------------------

    #nop -------------------------------------------------------------------------
    #nop Loop through room 1 to 1000 and change the color of rooms with the
    #nop static (16) flag to <168>.
    #nop -------------------------------------------------------------------------

    #alias {color_static}
    {
    	#loop 1 1000 vnum
    	{
    		#map at $vnum
    		{
    			#map get roomflags result;
    			#if {$result & 16}
    			{
    				#map set roomcolor <168>
    			}
    		}
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Capture system information. #script stores the output as a list,
    #nop hence the need to convert it into a normal variable.
    #nop -------------------------------------------------------------------------

    #script {dir} {pwd}
    #var dir $dir[1]

    #script {home} {echo $HOME}
    #var home $home[1]

    #nop -------------------------------------------------------------------------
    #nop Automatically reconnect on disconnect.
    #nop -------------------------------------------------------------------------

    #event {SESSION CONNECTED}
    {
    	#event {SESSION DISCONNECTED}
    	{
    		#gts #delay 5 {#session %0 %1 %3}
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Execute a random social at random time intervals.
    #nop -------------------------------------------------------------------------

    #tick {randomsocial}
    {
    	#delay {1d180}
    	{
    		#switch {1d4}
    		{
    			#case {1} {cheer};
    			#case {2} {greet all};
    			#case {3} {smile};
    			#case {4} {laugh self}
    		}
    	}
    }
    {200}

    #nop -------------------------------------------------------------------------
    #nop Maintain a friendlist. %i creates a case insensitive regex.
    #nop -------------------------------------------------------------------------

    #variable {friendlist}
    {
    	{bubba};{pamela};{cookie};{harry potter}
    }

    #function isfriend
    {
    	#return &friendlist[%i%0];
    }

    #act {%1 follows you.}
    {
    	#if {@isfriend{%1}}
    	{
    		group %1
    	};
    	#else
    	{
    		unfollow %1
    	}
    }

    #alias {addfriend}
    {
    	#format name %l {%0};

    	#var friendlist[$name] {};

    	#showme $name has been added to your friendlist.
    }

    #alias {delfriend}
    {
    	#format name %l {%0};

    	#if {@isfriend{$name}}
    	{
    		#unvar friendlist[$name];
    		#showme $name has been deleted from your friendlist.
    	};
    	#else
    	{
    		#showme $name is not on your friendlist.
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Append a goto to your current room when saving a map. Alternatively, you
    #nop can use #map return.
    #nop -------------------------------------------------------------------------

    #alias {savemap}
    {
    	#map write %0;
    	#map get roomvnum room;
    	#system echo '#map goto $room' >> %0
    }

    #nop -------------------------------------------------------------------------
    #nop Log all text to a file with a timestamp with decisecond precision.
    #nop Alternatively you can use #log timestamp.
    #nop -------------------------------------------------------------------------

    #function {timestamp}
    {
    	#format utime {%U};

    	#format result {%t.%m} {%Y-%m-%d %H:%M:%S} {$utime % 1000000 / 100000}
    }

    #event {RECEIVED LINE}
    {
    	#line log mylog.txt {<178>@timestamp{} \};
    	#line log mylog.txt
    }

    #nop -------------------------------------------------------------------------
    #nop Old school tick support.
    #nop -------------------------------------------------------------------------

    #tick {oldtick}
    {
    	#delay 50 #showme #10 SECONDS TO TICK!!;
    	#showme #TICK!!!
    }
    {60}

    #alias {tickers}
    {
    	#info tickers save;

    	#echo {<128>%+20s %+20s %+20s} {Name} {Interval} {Remaining};

    	#draw Yellow scroll line 1 1 1 62;

    	#format utime %U;

    	#loop 1 &info[TICKERS][] index
    	{
    		#math uval $info[TICKERS][+$index][arg3] * 1000000;

    		#echo {%+20s %+20s %+20m}
    			{$info[TICKERS][+$index][arg1]}
    			{$info[TICKERS][+$index][arg3]}
    			{($uval - ($utime - $info[TICKERS][+$index][arg4]) % $uval) / 1000000.00}
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Execute speedwalks with .
    #nop -------------------------------------------------------------------------

    #alias {.%0}
    {
    	#var cnt {};

    	#parse {%0} {char}
    	{
    		#if {"$char" >= "0" && "$char" <= "9"}
    		{
    			#var cnt $cnt$char
    		};
    		#elseif {"$cnt" == ""}
    		{
    			#send $char
    		};
    		#else
    		{
    			#$cnt #send $char;
    			#var cnt {}
    		}
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Targetting script
    #nop -------------------------------------------------------------------------

    #var targets {}

    #alias {target}
    {
    	#if {"%0" == ""}
    	{
    		#showme {Current targets: $targets[]}
    	};
    	#elseif {&targets[%0]}
    	{
    		#unvar targets[%0];
    		#showme Target '%0' removed.
    	};
    	#else
    	{
    		#var targets[%0] {};
    		#showme Target '%0' added.
    	}
    }

    #act {%1 arrives}
    {
    	#if {&targets[%1]} {kill %1}
    }

    #act {%1 is standing here}
    {
    	#if {&targets[%1]} {kill %1}
    }

    #action {%1 is dead! R.I.P.}
    {
    	#if {&targets[%1]} {target %1}
    }

    #nop -------------------------------------------------------------------------
    #nop Show xterm 256 colors.
    #nop -------------------------------------------------------------------------

    #alias {color_table}
    {
    	#var temp {};

    	#foreach {0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15} {var1}
    	{
    		#showme {$var1 \e[38;5;${var1}m}
    	};

    	#foreach {a;b;c;d;e;f} {var1}
    	{
    		#foreach {a;b;c;d;e;f} {var2}
    		{
    			#foreach {a;b;c;d;e;f} {var3}
    			{
    				#var temp {$temp <$var1$var2$var3><<888>$var1$var2$var3>}
    			};
    			#showme $temp;
    			#var temp {}
    		}
    	};

    	#loop 0 23 cnt
    	{
    		#format temp {$temp <g%+02s><<888>g%+02s} {$cnt} {$cnt};
    	};
    	#showme $temp
    }

    #nop -------------------------------------------------------------------------
    #nop Draw a health bar. Alternatively: #draw bar -2 1 -2 20 {%1;%2;<faa><afa>}
    #nop -------------------------------------------------------------------------

    #alias {hpbar}
    {
    	#math {hp_percent}{100 * %1 / %2};
    	#math {hpbars1}   {$hp_percent / 5};
    	#math {hpbars2}   {20 - $hpbars1};

    	#format {hpbar} {<011>%+${hpbars1}s<099><000>%+${hpbars2}s<099> };

    	#showme [$hpbar]
    }

    #alias {test}
    {
    	hpbar 30 100
    }

    #nop -------------------------------------------------------------------------
    #nop Syntax: sleep <seconds to delay> {commands}
    #nop
    #nop If there is already a pending sleep the delay will be stacked.
    #nop -------------------------------------------------------------------------

    #var sleeptime 0
    #var sleepcurr 0

    #alias {sleep %1 %2}
    {
    	#format sleeptime %U;

    	#if {$sleeptime > $sleepcurr}
    	{
    		#math sleepcurr $sleeptime + (%1) * 1000000;

    		#delay {%1} %2;
    	};
    	#else
    	{
    		#math sleepcurr $sleepcurr + (%1) * 1000000;

    		#delay {($sleepcurr - $sleeptime) / 1000000.000} %2
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop This function and substitution will highlight spelling errors as red.
    #nop -------------------------------------------------------------------------

    #function spellcheck
    {
    	#format result %S %1;
    	#if {$result == 0}
    	{
    		#var result %1
    	};
    	#else
    	{
    		#var result <118>%1<900>
    	}
    }

    #substitute {{\b[a-zA-Z]+\b}} {@spellcheck{%1}}

    #nop -------------------------------------------------------------------------
    #nop This function and substitution will add a speed reader to the split line
    #nop -------------------------------------------------------------------------

    #split

    #function {spellcheck}
    {
    	#format result %S %1;
    	#if {$result == 0}
    	{
    		#var result %1
    	};
    	#else
    	{
    		#var result <118>%1<900>
    	};
    	#list speedread ins -1 {$result}
    }

    #substitute {{\b[a-zA-Z]+\b}} {@spellcheck{%1}}

    #tick {speedread}
    {
    	#if {&{speedread[]}}
    	{
    		#draw tile -2 1 -2 20 {$speedread[1]};
    		#list speedread delete 1
    	}
    }
    {0.1}

    #nop -------------------------------------------------------------------------
    #nop This function tests the random number engine
    #nop -------------------------------------------------------------------------

    #alias {random}
    {
    	#var random {};
    	#loop 1 1000 cnt
    	{
    		#math tmp 1d1000000000 % 10;
    		#math random[$tmp] $random[$tmp] + 1
    	};
    	#var random
    }

    #nop -------------------------------------------------------------------------
    #nop This macro allows pasting multi-line code fragments on pressing ctrl-v.
    #nop Alternatively, use ctrl-enter after pressing ctrl-v and pasting a script.
    #nop -------------------------------------------------------------------------

    #macro {\cv}
    {
    	#cursor {convert meta} on;
    	#line oneshot #event {CATCH RECEIVED INPUT}
    	{
    		#line sub {esc} #var paste {%0};
    		#replace paste {\\n\\n} {;};
    		#replace paste {\\n} {};
    		#replace paste {\\t} {};
    		#replace paste {;;} {;};
    		#1 {$paste}
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop This event will cause tintin to always report your screen width as 80
    #nop columns
    #nop -------------------------------------------------------------------------

    #event {CATCH IAC DO NAWS}
    {
    	#screen get rows ROWS;
    	#format ROWS %a $ROWS;

    	#send {\xFF\xFB\x1F\xFF\xFA\x1F\x50\x00${ROWS}\x00\xFF\xF0\}
    }

    #nop -------------------------------------------------------------------------
    #nop Remove duplicate lines and add a counter. Does not work in gts because
    #nop it uses named delays.
    #nop -------------------------------------------------------------------------

    #var repeat[str] {}
    #var repeat[cnt] 1

    #act {~%+}
    {
    	#if {{%0} === {$repeat[str]}}
    	{
    		#math repeat[cnt] $repeat[cnt] + 1;
    		#delay {repeat} {repeat_show} {0}
    	};
    	#else
    	{
    		repeat_show;
    		#var repeat[str] {%0}
    	};
    	#line gag
    }

    #alias {repeat_show}
    {
    	#if {$repeat[cnt] <= 1}
    	{
    		#line ignore #showme {$repeat[str]}
    	};
    	#else
    	{
    		#line ignore #showme {<128>($repeat[cnt]) <088>$repeat[str]}
    	};
    	#var repeat[str] {};
    	#var repeat[cnt] 1
    }

    #nop -------------------------------------------------------------------------
    #nop These macros will allow you to move around with the arrow keys while
    #nop holding down the control key. You can move ne by pressing arrow up +
    #nop right simultaniously. Move up by pressing arrow up + down simultaniously.
    #nop Move down by pressing arrow left + right simultaniously.
    #nop -------------------------------------------------------------------------

    #macro {\e[1;5A} {#cursor macro preserve;#delay {move} {#cursor macro reset;n} {0.05}}
    #macro {\e[1;5C} {#cursor macro preserve;#delay {move} {#cursor macro reset;e} {0.05}}
    #macro {\e[1;5B} {#cursor macro preserve;#delay {move} {#cursor macro reset;s} {0.05}}
    #macro {\e[1;5D} {#cursor macro preserve;#delay {move} {#cursor macro reset;w} {0.05}}

    #macro {\e[1;5A\e[1;5A} {#undelay {move};#cursor macro reset;n;n}
    #macro {\e[1;5C\e[1;5C} {#undelay {move};#cursor macro reset;e;e}
    #macro {\e[1;5B\e[1;5B} {#undelay {move};#cursor macro reset;s;s}
    #macro {\e[1;5D\e[1;5D} {#undelay {move};#cursor macro reset;w;w}

    #macro {\e[1;5A\e[1;5B} {#undelay {move};#cursor macro reset;u}
    #macro {\e[1;5B\e[1;5A} {#undelay {move};#cursor macro reset;u}

    #macro {\e[1;5C\e[1;5D} {#undelay {move};#cursor macro reset;d}
    #macro {\e[1;5D\e[1;5C} {#undelay {move};#cursor macro reset;d}

    #macro {\e[1;5A\e[1;5C} {#undelay {move};#cursor macro reset;ne}
    #macro {\e[1;5C\e[1;5A} {#undelay {move};#cursor macro reset;ne}

    #macro {\e[1;5B\e[1;5C} {#undelay {move};#cursor macro reset;se}
    #macro {\e[1;5C\e[1;5B} {#undelay {move};#cursor macro reset;se}

    #macro {\e[1;5D\e[1;5B} {#undelay {move};#cursor macro reset;sw}
    #macro {\e[1;5B\e[1;5D} {#undelay {move};#cursor macro reset;sw}

    #macro {\e[1;5D\e[1;5A} {#undelay {move};#cursor macro reset;nw}
    #macro {\e[1;5A\e[1;5D} {#undelay {move};#cursor macro reset;nw}

    #nop -------------------------------------------------------------------------
    #nop Place tells in the top 5 lines of the screen
    #nop -------------------------------------------------------------------------

    #VARIABLE {COMMS} {}

    #ACTION {~%1 tells you %2}
    {
    	addtowin %1 tells you %2
    }

    #ACTION {~%1 chats %2}
    {
    	addtowin %1 chats %2
    }

    #ALIAS {addtowin}
    {
    	#format temp {%w} {%0};

    	#loop {1} {&temp[]} {cnt}
    	{
    		#list COMMS ins -1 {$temp[$cnt]}
    	};
    	#while {&COMMS[] > 100}
    	{
    		#list COMMS del 1
    	};
    	showwin
    }

    #ALIAS {showwin}
    {
    	#screen clear square 1 1 5 -1;

    	#list temp create $COMMS[-5..-1];

    	#loop {1} {&temp[]} {cnt}
    	{
    		#regexp {$temp[$cnt]} {^$}
    		{
    			#nop
    		};
    		#else
    		{
    			#line ignore #showme {$temp[$cnt]} {$cnt} {1}
    		}
    	}
    }

    #ALIAS {test}
    {
    	#split 5 1;
    	#showme <138>Bubba tells you 'hello';
    	#showme <158>Pamela chats 'bye';
    }

    #nop -------------------------------------------------------------------------
    #nop Display two sessions next to each other
    #nop -------------------------------------------------------------------------

    #event {SCREEN RESIZE}
    {
    	#var ROWS %0;
    	#var COLS %1;
    	#draw line 1 {$COLS / 2} -3 {$COLS / 2};

    	#left #screen scroll 1 1 -3 {$COLS / 2 - 1};
    	#right #screen scroll 1 {$COLS / 2 + 1} -3 -1;
    }

    #event {PROGRAM START}
    {
    	#screen raise SCREEN RESIZE;
    	#ses right localhost 4321;
    	#ses left localhost 4321;
    }

    #event {SESSION CREATED}
    {
    	#var name %0;
    }

    #event {SESSION ACTIVATED}
    {
    	#gts #var active %0;
    }

    #event {RECEIVED OUTPUT}
    {
    	#if {"@gts{$active}" == "$name"}
    	{
    		#return;
    	};

    	#switch {"$name"}
    	{
    		#case {"left"} {#draw Red boxed foreground buffer 1 1 -3 {$COLS / 2 - 1};};
    		#case {"right"}{#draw Red boxed foreground buffer 1 {$COLS / 2 + 1} -3 -1};
    	};
    }

    #nop -------------------------------------------------------------------------
    #nop Follow the group leader on the map.
    #nop -------------------------------------------------------------------------

    #var short_dir
    {
    	{north}{n}
    	{northeast}{ne}
    	{east}{e}
    	{southeast}{se}
    	{south}{s}
    	{southwest}{sw}
    	{west}{w}
    	{northwest}{nw}
    }

    #action {%1 walks %2.$}
    {
    	#var {follow_targets[%1]} {$short_dir[%2]}
    }

    #action {^You follow %1.$}
    {
    	#if {&follow_targets[%1]}
    	{
    		#map move $follow_targets[%1]
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Use mouse click to change the input cursor's position.
    #nop -------------------------------------------------------------------------

    #config mouse on

    #split

    #event {SHORT-CLICKED MOUSE BUTTON ONE -1}
    {
    	#cursor position %1
    }

    #nop -------------------------------------------------------------------------
    #nop Move the VT100 map from the top to the right of the screen
    #nop -------------------------------------------------------------------------

    #map create
    #map flag vtmap
    #map flag unicode
    #map goto 1

    #split 0 1 0 -80;
    #map offset 1 82 -5 -1

    #screen resize horizontal 120

    #nop -------------------------------------------------------------------------
    #nop Add clickable session tabs at the top of the screen
    #nop -------------------------------------------------------------------------

    #event {PROGRAM START}
    {
    	#split 3 1;
    	#config mouse on;
    	#var active gts;
    	session_activated gts;
    }

    #event {SESSION CREATED}
    {
    	#gts session_activated %0
    }

    #event {SESSION ACTIVATED}
    {
    	#gts session_activated %0
    }

    #alias {session_activated}
    {
    	#line sub esc #var sessions[$active] {<138>\e]68;2;TABS;#$active\a\e[4;24m$active\e[24m};
    	#var active {%0};
    	#line sub esc #var sessions[%0] {<128>\e]68;2;TABS;#nop\a\e[4;24m%0\e[24m};
    	#draw foreground Azure table 1 1 3 -1 {$sessions[%*]}
    }

    #event {PRESSED SECURE LINK TABS MOUSE BUTTON ONE}
    {
    	%4
    }


    #nop -------------------------------------------------------------------------
    #nop Add basic MXP link and color handling
    #nop -------------------------------------------------------------------------

    #config mouse on

    #event {IAC DO MXP}
    {
    	#send {\xFF\xFB\x5B\}
    }

    #function {mxp_link}
    {
    	#line sub esc #var result {\e]68;1;%1;%2\a\e[4m%3\e[24m}
    }

    #act {~\e[1z<VERSION>} {#send {\e[4z<VERSION MXP=1.0 CLIENT=TINTIN++ VERSION=2.02.04>}}
    #act {~\e[1z<SUPPORT>} {#send {\e[4z<SUPPORTS +SEND +COLOR>}}

    #sub {~\e[4z<COLOR #%1>%2\e[4z</COLOR>} {<f%1>%2<900>}

    #sub {~\e[4z<SEND HREF="%1">%2\e[4z</SEND>} {@mxp_link{MXP;%1;%2}}

    #event {PRESSED LINK MXP MOUSE BUTTON ONE}
    {
    	#send {%4}
    }

    #sub {~\e[4z{<RExits>|</RExits>|<RDesc>|</RDesc>|<PROMPT>|</PROMPT>|<RName>|</RName>}} {}

    #sub {~\e[4z<RNum %d />} {}

    #sub {&lt;} {<}
    #sub {&gt;} {>}

    #nop -------------------------------------------------------------------------
    #nop Example script for using #list indexing.
    #nop -------------------------------------------------------------------------

    #var players[1] {{name}{bubba}{age}{15}{level}{24}}
    #var players[2] {{name}{pamela}{age}{19}{level}{2}}
    #var players[3] {{name}{ronald}{age}{69}{level}{13}}
    #var players[4] {{name}{bubba}{age}{26}{level}{30}}
    #var players[5] {{name}{ronald}{age}{11}{level}{31}}

    #alias {display}
    {
    	#var out {};

    	#loop 1 &players[] cnt
    	{
    		#var out[$cnt] {$cnt;$players[+$cnt][name];$players[+$cnt][age];$players[+$cnt][level]};
    	};
    	#draw scroll grid table 1 1 2+&players[]*2 80 $out[%*]
    }

    #alias {test1}
    {
    	#list players index name;
    	#list players order;
    	display
    }

    #alias {test2}
    {
    	#list players index name;
    	#list players order;
    	#list players reverse;
    	display;
    }

    #alias {test3}
    {
    	#list players index name;
    	#list players order;
    	#list players index level;
    	#list players order;
    	display
    }

    #nop -------------------------------------------------------------------------
    #nop Example script for creating clickable menus in the scrolling region.
    #nop -------------------------------------------------------------------------

    #con mouse on

    #function link {#var result {\e]68;1;%1;%2\a\e[4m%3\e[24m}}

    #event {PRESSED LINK MENU MOUSE BUTTON ONE}
    {
    	#local {link} {%4};

    	#foreach {*link[]} {key}
    	{
    		#line {substitute} {variables;functions}
    		{
    			#var link[$key] {@link{MENU_ITEM;$link[$key];<faa>$key}}
    		}
    	};
    	#draw Azure scaled box %0+1 %1 %0+1 %1+9 $link[%*]
    }

    #event {PRESSED LINK MENU_ITEM MOUSE BUTTON ONE}
    {
    	#showme {<ffa>%4};
    	#buffer refresh
    }

    #showme {Example link: @link{MENU;{{bli}{bla}{blo}{blu}};<128>click me}}

    #nop -------------------------------------------------------------------------
    #nop This creates two input lines that can be switched between using the tab
    #nop key.
    #nop -------------------------------------------------------------------------

    #line quiet #split

    #macro {\t} {inputswitch}

    #var input[width] 1

    #alias {inputswitch}
    {
    	#cursor get {input[current]};
    	#cursor clear;
    	#cursor set {$input[buffer2]};
    	#cursor end;
    	#var input[buffer2] {$input[current]};
    	#draw Ebony tile {-1-$input[width]} 1 -2 -1 {$input[buffer2]}
    }

    #nop -------------------------------------------------------------------------
    #nop This allows for split screen scroll back, just use the mouse wheel in
    #nop the upper half of the screen.
    #nop -------------------------------------------------------------------------

    #event {PROGRAM START}
    {
    	#config mouse on;
    	#var SCROLL[MODE] 0;
    	#split 0 1;
    	#screen raise SCREEN RESIZE;
    }

    #event {SCREEN RESIZE}
    {
    	#var ROWS %0;
    	#var COLS %1;
    	#screen get SCROLL_TOP_ROW SCROLL[TOP_ROW];
    	#screen get SCROLL_TOP_COL SCROLL[TOP_COL];
    	#screen get SCROLL_BOT_ROW SCROLL[BOT_ROW];
    	#screen get SCROLL_BOT_COL SCROLL[BOT_COL];
    }

    #EVENT {SCROLLED MOUSE WHEEL UP}
    {
    	#if {$SCROLL[MODE] == 0}
    	{
    		#if {%0 < $ROWS / 2}
    		{
    			#var SCROLL[MODE] 1;
    			#var SCROLL[OLD_ROW] $SCROLL[BOT_ROW];
    			#math SCROLL[BOT_ROW] $SCROLL[OLD_ROW] / 2;
    			#var BUFFER {};
    			#screen scroll $SCROLL[TOP_ROW] $SCROLL[TOP_COL] $SCROLL[BOT_ROW] $SCROLL[BOT_COL];

    			#draw red teed line $SCROLL[BOT_ROW]+1 $SCROLL[TOP_COL] $SCROLL[BOT_ROW]+1 $SCROLL[BOT_COL];

    			#nop #screen clear square $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL];
    		};
    	};
    	#if {$SCROLL[MODE] == 1}
    	{
    		#buffer up 1
    	}
    }

    #EVENT {SCROLLED MOUSE WHEEL DOWN}
    {
    	#if {$SCROLL[MODE] == 1}
    	{
    		#if {%0 < $ROWS / 2}
    		{
    			#buffer down 1;

    			#buffer info save SCROLL[INFO];

    			#if {$SCROLL[INFO][LINE] == -1}
    			{
    				#var SCROLL[MODE] 0;
    				#var SCROLL[BOT_ROW] $SCROLL[OLD_ROW];

    				#split 0 1;
    				#buffer end;
    			}
    		}
    	}
    }

    #event {RECEIVED LINE}
    {
    	#if {$SCROLL[MODE] == 1}
    	{
    		#if {&BUFFER[] > $ROWS}
    		{
    			#list BUFFER del 1
    		};
    		#list BUFFER add {%0};

    		#draw tile $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL] $BUFFER[%*];
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop This is a script to connect to Gemstone 4.
    #nop Visit play.net/gs4, login, and hit the 'GO PLAY' button.
    #nop Select the Storm Front radio button and hit the 'GO PLAY' button.
    #nop Save the .sal file to your script directory and name it gemstone.sal.
    #nop Use the 'gemstone' alias to connect.
    #nop -------------------------------------------------------------------------

    #alias {gemstone}
    {
    	#var gemstone {};

    	#line oneshot #action {^GAMEHOST=%*} {#var gemstone[host] %%1};
    	#line oneshot #action {^GAMEPORT=%*} {#var gemstone[port] %%1};
    	#line oneshot #action {^KEY=%*} {#var gemstone[key] %%1};

    	#scan txt gemstone.sal;

    	#if {&gemstone[] != 3}
    	{
    		#showme Failed to load gemstone.sal file.;
    		#return
    	};
    	#ses gemstone $gemstone[host] $gemstone[port];
    	#send {$gemstone[key]};
    	#send {>/FE:JAVA}
    }

    #nop -------------------------------------------------------------------------
    #nop Start a dated log file in the logs directory when a session connects. See
    #nop #help time for the available date options for #format %t.
    #nop -------------------------------------------------------------------------

    #event {SESSION CONNECTED}
    {
    	#format date %t %Y-%m-%d-%H-%M;

    	#log append logs/%0_$date.log
    }

    #nop -------------------------------------------------------------------------
    #nop Sometimes an error doesn't give enough information and it's useful to
    #nop see the calling script.
    #nop -------------------------------------------------------------------------

    #event {RECEIVED ERROR}
    {
    	#echo <118>%h { TOKENIZER };
    	#info tokenizer -1;
    	#echo <118>%h
    }

    #nop -------------------------------------------------------------------------
    #nop It can be annoying to have short commands clog up the command history.
    #nop This script will remove commands shorter than 3 letters.
    #nop -------------------------------------------------------------------------

    #event {HISTORY UPDATE}
    {
    	#if {{%0} != {%+3*%*}}
    	{
    		#history delete
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Run to a room when you click it on the vtmap.
    #nop -------------------------------------------------------------------------

    #config mouse on

    #event {MAP ROOM SHORT-CLICKED MOUSE BUTTON ONE}
    {
    	#map run {%4} 0.25
    }

    #nop -------------------------------------------------------------------------
    #nop zMUD has the feature where your last command is highlighted and any input
    #nop other than enter will clear it. This scripts reproduces this behavior.
    #nop -------------------------------------------------------------------------

    #CONFIG REPEAT_ENTER ON

    #event {HISTORY UPDATE}
    {
    	#delay 0 #line ignore #showme {<aaf><FFF><788>%0<088>} {-1};
    	#var last_input {%0}
    }

    #event {PROCESSED KEYPRESS}
    {
    	#if {{%1} != {10} && {$last_input} !== {}}
    	{
    		#var last_input {};
    		#line ignore #showme {} {-1};
    		#cursor end;
    		#history insert {}
    	}
    }

    #nop -------------------------------------------------------------------------
    #nop Digitalize a spoken number, example: wton one hundred and thirty-six
    #nop -------------------------------------------------------------------------

    #alias {wton}
    {
    	#var wton {%0};
    	#replace wton {-} {};
    	#replace wton { and } {};

    	#replace wton {ninety} {+90};
    	#replace wton {eighty} {+80};
    	#replace wton {seventy} {+70};
    	#replace wton {sixty} {+60};
    	#replace wton {fifty} {+50};
    	#replace wton {forty} {+40};
    	#replace wton {thirty} {+30};
    	#replace wton {twenty} {+20};
    	#replace wton {twelve} {+12};
    	#replace wton {eleven} {+11};
    	#replace wton {teen} {+10};
    	#replace wton {ten} {+10};
    	#replace wton {nine} {+9};
    	#replace wton {eight} {+8};
    	#replace wton {eigh} {+8};
    	#replace wton {seven} {+7};
    	#replace wton {six} {+6};
    	#replace wton {five} {+5};
    	#replace wton {fif} {+5};
    	#replace wton {four} {+4};
    	#replace wton {three} {+3};
    	#replace wton {thir} {+3};
    	#replace wton {two} {+2};
    	#replace wton {one} {+1};

    	#replace wton {%S billion} {+ (&1) * 1000000000};
    	#replace wton {%S million} {+ (&1) * 1000000};
    	#replace wton {%S thousand} {+ (&1) * 1000};
    	#replace wton {%S hundred} {+ (&1) * 100};

    	#math wton $wton;

    	#line ignore #showme <118>wton %0 = $wton
    }

    #nop -------------------------------------------------------------------------
    #nop Utility aliases to save variables as json, and load json as variables.
    #nop -------------------------------------------------------------------------

    #alias {json_save}
    {
    	#if {"%1" == "" || "%2" == ""}
    	{
    		#showme Syntax: json_save <variable> <filename>;
    		#return
    	};

    	#line quiet #log remove %2;
    	#line json {%1} {#line log {%2} {&0}}
    }

    #alias {json_load}
    {
    	#if {"%1" == "" || "%2" == ""}
    	{
    		#showme Syntax: json_load <variable> <filename>;
    		#return
    	};
    	#line quiet #unvar {%2};
    	#scan json {%2} {%1}
    }

    #nop -------------------------------------------------------------------------
    #nop Example of switching to an editing window, with mouse support. Use #edit
    #nop create to start editing. After editing is finished you can use #edit save
    #nop to store the data to a variable.
    #nop -------------------------------------------------------------------------

    #config mouse on

    #event {PROGRAM START}
    {
    	#screen raise {SCREEN RESIZE}
    }

    #event {SCREEN RESIZE}
    {
    	#screen clear all;

    	#screen scroll  2 2 -10 -2;
    	#screen input  -7 2 -2 -2;

    	#draw azure rounded left right bot top side 1 1 -9 -1;
    	#draw azure rounded left right bot top side -8 1 -1 -1
    }

    #event {PRESSED INPUT MOUSE BUTTON ONE}
    {
    	#cursor position %0 %1
    }

    #event {EDIT STARTED}
    {
    	#screen inputregion 2 2 -10 -2;
    	#screen scrollregion -7 2 -2 -2
    }

    #event {CATCH EDIT FINISHED}
    {
    	#screen input  -7 2 -2 -2;
    	#screen scroll  2 2 -10 -2;
    	#showme <138>EDIT FINISHED %0. LINES: %1  SIZE: %2
    }

    #nop -------------------------------------------------------------------------
    #nop Example script for drawing health bars
    #nop -------------------------------------------------------------------------

    #split 26 0
    #screen clear top

    #alias {draw_bar}
    {
    	#math value 0;
    	#loop 1 26 cnt
    	{
    		#draw ralign tile $cnt 1 $cnt 8 <178>$value/100;
    		#draw horizontal bar $cnt 10 $cnt 20 {$value;100;%0};
    		#math value $value + 4
    	}
    }

    draw_bar <faa><afa>

    #nop -------------------------------------------------------------------------
    #nop This script uses the '#snoop <session> scroll` option to display output
    #nop to another session. Split is used to reserve the top 6 rows, and the
    #nop scroll region of the snooped session is set to the top 5 rows.
    #nop -------------------------------------------------------------------------

    #line background #port init comm 0

    #ACTION {~%1 tells you %2}
    {
    	#comm #showme {%1 tells you %2\}
    }

    #ACTION {~%1 chats %2}
    {
    	#comm #showme {%1 chats %2\}
    }

    #ALIAS {test}
    {
    	#split 6 1;
    	#screen clear top;
    	#draw green horizontal line 6 1 6 -1;

    	#comm #screen scrollregion 1 1 5 -1;
    	#snoop comm scroll;

    	#showme <138>Bubba tells you 'hello';
    	#showme <158>Pamela chats 'bye';
    	#showme <168>Bobby tells you 'bli bla blo';
    	#showme <158>Dobby chats 'blu'
    }

    #CONFIG MOUSE ON

    #BUTTON {1;1;5;-1;SCROLLED MOUSE WHEEL UP} {#comm #buffer up 1}
    #BUTTON {1;1;5;-1;SCROLLED MOUSE WHEEL DOWN} {#comm #buffer down 1}

    #nop -------------------------------------------------------------------------
    #nop Enable the kitty terminal input extensions as specified at:
    #nop   https://sw.kovidgoyal.net/kitty/keyboard-protocol/
    #nop This allows the numpad keys to be bound properly.  Tested with Kitty and
    #nop Ghostty terminals.
    #nop -------------------------------------------------------------------------

    #alias kitty_keypad
    {
    	#if {"%1" == "on"}
    	{
    		#showme {>>> enabling kitty input\e[>1u};
    		#nop Set up the numpad keys;
    		#macro {\e[57423u} {nw};
    		#macro {\e[57419u} {n};
    		#macro {\e[57421u} {ne};
    		#macro {\e[57417u} {w};
    		#macro {\e[57427u} {!};
    		#macro {\e[57418u} {e};
    		#macro {\e[57424u} {sw};
    		#macro {\e[57420u} {s};
    		#macro {\e[57422u} {se};
    		#nop Set up the line editor keys;
    		#macro {\e[97;5u} {#cursor HOME};
    		#macro {\e[98;5u} {#cursor BACKWARD};
    		#macro {\e[100;5u} {#cursor CTRL_DELETE};
    		#macro {\e[101;5u} {#cursor END};
    		#macro {\e[102;5u} {#cursor FORWARD};
    		#macro {\e[104;5u} {#cursor BACKSPACE};
    		#macro {\e[107;5u} {#cursor CLEAR_RIGHT};
    		#macro {\e[110;5u} {#cursor HISTORY_NEXT};
    		#macro {\e[112;5u} {#cursor HISTORY_PREV};
    		#macro {\e[114;5u} {#cursor HISTORY_SEARCH};
    		#macro {\e[117;5u} {#cursor CLEAR_LEFT};
    		#macro {\e[118;5u} {#cursor CONVERT_META};
    		#macro {\e[119;5u} {#cursor DELETE_WORD_LEFT};
    		#macro {\e[121;5u} {#cursor PASTE_BUFFER};
    		#macro {\e[122;5u} {#cursor SUSPEND};
    		#nop Reset the terminal state at exit;
    		#gts #event {PROGRAM TERMINATION} {#line verbose #showme >>> disabling kitty input\e[<1u}
    	};
    	#if {"%1" == "off"}
    	{
    		#showme {>>> disabling kitty input\e[<1u};
    	}
    }
