Ace-inline filter demo

This page demonstrates the capabilities of the new and experimental Ace inline Moodle filter. This filter operates on the rendered HTML of a page, so its use requires that teachers be able to edit content in HTML. See the filter documentation for details.

The original HTML of (most of) this page can be inspected by importing the description 'question' demoaceinline.xml into the question bank on your own Moodle server and opening it for edit in HTML mode. Or you can simply open that link directly in your browser, if you're able to read the XML itself and identify the relevant embedded HTML within it (essentially, all the blue text).

To revert any edited code to its original version just reload the page.

Note: the Ace inline filter requires a new version of CodeRunner that provides a sandbox web service (version 4.2.1 or later).

Highlighting code

The simplest use of the filter is to let the Ace editor do syntax colouring of code. This is achieved by putting the code into a HTML <pre> element with the class ace-highlight-code. The default language is python; if you want another language you should add to the pre element an attribute like data-lang="java". Here are two examples, the first in Python, the second in Java.

A python example

print("Some squares")
for i in range(10):
print(i, i ** 2)

A Java example

public class hello {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}

Note: for strict HTML5 compliance, all non-standard element attributes must be prefixed with 'data-', which is why the language attribute is called 'data-lang' rather than just 'lang'. However, if you don't care about such compliance, you can drop the prefix; the code will still work but will not pass HTML5 validator checks. All code in this test/demo question use the full 'data-' form for attributes.

Options for highlighting

Line numbers are not shown by default, but an attribute data-start-line-number can be added to set the line number to use on the first line. Its default value is none, resulting in no line numbers being displayed. If non-none, the usual value is '1', but other values can be used in special cases, for example if code is broken into two separate highlighted segments.

There is also an optional attribute data-font-size to set the font size within the Ace editor.

The following example shows the Java hello world program with line numbers starting at 5 and a font-size of 16 pts.

public class hello {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}

Making code interactive

If the class of the HTML <pre> element containing the code is instead set to ace-interactive-code, a Try it! button is added below the Ace editor panel. When clicked, the code is sent to the CodeRunner sandbox (usually a Jobe server) for execution and the result is displayed below the button. The code can be edited and re-run an arbitrary number of times.

Here are firstly the same two examples from above, but with class ace-interactive-code, and then C and C++ hello world programs. An extra blank line is being displayed in these cases by moving the terminating '</pre>' onto a new line rather than putting it hard up against the last non-whitespace character in the code. This makes it clear that all the editable code is being displayed, but you might prefer not to do this - your call.

A python example

print("Hello squares")
for i in range(10):
print(i, i ** 2)


A Java example

public class hello {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}


Hello world in C

#include <stdio.h>
int main() {
puts("Hello world!");
}


Hello world in C++

#include <iostream>
using namespace std;
int main() {
cout << "Hello world" << endl;
}


Providing standard input (the new approved way)

Using stdin in conjunction wiht ace-interactive-code samples is problematic if users are expecting an interactive prompt-read-prompt-read style of standard input. This really isn't possible with this filter because clicking Try it! simply sends a job to the jobe server for execution and then displays the results. However, the author can provide the user with a text area into which they can enter any standard input (in general, multiple lines) which are then read on demand by the program. The data-stdin-taid attribute of the <pre> element specifies the text area (or other HTML element with a val() method) to be used in this way. For example:

Standard input:

while 1:
try:
print(input())
except EOFError:
break


If the author wishes to provide fixed uneditable standard input they can simply hide the textarea.

Providing standard input (the old deprecated way)

If there is no data-stdin-taid attribute, the question author can provide a standard input string using the attribute data-stdin. Since HTML5 allows multiline literal strings, the stdin stream can be multiline too.

The following example shows a Python program that reads standard input until EOF. The stdin attribute here is

Chaos reigns within.
Reflect, repent, and reboot.
Order shall return.
while 1:
try:
print(input())
except EOFError:
break


Providing files

Files can uploaded into the working directory of the program in two different ways. Both require the author to add additional HTML elements to the page.

1. Named strings, or pseudo-files, can be defined by the data-file-taids attribute. This is a JSON object mapping filenames (fixed by the question author) to the IDs of textareas on the same page. The user can enter text into the textareas to define the pseudo-file contents prior to clicking Try it! The question author can hide the textareas if they wish to fix the file contents, e.g. as support files for the run.
2. Actual files can be uploaded by the user via a standard <input type="file"> element by the data-file-upload-id attribute, which is the HTML element ID of the <input> element.

If both attributes are defined, files uploaded via the uploader override any identically named pseudo-files.

Pseudo file example: an HTML encoder

Copy the text that you wish to HTML encode into the text area, then click Try it!

from html import escape
with open('raw.txt') as infile:
if len(raw.strip()) == 0:
print("NO INPUT SUPPLIED!")
else:
print(escape(raw))


File upload example: an HTML encoder

Select a single file of type .txt, then click Try it!

import os
from html import escape
text_files = [filename for filename in os.listdir() if filename.endswith('.txt')]
if len(text_files) == 0:
print("No '.txt' files found!")
elif len(text_files) != 1:
else:
with open(text_files[0]) as infile:
if len(raw.strip()) == 0:
print("EMPTY FILE!")
else:
print(escape(raw))


The complete set of ace-interactive-code options

The complete set of ace-interactive-code elements is as follows. Attributes in bold have not been introduced above.

Attribute Meaning
data-ace-lang
The language to use for the Ace editor syntax highlighting, if different from the language of the job as run on Jobe. For example, the data-code-mapper option might be used to wrap a program in C within a Python script that is executed on Jobe.
data-button-name
Sets the label to use for the button instead of 'Try it!'
data-start-line-number
Can be set to 'none' to suppress line numbers or to an integer to start numbering with the given value
data-readonly
If set (to any value) the supplied code cannot be edited by the user
data-code-mapper
The name of a global JavaScript function (i.e. an attribute of the window object) that takes as a parameter the code from the Ace editor and returns a modified version. This can be used to perform arbitrary transformations of the code the student is writing into some other program. If prefix or suffix code is supplied (see below) it is added after the code-mapper has been used.
data-dark-theme-mode
Selects when to use a dark mode for the Ace editor. Has values 0, 1 or 2 for no, maybe and yes. If 1 (maybe) is chosen, the dark theme will be used if the browser's prefers-color-scheme:dark media query returns a match, so this may change with browser, operating system or time of day. The default value is set by the administrator setting for the plugin.
data-file-upload-id
The ID of an HTML input element of type file, which can be used to select multiple files for uploading into the working directory when Try it! is clicked.
data-file-taids
A JSON string defining a mapping from pseudo-filenames to textarea element IDs containing the pseudo-file contents. When Try it! is clicked, a file is created for each listed textarea and uploaded to the working directory.
data-font-size
The font size to use in the Ace editor, e.g. '11pt'.
data-html-output
If set (to any value) the output from the program is interpreted as raw html to insert into the DOM, rather than being escaped and displayed in a <p> element.
data-min-lines
The minimum number of lines to display in the Ace editor. Default 4.
data-max-lines
The maximum number of lines to display in the Ace editor without a scrollbar. Default 50.
data-max-output-length
The limit to the displayed length of stdout and stderr strings. Strings longer than this are truncated prior to display. Default: 10,000.
data-params
A JSON string of run-time parameters, passed to the Jobe engine (q.v.). For example, {"cputime": 5}, which is the default value of the attribute and sets a time limit of 5 seconds for the run. Rarely needed.
data-prefix
Defines code that will be inserted before the code from the Ace editor (so the student doesn't see it). An extra newline is not inserted between the prefix and the visible code - you must insert it explicitly if you want one.
data-readonly
If set, to any value, prevents the user modifying the supplied code.
data-start-line-number
Sets the number to use for the first line of code in the Ace editor. Default 1.
data-stdin (deprecated)
Defines a string to be used as standard input when the program is run. Deprecated in favour of data-stdin-taid
data-stdin-taid
Specifies the ID of a textarea element (or other HTML element with a jQuery val() method that supplies standard input to the program.
data-suffix
Defines code that will be inserted after the code from the Ace editor (so the student doesn't see it). An extra newline is not inserted between the visible code and the suffix - you must insert it explicitly if you want one.

A simple data-html-output example

The following example shows how the data-html-output option works. It's only rarely useful in isolation but in conjunction with data-code-mapper and/or data-prefix and data-suffix it can be used by question authors to provide arbitrary output. The following example also changes the button name.

print("<h2>I'm a heading</h2>")
print("<ol><li>Bullet 1</li><li>Bullet 2</li></ol>")


A simple use of code-mapper

In this case we define (using a <script> element) a function called doubler that returns its parameter concatenated onto itself. The <pre> element that wraps the following code has the attribute data-code-mapper set to 'doubler'.

print("Hello world!")


A simple use of data-prefix

In the above example showing the use of stdin, the input() function was called and the result printed. But if students are using input() interactively, they expect to see what they enter from the keyboard echoed to the screen. To achieve such an effect in Python, prefix code could be added that simulates this echoing. For example, here's a program that asks the student for their name and age and prints a message telling them their age next year.The data-stdin attribute of the <pre> element has been set to contain the two lines 'jeremy' and '11'.

name = input("What's your name? ")
age = int(input("How old are you? "))
print(f"Hi {name}, next year you'll be {age + 1}")


Displaying matplotlib images

By using the data-code-mapper option (and/or data-prefix and data-suffix) in conjunction with data-html-output it is possible, with some difficulty, to define an ace-interactive-code block that will let students run matplotlib code and display both the textual output from the question and any output images. Here is an example, which also shows the use of the dark-theme mode and the use of the data-max-lines attribute (set to 15). Inspect the HTML at your peril!

import matplotlib.pyplot as plt
import numpy as np

# Generate some text output
print("I am a line of output")
print("And so am I")

# Now the graph plotting
axes = plt.axes()
xs = np.linspace(0, 720, 200)
ys = np.sin(2 * np.pi * xs / 360)
axes.plot(xs, ys)
axes.set_title("y = sin(x)")
axes.set_xlabel('x (degrees)')
axes.set_ylabel('y')
axes.grid()
plt.show()


Using Ace-interactive-filter for applets

The latest version of the ace-interactive-filter plugin allows you to upload files and to read the contents of various textareas or other HTML elements (anything with a jquery val method) as if they were files. You can also hide the actual code. Consequently it's possible to use the Ace inline filter to embed executable code rather like traditional applets, using any language of your choice. [Which of course, should be Python.]

This approach to applets is, in most cases, much weaker than using JavaScript directly. For example you can't do any event handling or manipulate the DOM directly. But it has the big advantages of:

• Language familiarity (for those who are more familiar with Python than JavaScript)
• The power of Python for more advanced tasks, such as processing CSV files, plotting graphs, numerical analysis, etc.

For example: