tb-code¶
The tb-code directive creates a runnable source-code block.
In HTML, readers can send code to a remote server and optionally
edit the source before running it again.
Synopsis¶
The general format of the tb-code directive is:
.. tb-code:: language
:optional parameter: value
+ --- Source code area ---
|
| one or more lines of source code
|
+ ------------------------
The source code area is required.
The language can be supplied as the directive argument or as the language
option.
Options¶
- caption
String. Optional. Standardcode-blockcaption displayed with the static code listing. A caption alone does not create a hyperlink target. Combinecaptionwithnamewhen a block should be referenced with:numref:.- class
StringorList. Optional. A CSS class to add to the directive. See Common options for details.- compileargs, linkargs, runargs, interpreterargs
Stringorlist. Optional. Arguments passed through the Jobeparametersobject. Use Python-style list syntax when an argument contains punctuation or spaces, for example:compileargs: ['-Wall', '-std=c++11']. A simple shell-style string such as:runargs: --verbose sample.txtis also accepted. Whenrunargsis present, HTML shows the value in an editable text input.- dedent
Integer. Optional. Standard Sphinxcode-blockdedent option passed through to the static highlighted listing. See the Sphinx code-block documentation for more information.- edit-label, hide-edit-label
String. Optional. Labels for the edit toggle button.edit-labelis used when the editor is hidden, andhide-edit-labelis used when the editor is visible.- emphasize-lines
String. Optional. Standard Sphinxcode-blockemphasize-lines option passed through to the static highlighted listing. See the Sphinx code-block documentation for more information.- endpoint
String. Optional. Jobe-compatiblerunsendpoint for this code block. Defaults totb_code_default_endpoint.- files
String. Optional. Attaches one or moretb-fileartifacts to the run request. Use filenames from thetb-filefilenameoption, separated by spaces, commas, or new lines.:files: input.txt data/config.jsonText files appear in HTML as editable file textareas unless the
tb-filewas markedreadonly. Binary files are attached as read-only base64 content.- files-endpoint
String. Optional. Jobe-compatiblefilesendpoint used to upload support files before a run. Defaults totb_code_files_endpoint.- force
Boolean. Optional. Standard Sphinxcode-blockforce option passed through to the static highlighted listing. See the Sphinx code-block documentation for more information.- hidden
Boolean. Optional. Hides rendered output. Hidden blocks can still be named and included by anothertb-codeblock.- include
String. Optional. Replaces{{PLACEHOLDER}}tokens in this block with literal source copied from a namedtb-code,code-block, orliteralincludedirective. Use one mapping per line::include: PUBLIC_MEMBERS: account-methods PRIVATE_MEMBERS: account-fieldsIf the placeholder appears on its own indented line, the inserted source uses the same indentation. Include names use normal Sphinx reference names, so they can refer to named code in another source file. Duplicate include fragment names stop the build.
- language
String. Optional. Source language. This may also be supplied as the directive argument. Default is configured bytb_code_default_language.- lineno-start
Integer. Optional. Standard Sphinxcode-blocklineno-start option passed through to the static highlighted listing. See the Sphinx code-block documentation for more information.- linenos
Boolean. Optional. Standard Sphinxcode-blocklinenos option passed through to the static highlighted listing. See the Sphinx code-block documentation for more information.- name
String. Optional. Sphinx reference name for this runnable code block. Usenameby itself for explicit-title references such as:ref:`run this code <example-code>`. Usenamewithcaptionfor numbered references such as:numref:`example-code`. See Common options for details.- readonly
Boolean. Optional. Hides the edit control in HTML output.- revision-label
String. Optional. Label for the source version slider.- run-after
String. Optional. One or more named code fragments appended to the current source only when code is sent to the execution service. The appended source is not shown in the static listing, editor, or source version history.Use one name per line, or separate names with commas:
:run-after: test-main assertions- run-before
String. Optional. One or more named code fragments prepended to the current source only when code is sent to the execution service. The prepended source is not shown in the static listing, editor, or source version history.Use one name per line, or separate names with commas:
:run-before: imports setup-fixture- run-label
String. Optional. Label for the HTML run button.- show-tutor
Boolean. Optional. If present, HTML adds a Python Tutor button for supported languages: C, C++, Python, Java, and JavaScript. The button opens a new window with a Python Tutor permalink containing the current execution source, including anyrun-beforeandrun-afterfragments.- stdin
String. Optional. Standard input sent with the run request. When present, HTML shows this value in an editable text input.
Reference behavior¶
tb-code follows Sphinx code-block reference conventions.
Use caption for the visible listing caption.
Use name for a stable hyperlink target.
Use both options when a code block should be referenced with :numref::
See :numref:`hello-code`.
.. tb-code:: python
:name: hello-code
:caption: Hello example
print("Hello")
If only name is set, use an explicit-title :ref::
See :ref:`this runnable example <hello-code>`.
.. tb-code:: python
:name: hello-code
print("Hello")
Sphinx configuration options¶
tb_code_default_endpointString. Default Jobe-compatible run endpoint. The project default ishttps://delicate-frost-8843.fly.dev/jobe/index.php/restapi/runs/.tb_code_languages_endpointString. Jobe-compatible language discovery endpoint. The project default ishttps://delicate-frost-8843.fly.dev/jobe/index.php/restapi/languages.tb_code_files_endpointString. Jobe-compatible file upload endpoint. The project default ishttps://delicate-frost-8843.fly.dev/jobe/index.php/restapi/files/.tb_code_validate_languageBoolean. If true, query the languages supported before running code. If discovery reports that the configured language is unsupported, show a warning. If discovery is unavailable, execution still proceeds.tb_code_default_languageString. Default source language. The project default ispython3.tb_code_language_mapdict. Optional aliases from author-facing language names to Jobe language identifiers. Use this when authors prefer a name that differs from the Jobe server’s language ID, or when you wanttb-codeto match language names used elsewhere in the book.For example,
{"python": "python3", "c++": "cpp", "js": "nodejs"}lets authors write.. tb-code:: python,.. tb-code:: c++, or.. tb-code:: jswhile Jobe receivespython3,cpp, ornodejs. If the author-facing name already matches the Jobe ID, such asjavatojava, no mapping is needed.tb_code_language_defaultsdict. Optional per-language Jobe parameter defaults. Keys may be author-facing language names such asc++or Jobe language identifiers such ascpp. Values are dictionaries containingcompileargs,linkargs,runargs, orinterpreterargslists. If both an author-facing name and its mapped Jobe ID have defaults, the author-facing name takes precedence.tb_code_block_defaultsdict. Optional defaults for standard Sphinxcode-blockoptions used bytb-code. This is useful for presentation settings that should apply to every runnable code block, such as line numbers or custom styling.tb_code_block_defaults = { "linenos": True, "lineno-start": 1, "class": ["touchbook-code"], }
Directive options override matching values from
tb_code_block_defaults. Avoid settingnamein this dictionary because reference names should be unique per block.tb_code_run_labelString. Default label for the run button. The project default isRun.tb_code_edit_labelString. Default label for the edit button when the editor is hidden. The project default isEdit.tb_code_hide_edit_labelString. Default label for the edit button when the editor is visible. The project default isHide editor.tb_code_revision_labelString. Default label for the source version slider. The project default isSource version.
Service contract¶
Code that cannot be compiled natively in a browser is sent to a Jobe server for processing.
tb-code sends a Jobe-compatible request shaped like this:
{
"run_spec": {
"language_id": "cpp",
"sourcecode": "int main() { return 0; }",
"input": "Alice",
"file_list": [["tbfileabc123", "input.txt"]],
"parameters": {
"compileargs": ["-Wall", "-std=c++11"],
"linkargs": [],
"runargs": [],
"interpreterargs": []
}
}
}
The directive options compileargs, linkargs, runargs, and
interpreterargs populate the corresponding keys in parameters.
Values set on an individual directive override matching values from
tb_code_language_defaults.
Defaults for keys not supplied on the directive still apply.
If stdin or runargs are configured, HTML presents editable text inputs
initialized from those values.
The current input values are used when the reader presses Run.
These runtime inputs are separate from the source version history.
When files is configured, each attached file is uploaded to the configured
Jobe files endpoint before the run request is sent. The run request then
uses Jobe’s file_list field to map each uploaded file identifier to the
filename visible inside the execution workspace.
When run-before or run-after is configured, those named fragments are
combined with the current source only for the execution request. They are not
shown in the static listing or editor. Treat these fragments as hidden from the
page interface, not as private code; generated HTML can still be inspected by a
reader.
When show-tutor is configured for C, C++, Python, Java, or JavaScript,
HTML adds a Python Tutor button. The permalink uses the same execution source
that the Run button sends to Jobe. Runtime standard input, run arguments, and
attached files are not included in the Python Tutor URL.
Accessibility behavior¶
The no-JS HTML fallback is a normal Sphinx-highlighted code listing. HTML adds
native button controls, a textarea editor, a source version slider,
optional runtime text inputs, a polite status region, and a labeled output
region.
The edit button is a toggle. When the editor is opened, its label changes from
tb_code_edit_label to tb_code_hide_edit_label and aria-expanded is
updated. The source version slider starts with the original source as version 1
and appears after the editable source creates a second version. Once more than
one version exists, the slider remains visible when the editor is hidden so
readers can select and run an older source version. Loading a version updates
the textarea and the visible source listing.
Fallback behavior¶
PDF and text builders render the source code as static readable content.
Examples¶
Example 1: Basic Python¶
Source
.. tb-code:: python
print("Hello, world")
Rendered
1print("Hello, world")
Example 2: Python defaults¶
Python usually does not require compile or link arguments, but defaults can
still be set in conf.py. The example below maps python to Jobe’s
python3 language identifier and provides an interpreter argument default.
conf.py
tb_code_default_language = "python3"
tb_code_language_map = {
"python": "python3",
}
tb_code_language_defaults = {
"python3": {
"interpreterargs": ["-B"],
},
}
Source
.. tb-code:: python
:caption: Hello from Python
:interpreterargs: ['-B']
print("Hello, world")
Rendered
1print("Hello, world")
Example 3: Include named code¶
Use include to assemble a runnable block from named source fragments. This
is useful when an example needs to show part of a program separately and later
run it in a larger context.
Source
.. tb-code:: cpp
:name: account-methods
:hidden:
public:
int balance() const;
.. code-block:: cpp
:name: account-fields
private:
int balance_;
.. tb-code:: cpp
:name: code-ex3
:caption: Account class assembled from named code
:include:
PUBLIC_MEMBERS: account-methods
PRIVATE_MEMBERS: account-fields
class account {
{{PUBLIC_MEMBERS}}
{{PRIVATE_MEMBERS}}
};
Rendered
private:
int balance_;
1class account {
2 public:
3 int balance() const;
4 private:
5 int balance_;
6};
Example 4: Execution-only test runner¶
Use run-after when code should be sent to the execution service without
being shown in the static listing or editor. This is useful for test runners
or support code that would distract from the code students should read.
Source
.. tb-code:: cpp
:name: account-balance-tests
:hidden:
int main() {
account sample;
return sample.balance() == 100 ? 0 : 1;
}
.. tb-code:: cpp
:name: code-ex4
:caption: Account implementation with hidden tests
:run-after: account-balance-tests
:show-tutor:
class account {
public:
int balance() const {
return 100;
}
};
Rendered
1class account {
2public:
3 int balance() const {
4 return 100;
5 }
6};
Example 5: Python command-line arguments¶
Use runargs when a program expects command-line arguments. In HTML, the
initial value appears in an editable text input before the program runs.
Source
.. tb-code:: python
:name: code-ex5
:caption: Python command-line arguments
:runargs: Ada Lovelace
import sys
if len(sys.argv) < 3:
print("Please provide a first and last name.")
else:
first = sys.argv[1]
last = sys.argv[2]
print(f"Hello, {first} {last}!")
Rendered
1import sys
2
3if len(sys.argv) < 3:
4 print("Please provide a first and last name.")
5else:
6 first = sys.argv[1]
7 last = sys.argv[2]
8 print(f"Hello, {first} {last}!")
Example 6: Java¶
Java examples often need JVM limits. These can be configured once in
conf.py and overridden on a specific tb-code block when needed.
conf.py
tb_code_language_defaults = {
"java": {
"interpreterargs": ["-Xrs", "-Xss8m", "-Xmx128m"],
},
}
Source
.. tb-code:: java
:name: code-ex6
:caption: Fahrenheit to Celsius
:emphasize-lines: 9
:interpreterargs: ['-Xrs', '-Xss8m', '-Xmx128m']
:stdin: 100
import java.util.Scanner;
public class TempConv {
public static void main(String[] args) {
Double fahr;
Double cel;
Scanner in;
in = new Scanner(System.in);
System.out.println("Enter the temperature in F: ");
fahr = in.nextDouble();
cel = (fahr - 32) * 5.0/9.0;
System.out.println(fahr + " degrees F is: " + cel + " C");
}
}
Rendered
1import java.util.Scanner;
2
3public class TempConv {
4 public static void main(String[] args) {
5 Double fahr;
6 Double cel;
7 Scanner in;
8
9 in = new Scanner(System.in);
10 System.out.println("Enter the temperature in F: ");
11 fahr = in.nextDouble();
12
13 cel = (fahr - 32) * 5.0/9.0;
14 System.out.println(fahr + " degrees F is: " + cel + " C");
15 }
16
17}
Example 7: C++¶
For C++, use compileargs for compiler flags and linkargs for linker
flags. The language map lets authors write c++ while sending Jobe the
cpp language identifier.
conf.py
tb_code_language_map = {
"c++": "cpp",
"cpp": "cpp",
}
tb_code_language_defaults = {
"cpp": {
"compileargs": ["-Wall", "-Wextra", "-pedantic", "-std=c++11"],
},
}
Source
.. tb-code:: c++
:name: code-ex7
:caption: Hello from C++
:compileargs: ['-Wall', '-Wextra', '-pedantic', '-std=c++11']
:runargs: --repeat=3
:stdin: Alice
// A simple test for C++11 compiler
#include <cstdlib>
#include <iostream>
#include <string>
int main(int argc, char* argv[]) {
int test[] = { 1, 2, 3, 5, 8 };
for (auto i: test) {
std::cout << "i is " << i << '\n';
}
int repeat = 1;
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg.find("--repeat=") == 0) {
repeat = std::atoi(arg.substr(9).c_str());
if (repeat < 1) {
repeat = 1;
}
}
}
std::string name;
std::cin >> name;
for (int i = 0; i < repeat; ++i) {
std::cout << "Hello, " << name << "!\n";
}
return 0;
}
Rendered
1// A simple test for C++11 compiler
2#include <cstdlib>
3#include <iostream>
4#include <string>
5
6int main(int argc, char* argv[]) {
7 int test[] = { 1, 2, 3, 5, 8 };
8 for (auto i: test) {
9 std::cout << "i is " << i << '\n';
10 }
11
12 int repeat = 1;
13 for (int i = 1; i < argc; ++i) {
14 std::string arg = argv[i];
15 if (arg.find("--repeat=") == 0) {
16 repeat = std::atoi(arg.substr(9).c_str());
17 if (repeat < 1) {
18 repeat = 1;
19 }
20 }
21 }
22
23 std::string name;
24 std::cin >> name;
25 for (int i = 0; i < repeat; ++i) {
26 std::cout << "Hello, " << name << "!\n";
27 }
28 return 0;
29}
Example 8: GNU Octave¶
Octave is a powerful Scientific Programming Language designed to be largely compatible with Matlab. Although Octave does support built-in 2D/3D plotting and visualization tools those tools are not available through the touchbook interface. Output is limited to text.
Source
.. tb-code:: octave
:name: code-ex8
:caption: Solve Linear Algebra Equations with Octave
# Define matrices
A = [2, 1; 1, 3];
B = [5, 6; 4, 7];
# Solve matrix equation X = A\B
X = A \ B
Rendered
1# Define matrices
2A = [2, 1; 1, 3];
3B = [5, 6; 4, 7];
4
5# Solve matrix equation X = A\B
6X = A \ B