The Offsider framework is implemented as a collection of executables, which together provide a novel and powerful paradigm for building systems, from simple to extremely complex.
The framework allows the programmer to build systems which respond as though they were objects. Such a system is called an offsider. In fact, an offsider is an object, and you interact with it by sending it messages.
The framework contains a single high-level executable, offsider, which provides the mechanism for sending messages to offsiders. (It can even send a message without an offsider being there to receive the message. This is how offsiders are created in the first place.)
By default, a newly created offsider will respond to a large number of methods. These are all of the methods that are provided by the framework itself. It is these methods that are documented below.
Once an offsider has been created, the programmer is free to override the methods that it responds to, or create new methods, without modifying any of the methods provided by the framework.
To understand the offsider framework, you need to understand the following concepts:
Each offsider is fully contained within a single directory within the file system. This directory is known as the base directory. This directory specifies the offsider completely and uniquely. Without it, the framework does not know where to send the message.
When we talk of an offsider's infrastructure, we are simply referring to the contents of the base directory. The infrastructure completely determines the functionality, and the state, of that offsider. (Ignoring, of course, the default functionality provided by the framework).
A named executable is a convenience provided for the programmer. It is just a wrapper for the offsider executable. It simplifies the task of sending a message to a particular offsider by providing a unique executable that will send messages to that offsider, and no other.
For example, if we have an offsider with a base directory /path/to/Foo, and it has a named executable ~/bin/foo, then the following are equivalent:
The named executable is easier to type, and easier to remember.
Normally the named executable is specified and created at the same time that the offsider is created.
For example:
Once you have a named executable, you don't ever have to know or care where the base directory is. A common way to create a new offsider is to specify only the named executable, and let the framework come up with the base directory:
Next, we describe the executable offsider, and its alias this.
offsider will send a message to an offsider.
The syntax is:
where
baseDirectory is the base directory of the offsider to receive the message.
If the baseDirectory is not specified, then offsider will look to see if the environment variable $BASEDIRECTORY has been set. If it has, then it will get the base directory from there.
If no base directory is specified at all (using either of these methods), then the message will still be sent, but it will have no target. Whether this results in an error is completely up to the method being envoked. For example, the method create does not require an offsider to receive the message, and will not generate an error. Many other methods do require an offsider to receive the message, and will generate an error.
offsider also has some debugging modes that allow you to see what methods are being called, and also to profile the execution to see where the time is being spent. Refer to the man page for more detail (man offsider).
this is just an alternative name for offsider. Nothing in the framework distinguishes between these two names. It is just that this makes more sense when used within a method definition.
Typical usage is:
which is equivalent to:
provided $BASEDIRECTORY is set. Within a method definition, it is always safe to assume that $BASEDIRECTORY is set, since the framework ensures that this has been done.
This API documentation documents methods. The method is invoked by sending a message to an offsider.
For illustration purposes, suppose we have an offsider with base directory /path/to/Foo, and named executable foo. We want to envoke a method baz with arguments a b c.
The message to be sent to the offsider is:
From the command line, we can send the message using:
or
From within a method envoked on this offsider, we can use:
In the documentation that follows, we would document the syntax for this method as follows:
syntax:
Throughout this documentation, I will talk about offsiders as though they were dynamic, active entities. So, for example I will say things like you send a message to an offsider and the offsider responds to the message.
This is an easy way to conceptualise what is happening at the high level, but it is really a false picture of what is happening behind the scenes.
In fact, the offsider is a purely passive thing. It is nothing more than a repository for data and executable code. The active component is actually the offsider framework, and in particular the offsider executable.
The offsider executable is what takes the message, parses it and takes appropriate action. It does this on behalf of the offsider, by referring to the offsider, by taking note of what executables and data are contained within the offsider. It delegates as appropriate to executables that implement the required functionality (methods) on behalf of the offsider.
Keep this in mind as you read through the documentation.
here will send a message to the current working directory, as though it were an offsider.
Syntax:
If the current working directory contains a subdirectory Here/, the message will be sent to that directory instead.
my will send a message to the user's home directory, as though it were an offsider.
Syntax:
If the user's home directory contains a subdirectory My/, the message will be sent to that directory instead.
Types were introduced in version 0.9.0 . Before that, the various types (keys, methods, attachments etc) were handled each in their own particular way by methods written specifically for that type.
The types framework is a set of methods that can be used with any type, including types created by the user.
The advantages of this new approach is that we now have a consistent generic API that works exactly the same across all types. In addition, the user can easily add new types as required.
In addition, a couple of wrapper methods (in and to), plus a new set of syntactic sugar, provides different ways of coding the actions on type members. This means you can choose the syntax that seems most intuitive and readable for any given context.
A type is a collection of data or executables stored within the offsider infrastructure. Each type is a separate collection.
Implementation detail: The type is implemented as a subdirectory of the offsider's base directory. The Type framework also provides mechanisms for placing directories and offsiders into such a collection, so the Type framework is in effect just an abstraction of normal file and directory operations.
Note especially that, unlike most application programming languages, the types are specific to each offsider. They are not defined at the framework level. (Although there are conventions that are used by the default framework. In particular methods and to a lesser extent keys play an important role in the logic of the Offsider framework.)
The full name of the type is the name of the directory that holds the collection.
For example keys is the full name of the directory that holds all the offsider's keys.
You can often refer to a collection by providing an abbreviated name, for example key and k can usually be used as names for the type with full name keys.
The name can be used provided it provides no ambiguity. In otherwords if you have types foobah and foozball, then foob is valid for foobah and fooz is valid for foozball, but foo is not valid as a type name.
A type is a collection, a member is an element of such a collection.
A member can be ordinary data, an executable, or another collection, such as a directory or an offsider.
Implementation detail: The type is implemented as a directory, and each member is just a file or directory in that directory.
An action is something that is done to a member. For example get the value, or rename it.
All of the existing methods (eg getKey, pipeToAttachment, methods) are still available, but they are deprecated. They will almost certainly not be available in version 1.0.
Some methods are now replaced by an equivalent form of syntactic sugar. For example, the message keys used to be implemented as a method. The same message is now handled by syntactic sugar, which converts the message to listType keys. The end result is the same.
Previously, methods like attachment, addChildDictionary and so on, would automatically create the appropriate subdirectory if it did not already exist. This is no longer the case. You will now need to explicitly create the appropriate type, like so:
It is possible that the standard directories attachments and offsiders (previously named subdictionaries) will be created automatically when the offsider is first created. This will be finalised before version 0.10.0 .
append and so on do not do atomic updates (unlike their deprecated equivalents). If you want an atomic update, you will need to create a temporary member, and then rename it once it is complete.
has existed in earlier versions, and has not been modified. It does not (yet) use isType to work out the full name of the type. It simply tries adding a terminal s. This will be fixed.
Create a new type.
syntax:
where fullType is the full name of the type.
Perform an action on each member of a type.
syntax:
where type is the name of the type (possibly contracted), action is an action to perform on each member and arguments are the arguments to that action.
Perform a specified action to a type member.
syntax:
where type is the (abbreviated) name of the type, action is the specified action, member is the name of the member and arguments are the arguments for the action.
NOTE: This method is merely a wrapper for the various action methods. It is provided as an alternative syntax.
Determine if an action is recognised as a valid action.
syntax:
Returns the name of the action if it is a valid action.
Look for a member amongst all types in this offsider.
syntax:
Returns a list of all types that contain the named member.
Determine if a type exists for this offsider.
syntax:
where type is an abbreviated name for a type.
Returns the full name of the type if it matches uniquely.
List all members of a type.
syntax:
where fullType is the full name of the type.
Return the path to a given type or member.
Syntax:
type is the abbreviated name of the type, and member is the name of a member
If member is not given, returns the filepath to the type otherwise returns the filepath to the member.
Unlike has, this will only check for the existence of type, not the existence of member.
Remove a type from this offsider. Also removes all the members for that type.
syntax:
where type is the full name of the type.
Rename a type for this offsider.
syntax:
where name is the full name of the type and newName is the full new name of the type.
Does nothing if the named type does not exist.
It is an error if there is already a type called newName
Perform a specified action to a type member.
Syntax:
or
where fullType is the full name of the type, type is the (contracted) name of the type, member is the name of the member, action is the specified action, arguments are the arguments for the action.
NOTE: This method is merely a wrapper for the various action methods. It is provided as an alternative syntax.
Set or get the group of a type.
Syntax:
Where fullType is the full name of the type, and group is a UNIX group who will own the type.
If group is not given, return the current group, else set the group for the type's directory.
Set or get the owner of a type.
Syntax:
Where fullType is the full name of the type, and owner is a UNIX user who will own the type.
If owner is not given, return the current owner, else set the owner.
Get or set the permission for a type.
Syntax:
Where fullType is the full name of the type, and permissions is a permission setting, as understood by UNIX chmod.
If permissions is given, set the permissions of the type directory, otherwise returns the permissions, as reported by UNIX ls -l.
List all types for this offsider.
Syntax:
Output a summary of the specified type.
Syntax:
type is the fullname of the type. If not given, the arguments default to
If the keyword contents is given, then the contents of each member is displayed after the member name, like so:
If the keyword contents+ is given, then the contents of each member is displayed, and for each line after the first, the format
is used.
If neither keyword is given, just the member names are displayed.
Each of the methods in this section implements an action which can be performed on a member of a type
Create a directory within a type.
Syntax:
where type is the (contracted) name of the type and name is the name of the new directory
Create an offsider within a type.
Syntax:
where type is the (contracted) name of the type member is the name of the member
template is an existing offsider, (either the named executable or the base directory) If specified, the new offsider will be a clone of template.
Append to the value of type member from stdin or from a file.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and file is the name of a file
If file is not given, will append from stdin.
If the member doesn't already exist, it will be created.
Set the value of type member from the contents of a file.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and file is the name of a file.
If the member doesn't already exist, it will be created.
USAGE NOTE: The positions of the membername and filename may conflict with normal usage with existing Unix cp, and other copy paradigms, especially when you consider the various syntactic possiblities provided by the Offsider type framework. Just keep in mind that it is entirely consistent with all of the rest of the Offsider Type framework.
Edit a type member using a text editor.
Syntax:
where type is the (contracted) name of the type, member is the name of the member to edit and editor is the editor to use.
By default, the editor is vi, or the value of the $EDITOR environment variable.
If the member doesn't already exist, it will probably be created by the editor.
Get the value of type member.
Syntax:
where type is the (contracted) name of the type and member is the name of the member.
If the member doesn't exist, a null string will be returned.
Get or set the group for a member of a type.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and group is a UNIX user, who is to own the member.
If group is given, then sets the group for the member, otherwise, returns the current group
Get or set the owner for a member of a type.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and owner is a UNIX user, who is to own the member.
If owner is given, then sets the owner for the member, otherwise, returns the current owner
Get or set the permissions for a member of a type.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and permission is a permission specification, as understood by UNIX chmod.
If permission is given, then sets the permission for the member, otherwise, if the member exists, returns the permissions as per UNIX ls -l.
Set the value of type member from stdin
Syntax:
where type is the (contracted) name of the type and member is the name of the member.
If the member doesn't already exist, it will be created.
Prepend to the value of type member from stdin or from a file.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and file is the name of a file.
If file is not given, will prepend from stdin.
If the member doesn't already exist, it will be created.
Remove a member.
Syntax:
where type is the (contracted) name of the type and member is the current name of the member.
Rename a member.
Syntax:
where type is the (contracted) name of the type member is the current name of the member newName is the new name for the member
WARNING: Will over-write any existing member with newName
Execute a type member, if possible.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and arguments are the arguments for the executable.
If the member doesn't exist, or is not executable, nothing happens.
Send a message to a type member.
syntax:
where type is the (contracted) name of the type, member is the name of the member and message is the message to send, and may contain blanks.
Will not send the message if the member is not a directory.
Set the value of type member.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and value is the value to set, and may contain blanks.
If the member doesn't already exist, it will be created.
Append to the value of type member from the command line arguments.
syntax:
Where type is the (contracted) name of the type, member is the name of the member, and value is the value to append to the current value. may contain blanks.
If the member doesn't already exist, it will be created.
Set the permission for a member to make it executable.
syntax:
where type is the (contracted) name of the type member is the name of the member
The permission used is a+x, as understood by UNIX chmod.
Set the value of type member from the contents of a file. Make the resulting file executable.
Syntax:
where type is the (contracted) name of the type, member is the name of the member and file is the name of a file.
If the member doesn't already exist, it will be created.
USAGE NOTE: The positions of the membername and filename may conflict with normal usage with existing Unix cp, and other copy paradigms, especially when you consider the various syntactic possiblities provided by the Offsider type framework. Just keep in mind that it is entirely consistent with all of the rest of the Offsider Type framework.
Edit a type member using a text editor. Make the resulting file executable.
Syntax:
where type is the (contracted) name of the type, member is the name of the member to edit and editor is the editor to use.
By default, the editor is vi, or the value of the $EDITOR environment variable.
If the member doesn't already exist, it will probably be created by the editor.
Set the value of type member from stdin. Make the resulting file executable.
Syntax:
where type is the (contracted) name of the type and member is the name of the member
If the member doesn't already exist, it will be created.
A variety of syntactic sugar has been implemented to go with new Type framework.
This provides a number of alternative ways to express the fact that you want to perform an action on a member of a type.
The methods documented in this section implement the syntactic sugar.
Each has the syntax:
where message is the incoming message, which is being parsed for syntactic sugar.
Each method will output a string in the form:
provided the incoming message is recognised by syntacticSugarMethod.
Normally, you would not use any of these methods explicitly. They are all called by the parseMessage method, which is envoked by the offsider executable.
Syntactic sugar for keys and attachments only
Message:
To return the value of a key or attachment:
To set the value of a key only:
Returns:
.. as appropriate
NOTE: will probably assume the member is a key, even if the key doesn't exist.
Syntactic sugar for listType
Message:
where fullType is the full name of the type.
returns
Syntactic sugar for a member and action
Message:
where member is the name of a member, action is the action to perform and args are the arguments for that action. The type is not specified.
If any type contains a member with name member, then the type will be set to be the first type that it is found in. So be careful!
returns
Syntactic sugar for a member name, where the member is a directory.
Message:
where member is the name of a member, which is a directory. The type is not specified.
If any type contains a member with name member, and the member is a directory, then the type will be set to be the first type that it is found in. So be careful!
returns
Syntactic sugar for a type.
Message:
where type is the (contracted) name of a type, member is the name of a member in that type, action is the action to perform on that member and arguments are the arguments for that action.
returns
A key is data that can be associated with an offsider. It is one way of specifying an offsider's state.
Each key has a name, and each key contains a value.
There is specific syntactic sugar to make it easier to get and set the value for a key:
Get the value for a key:
Set the value for a key:
Almost identical to the concept of a key is the concept of an attachment. See the section on attachments for more detail.
In practice you would use a key for storing data that consists of one or two lines of printable text, and an attachment for anything else.
All of the methods documented here for Keys are deprecated as of version 0.9.0. Use methods described in the section on Types instead.
Append data to a key using the contents of a named file, or stdin.
Syntax:
or
where key is the name of the key.
filename is the file from which the extra data is to be copied.
stream represents a stream, for example cat file, or some other process that can generate data for the key.
Edit a key using a text editor.
Syntax:
where name is the name of the key to edit, and editor is the editor to use.
By default, the editor is vi, or the value of the $EDITOR environment variable.
If the key doesn't already exist, it will be created.
Return the value for a key.
If the key doesn't exist, return an empty string.
Syntax:
Determine whether the offsider has a specified key.
Syntax:
If the key exists, return the full path to the key. Otherwise, return an empty string, and raise an error condition.
Return the path that a key would have whether or not it actually exists.
syntax:
where key is the name of the key.
Return a list of all the keys in the offsider.
Syntax:
Return a list of all the keys in the offsider, together with their values.
For each key, returns
Notice that this output is the same format as the syntactic sugar for setting the value of a key.
Set the value for a key from stdin.
If the key doesn't exist, create it.
syntax:
where key is the name of the key, and
stream is a process that generates the value for the key.
Remove a key.
syntax:
If the key does not exist, then an error condition is raised.
Set the value for a key.
If the key doesn't exist, creates it.
syntax:
where key is the name of the key.
value is the value for the key and can contain spaces.
A method is executable code that an offsider is capable of executing. You send a message to the offsider, the offsider responds by executing a method.
The methods documented in this section relate to listing and modifying the methods for a particular offsider.
An offsider can execute methods that belong specifically to itself, and others that are external to it, but which it can access. Unless otherwise specified, all of the methods documented in this section work on methods that are owned specifically by the offsider.
Many of these methods will return paths to executables. This is dependent on the specific implementation of the offsider framework, and is not something that would neccessarily be available in an alternative implementation. Therefore, those methods should be regarded as low-level tools that effectively break the information-hiding principle of object-oriented programming.
The offsider framework will maintain the current implementation at least until Version 2.0.
All of the methods documented here for Methods are deprecated as of version 0.9.0. Use methods described in the section on Types instead.
List all methods that this offsider responds to
usage:
If the keyword fullpath is used, then the full path to each method's executable is returned, otherwise just the method names are returned.
Hint: You can pipe the result into column to get the list formatted into columns so it is easier to view on a terminal.
Return the contents of an offsider's method.
syntax:
Where name is the name of the method.
Will only work if the method belongs specifically to the offsider. Use hasMethod to determine this.
Very useful for viewing the content of methods that are implemented as a script.
Edit a method using a text editor.
Syntax:
here name is the name of the method to edit, and editor is the editor to use.
By default, the editor is vi, or the value of the $EDITOR environment variable.
If the method doesn't already exist, it will be created.
editMethod is useful for editing methods that are implemented as scripts.
Provide a list of all methods that the offsider understands, which are not specifically owned by the offsider.
syntax:
If the keyword fullpath is used, then the full path to each method's executable is returned, otherwise just the method names are returned.
Determine if the offsider contains a specific method. (This is not the same as determining whether an offsider recognises a specific method - see isMethod in the section on messages)
Syntax:
where method is the name of the method.
If the offsider contains the method, then returns the full path to the executable. Otherwise, returns an empty string.
Create or modify an offsider method by copying a file, or stdin.
Syntax:
or
where name is the name of the method, and filename is the file from which the method executable is to be copied.
stream represents a stream, for example cat file, or some other process that can generate the contents of an executable.
The resulting method will be made executable using chmod.
Print the paths to the offsider's methods, or a given method.
Syntax:
where name is the name of a method, and is optional.
If name is given, will return the full path to that executable. Otherwise will return the path to the directory that contains all the offsider's executable methods.
NOTE: Will return a path even if the named method does not exist.
Return a list of all the methods in the offsider.
usage:
If the keyword fullpath is used, then the full path to each method's executable is returned, otherwise just the method names are returned.
Remove an offsider's method.
Syntax:
where name is the name of the method to remove.
An attachment is data that can be associated with an offsider. Functionally, an attachment is entirely equivalent to a key. The only difference is that typically the values of keys are given when producing a summary of an offsider (for example, using asText), whereas for an attachment, only the name is given.
Therefor you can use keys and attachments more or less interchangably if you don't care about presentation.
In practice you would use a key for storing data that consists of one or two lines of printable text, and an attachment for anything else.
All of the methods documented here for Attachments are deprecated as of version 0.9.0. Use methods described in the section on Types instead.
append data to an attachment using the contents of a named file, or stdin.
syntax:
or:
Create or overwrite an attachment, using the contents of a named file, or stdin.
syntax:
or
Creates the attachment atomically, meaning that there is no possibility of accessing a partially written attachment.
List the names of all attachments for this offsider
syntax:
Edit an attachment using a text editor
syntax:
By default, the editor is vi, or the value of $EDITOR.
Get the contents of an attachment
syntax:
Determine whether an attachment exists
Syntax:
Returns the name of the attachment if it exists, otherwise, returns a null string and an error condition
Remove an attachment.
syntax:
This section documents methods that are used to create an offsider.
Warning: It is likely that there will be changes to this API following a review prior to version 1.0
Create a new offsider by copying everything from this one.
The new offsider is a complete deep copy of the current one, although the metadata in the var/ subdirectory is generated from scratch.
Syntax:
where name is the name for the named executable, and baseDirectory is the base directory for the new offsider.
To specify the base directory, where no named executable is to be created, use:
If no base directory is given, one is generated.
If either the named executable or the base directory already exists, then an error is generated and nothing is created.
Returns the base directory of the newly created offsider.
Create a new offsider, and optionally a named executable.
Syntax:
To specify the base directory, where no named executable is to be created, use:
If name is specified, create a named executable with the given name, otherwise do not create a named executable. If the name contains a path, then create the named executable at that location, otherwise use a standard location (typically ~/bin).
If baseDirectory is specified, then build the offsider infrastructure there, otherwise create the offsider at a standard location (typically under ~/.offsiders).
If either the base directory, or the named executable already exists, does nothing and generates an error.
Returns the base directory of the newly created offsider.
Create a new offsider in a standard location. Also, create a named executable at a standard location.
syntax:
If you are root, the base directory is /usr/local/share/Offsider/offsiders/name otherwise it is ~/.offsiders/name
If you are root, the named executable is /usr/local/bin/name else, it is ~/bin/name
If either the base directory, or the named executable already exists, does nothing and generates an error.
Returns the base directory
Remove all trace of an offsider, including the named executable.
Syntax:
This method will definitely remove the base directory and all the infrastructure contained therein. It will remove the named executable if it was created at the same time as the offsider, and has not been moved to another location since then. If you created extra named executables manually, it will probably not be aware of them.
Create the contents of an executable which can send messages to an offsider.
The executable is a script, and the source code is written to stdout.
Syntax:
baseDirectory is the base directory for an offsider. The executable will send messages to the offsider at that base directory.
If baseDirectory is not given, it defaults to the base directory for this offsider.
Usage:
Create the contents of an executable which can send messages to a child offsider.
The executable is a script, and the source code is written to stdout.
Syntax:
relativePath is a relative path from this offsider's base directory to the base directory for the child offsider. The executable will send messages to the offsider at that base directory.
Example usage:
We have an offsider foo at /path/to/Foo. We also have an offsider at /path/to/Foo/childDictionaries/Baz. We want to create an executable for the child offsider.
Create the named executable:
Envoke a method bah on baz
From within the method bah, send a message to foo (the parent of baz):
All interaction with an offsider is by means of messages. A message is a string of text which is sent to the offsider. This is normally done by providing the message as the arguments to an executable, for example
In every case, the message is parsed by the offsider in order to determine which method needs to be run, and what arguments need to be sent to that method.
All of the methods documented in this section have something to do with the process of parsing a message and determining what action to take.
Remember, it is the object itself that parses the message, not some language engine.
[Version 0.9] Introduced a comprehensive set of new syntactic sugar to handle the new Types framework. Those methods, and the syntactic sugar they implement, are documented in the section on Types.
This method is not implemented in the framework. However, if you implement this method for an offsider, then parseMessage will run this method after other checks for syntactic sugar.
The syntax must be:
The method must return a string in the form:
where knownMethod is the name of a method known to that offsider, and arguments are the arguments to be passed to that method.
If the message is not recognised by overrideSugar then it must return an empty string, so that offsider can continue its processing.
WARNING: If you implement this method for an offsider:
Only use syntax like this knownMethod arguments, rather than the more general this message, to avoid infinite recursion. Be even more careful if isMethod has been over-ridden.
Determine whether this offsider recognises the named method.
If so, return the full path to the executable that implements the method. Otherwise, an empty string is returned.
syntax:
By default, looks for executables in the following order:
baseDirectory/methods/methodName
offsider.methodName ( as per the $PATH environment variable )
Dictionary.methodName (Deprecated. Will be removed in version 1.0)
This method can be overridden for any offsider, to change the way in which methods are found.
This method is deprecated as of version 0.9.0, and is no longer used by offsider or parseMessage.
Parse a message and convert it to a canonical form of
Specifically, looks for messages in the form:
key (which converts to) getKey key
key: value (which converts to) setKey key value
Syntax:
If the message is in the appropriate form, then returns the canonical form:
else, returns an empty string.
If getKey is implied for a key that doesn't exist, then an empty string is returned (so we can substitute messageNotImplemented or similar.)
If getKey is implied, but more arguments are supplied, an Error is raised.
It can be seen that this method has a high probability of deciding that the message is in the correct form, because it doesn't mind if the key doesn't already exist.
This method is called by parseMethod, only if the message was not already in the form method arguments (using the test isMethod method).
WARNING: If you extend or over-ride this method for an offsider:
Only use syntax like this knownMethod arguments, rather than the more general this message, to avoid infinite recursion. Be even more careful if isMethod has been over-ridden.
What to do when a message is not understood by this offsider.
The standard response (implemented here) is to do nothing.
Do not rely on this method to capture typos. There is a lot of scope for the default syntactic sugar to swallow messages, even if the message doesn't actually match anything. This is especially true of getSetSugar.
See offsider, and methods parseMessage and isMethod
What to do when an empty message is sent to an offsider.
The default action is to return the base directory for the offsider.
Note. noCommand is a deprecated name for this method.
No action is taken.
This method cannot be over-ridden. The response to this message is hard-coded into the offsider executable.
This method is not implemented in the framework. However, if you implement this method for an offsider, then parseMessage will run this method before other checks for syntactic sugar.
The syntax must be:
The method must return a string in the form:
where knownMethod is the name of a method known to that offsider, and arguments are the arguments to be passed to that method.
If the message is not recognised by overrideSugar then it must return an empty string, so that parseMessage can continue checking.
WARNING: If you implement this method for an offsider:
Only use syntax like this knownMethod arguments, rather than the more general this message, to avoid infinite recursion. Be even more careful if isMethod has been over-ridden.
Parse a message and convert it to a canonical form of
Includes the possibility of syntactic sugar.
syntax:
where message is the incoming message.
If the keyword notMethod is specified, then will not check to determine whether the first token is a method name.
returns a message in the form
NOTE: The offsider executable calls this method with the notMethod keyword specified, after it has already checked to see if the first word is a known method name. This means that you can't override parseMessage to hide the names of known methods.
WARNING: If you extend or over-ride this method for an offsider:
Only use syntax like this knownMethod arguments, rather than the more general this message, to avoid infinite recursion. Be even more careful if isMethod has been over-ridden.
This method is a special-purpose method, and is used by offsider to get a foot-hold into the operation of a particular offsider.
By default, isMethod is a wrapper to rawFind, so they have the same functionality.
rawFind cannot be overridden, any attempt to do so will fail.
An application programmer would not normally have a reason to use rawFind. Use isMethod in preference to rawFind unless you have studied the source-code to offsider in detail and understand exactly what you are doing (and why). Do not be fooled by the similarity in functionality. The two methods have very different reasons for existing.
Note. This method is absolutely critical to the correct functioning of the Offsider framework.
This method is deprecated as of version 0.9.0, and is no longer used by offsider or parseMessage.
Parse a message and convert it to a canonical form of
This is called by parseMethod, only if the message was not already in the form method arguments (as determined by isMethod method.)
Specifically, looks for syntactic sugar other than the normal key and key: value stuff.
syntax:
If the message is a recognised form of syntactic sugar, then returns a message in the form
else, returns an empty string.
The default Offsider behaviour is to do nothing. Syntactic sugar to do with getting and setting keys is handled seperately by the keySugar method.
WARNING: If you extend or over-ride this method:
Only use syntax like this knownMethod arguments, rather than the more general this message, to avoid infinite recursion. Be even more careful if isMethod has been over-ridden.
This method acts like the normal UNIX which command. It was neccessary to implement it as a method due to intractible differences in the which command across different variants of UNIX.
Syntax:
Where executable is the name of an executable.
which will search through the directories listed in the $PATH environment variable, looking for an executable named executable.
If found, it will return the full path to that executable.
If not found, it will return an empty string. (Not all versions of UNIX which do this).
Code reusage is an important concept in object oriented programming, and is often listed as one of the key strengths of the object oriented paradigm.
In an object-oriented application language, code reusage is typically (but not always!) implemented by means of classes and inheritence.
This is not really an option in the offsider framework, due to the persistent and exposed nature of the offsider's infrastructure. (It is possible to implement classes and inheritence, but they turn out to be very problematic, and create as many difficulties as they solve).
Instead, the offsider framework provides quite different ways to reuse code. They are more in line with existing Unix practices.
Basically, the methods documented in this section provide various ways to copy code into an offsider from different sources.
Warning: The methods documented in this section may well change between now and version 1.0, since we do not feel this is the best possible API for code-reusage in the offsider framework.
Copy keys, methods or other information from another offsider.
allFrom will overwrite existing files, whereas moreFrom will not.
syntax:
offsider is either the base directory of the offsider, or its named executable.
type specifies the type of information to copy, eg methods, keys, etc.
type is in fact the name of a subdirectory within the source offsider.
type defaults to methods.
if all is specified for type, will copy everything except var/.
if recursive is given as a keyword, then the copy is recursive.
Copy files from one directory to another.
syntax:
sourceDirectory contains files which are the keys to be copied.
targetDirectory is the directory that the keys are put (normally baseDirectory/keys)
copy data from a specification file into files in a specified offsider
syntax:
sourceFile contains lines in the form
(may also contain empty lines, and comment lines starting with # , both of which are ignored)
targetDirectory is the directory that the keys are put (normally baseDirectory/keys)
Copy executables from one directory to another.
syntax:
sourceDirectory is the directory that contains the methods to install
targetDirectory is the directory to install into (normally baseDirectory/methods)
Modify the offsider by copying methods and keys from another one.
Will only copy methods or keys that do not already exist. (Use allFrom if you want to overwrite existing methods or keys)
syntax:
offsider is either the base directory of an offsider, or its named executable.
Upgrade an offsider from its source directory. The offsider must be set up before-hand, by setting appropriate keys.
Syntax:
The source directory is specified in the offsider key sourceDirectory.
The upgrade is performed by the method upgradeMe
The arguments for upgradeMe is specified in the offsider key sourceUpgradeList.
Upgrade an offsider's methods and keys from information in the current directory.
Methods are taken from a subdirectory methods/
Keys are taken from a file pairs and a subdirectory keys/
syntax:
directoryList is a list of directories and keywords, the same as for method upgradeMeFrom
If not given, upgrade from pairs, keys and methods, using upgradeMeDefault.
Before copying any files, run ./pre.upgrade if it exists. After copying all files, run ./post.upgrade if it exists.
Upgrade an offsider's methods and keys from information in the current directory.
Methods are taken from a subdirectory methods/
Keys are taken from a file pairs and a subdirectory keys/
Syntax:
This method is a wrapper for the methods installMembersTo, installMemberDirTo and installMethodsTo. Refer to them for more detail.
Copy code or data from the current directory into the offsider, by listing the subdirectories to copy.
syntax:
where directoryList is a list of subdirectories and optional keywords.
For each directory in the list, the contents of that subdirectory is copied from the current directory to the offsider infrastructure.
The following keywords are also recognised:
executable - from now on, ensure that all files copied are made executable.
regular - from now on, don't force files copied to be executable (this is the default).
pairs - look for a file named pairs. Use it to create files in the keys/ directory, according to the information in that file.
This method is a wrapper for the methods installMembersTo, installMethodsTo and installMemberDirTo. Refer to them for more detail.
An offsider can have one or more children, which are themselves offsiders. These are called Child Offsiders. For historical reasons, these are also called Child Dictionaries.
Typically, you would send a message to a child offsider by sending the message through its parent.
For example, if offsider Foo has a child offsider Baz, then you would send a message to Baz by going:
Child offsiders are implemented in such a way that it is completely contained within the parent offsider's infrastructure. In addition, the parent can be moved within the filesystem, or archived using tar or similar, without breaking the parent/child relationship or the ability to send a message to the child through the parent.
NOTE: Most of the following methods will be deprecated soon. The following methods all assume that the Type is called subdictionaries. In future, this is likely to change to offsiders, and many of these methods will be deprecated for the various actions defined in the Type framework.
Create a new offsider, and implement it as a child of the current one.
Syntax:
If offsider is given, (as either a baseDirectory, or a named executable), then the child is a clone of that offsider. Otherwise the offsider is a default offsider, (effectively empty).
The new offsider infrastructure is placed within the current offsider infrastructure. This allows the current offsider to be moved or tarred without breaking any links.
List the names of all child dictionaries for this offsider.
Syntax:
Determine whether a child offsider exists
Syntax:
Returns the absolute path to the child offsider, if it exists. otherwise, returns a null string and an error condition
Assuming this is a child offsider, send a message to the parent offsider.
syntax:
WARNING: No checks are done to determine whether this truly is the child of an offsider.
This section documents various miscellaneous methods that don't fit into any other section.
Return a summary of an offsider. Includes the names and values of keys, and the names of all methods and attachments.
syntax:
If the keyword all is used, the summary will include the names of all methods that the offsider recognises, and the contents of the offsider's meta-data.
Returns the base directory as a fully resolved absolute path.
Syntax:
Provide a simple command line interface, to allow the user to send a series of messages to the offsider.
Syntax:
option list can contain any of the following, in any order:
prompt: string make string the prompt
prompt turn prompts on (this is the default, so it's not needed)
noprompt turn prompts off
echo echo each command before it is executed
noecho do not echo commands. (this is the default, so it's not needed)
Note: There does not seem to be any way to force the prompt to contain spaces.
Usage (within a shell-script):
Generate an error condition.
- prints an error message to stderr
- prints an error number to stdout
- uses the same error number as an exit code, so exits with an error code.
Syntax:
where messageKey is a string that identifies the error message, and parameters are extra parameters that are inserted into the error message, according to the specifications for that message.
Usage:
By default, prints the entire process calling tree. If no-tree is specified, the calling tree is suppressed, but the error message is still printed.
Determine whether the offsider has a particular type of member, with a particular name.
Syntax:
type is the type of member, for example key, method or attachment.
name is the name of the member.
Returns the full path to that member, if it exists. Returns an empty string if the member does not exist.
For example:
Test if the offsider has a key named foo:
Test if the offsider has a method named bah:
Note: Because of the way offsiders are implemented, you can also specify the plural form for type:
You cannot, however, specify more than one name.
Explanation: Each type is stored in a subdirectory named for that type, so for example all keys are stored in a subdirectory called keys/.
This is why the plural form is also recognised. In fact, this method first searches for a subdirectory having the same name as the type argument, and if it doesn't find it, it adds a terminal s to the type argument and searches for a subdirectory with that name.
This method is an attempt to replace the various methods hasKey, hasMethod and so on with a single, inclusive method. It also means that if you create new member types for custom offsiders, then this method will still work on those new member types.
Returns the unique identifier for this offsider.
Syntax:
This identifier is generated when the offsider is created, and uniquely identifies this offsider, even if it is a clone of another offsider.
Warning: A known bug means that child offsiders of a cloned offsider will inherite the same Id as the corresponding children of the original offsider.
Returns licencing information.
The Offsider software is released under the terms of the GNU General Public License (GPL), version 3 or later.
Return the offsider's metadata
Syntax:
An offsider's metadata consists of the contents of the files in the var/ subdirectory of the offsider's base directory.
Reverse the (logical) sense of a message.
Syntax:
Like the shell, an offsider uses an empty string for false. Any other string is considered true.
This method first sends message to the current offsider, using
If an empty string results, it returns a non-empty string.
If a non-empty string results, it returns an empty string and exits with a non-zero return code.
Write a message to a logfile, including a timestamp.
Syntax:
where message is some text.
The location of the logfile is determined by the environment variable $OFFSIDERPROFILETO. If not set, it defaults to /usr/local/share/Offsider/Profiler.out
Note: The executable that implements this method (offsider.Profiler) is used by offsider to do automated profiling. offsider has its own convention that enables the logfile to be analysed by a special-purpose offsider called Profiler.
You are free to use this method, but please be aware that it may be in conflict with the normal profiling operations.
offsider uses the environment $OFFSIDERPROFILE to determine whether to perform profiling. If non-empty then offsider will produce profiling information.
Note: The Offsider framework comes with a dummy place-holder method, and an optional Profiler package which needs to be installed separately.
To get true profiling, you need to install the optional package.
The Profiler offsider is documented separately. It has methods for analysing the logfile produced by offsider.
Show the process tree, from the current process down to init.
Syntax:
Execute shell commands within the context of the offsider.
syntax:
This method first makes the base directory the current working directory, then executes the shell command with the arguments.
Be careful with wild-cards, escape characters, and other characters that have special meaning to the shell. It is unlikely that they will survive the offsider processing stages, no matter how you quote them.
Use of this method is discouraged, because it provides a temptation to break the object-oriented principle of information hiding.
If you find that you are using this method repeatedly to do the same task, you should consider writing a method to wrap the usage of shell. At least that will provide a more object-oriented interface for the same functionality.
You should also look again at the methods provided by the framework. Maybe there is already a method that does what you want.
You should also review why you are resorting to the shell method. Are you thinking in the offsider paradigm or the UNIX shell paradigm? In other words, are you thinking of the offsider as an object, or as a directory?
Takes either a named executable or the base directory for an offsider.
Returns the base directory.
Syntax:
or
This is a utility method. Sometimes it is convenient to specify an offsider by giving the named executable, at other times the base directory is more convenient. This method allows either form to be used.
Returns a string that identifies the specific version of the installed Offsider framework software.
Syntax:
Be aware that this method might be over-ridden for specific offsiders, especially if you have downloaded special-purpose offsiders as separate packages.
The executable offsider.version will return the version of the Offsider framework.
(20100614 18:56:28) This page was produced using rsml. Source file was OffsiderAPI-0.9.1