This is MiscShell.rtf in view mode; [Download] [Up]
Release 0.1 Copyright ©1994 by Steve Hayman & Associates All Rights Reserved. MiscShell Inherits From: Object Declared In: misckit/MiscShell.h Class Description A MiscShell object combines a MiscSubprocess object (which executes a Unix process) with a MiscStringArray object (which holds the individual lines of output), and features a target/action paradigm so that messages can be sent to other objects for each line of process output. NOTE: If you want to load the MiscShell palette, you must load the MiscString palette first. The MiscShell object needs to use the MiscString class, and expects to find it already loaded by Interface Builder. You can use a MiscShell on its own to capture the output of a Unix command into a MiscStringArray. In addition, MiscShell includes a variety of convenience methods to facilitate hooking up MiscShell objects from within Interface Builder. The MiscShell palette provides a MiscShell object with an inspector that can be used to type up a shell script for the MiscShell to execute, and allows you to prepare a script, hook up target/action methods, indicate where the shell's standard output should go and so on, all totally inside of Interface Builder. You can build some interesting programs that do Unix-y file manipulation type things in this way, without writing any Objective-C code at all. MiscShell operates more or less like this when told to execute a particular Unix command or shell script. · Collect the values of various UI objects it knows about, and add their values to the subprocess's environment; · Create a MiscSubprocess to execute the script; · for each line of output from the script send a target/action message display that line of output on a UI object add that line of output to a list Running a command and examining its output The idea is that you allocate and initialize a MiscShell object, tell it what script to execute, and tell it to execute that script. The MiscShell collects the output generated by the script into individual lines and keeps these lines in a MiscStringArray. A convenience method initWithCommand: is available to simplify the execution of some commands. You give this method a command you would like to have executed, and it executes it and returns when the command has completed. For instance, suppose you want to run the who command to count the number of users logged into your machine. You might use it like this: id myShell = [[MiscShell alloc] initWithCommand:"who"]; printf("There are %d users\n", [myShell lineCount]; and you could loop through the individual lines of output with the line: method, which returns a MiscString object containing the contents of line i: for ( i = 0; i < [myShell lineCount]; i++ ) { printf("Line %d: %s\n", i, [[myShell line:i] stringValueAndFree] ); (You must free the object returned by the line: method yourself.) You can also use the line:field: method to extract a particular field of a particular line: /* Username is the first field of the "who" output */ printf("First User: %s\n", [[myShell line:0 field:0] stringValueAndFree]; MiscShell is using a MiscStringArray internally to store the individual lines of script output; you can get access to this array directly with the lines method. Displaying Standard Output on User Interface objects With Interface Builder, you can drag a MiscShell off of its palette and set some of its instance variables to other objects in your user interface. You can use MiscShell's inspector to type up a simple Unix script, or you can arrange for the script itself to be taken from the title, altTitle or stringValue of other objects in the interface This gives you an easy way, without writing any Objective-C, to run a Unix command and display its output. A MiscShell object can be connected to display its standard output on a variety of different user interface objects · Text Fields · Scrolling Text objects · One-column NXBrowsers · DBTableView or NXTableView, with the output separated into columns · Anything else that understands setStringValue by connecting the object's standardOutput outlet to a suitable user interface object. MiscShell knows how to write data to various different UI objects. If standardOutput is a ... each line of output is ... TextField Written to the text field, replacing the previous contents Scrolling Text Written to the text, appended after the previous contents NXBrowser Appended as another row to the (single-column) browser. (The MiscShell automatically sets itself to be the delegate of the browser.) DBTableView / NXTableView Split into fields and appended to the table view. (The MiscShell automatically sets itself to be the data source of the table view.) Another MiscShell Written to the shell's standard input. (Untested.) Each line of data written to a Table View is split into fields according to the separator instance variable, and individual fields will appear in individual columns of the table view. In addition, the MiscShell supports the standard target/action paradigm. Each time the MiscShell reads a complete line of output from the MiscSubprocess, it will execute the desired target/action message. By default, MiscShell's executeScript: method will execute a command asynchronously, meaning that the executeScript: method will return right away, and the MiscShell will keep an eye on data being written by the subprocess and will wake up and handle it whenever necessary. This is OK for a long-running command, but sometimes you would like the shell just to read all the data and return from the executeScript: method when the script has completed. You can do this by setting the runToCompletion variable. Taking Values from user interface objects. You can also connect four instance variables v1, v2, v3, v4 to other UI objects in your program. Before the script executes, MiscShell checks the stringValue of each of these objects and adds "varname=stringValue" statements to the script's Unix environment. For instance, if you have connected v1 to a slider, and then execute the script, the script will be able to check the $v1 environment variable to find the current value of the slider. If the variable is connected to a DBTableView, MiscShell will figure out the value of the currently selected rows of the table view and use that as the value of the variable (with columns separated by tabs, and rows by newlines.) The MiscShell also adds a few other special convenience environment variables that your script can consult. $sender The string value of the object that sent the execute* method. $senderTag The tag of the object that sent the execute* method. $mainBundle The pathname of the application's mainBundle. Magic Output Strings Certain magic strings in the subprocess's output will cause MiscShell to take special actions. If your subprocess outputs the string ALERT;a message here;Yes;No MiscShell will split up the line on the semicolons (which must be included) and pass the arguments to NXRunAlertPanel() , and write the (integer) result of the Alert panel back to the shell's input. So your shell could read that line of input and react accordingly. echo 'ALERT;Are you sure you want to reformat the disk?;Yes;No' # MiscShell now runs an alert panel and writes the result # of NXRunAlertPanel to this process. We'll read 1 for Yes, # 0 for No. read ans case $ans in 1) # yes reformat-disk ;; *) # no ;; esac The string OPEN causes MiscShell to pop up an Open panel to prompt for a filename. The file chosen will then be written back to the subprocess. The string var=value, where var is one of v1, v2, ... v9, will cause the message [var setStringValue:value] to be sent. This gives the shell script a way to write specific values to specific user interface objects. For instance, you could connect v2 to some text field, and during execution your script could do echo v2=`date` which would display the current date on that text field. If MiscShell recognizes one of these special lines, it performs the appropriate action but does NOT do the normal target/action and standard output handling that would otherwise happen. DBTableView and NXTableView This section isn't written yet. It will describe how you can make a MiscShell a delegate of a DBTableView (which it sets up automatically if you make the table view the MiscShell's standard output), and have the MiscShell resort its output in response to column moves in the table view. Go try it. Instance Variables id standardOutput; id standardError; id standardInput; id v1; id v2; id v3; id v4; SEL action; MiscString *script; MyMiscSubprocess *process; MiscString *currentLine; MiscString *fullOutput; BOOL currentLineIsComplete; BOOL executionInProgress; BOOL runToCompletion; MiscString *execArg0; MiscString *execArg1; MiscString *execArg2; MiscStringArray *lines; char delimiter; standardOutput An object to which the script's standard output should be sent standardError An object to which the script's standard error should be sent. standardInput Not currently implemented. v1, v2, v3, v4 Objects whose string values can be interpolated into the script as it executes. action The message sent to the shell's target. script A MiscString containing the actual shell script to be executed. process The MiscSubprocess that's created to execute the script. currentLine The current output line from the script. fullOutput A MiscString containing all the output generated by the script. currentLineIsComplete Indicates whether the currentLine string is complete - i.e. includes output up to a newline. executionInProgress If true, the subprocess is currently executing. runToCompletion If true, the executeScript: method should run the script and wait for it to complete, rather than launching it and returning. execArg0 No description. execArg1 No description. execArg2 No description. lines A MiscStringArray containing the individual output lines generated by the script. delimiter A field separator character, used to split individual output lines into fields. If 0, lines will be split on word boundaries (whitespace). Method Types - action - delimiter - doubleValue - executeFromAltTitle: - executeFromStringValue: - executeFromTitle: - executeScript: - fieldsInLine: - floatValue - free - init - initWithCommand: - intValue - lines - line: - line:field: - pause: - read: - resume: - runToCompletion - script - setAction: - setDelimiter: - setExecArgs::: - setRunToCompletion: - setScript: - setTarget: - stringValue - target - takeStdinFrom: - terminate: - write: Instance Methods action - (SEL)action Returns the action message sent to the script's target whenever a complete line has been read. See also: delimiter - (char)delimiter Returns the character used to split output lines into fields. If it's 0, output lines will be split on word (whitespace) boundaries. See also: doubleValue - (double)doubleValue Equivalent to atof( [self stringValue] ). See also: executeFromAltTitle: - executeFromAltTitle:sender Asks the sender for its altTitle, sets its script to that string, and executes the script. You might set up a button to send this message to the MiscShell, and give the button a Unix command as its alternate title (which can be set in the Button inspector in Interface Builder). See also: executeFromStringValue: - executeFromStringValue:sender Sets the script to be the sender's stringValue, and executes the script. See also: executeFromTitle: - executeFromTitle:sender Sets the script to be the sender's title, and executes the script. See also: executeScript: - executeScript:sender Executes the script, which should have been set by one of the other methods.. See also: fieldsInLine: - (int)fieldsInLine:(int)lineNum Returns the number of fields in output line lineNum See also: floatValue - (float)floatValue Equivalent to atof( [self stringValue]) . See also: free - free Terminates the subprocess, frees its allocated instance variables and itself. See also: init - init Initializes a newly allocated MiscShell. Sets the script to an empty MiscString, sets delimiter to '\0', sets runToCompletion to NO, and returns. You'll need to set the script somehow after using init. See also: initWithCommand: - initWithCommand:(const char *)command A convenience method that initializes a newly allocated MiscShell, sets the script to the indicated command, sets runToCompletion to YES, executes the script, and waits for it to complete before returning. See also: intValue - (int)intValue Equivalent to atoi( [self stringValue] ). See also: lines - (MiscStringArray *) lines Returns the MiscStringArray object that the MiscShell is using to store individual lines of the process's output. You're on your honour not to muck around with it. See also: line: - (MiscString *) line:(int)lineNum Returns a newly allocated MiscString object containing the contents of output line lineNum. You should free this string yourself when you're done with it. The first line is line 0. See also: line:field: - (MiscString *) line:(int)lineNum field:(int)fieldNumber Returns a newly allocated MiscString object containing the contents of field number fieldNumber of output line lineNum. The appropriate output line is split into fields according to the delimiter variable. If it's 0, fields are split into whitespace-delimited words. The first field is field 0. See also: lines - (MiscStringArray *) lines Returns the MiscStringArray object that the MiscShell is using to store individual lines of the process's output. You're on your honour not to muck around with it. See also: lineCount - (int) lineCount Returns the number of output lines received so far. See also: pause: - pause:sender Sends pause: to the MiscSubprocess object. See also: read: - read:(NXTypedStream *)stream Your basic archiving method. See also: resume: - resume:sender Sends resume: to the MiscSubprocess object. See also: runToCompletion - (BOOL)runToCompletion If true, the executeScript: method will launch the subprocess, read all of its output into the lines array, and wait for the script to execute before completing. If false, the executeScript: method merely launches the subprocess and returns without waiting for it to complete. See also: script - (MiscString *)script Returns the shell script to be executed. See also: setAction: - setAction:(SEL)anAction Set the action message to be sent whenever the script produces a complete line of output. See also: setDelimiter: - setDelimiter:(char)c Sets the delimiter character to be used when splitting individual output lines into fields. See also: setExecArgs::: - setExecArgs:(const char *) a1: (const char *)a2 :(const char *)a3 Sets the strings to be used by the custom subclass of MiscSubprocess when executing the child script. By default, these are "/bin/sh", "sh", "-c". See also: setRunToCompletion: - setRunToCompletion:(BOOL)c Sets the runToCompletion flag. See also: setScript: - setScript:(MiscString *)script Set the script to be executed to the indicated MiscString. See also: setTarget: - setTarget:aTarget Set the target object to which messages should be sent after each line read. See also: stringValue - (const char *)stringValue Returns the last complete line of output read. See also: takeStdinFrom: - takeStdinFrom:sender Asks sender for its stringValue, and writes that string to the standard input of the script. Presumably the script will then read this value. See also: target - target The target object to which target/action messages should be sent. See also: terminate: - terminate:sender Sends the terminate: message to the MiscSubprocess. See also: write: - write:(NXTypedStream *)stream Your basic archiving method. See also: - writeToStdin:(const char *)str Writes some data to the process's standard input.
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.