3.5 Programming Argo Commands
New commands can be added to Argo relatively easily. To do so, copy and mofify asys-xcoms, the skeleton program for Argo commands.
Below is an example of the command creation process, in which we
modify the skeleton to create a program called asys-realminfo, handled
The first step is to copy asys-xcoms to a new file, asys-realminfo.
Then, we need to replace all instances of two generic replacement
Similarly, all instances of
There is one place where you would modify these instructions
slightly... at the outset, we said our command would be named
... we need to specify the whole command name, including the alias:
In all other instances, replace
Multiple CommandsIn our example, the program only handles one command. We can do searches and replaces using the skeletion program `as is'. If the program were to handle multiple, related commands, a few sections of code would need to be duplicated for each command. In
... would need to be copied and pasted in, creating one instance for each command.
would require duplication.
Finally, the lines in
Setting Up Command Syntax
Next we should decide on how the command will be used. We have specified that the command should be able to do three things: let staff members edit notes on an existing realm, let players or staff see a list of defined realms, or let players or staff view notes on a defined realm. The best syntax to use is of course a matter of judgment; something like the following should work pretty well, and will be consistent with other Argo programs:
It would be nice to be able to use
Using this, it should be pretty straightforward to parse the command
arguments and route execution to the appropriate function. Our primary
: DoRealmInfo ( -- ) (* find notes function; route *) ourArg @ if DoShowNotes else DoListRealms then ;
A line added to the portion of
"#notes" ourOption @ stringpfx if DoEditNotes exit else "#enable" ourOption @ stringpfx if DoEnable exit else "#disable" ourOption @ stringpfx if DoDisable exit else "#version" ourOption @ stringpfx if DoVersion exit else "#install" ourOption @ stringpfx if DoInstall exit else "#uninstall" ourOption @ stringpfx if DoUninstall exit else then then then then then then
Note that in adding the
Of course, the contents of functions particular to each new command will vary widely. We're now ready to set up the functions that handle our three actions. Along the way, we'll see some examples of routine tasks in Argo programs. Example pages following this one will introduce others.
Our three functions that actually carry out the command are
The lists containing notes will need to be created before we can do
much else, so it makes sense to discuss
: DoEditNotes ( -- ) (* edit notes on an existing realm *) StaffCheck not if (* check permission *) ">> Permission denied." Tell exit then ;
We then need to prompt for the name of the realm we want to create or
edit notes for. For user-friendliness and consistency with other
Argo commands, we should give the user the option of listing
available choices. Displaying the list of choices and verifying the
input are logically separate tasks, so we should probably bundle them
off in separate functions. We've already said that we're going to create
(* get name of realm *) begin ">> What realm do you want to edit notes for?" Tell ">> [Enter realm name, or .l to list choices, or .q to quit]" Tell ReadLine strip QCheck ".list" over stringpfx if DoListRealms NukeStack continue then dup DoVerifyRealmName if CapAll ourRealm ! break else ">> Sorry, there is no realm named '$realm'." swap CapAll "$realm" subst Tell then repeat
A few things to notice here. Output is handled with
Input is handled by the
A method similar to that used by
We could be extra careful with our stack, and keep the entered realm
name there, but let's instead stick in a variable: at the top of the
program, we declare
Once the realm name has been input and verified, we can use the
#0 "@a/realmnotes/" ourString @ strcat EditList
OK, the list is edited. We can exit.
: DoVerifyRealmName ( s -- i ) (* return true if s is a valid realm name *) scratch ! 0 ourBoolean ! (* store name to search; zero out ourBool *) (* put realm env rooms on stack as dbref range *) #0 "@a/realms" REF-allrefs ourCounter ! (* loop through, looking for one with @a/dataobj that matches *) begin ourCounter @ while dup "@a/dataobj" getpropstr dup if scratch @ smatch if 1 ourBoolean ! (* store true in ourBool if we get a hit *) then else pop then (* keep going regardless; we need to clear out the range *) pop ourCounter @ 1 - ourCounter ! repeat (* check ourBool... it will be true if s was a valid realm name *) ourBoolean @ if 1 else 0 then ;
This task could be handled in several different ways... This way will
work; there's nothing Argo-specific about the code though,
beyond pulling the needed dbrefs from
: DoListRealms ( -- ) (* list defined realms *) (* get realm env rooms as dbref range *) #0 "@a/realms" REF-allrefs ourCounter ! (* loop through range, converting dbrefs to realm name *) begin dup dbref? while "@a/dataobj" getpropstr dup if (* make sure it's a data obj *) #0 "@a/realmnotes/$realm#/" (* if so, see if there are notes *) 3 pick "$realm" subst nextprop if "*" strcat (* star realms that have notes *) then else (* pop non-data-obj dbrefs; decrement count *) pop ourCounter @ 1 - ourCounter ! (* shouldn't happen, but hey *) then ourCounter @ rotate repeat (* if we still have data, display it *) ourCounter @ if ">> DEFINED REALMS:" Tell " " Tell ourCounter @ 3-coln ">> Realms marked with an * asterix have notes." " " Tell Tell else ">> No realms have been defined." Tell then ;
Again, very little of this is Argo-specific; looping through
the contents of a propdir and doing something with the properties or
their values is a very common task in
: DoShowNotes ( -- ) (* show notes on an existing realm *) #0 "@a/realmnotes/$realm#/" ourArg @ "$realm" subst nextprop if ">> NOTES FOR THE $REALM REALM:" ourArg @ toupper "$REALM" subst Tell " " Tell #0 "@a/realmnotes/$realm" ourArg @ "$realm" subst ShowList else ">> There are no notes for the $realm realm." ourArg @ CapAll "$realm" subst Tell then ;
Asys-realminfo now does what it's supposed to, but we're not quite
through. We need to document the program. This would include adding a
: DoHelp ( -- ) (* display help screen *) " " Tell prog name " (#" strcat prog intostr strcat ")" strcat Tell " " Tell "The $com command can be used to list Argo realms defined on the " "MUCK and display notes about a realm's theme, policies, etc." strcat command @ "$com" subst Tell " " Tell " $com ..................... Display list of realms" command @ "$com" subst Tell " $com <realm> ............. Display notes for <realm>" command @ "$com" subst Tell " $com #notes .............. Edit realm notes (staff only)" command @ "$com" subst Tell " " Tell ;
The header comment should give the name of the program, your name (RL or VR, your choice), the date and version number of the program, installation instructions, a summary of the program's use, and conditions for copying or modifying the program. See any of the standard Argo programs for an example.
We're done! Here is the final product.