								1998-09-24
								Emil Brink

				Gentoo Command Architecture II

1. INTRODUCTION
This document describes a plausible alternative command architecture for
gentoo, the GTK+ file manager I've been poking around with somewhat
lately.


2. THE OLD ARCHITECTURE
The current command architecture is a three-tier thing; there are three
basic components used to perform actions. These are (in order of increasing
conceptual size):
	1. Built-In Commands
	2. User Commands
	3. Command Sequences
Let's have a look at each of these three kinds of components in turn:

2.1 BUILT-INS
A built-in command is a named entity that exists within gentoo, as an
always-present basic part of it. Built-ins are accessed by name; each
built-in has a unique name. Examples of built-in command names are Quit,
DirEnter, SelectRE and FileDefault. All built-in commands have names
that begin with a capital letter, and have capital initials in any sub-
sequent words. The names never contain whitespace or underscores.

2.2 USER COMMANDS
A user command is a lot more complex in appearance than is a built-in.
As their name sort of implies, user commands are defined and implemented
by the user, using external programs (such as shell commands and general
applications). A user command has a name, by which it is referenced. It
also has a definition, i.e. a string telling which external program is
to be envoked, and with which arguments. Special codes can be used inside
the definition in order to have gentoo substitute special data (such as
names of selected files, directory paths to panes, etc). There are also
a number of flags for each user command, that control various aspects
of the command's execution.

2.3 COMMAND SEQUENCES
A command sequence is a very dumb thing; it's just a list of commands,
that gentoo executes one by one in turn (or in parallel, but that is
really just a special case:). The sequence has no name. You connect a
command sequence to an action (such as a file style action or a button)
by explicitly defining the command sequence when defining the style,
button or other thing.

Once a sequence is defined, you cannot use it from somewhere else without
simply defining a duplicate of the same sequence.

The ONLY thing you can bind to an action is a command sequence; there
is no way to just put a "bare" command reference in a button.


3. PROBLEMS
There are a few problems with the present command architecture, mainly:
	1. Since most actions only need a single command, it's in-
	   convenient to first define it as a user command and THEN
	   define a short sequence containing jus the command.
	2. On the few occasions when you really want more than one
	   command in a sequence, you create something complex that
	   can't be reused. That is dumb.
	3. It's done, and needs no more twiddling to work. :^)


4. NEW ARCHITECTURE
Here is a proposed (i.e., I'm not sure I'll ever get around to imple-
menting this, but I sure want to) new architecture.

The core idea here is KISS, at least sort of. To make a complex thing
simple, it's often a good idea to see that can be removed. Try to do
that to the current way things works, and you might hit a wall directly,
since (at least to me) it seems as if everything is necessary. You
can't remove the built-ins, since they're what make gentoo tick in the
first place. Removing the user commands looks bad too, since you'll
want the ability to use external programs. And of course, you need
command sequences to allow packaging multiple commands into a unit.

If you feel like this, then I'm happy, because that means that my
original design doesn't seem all that stupid to you, after all. :)
Unfortunately, it does to me, now... Here's the new deal:

	1. Keep the built-ins, of course.
	2. Remove the user-commands (wait!)
	3. Redefine the command sequences.

Details follow.

4.1 THE BUILT-INS
Really no change here, except that I might make it possible for built-
in commands to accept general arguments, thus allowing the shortcuts
to be reimplemented as ordinary commands (e.g. "DirEnter {$HOME}"). Nice!

4.2 THE USER COMMANDS
I want to get rid of the concept of named user-commands altogether.
See below.

4.3 COMMAND SEQUENCES
The big change will be in the command sequences. Currently, a sequence
can be thought of as a comma-separated list of command names to execute
(for example: "ActivateOther,DirFromOther,DirEnter,ActivateOther,
UnselectFirst"). This is very simple, and works pretty well. It is not
very flexible, though. The proposed solution (?) I have goes like
this:
	1. Make the sequences named (makes them reusable).
	2. Free form format, with "inlined" user commands.

The latter point means that it should be possible to define a sequence
like this: "xv {fp}; UnselectFirst; xv {fp};", to take a silly example.

Note how this simply dumps the idea of named user commands, throwing
them directly into the sequence.

4.4 PROPOSED CONFIG FORMAT
Since sooner or later, any new format must be expressed as a serial
data stream in the config file, I might just as well sketch a little on
that, too.

What we have is a set of named sequences, each sequence consisting of
any number (from 1 and up) of rows. Each row has a definition string,
which might consist of just about anything, a type (I still like to keep
built-ins clearly separate from anything else), and some amount of
other, type-specific, data (for external commands, that would be the
various flags). Here's a sketch of how we might represent this in
the config (stuff in parentheses are comments):

<Commands>				(The main commands node)
  <Command>				(A command (i.e. a sequence))
    <name>show_image</name>
    <CDef>
      <CRow>
	<type>1</type>			(Type 1: external program)
	<def>"xv {fp}"</def>		(Definition; call 'xv')
	<EFlags>			(Flags for external command)
	  <general>4712</general>	(Some general flags; background etc)
	  <before>0</before>		(The classic before and after
	  <after>0</after>		 flags)
	</EFlags>
      </CRow>
      <CRow>
	<type>0</type>			(Type 0: built-in)
	<def>"UnselectFirst"</def>	(Just a call of a built-in)
      </CRow>
    </CDef>				(End of 'show_image' definition)
  </Command>
</Commands>				(End of all commands)

4.5 PROPOSED INTERNAL FORMAT
Knowing how something will look in the config is all fine and nice,
but the config file is only that - a file stored on disk. While gentoo
is running, I would like a somewhat more straight-forward storage format.

Executing commands is something done very often in gentoo, and although
I'm sure we could parse the entire config from scratch everytime and
still not think it's sluggish, I would know that it were and hate it. :)

Here's a proposed way of representing these things internally, using
a bunch of simple C structures and some of that wonderful glib glue:

typedef enum { CRTP_BUILTIN, CRTP_EXTERNAL } CRType;

typedef struct {		/* Extra info for external commands. */
	guint32	gflags;			/* General flags. */
	guint32	baflags[2];		/* Before and after flags. */
} CX_Ext;

typedef struct {		/* A command "row". */
	CRType	type;			/* The type of the row. */
	GString	*def;			/* The row definition string. */
	guint32	flags;			/* Flags common to all types. */
	union {				/* Type-specific row info. */
	CX_Ext	external;		/* Extra info for external commands. */
	} extra;
} CmdRow;

typedef struct {
	char	name[CMD_NAME_MAX];	/* Name of this command, really. */
	guint32	flags;			/* Flags for this command. */
	GList	*row;			/* List of CmdRow definition rows. */
} Command;

The defined commands will then be represented in memory as a bunch of
Command structures, hashed into a table for quick and easy access.

4.6 FEATURES
Here are some things that I find particularly neat about this way
of doing stuff, and that really make me itch to start hacking on
it:

4.6.1 Extensible
The above defines two types of command definition rows; built-ins and
externals. Of course, it would be easy to extend this to support more,
perhaps another kind of external command (such as a Guile program) or
even some other kind of internal action. Just define a CRType and hack
away.

4.6.2 Compatible
One of the most troublesome/hairy parts of command execution in the
current version of gentoo is the continuation of a command sequence,
i.e. stopping it in the middle and then continuing at a later time
(after the death of a synchronous child). The architecture described
above should be very compatible with the current way of representing
an interrupted sequence, which is just a pointer and an index. In fact,
since the individual rows of the command are in a standard GList, I can
just use g_list_nth() rather than my own (pretty complex) stuff.

4.6.3 Flags
The 'flags' field makes it possible to implement the "repeat" feature
in a much cleaner way (I won't even mention how it's done using today's
dumb sequences - just let's me say that it's UG-LY!).

4.6.4 Flexibility
Notice how a row's definition is always just a GString, rather than
being dependant on the type of the command? This makes it possible to
add arguments to built-ins in a very natural way; just type them after
the command name! I'm not 100% convinced that I want this (only ~99.9),
but I sure like leaving the door open. Built-in commands will still be
executed by just looking their name up in a hash table, of course.


5. PROBLEMS
The single biggest "problem" with all of the above is that it is more
or less a full rewrite of large parts of gentoo. But then again, this
feels a whole lot more like the Right Way of implementing the commands
than does the old stuff...


6. UPDATE!
After writing the above, which kind'a served like a planning session,
I tore out the entire old command subsystem and rewrote it as described
here. It was a 3,000+ line rewrite. Now it just plain rules!
