<program interactive="activecode" label="hello-world-cpp" language="cpp" compiler-args="-std=c++17,-Wall,-g" linker-args="-g,-s">
<code>
#include <iostream>
#include <string>
using namespace std;
int main() {
string name;
cin >> name;
cout << "Hello, " << name << endl;
return 0;
}
</code>
<stdin>Jane</stdin>
</program>
Section 3.2 ActiveCode
Programs in supported languages are made interactive in HTML when for a list of what languages are supported in which environs.
@interactive
is set to activecode
. Some languages can be made interactive on any server, while others require being served from Runestone servers. See Interactive Programs Capabilities in the PreTeXt Guide1
pretextbook.org/doc/guide/html/topic-program-console.html#interactive-program-capabilities
Otherwise they are rendered as text with syntax coloring. Either way, if a
@language
is not specified, docinfo/programs/@language
will be checked to determine what language to assume the code is written in.print("Hello, World!")
A C program will only be interactive if hosted on a Runestone server.
#include <stdio.h>
int main(void)
{
puts("Hello, world!");
}
A Java program will only be interactive if hosted on a Runestone server.
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
}
}
Javascript programs are made interactive in HTML, on request.
Some languages, like Java or C++, are only interactive when run on a Runestone server where the code can be compiled and run. Those languages can specify
@compiler-args
and @linker-args
or @interpreter-args
as appropriate to the language. Default values for those options can be set in <docinfo/programs>
- any defaults set there will be used for any program that lacks the corresponding attribute.View Source for program
#include <iostream>
#include <string>
using namespace std;
int main() {
string name;
cin >> name;
cout << "Hello, " << name << endl;
return 0;
}
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
}
}
An Octave program will also only be interactive if hosted on a Runestone server. Octave is meant to be a drop-in replacement for Matlab.
View Source for program
<program xml:id="octave-simple" interactive="activecode" language="octave">
<code>
x = 2 + 2
printf("%d\n", x)
</code>
</program>
x = 2 + 2
printf("%d\n", x)
A language not supported by Runestone Services will always be rendered static.
View Source for program
<program xml:id="pascal-mistake" interactive="activecode" language="pascal">
<code>
program HelloWorld;
begin
WriteLn('Hello, world!');
end.
</code>
</program>
program HelloWorld;
begin
WriteLn('Hello, world!');
end.
The
@highlight-lines
works on ActiveCode programs, but the highlighted lines are only shown when viewing the initial code. Any version of the code that the reader has edited may have shifted lines of code and thus highlighting might affect the wrong lines, causing confusion.View Source for program
<program interactive="activecode" language="python" label="program-activecode-highlights" highlight-lines="1-2,5">
def add(a, b):
return a + b
# Use the function
result = add(2, 3)
if result == 5:
print("Test passed")
else:
print("Test failed")
</program>
A program can have a
<preamble>
and/or <postamble>
which are added to the code that the user writes before it is run. They are visible by default, but can be made invisible with @visible
set to "no"
. When visible, the code editor will prevent those regions from being modified. The indentation for lines in the preamble/code/postamble
elements will be calculated relative to each other - make sure to indent them all to a similar extent. (In the source for the sample below, the # TODO...
is intentially indented one stop extra so that the user’s code is part of the add
function.<tests>
are similar to <postamble>
in that it represents code that is added to the users submission. However, <tests>
is intended specifically for unit testing code (see examples below for unit testing in Python, Java, C++, SQL). Tests are invisble by default and can be made visible with @visible
set to "yes"
. For historical reasons, the indentation of the <tests>
is treated separately from the rest of the program.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>
Here is the same Python program from the previous section, but now with a
<preamble>
and <postamble>
that are invisible. The user will not see the code that is added to their submission. Not actually useful in this case, but it might be if you wanted to hide boilerplate setup from the reader.View Source for program
<program interactive="activecode" language="python" label="program-activecode-python-ambles-invisible">
<preamble visible="no">
def add(a, b):
</preamble>
<code>
# TODO - complete the add function
</code>
<postamble visible="no">
# Use the function
result = add(2, 3)
if result == 5:
print("Test passed")
else:
print("Test failed")
</postamble>
</program>
The following Python program is in a
<listing>
since we will want to reference it shortly. The program does not do very much, it just defines four variables whose values are lists of statistics. It should run, and there will be no syntax errors, but it is a bit boring since there is no output. Note that it does not have an @language
and is relying on the default one specified in <docinfo/programs>
View Source for program
<program xml:id="python-statistics" interactive="activecode" label="statistics">
<code>
loan_amount = [1250.0, 500.0, 1450.0, 200.0, 700.0, 100.0, 250.0, 225.0, 1200.0, 150.0, 600.0, 300.0, 700.0, 125.0, 650.0, 175.0, 1800.0, 1525.0, 575.0, 700.0, 1450.0, 400.0, 200.0, 1000.0, 350.0]
country_name = ['Azerbaijan', 'El Salvador', 'Bolivia', 'Paraguay', 'El Salvador', 'Philippines', 'Philippines', 'Nicaragua', 'Guatemala', 'Philippines', 'Paraguay', 'Philippines', 'Bolivia', 'Philippines', 'Philippines', 'Madagascar', 'Georgia', 'Uganda', 'Kenya', 'Tajikistan', 'Jordan', 'Kenya', 'Philippines', 'Ecuador', 'Kenya']
time_to_raise = [193075.0, 1157108.0, 1552939.0, 244945.0, 238797.0, 1248909.0, 773599.0, 116181.0, 2288095.0, 51668.0, 26717.0, 48030.0, 1839190.0, 71117.0, 580401.0, 800427.0, 1156218.0, 1166045.0, 2924705.0, 470622.0, 24078.0, 260044.0, 445938.0, 201408.0, 2370450.0]
num_lenders_total = [38, 18, 51, 3, 21, 1, 10, 8, 42, 1, 18, 6, 28, 5, 16, 7, 54, 1, 18, 22, 36, 12, 8, 24, 8]
</code>
</program>
An ActiveCode running on the Runestone server (rather than in a browser) can be provided with attributes that are flags to influence the compiler and linker, as in this
<program>
recycled from before.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
}
}
Now a programming exercise. The program upcoming is going to include all the code of the program preceding. This is accomplished with an
@include
attribute on the including program whose value is the @xml:id
of the included program. So by running the next program, it should pass all of its three tests (for example another example using unit tests, see Checkpoint 3.4.4). Now reload the page, do not run the program in the listing, and then see that the program in the exercise still runs correctly.You’ll see nothing that tells the reader that the one chunk of code is prefacing the other. And in static formats it might be even less obvious. So you will want to say something to alert the reader. Here it is easy: Checkpoint 3.2.14 includes all the code from Listing 3.2.12.
This program also makes use of
@autorun
to execute on page load and the @codelens
to disable the codelens feature.Checkpoint 3.2.14. A Python program, including another.
View Source for exercise
<exercise xml:id="exercise-python-including">
<title>A Python program, including another</title>
<statement>
<p>Compute the total amount of money loaned and store it in the variable <c>loan_total</c>.</p>
</statement>
<program autorun="yes" codelens="no" xml:id="python-summation" interactive="activecode" language="python" label="python-sum-total" include="python-statistics">
<code>
loan_total = 0
for loan in loan_amount:
loan_total += loan
print(loan_total)
</code>
<tests>
from unittest.gui import TestCaseGui
class MyTests(TestCaseGui):
def testOne(self):
self.assertTrue('loan_total' in self.getEditorText(), "you need a loan_total variable")
self.assertEqual(loan_total, sum(loan_amount), "Use the accumulator pattern to add up all the loans")
self.assertFalse('sum(' in self.getEditorText(), "you may not use sum()")
MyTests().main()
</tests>
</program>
</exercise>
Compute the total amount of money loaned and store it in the variable
loan_total
.Exact same exercise again, but now we include two programs. We first get the simple “Hello, world!” program at Listing 3.2.1 and then the same program defining the variables with lists of statistics at Listing 3.2.12. So the output just includes the extra result from the
print()
statement.This program also makes use of
@hidecode
to initially keep the code hidden and @download
to enable a file download of the program (that includes all the included code).Checkpoint 3.2.15. A Python program, including two others.
View Source for exercise
<exercise xml:id="exercise-python-including-two">
<title>A Python program, including two others</title>
<statement>
<p>Compute the total amount of money loaned and store it in the variable <c>loan_total</c>.</p>
</statement>
<program xml:id="python-summation-two" interactive="activecode" language="python" label="python-sum-total-two" include="python-hello-world python-statistics " hidecode="yes" download="yes">
<code>
loan_total = 0
for loan in loan_amount:
loan_total += loan
print(loan_total)
</code>
<tests>
from unittest.gui import TestCaseGui
class MyTests(TestCaseGui):
def testOne(self):
self.assertTrue('loan_total' in self.getEditorText(), "you need a loan_total variable")
self.assertEqual(loan_total, sum(loan_amount), "Use the accumulator pattern to add up all the loans")
self.assertFalse('sum(' in self.getEditorText(), "you may not use sum")
MyTests().main()
</tests>
</program>
</exercise>
Compute the total amount of money loaned and store it in the variable
loan_total
.Here is an activecode with
@language
set to sql
uses the @database
to load a SQLite database file.Checkpoint 3.2.16. An SQL program that uses an SQLite database file.
View Source for exercise
<exercise xml:id="exercise-sql-using-db">
<title>An SQL program that uses an SQLite database file</title>
<statement>
<p>Select all the columns of all the rows in the <c>test</c> database table.</p>
</statement>
<program xml:id="sql-using-db" interactive="activecode" language="sql" label="sql-using-db" database="sql/test.db">
<code>
SELECT * FROM test
</code>
<tests>
assert 1,1 == world
assert 0,1 == hello
assert 2,1 == 35
</tests>
</program>
</exercise>
Select all the columns of all the rows in the
test
database table.Now a C++ program that is spread across multiple files. This example will only be interactive on a Runestone server.
First, we have a
.h
file that defines an @filename
. It has an @xml:id
so other elements can reference it. It also has an @label
which is it’s unique identifier in the Runestone database. (The label is intentionally different than the xml:id for demonstration purposes, but they can be the same.) The @filename
is used to indicate what to name to use when the contents of the element are written to a file on the server - other program code and/or tools on the server can look for it using this name. The @filename
need not be unique—we could have multiple programs with @filename="add.h"
. As we will see below, the author specifies which “version” of a file should be used in any given location with its unique xml:id.The
<program>
is inside of a <listing>
so that we have a place to add a caption and so that we can reference the code sample, including that caption, with an <xref>
from elsewhere. Note that the <listing>
has both a <caption>
and a <title>
. The <caption>
will be rendered with the program. The <title>
will not appear locally. It will be used if an <xref>
links to the <listing>
using @text="title"
View Source for program
<program filename="add.h" xml:id="addh-v1" label="addh-v1-label" language="cpp">
int add(int a, int b);
</program>
int add(int a, int b);
Next, a
.cpp
file. Note that because it is part of an exercise, the @label
is applied to the exercise that contains it. The @xml:id
and @filename
still belong on the program itself.It also has
@extra-compiler-args
. These will be added to any default compiler args for the book. In this case, the -c
indicates that we only want to compile this file when it is “Run” and not try to link it or actually run it.Checkpoint 3.2.18.
You can leave this code as is or modify it. When you click “Run”, the code will be compiled. However, it will not be run as this is not a standalone program. To run it, use the full program below.
int add(int a, int b) {
return a + b;
}
Finally, the core program.
@add-files
is used to specify (by xml:id) the files that need to be added to the program directory. @compile-also
specifies files that must be compiled with this source file (they will be assumed to be also part of @add-files
). Notice that when using @add-files
to reference code we want to include, we use the xml:id of the target program - it has the contents we want to include. When making a textual reference with an <xref>
we can’t link to the program, as it lacks the contextual information required to create a valid reference. Instead, we should link to a listing (or some other container) that surrounds the code, like this: Listing 3.2.17 or add.h (version 1)
View Source for program
<program label="multiple-file-program" interactive="activecode" add-files="addh-v1" compile-also="addcpp-v1" language="cpp">
#include "add.h"
#include <iostream>
using namespace std;
int main() {
int a = 1;
int b = 2;
cout << "The sum of " << a << " and " << b << " is " << add(a, b) << endl;
}
</program>
#include "add.h"
#include <iostream>
using namespace std;
int main() {
int a = 1;
int b = 2;
cout << "The sum of " << a << " and " << b << " is " << add(a, b) << endl;
}
Note that there is a cross page test of
@add-files
located in Exercises 3.19
A nonsense paragraph just to check on spacing. A nonsense paragraph just to check on spacing. A nonsense paragraph just to check on spacing. A nonsense paragraph just to check on spacing.