DIRECTORY Commander USING [Handle], IO USING [STREAM], Rope USING [ROPE]; CommanderOps: CEDAR DEFINITIONS = BEGIN ROPE: PRIVATE TYPE = Rope.ROPE; ArgumentVector: TYPE = REF ArgHandleObject; ArgHandleObject: TYPE = RECORD [s: SEQUENCE argc: NAT OF ROPE]; Failed: ERROR [errorMsg: ROPE]; QuoteTreatment: TYPE ~ {stripQuotes, leaveQuotes}; ParseToList: PROC [cmd: Commander.Handle, quoteTreatment: QuoteTreatment ¬ stripQuotes] RETURNS [list: LIST OF ROPE, length: NAT]; Parse: PROC [cmd: Commander.Handle, quoteTreatment: QuoteTreatment ¬ stripQuotes] RETURNS [argv: ArgumentVector]; NumArgs: PROC [cmd: Commander.Handle] RETURNS [INT]; NextArgument: PROC [cmd: Commander.Handle, quoteTreatment: QuoteTreatment ¬ stripQuotes] RETURNS [ROPE]; ArgN: PROC [cmd: Commander.Handle, n: INT, quoteTreatment: QuoteTreatment ¬ stripQuotes] RETURNS [ROPE]; Token: TYPE ~ RECORD [value, literal: ROPE, start: INT]; nullToken: Token ~ [NIL, NIL, 0]; GetCmdToken: PROC [stream: IO.STREAM] RETURNS [Token]; DoCommand: PROC [commandLine: ROPE, parent: Commander.Handle] RETURNS [result: REF]; DoCommandRope: PROC [commandLine, in: ROPE ¬ NIL, parent: Commander.Handle] RETURNS [out: ROPE, result: REF]; ExecuteCommand: PROC [cmd: Commander.Handle, wholeCommandLine: ROPE] RETURNS [result: REF, msg: ROPE]; PutProp: PROC [cmd: Commander.Handle, key, val: REF]; GetProp: PROC [cmd: Commander.Handle, key: REF] RETURNS [REF]; CreateFromStreams: PROC [in, out, err: IO.STREAM ¬ NIL, parentCommander: Commander.Handle ¬ NIL] RETURNS [cmd: Commander.Handle]; ReadEvalPrintLoop: PROC [cmd: Commander.Handle] RETURNS [hadFailure: BOOL]; END. – CommanderOps.mesa Copyright Σ 1989, 1991 by Xerox Corporation. All rights reserved. Michael Plass, November 21, 1989 9:18:30 am PST The CommanderOps is a simple stream-oriented command-line processor. This interface exports a programmer's interface to the CommanderOps and provides some facilities for managing command lines. Intended as a simplified replacement for L. Stewart's CommandTool. Types and Signals An ArgumentVector is a processed command line. It stands for "argument vector" for historical reasons. When arg: ArgumentVector, arg[0] is the command, arg[1] is the first argument, and arg[arg.argc-1] is last argument. Failed may be raised by the procedures below for reasons like mis-matched double-quotes on the command line. The errorMsg gives a user-intelligible reason. ERROR Failed may also raised by CommandProcs, instead of returning [result: $Failed, msg: "..."]. This will be caught and converted into a failed command, so most of the times the CommandProcs don't need to catch Failed. Procedures for Processing Command Lines The following procedures are usefully called by CommandProcs right after they get control. ! Failed; ParseToList breaks up cmd.commandLine into a list of tokens. Tokens are generally separated by whitespace, but a "double-quoted string" is a single token. ! Failed; Parse does the same job as ParseToList, but returns a sequence of tokens. In accordance with historical precedent, cmd.command is returned as argv[0] and the "real" arguments start at argv[1]. Returns number of argument tokens that would be produced by CommanderOps.Parse (including the name of the command itself). This is cmd.argv.argc. Returns the next command line token. ArgN sets the "pointer". The initial value of the pointer is the first token after the name of the command. Returns NIL after returning the last real argument. Returns the nth command line argument. ArgN[cmd, 0] is the name of the command. After any given ArgN, NextArgument will return the (n+1)st argument. Returns NIL if there is no nth argument. For clients that need to parse tokens off a stream, using the same conventions as the above parsing routines. The stream must support GetIndex and SetIndex. Returns nullToken on end-of-stream token.value has quotation marks stripped token.literal has quotation marks intact token.start is the index (via IO.GetIndex) of the start of the token Procedures for Executing commands Execute the given commandLine. Parent will be used to provide streams and the property list. cmd.command and cmd.commandLine will be overwritten. This is particularly useful for commands which wish to execute their own command lines as commands: DoCommand[cmd.commandLine, cmd]; Result is the result returned by the command. Execute the given commandLine. (The command name must be the first token on the commandLine). The in, out, and err streams connected to the corresponding ropes. The property list and error streams come from parent. If parent is defaulted NIL, then a standard property list will be created and error output will be directed to out along with standard output. Result is the result returned by the command. Execute the given wholeCommandLine. cmd must be a valid commander handle. Commander Properties These maintain cmd.propertyList, using mutable semantics. Creation/ReadEvalPrint Here is an example that ought to work in the Viewers world to create a new command tool: CreateCommandToolViewer: PROC = { in, out: IO.STREAM; [in: in, out: out] _ ViewerIO.CreateViewerStreams[name: "CommanderOps"]; TRUSTED {Process.Detach[FORK ReadEvalPrintLoop[CreateFromStreams[in: in, out: out]]]}; }; Clients that need to do more may refer to CommanderBackdoor. ΚΘ–(cedarcode) style•NewlineDelimiter ™code™Kšœ Οeœ7™BK™/K™KšΟtGœ|™ΓKšœB™B—K˜šΟk ˜ Kšœ Ÿœ ˜KšŸœŸœŸœ˜KšœŸœŸœ˜—K˜KšΟn œŸœŸ œŸœ˜(head™KšŸœŸœŸœŸœ˜K˜šœŸœŸœ˜+Kšœέ™έK™Kš œŸœŸœŸœŸœŸœŸœ˜?—K˜šœŸœ Ÿœ˜Kšœœ™œKšŸœΨ™έ——™'K™ZK™šœŸœ˜2K˜—š  œŸœFŸœŸœŸœŸœ Ÿœ˜‚Kšœ ™ Kšœ›™›K™—š œŸœGŸœ˜qKšœ ™ KšœΑ™Α—K˜š œŸœŸœŸœ˜4Kšœ’™’K™—š  œŸœGŸœŸœ˜hKšœœŸœ(™ΗK™—š  œŸœŸœ0ŸœŸœ˜hKšœ Ÿœ™ΐK™—Kš œŸœŸœŸœ Ÿœ˜8šœŸœŸœ˜!K˜—š   œŸœ ŸœŸœŸœ ˜6K™K™"K™(K™(K™D—K™—™!š   œŸœŸœŸœ Ÿœ˜TKšœΗ™ΗK™—š  œŸœŸœŸœŸœŸœ Ÿœ˜mKšœ˜™˜K™—š  œŸœ+ŸœŸœ ŸœŸœ˜fKšœJ™J——™šœ9™9K™—Kš œŸœ#Ÿœ˜5Kš  œŸœŸœŸœŸœ˜>—™š œŸœŸœŸœŸœ&ŸœŸœ˜K˜—š œŸœŸœŸœ˜KK˜—™Xš œŸœ™!Kšœ ŸœŸœ™KšœH™HKšŸœŸœ:™VKšœ™K™—K™