During the AIPS++ prototyping stage a basic command line user interface was developed. This attempt at easing the trouble of passing information to an executable program resulted in a set of C++ classes called Param and Input. The programmer may simply include the Input class into their code and have immediate Command Line User Interface (CLUI) capabilities. The programmer's AIPS++ application is run from the unix level prompt by invoking its name and listing linearly on the same command line the "keyword=values" or "-keyword values" associated with proper execution. The Input and Param classes will successfully parse the command line into the executable program and check for appropriateness.
The CLUI capabilities are further extended to a Graphical User Interface through the use of the Khoros Cantata environment. The user starts up Cantata from the unix prompt and, by utilizing a series of pull down windows, invisibly creates an X-based window for visual display of all parameters associated with the AIPS++ application's need for external input.
The Input and Param classes and their associated user interfaces should be viewed as AIPS++ development tools only. The limitations imposed by the current Khoros GUI techniques dictate the need for a more flexible system. It is believed that as the C++ environment matures an obvious candidate for the final AIPS++ Graphic User Interface will emerge. Until that time, the methods outlined here will, hopefully, reduce the programmer's worry list.
The basic command line user interface is an ordered series of "keyword=value" pairs, which we call parameters. The names parameter and keyword may correctly be used to refer to each other.
The class Param (see Param.h) implements one single such parameter.
Values may be Int, Block
Although the programmer must supply the user interface with a number
of predefined program parameters, the user interface itself will
create a small number of system parameters (help=, debug=). The
purpose of these is to tell the task how to communicate with the user
and it's environment, and give the user control over these items. For
example, the user may want to see (debug) messages above a certain
threshold level. The programmer simply adds debug levels to their
code and allows the user to specify how deeply they wish the debugging
to progress.
For example, a interactive UNIX shell session may look like:
In command 1% the user has set several parameters for the program
MyProgram to applicable values. The 2% command line invokes the
executable and sets the level of displayed debugging to the programmer
specified 5th level. Command 3%: the user is prompted, and parameter
default values are restored. Command 4% gives an example of the
self-describing mode of programs, where a pane description file for
Khoros has been constructed. The latter is the first step toward
building a Khoros Graphic User Interface.
The Input class is a means for building a linked list of parameters
and gaining access to them once created. Input takes care of
system/environment variables and assigns their values within the
programmer's code. The linked list of parameters is limited only by
the number of names the programmer can dream up. The programmer need
not think hard on the order of definition of parameters in Input. The
list of key=values given on the command line by the user need not be
in any specific order.
The definition of parameters is by simply creating an Input and then
using the appropriate Input Create member function. Then the
programmer adds to the list of parameters as necessary.
03 - This is the method of passing the command line through to the
main body of code. This obviously makes it mandatory. The inclusion
of the argc, argv is very well discussed in Stroustrup, The
C++ Programming Language, page 87.
05 - The instantiation of Input in the variable inputs(1) is done with
an integer argument of (1) to indicate the constructor should build
inputs with a pair of system parameters and read in values for them.
An argument of (0) would build an Input that was empty and would
obligate the programmer to build a list of Params explicitly.
07 - The version of the code is stored within the Input. Note the
optional use of RCS keyword substitution. See the "co" man page for
details. This allows the code to be automatically updated.
08-11 - The create member function of Input builds, in this case, a
parameter called xyfile, immediately filled with the String containing
the directory that holds the data. The help String is useful for new
users or prompting. The fourth argument of InFile is the optional
type of the parameter's value. Any suitable String may be used.
Missing from this example are the optional fifth and sixth arguments,
the parameter's value's range and units, respectively.
12 - This is another instantiation of a Param inside of Input. This
parameter will be referenced by the keyword "overplot". It is
initialized to False and is of type Bool.
13 - This line is the third and final Param placed in inputs and is
recognized by the code when accessed with keyword "lines".
16 - The call of readArguments(argc, argv) should be done after the
list of Params has been completed. This line of code fills the values
from the command line. A keyword that doesn't match will throw an
error.
19 - At this point the local variable filename is initialized to the
String value held within the parameter accessed through the key
"xyfile". Recall that the value of xyfile was originally set to
"/tmp/xy.aipsio" but would be replaced with the proper value at
execution. The getString member function returns either the default
value specified during the xyfile parameter's instantiation or the
value placed into it from the command line use of xyfile=myfile.
25 - Here the boolean value of the Param called lines is inserted into
the call to the function plot.
29 - Again the Input interface has its parameter called overplot
return a boolean to be used as a test for an "if". The getBool(key)
Input member function may be reading the default value of the
appropriate parameter called key or using the value passed from the
command line.
30 & 33 - Another call to plot that uses the boolean value stored in
the parameter called lines.
1% MyProgram key1=val1 key3=val3
2% MyProgram key1=val1 key2=val3 debug=5
3% MyProgram help=prompt
4% MyProgram help=pane > prog.pane
Example
01 #include <aips/Inputs/Input.h> // need this if you want it to work
02 #include <aips/Plot.h>
03 main(int argc, char *argv[])
04 {
05 Input inputs(1);
06 // Define our input structure
07 inputs.version("Id: xyPlot.C,v 1.1 1993/01/29 20:45:48 bglenden Exp");
08 inputs.create("xyfile",
09 "/tmp/xy.aipsio",
10 "File which contains xy vectors",
11 "InFile");
12 inputs.create("overplot", "False", "Multiple plots?", "Bool");
13 inputs.create("lines", "True", "Plot lines or points?", "Bool");
14
15 // and Fill them from the command line
16 inputs.readArguments(argc, argv);
17
18 try {
19 const Char *filename = inputs.getString("xyfile");
20 AipsIO xyfile(filename, ByteIO::Old);
21 Vector<float> x, y;
22 Plot plot;
23
24 xyfile >> x >> y; // initial vectors
25 plot(x,y,inputs.getBool("lines"));
26
27 for (;;) { // forever
28 xyfile >> x >> y;
29 if (inputs.getBool("overplot") == True) {
30 plot(x,y,inputs.getBool("lines"));
31 } else {
32 plot.newPlot();
33 plot(x,y,inputs.getBool("lines"));
34 }
35 }
36 } catch (AipsIOError x) {
37 ; // nothing - no more data
38 } catch (AllocError x) {
39 cerr << "AllocError : " << x.getMesg() << endl;
40 cerr << "Size is : " << x.size() << endl;
41 } catch (AipsError x) {
42 cerr << "aipserror: error " << x.getMesg() << endl;
43 return 1;
44 }
45
46 cout << "Any key to exit:\n";
47
48 char ch;
49 cin.get(ch);
50
51 return 0;
52 }
Let us discuss this program line for line.
Motivation
This module fit the early needs of a a simple user interface.
To Do
Classes