Ace-inline filter demo (updated version)

This page demonstrates the capabilities of the 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 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), and TinyMCE functionality requires Moodle 4.1.

Utilising Ace-inline filter

As of Moodle 4.1, the following code adding and editing options are available:

  • Utilising the new TinyMCE editor's 'Code sample' option.
    • This option is recommended for casual code authors, as the editing UI allows direct copying and pasting of code without reformatting. Note: Due to TinyMCE's quirks, certain options are limited.
  • Utilising Markdown Extra, either in the Moodle editor or externally for importing questions.
    • This option is recommended for code authors who may want to create questions outside of the editor in a readable format and import them into Moodle with expected behaviour.
  • Editing the HTML directly in an HTML editor.
    • This option is recommended for code authors who require full functionality/customisation and are comfortable using HTML.

Further information on how to use these options are detailed in the ReadMe on trampgeek/moodle-filter_ace_inline

Highlighting code

The simplest use of the filter is to let the Ace editor do syntax colouring of code. Using one of the above methods, the code will need to be wrapped in an HTML <pre> element. The attribute data-ace-highlight-code should be set in the <pre> tag. (Note: this will change to data-ace-highlight-code="" upon saving, which is equivalent.)

If using the TinyMCE option, you will not need to add any other attributes if the language chosen in the editor is the desired language to be displayed.

Otherwise, the default language is Python(3); 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: It is highly recommended to ensure the data- prefix is preserved for strict HTML5 compliance, as well as, to prevent unwanted editor-based stripping of attribute tags. Using this prefix is why the language attribute is called 'data-lang' rather than just 'lang'. However, if you don't care about such compliance and want to edit entirely in HTML, you can drop the prefix; the code will still work (in most instances; see ReadMe for more specific information) 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 an attribute of the HTML <pre> element containing the code is instead set to data-ace-interactive-codea 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 the attribute data-ace-interactive-code, and then C and C++ hello world programs.The following Python example will include step-by-step instructions on how to utilise HTML encoding, TinyMCE's Code sample feature and Markdown extra to execute this code snippet in a "description" type question. Make sure the ace-inline filter is set to "On" in the course: 

          

A Python example

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

By inspecting the HTML of the above paragraph, you should see:

<pre data-ace-interactive-code="">print("Hello squares")
for i in range(10):
    print(i, i ** 2)
</pre>
    

By inserting this HTML directly into the HTML of an HTML editor in Moodle, then save the question and "Preview" it,  you can utilise this Ace interactive feature.

    • Below is an example of inserting the HTML directly into the Atto Editor's HTML editor.



    • If you wish to use any language aside from Python, insert the language in the <pre> tag as data-lang="language" where "language" is your desired language wrapped in a string, e.g. data-lang="java". Further customisation options are listed in "The complete set of options:" section further down on this page.

This method also works for TinyMCE editor, however, there is an easier way to edit code in Moodle 4.1+.

  1. Ensure your editor is set to TinyMCE (not legacy).



  2. Select "Code sample..." under the "Insert" tab.



  3. Select the language you desire (the current Jobe server supports Java, C(++) and Python. HTML/XML will accept HTML and display it.



  4. Type/copy-and-paste the code you wish to execute in the area below and press "Save".



  5. The following will be displayed with in-built Prism highlighting and appear to be uneditable. To edit your code, double-click on the highlighted box.



  6. Feel free to change languages, if you wish. This will also change the in-editor highlighting.

  7. Now click on "Source code" under "View". The following code should look like:



  8. Insert into the <pre> tag data-ace-interactive-code as shown.



  9. Click "Save" and "Save changes and continue editing". You can now preview the question and see ace-inline filter applied and executable:



  10. When editing the question, you can freely change languages and add more data- prefixed attributes to get your desired output (note: read caveats at the bottom of the ReadMe). If the language is not available, the recommendation is to change the displayed language to HTML/XML and insert data-lang="language" in the same manner as using the HTML editor.

To use MarkdownExtra in editor, utilise the following steps:

  1. Ensure your editor is set to PlainText Editor.



  2. When viewing your editor, select "Markdown" in the drop down as demonstrated.



  3. Now add the following into the editor (ensure all customisable tags are in the first line, are space-separated and contain no spaces within them, as per MarkdownExtra syntax):

    ``` {data-ace-interactive-code= data-lang=python3}
    print("Hello squares")
    for i in range(10):
        print(i, i ** 2)
    ```
    
    
    
  4. After saving and viewing the "Preview", the ace-inline filter should be displayed:



  5. This question can also be imported (view the samples folder's markdowndemo.xml file for an example of import format) for editor-independent based ways of structuring questions.

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 with interactive 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 an element.innerText attribute) 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. These files are also accessible on the command line argv, therefore code can be implemented to ensure that any type of file can be accepted.

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:
    raw = infile.read()
    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:
    print("Please upload only a single .txt file")
else:
    with open(text_files[0]) as infile:
        raw = infile.read()
        if len(raw.strip()) == 0:
            print("EMPTY FILE!")
        else:
            print(escape(raw))

File upload alternative: Print the contents of the first file

As each file uploaded can be accessed from the argv, an easier way to access files of any kind would be to parse the argv to use as a filename. The arguments are in order of upload order. You can select multiple files to upload and the following code will output the text contents of the first file

import sys

files = sys.argv[1:]
if len(files) == 0:
    print("Please upload a file")
else:
    with open(files[0]) as infile:
        contents = infile.read()
        print(contents)

The complete set of options:

The complete set of customisable elements is as follows. All functionality is supported in direct HTML editing.

Attribute Description Supported/Available in:  
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. Highlight, Interactive, TinyMCE, Markdown
data-button-name
Sets the label to use for the button instead of 'Try it!' Interactive, TinyMCE, Markdown
data-start-line-number
Can be set to 'none' to suppress line numbers or to an integer to start numbering with the given value Highlight, Interactive, TinyMCE, Markdown
data-readonly
If set (to any value) the supplied code cannot be edited by the user Interactive, TinyMCE, Markdown
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. Note: due to TinyMCE editor stripping out any <script> tags, do not edit code with <script> tags in TinyMCE. Interactive,  Markdown
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. Highlight, Interactive, TinyMCE, Markdown
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. Interactive, TinyMCE, Markdown
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.  Interactive, TinyMCE
data-font-size
The font size to use in the Ace editor, e.g. '11pt'. Highlight, Interactive, TinyMCE, Markdown
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. Interactive, TinyMCE, Markdown
data-min-lines
The minimum number of lines to display in the Ace editor. Default 4.
Highlight, Interactive, TinyMCE, Markdown
data-max-lines
The maximum number of lines to display in the Ace editor without a scrollbar. Default 50.
Highlight, Interactive, TinyMCE, Markdown
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: 30,000.
Interactive, TinyMCE, Markdown
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. Interactive, TinyMCE
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. Interactive, TinyMCE, Markdown
data-stdin (deprecated)
Defines a string to be used as standard input when the program is run. Deprecated in favour of data-stdin-taid Interactive
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. Interactive, TinyMCE, Markdown
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.
Interactive, TinyMCE, Markdown
data-hidden
Hides the Ace editor and all the code within it, leaving only the Try it! button. This can be used to hide complex code from students; whilst still allowing them to execute the code. Interactive, TinyMCE, Markdown

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'. Note: If this code is edited using TinyMCE editor, the <script> element and all its components will disappear upon saving. It is advisable to avoid TinyMCE editor if using this functionality.

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-taid attribute of the <pre> element has been set to 'age-text'; the id of the textarea containing "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 interactive 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! (Note: this exact method would not work if editing was to occur in TinyMCE. An example of code which utilises only data-prefix and data-suffix is specified in the Github repository and is compatible with TinyMCE)

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 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:

Plot grade histogram

Upload a .csv file using the file selector below.  The csv file must have a single header row and there must be a grade column containing only grades (E, D, C-, C+, ...). Enter the required column name into the input field beside the file selector and click the Plot histogram button. 

Select CSV file:
Column name:

Last modified: Friday, 16 December 2022, 10:59 AM