lib/compiler.js
function(walk) {
    if (!walk.at('@ '))
      return false;
    // Find the end of the block, checking for adjacent blocks
    var startIdx = walk.position;
    var found = false;
    while (!found && walk.hasCurrent()) {
      walk.scrollToTerm().skipBlankLines();
      if (walk.atSpaces(this.blockIndent)) {
        var i = walk.position;
        walk.skipWhitespaces();
        if (!walk.at('@') && !walk.at('*')) {
          found = true;
          walk.startFrom(i);
        }
      } else found = true;
    }
    var g = this.stripSelector(new SubWalker(walk, startIdx, walk.position));
    this.emitAssociativeGroup(g);
    return true;
  }
function(walk) {
    if (!walk.at('@ '))
      return false;
    // Find the end of the block, checking for adjacent blocks
    var startIdx = walk.position;
    var found = false;
    while (!found && walk.hasCurrent()) {
      walk.scrollToTerm().skipBlankLines();
      if (walk.atSpaces(this.blockIndent)) {
        var i = walk.position;
        walk.skipWhitespaces();
        if (!walk.at('@') && !walk.at('*')) {
          found = true;
          walk.startFrom(i);
        }
      } else found = true;
    }
    var g = this.stripSelector(new SubWalker(walk, startIdx, walk.position));
    this.emitAssociativeGroup(g);
    return true;
  }
Associative groups enable users to drag select items into correct categories.

The exact dragging functionality must be implemented with client-side scripts.

Each category starts with marker `@ ` and must contain one or more select items,
which start with marker `* ` and are indented beyond category marker.

Example:

```
@ Category 1

* one
* two
* three

@ Category 2

* five
* six

```