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. Standard code-block caption displayed with the static code listing. A caption alone does not create a hyperlink target. Combine caption with name when a block should be referenced with :numref:.

class

String or List. Optional. A CSS class to add to the directive. See Common options for details.

compileargs, linkargs, runargs, interpreterargs

String or list. Optional. Arguments passed through the Jobe parameters object. 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.txt is also accepted. When runargs is present, HTML shows the value in an editable text input.

dedent

Integer. Optional. Standard Sphinx code-block dedent 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-label is used when the editor is hidden, and hide-edit-label is used when the editor is visible.

emphasize-lines

String. Optional. Standard Sphinx code-block emphasize-lines option passed through to the static highlighted listing. See the Sphinx code-block documentation for more information.

endpoint

String. Optional. Jobe-compatible runs endpoint for this code block. Defaults to tb_code_default_endpoint.

files

String. Optional. Attaches one or more tb-file artifacts to the run request. Use filenames from the tb-file filename option, separated by spaces, commas, or new lines.

:files: input.txt data/config.json

Text files appear in HTML as editable file textareas unless the tb-file was marked readonly. Binary files are attached as read-only base64 content.

files-endpoint

String. Optional. Jobe-compatible files endpoint used to upload support files before a run. Defaults to tb_code_files_endpoint.

force

Boolean. Optional. Standard Sphinx code-block force 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 another tb-code block.

include

String. Optional. Replaces {{PLACEHOLDER}} tokens in this block with literal source copied from a named tb-code, code-block, or literalinclude directive. Use one mapping per line:

:include:
   PUBLIC_MEMBERS: account-methods
   PRIVATE_MEMBERS: account-fields

If 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 by tb_code_default_language.

lineno-start

Integer. Optional. Standard Sphinx code-block lineno-start option passed through to the static highlighted listing. See the Sphinx code-block documentation for more information.

linenos

Boolean. Optional. Standard Sphinx code-block linenos 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. Use name by itself for explicit-title references such as :ref:`run this code <example-code>`. Use name with caption for 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 any run-before and run-after fragments.

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_endpoint

String. Default Jobe-compatible run endpoint. The project default is https://delicate-frost-8843.fly.dev/jobe/index.php/restapi/runs/.

tb_code_languages_endpoint

String. Jobe-compatible language discovery endpoint. The project default is https://delicate-frost-8843.fly.dev/jobe/index.php/restapi/languages.

tb_code_files_endpoint

String. Jobe-compatible file upload endpoint. The project default is https://delicate-frost-8843.fly.dev/jobe/index.php/restapi/files/.

tb_code_validate_language

Boolean. 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_language

String. Default source language. The project default is python3.

tb_code_language_map

dict. 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 want tb-code to 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:: js while Jobe receives python3, cpp, or nodejs. If the author-facing name already matches the Jobe ID, such as java to java, no mapping is needed.

tb_code_language_defaults

dict. Optional per-language Jobe parameter defaults. Keys may be author-facing language names such as c++ or Jobe language identifiers such as cpp. Values are dictionaries containing compileargs, linkargs, runargs, or interpreterargs lists. If both an author-facing name and its mapped Jobe ID have defaults, the author-facing name takes precedence.

tb_code_block_defaults

dict. Optional defaults for standard Sphinx code-block options used by tb-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 setting name in this dictionary because reference names should be unique per block.

tb_code_run_label

String. Default label for the run button. The project default is Run.

tb_code_edit_label

String. Default label for the edit button when the editor is hidden. The project default is Edit.

tb_code_hide_edit_label

String. Default label for the edit button when the editor is visible. The project default is Hide editor.

tb_code_revision_label

String. Default label for the source version slider. The project default is Source 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

Hello from Python
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_;
Account class assembled from named code
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

Account implementation with hidden tests
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

Python command-line arguments
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

Fahrenheit to Celsius
 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

Hello from C++
 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

Solve Linear Algebra Equations with Octave
1# Define matrices
2A = [2, 1; 1, 3];
3B = [5, 6; 4, 7];
4
5# Solve matrix equation X = A\B
6X = A \ B