Skip to main content

The PreTeXt Guide

Section 4.16 Programs

Subsection 4.16.1 Content and Placement of Programs

A <program> will be treated as verbatim text (see Section 3.16), subject to all the exceptions for exceptional characters (see Section 3.14). Indentation will be preserved, though an equal amount of leading whitespace will be stripped from every line, so as to keep the code shifted left as far as possible. So you can indent your code consistently along with your XML indentation. For this reason it is best to indent with spaces, and not tabs. A mix will almost surely end badly, and in some programming languages tabs are discouraged (e.g. Python).
The text contents of a program can be surrounded with <code>, but that is only necessary if you have other elements inside of the <program> like <preamble> or <tests> used by an interactive program (see Subsection 4.16.3 below for details).
Like a console (see Section 4.15) a <program> may be wrapped in a <listing> (see Section 4.20). If you want to assign a visible number, cross reference to the program, or assign it a visible filename a surrounding <listing> element is appropriate.
The @language attribute may be used to get some degree of language-specific syntax highlighting and/or interactive behavior. The current known languages are:
  • basic
  • c
  • cpp
  • go
  • java
  • javascript
  • lua
  • pascal
  • perl
  • python
  • python3
  • r
  • s
  • sas
  • sage
  • splus
  • vbasic
  • vbscript
  • clojure
  • lisp
  • clisp
  • elisp
  • scheme
  • racket
  • sql
  • llvm
  • matlab
  • octave
  • ml
  • ocaml
  • fsharp
  • css
  • latex
  • html
  • tex
  • xml
  • xslt
In some output formats, notably HTML, the syntax highlighter can add lines or highlight individual lines of code. Highlighting lines is not supported for output. To display line numbers, set the @line-numbers attribute to yes. To highlight particular lines, set @highlight-lines to a comma-separated list consisting of individual lines and/or ranges indicated with dashes. Some examples are: 5, 2,5, 2,5-8,10-15,15.
View Source for program
<program language="java" line-numbers="yes" highlight-lines="2,6-8">
    <title>"hi" in Java</title>
    <code>
    import javax.swing.JFrame;  //Importing class JFrame
    import javax.swing.JLabel;  //Importing class JLabel
    public class HelloWorld {
        public static void main(String[] args) {
            JFrame frame = new JFrame();           //Creating frame
            frame.setTitle("Hi!");                 //Setting title frame
            frame.add(new JLabel("Hello, world!"));//Adding text to frame
            frame.pack();                          //Setting size to smallest
            frame.setLocationRelativeTo(null);     //Centering frame
            frame.setVisible(true);                //Showing frame
        }
    }
    </code>
</program>
import javax.swing.JFrame;  //Importing class JFrame
import javax.swing.JLabel;  //Importing class JLabel
public class HelloWorld {
    public static void main(String[] args) {
        JFrame frame = new JFrame();           //Creating frame
        frame.setTitle("Hi!");                 //Setting title frame
        frame.add(new JLabel("Hello, world!"));//Adding text to frame
        frame.pack();                          //Setting size to smallest
        frame.setLocationRelativeTo(null);     //Centering frame
        frame.setVisible(true);                //Showing frame
    }
}
Listing 4.16.1. A static Java program with highlighted lines
For interactive versions hosted on Runestone servers, the @label attribute is critical, just like for interactive exercises. So be certain to read Best Practice 4.12.1.
Finally, when authoring programs, it may be helpful to keep the source code as plain text in separate files. This can avoid the need to manually escape characters that have special meaning in XML and can facilitate testing and updating the code samples. See Section 4.38 for how to do so.

Subsubsection 4.16.1.1 Default attributes for programs

Book-level default values for some program attributes can be set in docinfo/programs. If a value for an attribute is set in that location, it will be used for any <program> that lacks the corresponding attribute.
The following attributes can be given default values - some only are applicable to interactive programs (see Subsection 4.16.2 and Subsection 4.16.3): @compiler-args, @linker-args, @interpreter-args, @download, @language, @linenumbers, and @timelimit.

Subsection 4.16.2 Interactive Programs, CodeLens

CodeLens is an interactive version of a computer program, which can be visualized by stepping through the code one statement at a time, watching output, variables, and other data structures change. So it is similar to a debugger, except the reader does not set breakpoints or modify program data on-the-fly. This is possible automatically for several different languages when your HTML is hosted on a Runestone server (Chapter 32). This may also be accomplished “in browser” when hosted on any old generic web server. The catch is that for a generic server a publisher must generate trace data in advance, typically with the PreTeXt-CLI (Section 5.2). Place the <interactive> attribute on a <program> element with the value codelens to elect this behavior (no is the default value). Also, be sure to specify a language from the supported languages: Python, Java, C, and C++. Consult Table 4.16.4 below for a summary of various combinations. When an output format does not support an interactive CodeLens instance, the fallback is a static program listing.

Subsection 4.16.3 Interactive Programs, ActiveCode

ActiveCode is an interactive environment where a reader may work on code through repeated edit-compile-test cycles. Code can be provided by an author as a complete program to be modified, a partial program to be completed, or nothing at all. One good example is that maybe header files, import statement, and similar are provided, and a skeleton of a main entry-point procedure is also provided. Then a reader can concentrate on the more conceptual parts of the programming. Some languages will be executable “in browser” on any old generic web server, while others must be on a Runestone server (Chapter 32) where a Jobe Server
 1 
github.com/trampgeek/jobe
is running to support the execution.
Place the @interactive attribute on a <program> element with the value activecode to elect this behavior (no is the default value). Also, be sure to specify a language from the supported languages. Consult Table 4.16.4 below for a summary of various combinations. When an output format does not support an interactive ActiveCode instance, the fallback is a static program listing.
Inside the <program> of an ActiveCode, you can use the following elements:
preamble
Code that will be part of the program but not available for editing by the user and precedes the contents of <code>. This code will be visible unless the @visible is set to no.
Note that the contents of this element will be combined with the <code> before the indentation is adjusted. So any code in this block must be indented to the same baseline as the contents of <code>.
code
The body of the program that will be editable by the user.
postamble
Code that will be part of the program but not available for editing by the user and follows the contents of <code>. This code will be visible unless the @visible is set to no.
Note that the contents of this element will be combined with the <code> before the indentation is adjusted. So any code in this block must be indented to the same baseline as the contents of <code>.
tests
Tests may take the form of either structured input-output tests (see Subsubsection 4.16.3.1) or as a block of code that will be added after the <code> (as well as any <postamble>). The assumption is that code in <tests> is doing unit testing that the user should not see, so this code will be hidden unless the @visible is set to yes.
This code is processed by PreTeXt separately from the <code>, so indentation does not need to be consistent between it <code> and <tests>.
Some languages have support for unit testing frameworks. If you use one of them, the results of the tests will be parsed and displayed to the user as a visual results table. The following languages have support for unit testing frameworks:
  • python supports unittest
  • java supports junit
  • c and cpp support doctest (which tends to build and run significantly faster) and catch
stdin
If this element is provided, a text box will be created for the user to enter text that will be fed to the program via the stdin stream. If the <stdin> has text content, that will be provided to the user as a default input. Multiple lines of input are permissable. The text will be sanitized in the same way that the <program> itself is.
Here is a sample of a program with preamble and postamble. For more examples, see the Activecode section of the Sample Book
 2 
runestone.academy/ns/books/published/PTXSB/activecode.html
View Source for program
<program interactive="activecode" language="python" label="program-activecode-python-ambles">
    <preamble>
    def add(a, b):
    </preamble>
    <code>
        # TODO - complete the add function

    </code>
    <postamble>
    # Use the function
    result = add(2, 3)
    if result == 5:
        print("Test passed")
    else:
        print("Test failed")
    </postamble>
</program>
Listing 4.16.2. A Python program with preamble/postamble
There are a wealth of attributes that can be used to control the behavior of ActiveCode. (These are in addition to the standard ones allowed for for <program>. see Section 4.16 for those.) Below is a list of the extra attributes available. Any attribute that lists other elements for inclusion will take a list of @xml:ids for those elements.
autorun
If set to yes the program will run on page load.
chatcodes
Set to yes to enable users to talk about this code snippet with others.
codelens
In languages that support Codelens (see Subsection 4.16.2), there will be a button that allows the user to run the program via Codelens. Set this to no to remove it. This may be desireable if you know the code uses features that are not supported by Codelens (e.g. turtle graphics or image).
compiler-args
(C/C++ only) A comma separated list of strings to be passed to the compiler. Ex: -Wall, -std=c++17. A book-level default can be specified - see Subsubsection 4.16.1.1.
database
(SQL only) SQL based programs can make use of an SQLite database file. Use this attribute to specify the file to load as a string relative to the @external top-level directory.
datafile
A comma separated string identifying one or more <datafile>s that are available for processing in this program. See Section 4.17
download
Set to yes to enable users a download button that triggers downloading of the user code to a file. A book-level default can be specified - see Subsubsection 4.16.1.1.
hidecode
Set to yes to initially hide the code. When code is hidden, the ’Run’ button is also disabled. To run the code, a user either presses ’Show Code’, then ’Run’.
You might use this if you want to put an ActiveCode block in the page in order to include it in another ActiveCode block, but you don’t need or want students to see it right away. Or to hide the code of an ActiveCode with @autorun where you initially want to focus on the output instead of the program.
include
A comma separated string identifying one or more other ActiveCodes that are to be prepended to this program when it is run. See Section 4.17
This allows you to write examples that build on each other without having to duplicate all the code in each successive block. For example, if you write a function definition in one ActiveCode, you can include it in a later ActiveCode block that has code to call the function without having to visibly include the definition.
interpreter-args
(Python2/3/Java/octave only. Only applies to Python that is run on the server. See Table 4.16.4.) A comma separated list of strings to be passed to the compiler. Ex: -Xrs, -Xss8m, -Xmx200m. A book-level default can be specified - see Subsubsection 4.16.1.1.
language
Same options as <program>. A book-level default can be specified - see Subsubsection 4.16.1.1.
linker-args
(C/C++ only) A comma separated list of strings to be passed to the compiler. Ex: -lm, -g. A book-level default can be specified - see Subsubsection 4.16.1.1.
timelimit
A maximum time allowed, in milliseconds, for a program to compile and run. If not provided, the default is 25000 (25 seconds). A book-level default can be specified - see Subsubsection 4.16.1.1.

Subsubsection 4.16.3.1 Tests for Interactive Programs

There are currently two ways to make automated tests for ActiveCode programs. The first way is to simply provide code in the <tests> element of the <program> as described in Subsection 4.16.3. It will be assumed this code is unit tests and it will be run automatically with the user’s submission.
Below is an example of unit tested Python. For more examples, see the Coding Exercises section of the Sample Book
 3 
runestone.academy/ns/books/published/PTXSB/coding-exercises.html
Checkpoint 4.16.3. Coding Exercise, with Unit Tests.
View Source for exercise
<exercise xml:id="unit-test-example" label="coding-exercise-python-unit-test" xml:base="../../../examples/sample-book/rune-examples/activecode-unittest.xml">
  <title>Coding Exercise, with Unit Tests</title>

  <statement>
      <p>Fix the following code so that it always correctly adds two numbers. [Ed. Unit test support is experimental.]</p>
  </statement>
  <program interactive="activecode" language="python">
      <code>
      def add(a,b):
          return 4
      </code>
      <tests>
      from unittest.gui import TestCaseGui

      class myTests(TestCaseGui):

         def testOne(self):
             self.assertEqual(add(2,2), 4, "Adding two identical integers")
             self.assertEqual(add(7,13), 20, "Adding two different integers")
             self.assertAlmostEqual(add(2.0,3.0), 5.0, 5, "Adding two decimal numbers")

      myTests().main()
      </tests>
  </program>
  <answer>
      <p>We're not really sure.  But it would begin as follows:</p>
      <program language="c">
          <code>
          #include &lt;stdio.h&gt;

          int main(void)
          </code>
      </program>
  </answer>
</exercise>
Fix the following code so that it always correctly adds two numbers. [Ed. Unit test support is experimental.]
Answer.
We’re not really sure. But it would begin as follows:
#include <stdio.h>

int main(void)
The second way to automatically test code is to provide a set of structured input-output pair tests. For each test, the program will be run and fed the specified input. Then the program output will be compared against the test output to decide if the program handled the test correctly. This mechanism is useful for testing simple programs without functions and for languages that do not have a unit testing framework. A particular program can only have one of these two testing mechanisms.
IO tests are generally only available for programs that run on a Runestone server. (See Table 4.16.4 for a list of which languages support IO tests.). To preview them, see the Coding Exercises section of the Sample Book hosted on Runestone
 4 
runestone.academy/ns/books/published/PTXSB/coding-exercises.html
Structured IO tests are added as <iotest>s to the <tests> element. Each <iotest> element must have a single <input> and <output> element. The <input> element contains the input that will be fed to the program, and the <match> element contains the expected output of the program. Indentation for both will be normalized in the same way that programs are (so multiple-line sample output can be indented in your source document).
When evaluated, the program output and test <output> will have leading and trailing spaces removed. Other than that spacing, the two must match exactly to be considered a "passed" test.

Subsection 4.16.4 Interactive Program Capabilities

This table lists which types of interactivity are available on various combinations of servers and programming languages. The entry “AC + CL” means that both ActiveCode and CodeLens instances are available, but the ActiveCode instance will have a CodeLens button enabled. Although <tests> can be used to append code to any program, only in situations listed as “UT” below will the test output be parsed and interpreted by the server
Note that python is generic Python with the standard libraries (version 3.x). On the other hand python3 is a Runestone server installation (only) with a number of additional popular Python packages available, such as numpy and pandas.
Table 4.16.4. Interactive Programs
Language @language Server
Generic Runestone
Python python AC + CL + UT AC + CL + UT
Python 3 python3 AC + IO
Java java CL AC + CL + IO + UT
C c CL AC + CL + IO + UT
C++ cpp CL AC + CL + IO + UT
JavaScript javascript AC AC
HTML html AC AC
SQL sql AC AC
Octave octave AC + IO
AC = ActiveCode, CL = CodeLens, UT = Unit Tests (parsed), IO = IO Tests