Tutorial 06

Previous Table of contents Next

Description

Tutorial06 shows how to use a fully custom Autocompleter, with the goal to replace the static "calibrated units" option for the "units" type with the actual units string of the currently open image.

There is one (autocompletion) issue here, which will be addressed in the next tutorial: Once the user starts typing the text for the unit (let's say a 'p' for 'pixel(s)'), completion should stop (or even better, only suggest 'pixel(s)', because 'mm' doesn't start with 'p'). However, here it will just continue to suggest 'pixel(s)' as well as 'mm'.

For details, see also

The code


<!doctype html>
<html>
  <body>
    <!-- The HTML element that will hold the editor -->
    <div id="nls-container"></div>

    <!-- The only javascript file needed for nlScript -->
    <script src="https://cdn.jsdelivr.net/npm/@nlscript/nlscript@0.3.0/dist/umd/nlScript.js"></script>

    <!-- Load the library for the actual processing -->
    <script src="preprocessing.js"></script>

    <script>
      let preprocessing = new Preprocessing("output");
      
      // Unfortunately, the clown image doesn't have calibrated pixels. For demonstration
      // purposes, we artificially set a calibration here
      preprocessing.setPixelWidth(0.25, "mm");
      
      let parser = new nlScript.Parser();
      
      // The new feature is the use of the ParseStartListener, whose parsingStarted() function
      // gets called when parsing is started. At that time, the image to process is known, so its
      // pixel calibration unit string can be stored, to be used for autocompletion later.
      // Note: Parsing is not only performed once the user clicks on 'Run', but whenever the user's
      // text changes, for auto-completion.
      let imageUnits = "";
      parser.addParseStartListener(() => {
        imageUnits = preprocessing.getUnits();
      });
      
      parser.defineType("units", "{unitstring:[a-zA-Z()]:+}",
        pn => pn.getParsedString() !== "pixel(s)",
        // Here we use the saved pixel calibration unit string to specify a custom Autocompleter,
        // which in this case returns 2 literals, "pixel(s)" and the value of imageUnits.
        // The Autocompletion class provides many convenience functions for creating Autocompleters.
        (pn, justCheck) => nlScript.Autocompletion.literal(pn, ["pixel(s)", imageUnits]));
      
      parser.defineType("filter-size", "{stddev:float} {units:units}", pn => {
        let stddev = pn.evaluate("stddev");
        let units = pn.evaluate("units");
        if(units)
          stddev /= preprocessing.getPixelWidth();
        return stddev;
      }, true);
      
      parser.defineSentence(
        "Apply Gaussian blurring with a standard deviation of {stddev:filter-size}.",
        pn => {
          let stdDev = pn.evaluate("stddev");
          preprocessing.gaussianBlur(stdDev);
          preprocessing.show("output");
          return undefined;
        });
      
      new nlScript.ACEditor(parser, document.getElementById("nls-container"));

    </script>
  </body>
</html>

Demo

The result