texprl

Tiny expression language, is a very small language similar to languages found in spreadsheets.

The primary aim is to be a language that can be used across maputnik expressions and the fielda form builder. It is therefore a language without a runtime, it just returns a syntax tree in an array syntax suitable for storing in a file/database. See maplibre-expressions for an example.

Contents:

Features

The features of the language include

References are fairly unique to texprl and not found in many other languages. They are a way to look up information from a known lookup table in an editor. For example if I have a function called read which accepts a UUID for a remote resource on a server, for example read("9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d") it makes the code editor really verbose and messy/hard to read. The UUID will likely have a more human readable name somewhere in the system.

Editor

The language comes bundled with a codemirror editor which is designed to make it easy for beginners to get started with. The aims align with the aims of the texprl language. The main feature is adding widgets next to key functions to allow them to be edited in a structured way.

For example if we encounter a string of the format 2020-10-02 we add a date picker next to the date. The user will then know what 2020-10-02 means by opening the picker. The idea is to educate the user with small UI hints.

Another example is the function hsl(0,100,50). Developers might be well aware that the args to that function are hue, saturation and lightness however a user may be very inexperienced with this syntax. We display a color preview to let the user know that this represents a color and on click we allow the user to edit that color with the parts of the color labeled. The same is also true of rgb(255, 0, 0)

API

// Setup
const editor = texprl(el, {
  widgets: [
    {type: "Date", widget: DateWidget},
    {type: "DateTime", widget: DateTimeWidget},
    {type: "Time", widget: TimeWidget},
    {type: "Color", widget: ColorWidget},
  ],
  functions: [
    {name: "foo"},
    {name: "bar"},
    {
      name: "read",
      lookup: {
        "0", "PERSON",
      }
    }
  ]
});

// Update lookups
editor.setLookup([
  {
    type: "PERSON",
    values: [
      {
        editorId: "jane",
        backendId: "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
        name: "Jane Austen"
      },
      {
        editorId: "allen",
        backendId: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
        name: "Allen Ginsberg"
      },
    ]
  },
]);

Demo

The texprl code editor —

The JSON representation

The raw text output

The formatted code, see "Code formatter" below.

Advanced examples

Some more advanced examples that show off what the language/editor is capable of.

Known issues

This library is early in development and has some known issues.

Code formatter

The code formatter is in it's early stages. It mostly just adds some white space around binary expressions. So the expression with a structure of

["foo", ["+", 1, 1], 2, 3]

To something like the following

foo(1 + 1, 2, 3)

This requires more work and will need to be function aware in future. An example of this would be maplibre expressions

interpolate(linear(),get("mag"),2,2,6,6)

Would be best formatted as argument pairs, so

interpolate(
  linear(), get("mag"),
  2, 2,
  6, 6,
)

We need to do a lot more work here.

Parse errors

We currently don't display parse errors in the codemirror editor. We do however have them from the lezer syntax tree.