Home
About
Policies
FAQ
Forums
Registration
Password Recovery

User:Orbus

From Tapestries MUCK

Revision as of 21:43, 8 March 2015 by Orbus (Talk | contribs)
Jump to: navigation, search

Hi. I'm Orbus on Tapestries.

I write frameworks in MPI sometimes. I share them here before I publish them.

Contents

MPI Software

I'm making this code available for anyone to use. If you incorporate any of it into another piece of software, I'd appreciate (but don't require) hearing from you to find out what you're using it for.

CommandLib

CommandLib is a top-level command that you can use on an action to handle parsing of the actual command the player typed.

It's built to handle situations that use the standard MUCK convention of a base-level command that may take arguments and some subcommands that are single words beginning with #.

Source

These commands assume you have an object named command that you would like to install CommandLib onto. You'll want to change the name of the object appropriately.

These also assume you have an action linked to gen-nothing. On Tapestries, you can create this object and link it appropriately with the following commands:

@action command

@link command=$nothing

This code sets up CommandLib itself on the object:

@set command=_msgmacs/error:{if:{prop!:/_cmd/{:1}/_error},{exec!:/_cmd/{:1}/_error},{if:{prop!:/_error},{exec!:/_error},{:1}{if:{:2}, #{:2},} is not a valid command.}}

@succ command={with:subcmd,{sublist:{&arg},1,1, },{null:{if:{eq:{midstr:{&subcmd},1,1},#},{set:subcmd,{midstr:{&subcmd},2,-1}},{set:subcmd,}}}{if:{&subcmd},{if:{prop!:/_cmd/{&cmd}/_sub/{&subcmd}},{with:args,{strip:{sublist:{&arg} ,2,-1, }},{null:{set:arg,{&args}}}{exec!:/_cmd/{&cmd}/_sub/{&subcmd}}},{error:{&cmd},{&subcmd}}},{if:{prop!:/_cmd/{&cmd}/_base},{exec!:/_cmd/{&cmd}/_base},{error:{&cmd}}}}}

Implementing Your Command

Where You Put Code
  • /_cmd/command/_base
    • Called when the player enters command without a subcommand, with or without other arguments.
  • /_cmd/command/_sub/subcommand
    • Called when the player enters command #subcommand, with or without other arguments.
  • /_cmd/command/_error
    • Called when the player enters command #subcommand, with or without other arguments, but there isn't any code to run for that subcommand.
  • /_error
    • Called when the player enters command with or without a subcommand, but there isn't any code to run for that command.
    • Also called when the player enters command #subcommand, with or without other arguments, and there isn't any code to run for that subcommand, and there also isn't an error handler defined for that subcommand.
Getting User Input

Any MPI called by CommandLib can rely on three variables being defined:

  • {&cmd} works exactly the way that the docs define.
  • {&subcmd} will be blank if the player did not type a subcommand, or will have the name of the subcommand without the # if the player did.
  • {&arg} works the way that the docs define when there is no subcommand. If there is a subcommand, then the subcommand will be removed from {&arg} before your MPI is called.

Examples:

  • page orbus=Why did you write this crazy parser library?
    • &cmd: "page"
    • &subcmd: ""
    • &args: "orbus=Why did you write this crazy parser library?"
  • page #mail orbus=I missed you, I'll ask my question later!
    • &cmd: "page"
    • &subcmd: "mail"
    • &args: "orbus=I missed you, I'll ask my question later!"
  • page #help
    • &cmd: "page"
    • &subcmd: "help"
    • &args: ""
  • page
    • &cmd: "page"
    • &subcmd: ""
    • &args: ""

Example

Here's a simplified version of page that we'll use for an example:

page <player> = <message>
page #mail <players>=<mesg>
page #help

We also want it to work if the player types p instead of page.

First, we want to create an action that will accept the page or p commands:

@action page;p

@link page=$nothing

Then, we'll install CommandLib on that action. (See the Source section; we're not copying the code down here.)

Now, we can set up command handlers for page.

@set page=/_cmd/page/_base:{null:This would be the code that handles actually sending a message to someone.,{tell:Fake-page!}}

No, I'm not actually implementing page. This is an example of how argument-parsing works, not an exercise in re-implementing things that work well already.

@set page=/_cmd/page/_sub/mail:{null:This would be the code to handle sending mail.,{tell:Fake-mail!}}

@set page=/_cmd/page/_sub/help:{&cmd} player = message to send a page{nl}{&cmd} #mail player = message to send mail

As you can see, you can put raw text and MPI in these blocks. The result of evaluating your MPI and text will be shown to the player.

Duplicating all of that code for the p command would be annoying. So let's redirect anything that uses p to page:

@set page=/_cmd/p/_base:{exec!:/_cmd/page/_base}

@set page=/_cmd/p/_error:{if:{prop!:/_cmd/page/_sub/{&subcmd}},{prop!:/_cmd/page/_sub/{&subcmd}},{error:page,{&subcmd}}}

Okay, this is a little bit clever. Rather than registering every subcommand on p as a redirect to the corresponding subcommand on page, we register the unknown-subcommand error. All subcommands are unknown, so we always run this error handler when there's a subcommand. Then, the error handler checks whether the subcommand exists on page, and if it does it runs it. If it doesn't exist on page, it throws into the error handler again, but this time it runs the page error handler.

Personal tools
Namespaces
Variants
Actions
navagation
information
wiki
Toolbox