Skip to main content

pygments-step

PyPI version Python versions License: MIT

Pygments lexers for EXPRESS (ISO 10303-11) and STEP Part 21 (ISO 10303-21).

Lexer Standard Code fence File types
ExpressLexer EXPRESS, ISO 10303-11 ```express *.exp
StepFileLexer Part 21 exchange file, ISO 10303-21 ```step21 *.p21, *.stp, *.step

Additional aliases: exp, iso-10303-11 for EXPRESS; p21, step, stp, spf, iso-10303-21 for Part 21.

Both lexers are schema-agnostic. They lex the languages, not any single application protocol, so they work equally well for IFC, AP203, AP214 or any other STEP-based schema without carrying a schema-specific keyword table.

Install

pip install pygments-step

Or, with uv:

uv add pygments-step

The only runtime dependency is Pygments>=2.14. Python 3.9+ is supported.

Installing is all you need to do. The lexers register themselves with Pygments through pygments.lexers entry points, so every tool that renders code through Pygments — MkDocs, Sphinx, pygmentize, Rich, Jupyter — picks them up automatically. There is no configuration step.

Usage

Markdown code fences

Tag a fence with express or step21:

```express
ENTITY cartesian_point
  SUBTYPE OF (geometric_representation_item);
    coordinates : LIST [1:3] OF length_measure;
  DERIVE
    dim : INTEGER := HIINDEX(coordinates);
  WHERE
    valid_dim : SIZEOF(coordinates) <= 3;
END_ENTITY;
```
```step21
ISO-10303-21;
HEADER;
FILE_SCHEMA(('SOME_APPLICATION_PROTOCOL'));
ENDSEC;
DATA;
#1= CARTESIAN_POINT('',(0.,0.,0.));
#4= AXIS2_PLACEMENT_3D('',#1,#3,$);
#6= NAMED_UNIT(.T.,.F.,.UNSPECIFIED.);
ENDSEC;
END-ISO-10303-21;
```

This works out of the box in MkDocs (including Material for MkDocs, whose pymdownx.highlight extension delegates to Pygments) and in any other Markdown pipeline backed by Pygments — no mkdocs.yml changes required.

Python API

from pygments import highlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name

lexer = get_lexer_by_name("step21")
print(highlight("#1= CARTESIAN_POINT('',(0.,0.,0.));", lexer, HtmlFormatter()))

The classes can also be imported directly:

from pygments_step import ExpressLexer, StepFileLexer

Dispatch by filename works as well:

from pygments.lexers import get_lexer_for_filename

get_lexer_for_filename("schema.exp")   # EXPRESS
get_lexer_for_filename("model.stp")    # STEP Part 21

Command line

pygmentize -l express schema.exp
pygmentize -l step21 -f html -O full,style=friendly -o model.html model.stp

Because the file extensions are registered, -l can usually be omitted:

pygmentize schema.exp

What the lexers cover

EXPRESS (ISO 10303-11)

  • Case-insensitive keywords, per clause 6.1 and annex A.1.1.
  • Nested (* ... (* ... *) ... *) embedded remarks and -- ... tail remarks.
  • Declaration heads (SCHEMA, ENTITY, TYPE, FUNCTION, PROCEDURE, RULE, CONSTANT, SUBTYPE_CONSTRAINT) highlight the declared name distinctly from the keyword.
  • Literals: doubled-quote string escapes ('it''s'), binary literals (%10110), encoded string literals ("000000E9"), reals and integers.
  • Built-in functions (SIZEOF, HIINDEX, EXISTS, TYPEOF, …) and built-in types (INTEGER, LIST, SELECT, LOGICAL, …).

STEP Part 21 (ISO 10303-21)

  • Exchange structure keywords: ISO-10303-21, END-ISO-10303-21, HEADER, DATA, ENDSEC, ANCHOR, REFERENCE, SIGNATURE.
  • Entity instance definitions (#1=) are tokenised differently from references (,#1,), so the two read differently in rendered output.
  • Enumerations (.T., .F., .UNSPECIFIED.), unset values ($) and derived values (*).
  • String control directives: \S\, \P?\, \X\, \X2\...\X0\, \X4\...\X0\, plus '' escapes.
  • Print control directives \N\ and \F\, both inside strings and at any position where a token separator may appear.
  • Binary literals ("0F3A"), user-defined keywords (!USER_DEFINED_KEYWORD) and /* ... */ comments.

A note on IFC

IFC files are Part 21 files, so StepFileLexer handles them — but ifc and *.ifc are deliberately not claimed as an alias or filename pattern. IFC is only one of many SPF-based formats, and privileging it in a standards-level lexer would be arbitrary. Use step21 (or p21 / spf) for IFC content.

Test

Clone the repository and install with the test extra:

git clone https://github.com/AECVerge/pygments-step.git
cd pygments-step
uv sync --extra test
uv run pytest

Or with pip:

pip install -e ".[test]"
pytest

The suite also runs standalone, without pytest:

python tests/test_lexers.py

Tests cover alias and filename registration, token-level regressions for both lexers, and assert that neither fixture produces a single Error token.

tests/test_docs_pages.py does the same for the rendered docs/express and docs/step pages. Those pages are an exhaustive, category-by-category corpus for the two lexers (keywords, operators, types, literals, comments, …); the test parses every code fence on them and asserts that the lexer produces zero Error tokens, and that each page really covers the whole family of tokens it claims to. The docs build in CI runs with mkdocs build --strict, so a snippet that stops lexing cleanly blocks the deploy as well.

License

MIT

Metadata

Release files for pygments-step 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pygments-step 0.2.0
File Size Uploaded
pygments_step-0.2.0.tar.gz 13.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pygments-step 0.2.0
File Interpreter ABI Platform
pygments_step-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 25.6 kB

Release files / pygments_step-0.2.0.tar.gz

Download URL pygments_step-0.2.0.tar.gz
Size 13.8 kB
Tags Source
SHA-256 checksum
How to use checksums
921438a411a08f5f21d78cefbf83a774fd90202480bfd9335ee2093226a661db
BLAKE2b-256 checksum
How to use checksums
24f898297b6e3d5e8931b82ecfa3a0b1912079863212b23c63f6d8bfe255b0e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / pygments_step-0.2.0-py3-none-any.whl

Download URL pygments_step-0.2.0-py3-none-any.whl
Size 11.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8784ef110166d691d6115c7a11df22a14fe11eb5e56538fe959fe83dcec5fbc9
BLAKE2b-256 checksum
How to use checksums
b732ffc80a7a5fd1c7a46f2829fa9d2185dae8d4b1e3bdf80802eaf073c449f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page