How do I integrate EK9 formatting into my development workflow?

← Code Formatting · Ref: Q626

The EK9 formatter integrates naturally into both local development and CI pipelines.

LOCAL WORKFLOW

Format before committing:

  ek9 -F myproject.ek9
  git add -A
  git commit -m "feature: add new module"

This ensures every commit contains canonically formatted code.

PRE-COMMIT HOOK

Add a git pre-commit hook that formats and re-stages:

  #!/bin/sh
  ek9 -F myproject.ek9
  git add -u

This catches formatting issues before they reach the repository.

CI VERIFICATION

In CI, verify formatting without modifying files. Run:

  ek9 -F myproject.ek9
  git diff --exit-code

If -F produces any changes, git diff returns non-zero and the CI step fails. This ensures all committed code is correctly formatted.

AFTER AI CODE GENERATION

When an AI generates EK9 code, format it immediately:

  ek9 -ff generated.ek9

The -ff (force format) handles cases where the AI output might not parse perfectly. Then compile to verify correctness.

AFTER MERGE

After resolving merge conflicts:

  ek9 -fF myproject.ek9

Force-format handles any indentation corruption from the merge.

See Q622 for formatting a single file. See Q623 for formatting all files. See Q624 for force-formatting. See Q625 for why EK9 enforces a standard format. See Q281 for AI code verification.

Example

defines module qa.codeformatting.workflow

  defines function

    <?-
      Functions that represent a typical workflow:
      write code, format, compile, test, commit.
    -?>
    validateAge() as pure
      -> age as Integer
      <- valid as Boolean: false

      minimumAge <- 0
      maximumAge <- 150
      if age >= minimumAge and age <= maximumAge
        valid: true

    formatName() as pure
      ->
        firstName as String
        lastName as String
      <-
        fullName as String: `${firstName} ${lastName}`

  defines program

    WorkflowDemo()
      stdout <- Stdout()

      ageIsValid <- validateAge(25)
      name <- formatName("Jane", "Doe")

      stdout.println(`Name: ${name}`)
      stdout.println(`Valid age: ${ageIsValid}`)

Common mistakes

E50001 — Removing the variable declaration means later references to the variable become unresolved, triggering E50001. See ek9 -h E50001 for details.

Incorrect:

validateAge(25)

Correct:

ageIsValid <- validateAge(25)
Other ways to ask this
  • Should I format before or after committing?
  • How do I use the EK9 formatter in CI?
  • How do I set up a format-on-save workflow for EK9?

Coming from another language?

Go: gofmt integrated into most editors, goimports for import management, CI uses gofmt -l to check. Rust: cargo fmt, CI uses cargo fmt --check. Python: black with pre-commit framework, CI uses black --check. Java: spotless plugin in Maven/Gradle, CI runs spotless:check. JavaScript: prettier with husky/lint-staged, CI runs prettier --check. EK9: ek9 -F for formatting, git diff --exit-code in CI, -ff for AI/merge recovery, all built into one binary.

Keywords: verify, style, hook, pre-commit, integrate, CI, save, git, pipeline, workflow, commit, format, indent