From the NannyMUD documentation

LAST CHANGE

2000-12-16

TOPIC

NAME

        basic_shell - A basic shell tool for mortals.

DESCRIPTION

	The basic shell provides the following:

	* aliases
	* nicknames
	* variables
	* automatic execution of command sequences
	* history list, including recalling of commands
	* page breaking of command output

	All defines mentioned herein can be found in the file
	.

	ALIASES
	The shell stores all aliases, up to MAX_ALIASES, in the mapping
	'alias'.  Aliases can contain the special characters %1 to %9, and
	%*. These will be replaced with argument 1-9 and all arguments,
	respectively. They can be used in any order and an arbitrary number
	of times. The $ char can be changed to whatever is preferred by
	changing ALIAS_ARG_MARKER.

	+ Aliases are added like this: "alias x exa".
	+ They are listed by simply typing "alias".
	+ Typing "alias foo" show what the alias "foo" is set to.
	+ Finally, "unalias foo" removes the alias "foo".

	The aliases are handled by the internal function 'apply_alias()'.
	Recursive or chained aliases are allowed, to a max nesting depth of
	MAX_RECURSION.

	NICKNAMES
	The shell stores all nicknames, up to MAX_NICKNAMES, in the mapping
	'nickname'.  Nickname substitution is only done on arguments, not
	query_verb().  All nickname processing is done in the function
	'apply_nickname()'.  Recursive or chained nicknames are allowed, just
	as for aliases.  Adding, listing and removing nicknames work as for
	aliases above, with the commands "nickname" and "unnickname".


	VARIABLES
	The shell stores all variables, up to MAX_VARIABLES, in the mapping
	'variable'.  Variables work like a special kind of nickname, and are
	only evalutated when a player uses the "com" (can be changed by
	altering the defined CMD_COMMAND) command. Example:

	"set target orc" followed by "alias kk com kill $target",
	will expand "kk" to "kill orc".
	All variable processing is done in the function 'evaluate()'. 
	The "$" character can be changed to whatever is preferred by changing

	CMD_VARIABLE_MARKER.
	Adding, listing and removing variables work as for aliases above,
	with the commands "variable" and "unvariable".


	AUTOMATIC EXECUTION OF COMMANDS
	The shell offers the commands "do", "dotimes" and "walk". The first
	two use the internal variable 'cmd_stack', which is a stack of queues
	of commands to be executed. Thus, nestled usage is allowed of these
	commands. The commands are executed in 'heart_beat()'. The number of
	commands that should be executed per hb can be changed by changing
	MAX_CMDS_PER_HB, currently set to 2.  The commands are executed until
	'cmd_stack' is empty.

	"walk" works slightly differently, since it allows a player to walk
	in a given direction until finding a word in the long description of
	a room.  All walking functionality is handled in the function
	'check_walk()', which is called from do_cmd(). It uses two separate
	variables, 'walk_dir_stack' and 'walk_to_stack', both arrays of
	strings. If 'check_walk()' discovers the player is walking in some
	direction, the topmost element of 'walk_dir_stack' is pushed onto the
	generic 'cmd_stack', to be executed in 'heart_beat()'.

	To control execution, the commands "break", "wait" and "cont" exist.
	"break" will halt execution. "break" twice in a row will clear the
	command stack completely, removing all suspended and not yet executed
	commands.  If not cleared, execution can later be resumed with the
	"cont" command.  The "wait" command suspends automatic executions for
	n nr of seconds.  The resumed commands will be executed from the top
	of the command stack.

	All these commands can be changed by changing the defines CMD_DO,
	CMD_DOTIMES, CMD_WALK, CMD_BREAK, CMD_WAIT, CMD_CONTINUE.

	The starting and stopping of automatic command execution is handled
	by the private functions start() and stop().


	HISTORY
	A history list of the last MAX_HISTORY_LEN commands is kept. It is
	normally updated whenever a player types a command, but on occasions
	when another object's add_action has gained precedence over the
	shell's, it might cease working until the slow_beat_hook moves the
	shell back on top of the player's inventory again.

	The data structure used is a circular array 'history', with two
	associated variables; 'history_ptr' which points one step ahead of
	the last command saved in the list, and 'history_nr', which keeps
	track of the total number of commands saved in the history list.

	The command "history" will display a list of the MAX_HISTORY_LEN last
	commands.
	& will recall command nr .
	"last " will repeat the  last commands,
	using the automatic command functionality described above.

	These commands can be modified by changing the defines CMD_HISTORY
	and HISTORY_CHAR.

	PAGEBREAKING OF COMMAND OUTPUT
	The shell uses a shadow, whose location is given by PAGE_SHADOW, to
	buffer catch_tell to the player for one command. The shell then uses
	its own version of simplemore, 'shell_simplemore()' and
	'shell_flush()', to pagebreak the output to the player. The reason
	for this is to avoid conflicts with other commands that already use
	the simplemore inherent in the player object, such as the "who"
	command. The buffered output is temporarily stored in the
	'page_string' variable.

	OTHER FUNCTIONALITY
	Command overriding: Preceding a command by "\", for example typing
	"\out", will disable all shell parsing (aliases and nicknames, and it
	will not be added to the history list) for that command only. Modify
	by changing BYPASS_CHAR.

	Time command: "Time" shows the NannyMUD host computer's time, and
	Nanny game time (tm).  Modify by changing CMD_TIME.

	Automatic execution of a command for everyone in the room: "many
	" executes  once per living object in the room,
	appending the objects real_name/name/short to the 
	string. Example: "many smile" in a room with an orc and a dwarf will
	cause the player to do "smile orc" and "smile dwarf".  Modify by
	changing CMD_AUTO.

	.login alias: When 'restore()' is called in the shell (normally only
	at login), a call_out() of 2+random(5) seconds is made to the
	function 'login_alias()', which will execute the alias named
	".login", if it exists.

	FUNCTIONS
	Normally you should not need to patch this object. These functions
	are public, ie, can be called from the outside, mostly for debugging
	purposes:

	void show_info()
	Prints a nicely formatted list of aliases, nicknames, variables and
	if the automatic command execution is running or not.

	mapping query_alias()
	Returns a copy of the 'alias' mapping.

	mapping query_nickname()
	Returns a copy of the 'nickname' mapping.

	mapping query_variable()
	Returns a copy of the 'variable' mapping.

	string *query_history()
	Returns a copy of the 'history' array.

	string *query_walk_dir_stack()
	Returns a copy of the 'walk_dir_stack' array.
	
	string *query_walk_to_stack()
	Returns a copy of the 'walk_to_stack' array.
	
	object query_owner()
	Returns the variable 'owner', the owner of the shell. Should always
	be the same as the shell's environment.

	int query_history_nr()
	Returns the total number of commands that have been saved in the
	'history' list.

	int query_history_ptr()
	Returns the pointer to the current position in the 'history' array.

	void save()
	Saves the non-static shell variables, ie 'alias' and 'nickname' in
	SAVE_DIR.

	varargs void restore(object who)
	Restores the non-static shell variables, ie 'alias' and 'nickname'
	from SAVE_DIR. If no argument is given, the 'owner' variable is
	used.


	INTERNALS
	All commands are handled by the function 'parse()'. They are switched
	to the appropriate function. All shell commands can be redefined in
	shell.h.  'parse()' also handles adding commands to the history list.

	NOTE: If you inherit this shell for the purpose of adding new
	commands, you must override the 'parse()' function.

	The central functions are:

	private int execute(string cmd_string)
	Does command(cmd_string, owner), and moves the shell to the top of the
	owner's inventory afterwards. Returns the result from command().

	protected mixed apply_alias(string cmd, string arg)
	Takes 'cmd' and 'arg' as the player typed in, and performs alias
	substitution. If no substitution was made, 0 is returned, otherwise
	the new command string is returned. Called by 'parse()'.

	protected mixed apply_nickname(string arg)
	Takes a string 'arg' as the player typed in, and performs nickname
	substitution. If no substitution was made, 0 is returned, otherwise
	the substituted string is returned. Called by 'parse()'. Note that
	nicknames are substituted before aliases.

	private status evaluate(string arg)
	Takes the arguments to the "cmd" command, and performs alias,
	nickname and variable substitution (in this order). Then calls
	'execute()' to perform the command. Returns 1 unless arg is 0. 

	private void check_walk()
	Checks if the player is walking using the "walk" command, if the
	destination is reached, if it is not possible to continue in the given
	direction, and if so, pops the direction and looked-for word from
	'walk_dir_stack' and 'walk_to_stack' respectively. Otherwise, it
	pushes the walking direction on top of the 'cmd_stack'.

	public void heart_beat()
	Calls 'check_walk()' to see if any walk dirs gets pushed on the
	generic 'cmd_stack'. Then calls 'execute()' on commands from the
	'cmd_stack', and removes them afterwards. Turns itself off if
	the 'cmd_stack' is empty.