Introduction

WebWriter++ tries to meet a number of objectives in allowing authors to present code to students—

  1. The code should be presented in a fashion familiar to students. Typically, this means syntax-staining the code in a manner that is as close to the way their editor does it as possible.
  2. The code should be exportable to the Teaching Machine.
  3. The code should be isolated in a separate, compilable file, to allow an instructor to check for syntax and even debug it.
  4. Markup techniques available in the WebWriter++ toolset should be available for use with code.

It might seem that syntax-staining (1) and code mark-up (4) would be incompatible with the other two objectives. However, (1) is easily achieved by importing the source code and parsing and staining it on the fly. This feature was included in the toolset, which leaves only the fourth objective.

Enter pedagogical mark-up which is a small language that allows certain WebWriter++ calls to be embedded in C/C++ comments.

Supported Tools

Currently, the following tools are supported:

Indeed, pop-ups and rollover blocks were initially developed specifically to enable the marking of code.

Syntax

General

All mark-ups must appear inside C-style (multi-line) comments ('/* */'). Currently WebWriter++ is unforgiving about white space so that pedagogical markups must occur immediately after (and before) the comment operators, as follows:

		/*#p="integerPopup"*/int/*#/p*/ count = 0;	

Here, the keyword int has been marked as a pop link. The #p="integerPopup" command (which is wrapped in comment characters with no intervening spaces) declares that a pop link (which will call up a pop-up named integerPopup) starts at the keyword. Similarly, #/p marks the end of the link. Thus, the int keyword will appear as a link to the integerPopup when the code is displayed by WebWriter++.

Popups

   /*#P="popupName" "The text for the popUp"*/

Creates the pop-up. While html is allowed it does not currently work. A pop-up only has to be defined once (on a particular page). It can be linked multiple times. If you want cross-site pop-ups, use definitions and put them in the dictionary.

   /*#p="popupName"*/

Marks the beginning of a pop-up link. The "popupName" should be the name of the pop-up you want to see appear when the link is rolled over.

    /*#/p*/

Terminate a pop-up link.

Rollover Blocks

   /*#B="blockName"*/

Starts the block. The background colour of the block will change when its link is rolled over. Blocks may be wholly nested within each other.

    /*#/B*/

Terminate a block.

   /*#b="blockName"*/

Marks the beginning of a rollover block link. The "blockName" should be the name of the rollover block you want to see illuminated when the link is rolled over.

    /*#/b*/

Terminate a rollover block link.

Definitions

   /*#d="definitionName"*/

Marks the beginning of a definition link. The "definitionName" should be the name of the definition you want to see pop-up when the link is rolled over. Definitions are kept in a separate, standard dictionary.

    /*#/d*/

Terminate a definition link.

Tagging and invisible code

Tagging with #T

Any section of code can be tagged by adding before it

/*#T tagName */

and

/*#/T tagName */

after it. tagName can be any (nonempty) sequent of ascii letters and digits, except for "true" and "false". Leading and trailing whitespace are optional (that is, they are ignored).

A piece of code can carry as many tags as the instructor wishes. Tags do not have to nest. Consider

/*#TA*/Bob /*#/TA*/saw /*#TA*/a /*#TB*/big
/*#/TA*/hairy /*#/TB*/monster

Each section is associated with a set of tags as follows:

Section Tag set
Bob {A}
saw { }
a {A}
big
 
{A,B}
hairy {B}
monster { }

Tags are used in conjunction with a pair of selection expressions in the insertCode command to control what code sections are displayed by WebWriter++ and in the TM. Given a selection expression E and a section S with tag set T: S is selected if (and only if) E evaluates to true if we replace (in E) each tag in T with "true" and each tag not in T with "false". Only selected sections will be displayed.

Selection expression Displayed
default (!S&!L)

Bob saw a big
hairy monster

A Bob a big
 
B big
hairy
A|B

Bob a big
hairy

A&B big
 
!A saw hairy monster
!B Bob saw a monster
!A&!B saw monster

 

Here is a larger example.

class MyString{
public:
  MyString(char* p);	// Construct using a standard string
  MyString();			// "default" (no arguement) constructor
  MyString(MyString& orig);		// Copy constructor
  ~MyString();		// standard destructor to deal with heap

// Accessor functions - used to read object data without changing it
  int length() ;
  char getChar(int i) ;	// get char at location i
  void get(char* buff) ;	// Get the string & put it into user buff
  bool compare(MyString& other);	// true if equal
  
// Mutator functions - used to change string objects
  void setChar(int i, char c); // Change char at i to c
  void changeTo(char* newString);	// Change the whole string
  
/* Notice the change to pass by ref to improve efficiency */
  void changeTo(MyString& newString);	// Function overload

private:
  char* mPtr;	// pointer into the heap where the actual string will be
  int mLength;	// length of the string
  };

/*#TA*/// A class of users for network management
class User{
public:
  User(char* n, char* u, char* p);

// Accessors
  MyString& name();	// return reference
  int allocation();	// Disk space allowed
  MyString password();	// return value
  MyString uname() ;
  bool confirm(MyString& uName, MyString& pass);

// Mutators
  bool setPassword(MyString& p1, MyString& p2);
  void setAllocation(int a);

protected: MyString mName; // Notice attributes that are OBJECTS! MyString mUname; MyString mPassword; int mAllocation; // Memory allocation, in MBytes };/*#/TA*/ /*#TB*/class Student: public User{ public: Student(char* n, char* id, char* u, char* p); MyString id(); void buy(long amount); bool approvePrint(int pages); protected: MyString mId; long mPrintPennies; };/*#/TB*/ /*#TC*/class Faculty: public User{ public: Faculty(char* n, char* u, char* p, char* today); // accessor functions long pages(); MyString cleared(); // mutator functions bool approvePrint(int pages); // increases page count void clear(char* d); // clears count & notes date protected: long mPages; // Pages used since MyString mCleared; // last date cleared };/*#/TC*/

To expose only class User on the webSite the code is inserted using the insertCode command as follows:

function insertCode("userInherit.cpp", true, "code", "default.cfg", "A&~S&~L", "~S&~L")

which shows only code tagged with "A" on the eBook page, but the whole example when it is run in the TM. The ~S means don't display Scripts, referring to internal scripting calls which instructors can build into the code, and "~L" means don't show library code. It's a good habit to ensure "~S&~L" is implied by any selections, even when, as in this example, "S" and "L" tags aren't used. The final parameter in this call could be omitted, as "~S&~L" is the default.

Reserved Tags

Tags "S" and "Script" are equivalent and reserved for marking intenal scripting calls (only "S" should be used in the insertCode selection strings).

Tags "L" and "Lib" are equivalent and reserved for marking TM library code(only "L" should be used in the insertCodeselection strings).

Invisible Code

Code that needs to be hidden from regular compilers, but that should be compiled by the the Teaching Machine, can be put in a comment

/*#I code goes here*/

WebWriter will not show these comments at all (not even if the selection string is "S"). The Teaching Machine will treat the code as if it were tagged with "S" (or, equivalently, "Script"). See below for examples.

Invisible and tagged code in the TM

The TM will not display code that is currently unselected. Completely unselected lines are indicated by an ellipsis (...) when line numbers are displayed. For this reason, we suggest using a configuration file that turns off line numbers when scripting code is used.

You can use the TM's View menu to change the current selection.

Even white space that is selected will mean that the line is partially selected, i.e., not completely unselected.

Furthermore the TM will generally not stop on code that is on a completely unselected line. So scripting calls should be on completely unselected lines. The same mechanism is used to keep the TM from stopping in library code. (Library code is tagged with "L", and so is not selected by default.

The best way to mark up TM code is like this

#include <iostream>
#include <stdlib.h>/*#I
#include <ScriptManager> */
    .
    .
    .
    int array[SIZE]; /*#I
    // Use only single line comments in invisible regions.
    ScriptManager::relay("ArrayBar", "setArray", array);*/
    for (int i = 0; i < SIZE; i++) {
        array[i] = 0 ; }

or like this

#include <iostream>
#include <stdlib.h>/*#T S*/
#include <ScriptManager> /*#/T S*/
    .
    .
    .
    int array[SIZE]; /*#T S*/
    /* Either kind of comment is allowed here.*/
    ScriptManager::relay("ArrayBar", "setArray", array);/*#/T S*/
    for (int i = 0; i < SIZE; i++) {
        array[i] = 0 ; }

The first style is best if you don't want other compilers to see the code.

Note that there must be nothing --not even be spaces or tab characters-- after the final "*/". Whitespace characters after the final "*/" will be selected, by default, and so make the line appear in the TM. (This may change in the future. It's not a bug, but it is an annoyance.)

If the last line before the script code ends with a single line comment, you can do the following

    int array[SIZE]; // Make an array.
/*#I    ScriptManager::relay("ArrayBar", "setArray", array);
*/    for (int i = 0; i < SIZE; i++) {
        array[i] = 0 ; }

Note the funky indentation; it is deliberate. It is tempting here to put the "*/" before the newline. This would be fine for the TM, but WW would show a blank line before the "for" loop.

Mark-Up Removed for Presentation

While pedagogically marked code compiles just fine it is still messy and confusing for students to look at. Consequently, both WebWriter++ and the Teaching Machine automatically remove pedagogical markups from their displays.