soma.cell

Slugify — turn a title into a URL-safe slug

Lowercases, keeps alphanumerics, turns every run of other characters into a single hyphen, and trims leading/trailing hyphens. Demonstrates a per-char accumulator with a "last was separator" flag to collapse runs. Run: soma run slugify.cell --signal slugify "Hello, World! Foo--Bar"

A Soma program from the text part of the verified corpus: 45 lines, cells Slugify, SlugifyTest. It passes soma check with soma 3.2.4.

How it is built

The cell Slugify declares 1 signal in its face: slugify(title: String) -> String. Handlers: slugify (line 16).

The file also holds 1 test cell (SlugifyTest) with 5 assertions, run by soma test.

Generated from soma describe on this file.

The source

slugify.cell

// ============================================================================
// Slugify — turn a title into a URL-safe slug
// ============================================================================
//
// Lowercases, keeps alphanumerics, turns every run of other characters into a
// single hyphen, and trims leading/trailing hyphens. Demonstrates a per-char
// accumulator with a "last was separator" flag to collapse runs.
//
// Run: soma run slugify.cell --signal slugify "Hello, World!  Foo--Bar"

cell Slugify {
    face {
        signal slugify(title: String) -> String
    }

    on slugify(title: String) {
        let low = lowercase(title)
        let out = ""
        let pending_dash = false
        for i in range(0, len(low)) {
            let c = low[i]
            if (c >= "a" && c <= "z") || (c >= "0" && c <= "9") {
                if pending_dash && len(out) > 0 {
                    out = out + "-"
                }
                pending_dash = false
                out = out + c
            } else {
                pending_dash = true
            }
        }
        return out
    }
}

cell test SlugifyTest {
    rules {
        assert slugify("Hello World") == "hello-world"
        assert slugify("Hello, World!") == "hello-world"
        assert slugify("  Foo --  Bar  ") == "foo-bar"
        assert slugify("Already-Slug-99") == "already-slug-99"
        assert slugify("!!!") == ""
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check slugify.cell
warning: `out` grows by concatenation inside a loop — each step copies the whole value, so the loop is quadratic (8 MB took 32 s, a list + join() 30 ms): push the pieces to a List and `join(parts, "")` once
  --> slugify.cell:24:21
   |
24 |                     out = out + "-"
   |                     ^
✓ 1 warning(s), no errors.
$ soma test slugify.cell
test SlugifyTest ...
  ✓ assert slugify("Hello World") == "hello-world"
  ✓ assert slugify("Hello, World!") == "hello-world"
  ✓ assert slugify("  Foo --  Bar  ") == "foo-bar"
  ✓ assert slugify("Already-Slug-99") == "already-slug-99"
  ✓ assert slugify("!!!") == ""

5 tests: 5 passed, 0 failed
$ soma verify slugify.cell
Verifying slugify.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)

Builtins used

len, lowercase, range

Source file: /corpus/text/slugify.cell · examples/corpus/text/slugify.cell