Skip to content

Add CircuitPython module highlighting overlay#481

Merged
makermelissa merged 7 commits intocircuitpython:betafrom
makermelissa-piclaw:feature/circuitpython-highlight
Apr 29, 2026
Merged

Add CircuitPython module highlighting overlay#481
makermelissa merged 7 commits intocircuitpython:betafrom
makermelissa-piclaw:feature/circuitpython-highlight

Conversation

@makermelissa-piclaw
Copy link
Copy Markdown
Contributor

@makermelissa-piclaw makermelissa-piclaw commented Apr 29, 2026

Related to #363 (held open until beta features merge to main).

Targets the beta branch.

Approach

CodeMirror 6 dropped the simple extra_keywords mechanism that CM5 had, so instead of forking @codemirror/lang-python (and tracking it forever) this layers a small ViewPlugin on top of the existing Python syntax tree.

The plugin walks the visible syntaxTree, finds VariableName nodes whose text matches a known CircuitPython core module or common Adafruit library, and tags them with class tok-cp-module so the theme can color them distinctly.

Files

  • New: js/common/circuitpython_highlight.js — the overlay extension.
  • Edited: js/script.js — adds circuitpythonHighlight to editorExtensions.
  • Edited: sass/layout/_themes.scss — adds .tok-cp-module rule with a magenta accent (#FF79C6).

Module list

~125 names: all CircuitPython core modules (board, digitalio, displayio, busio, wifi, synthio, keypad, pulseio, pwmio, usb_cdc, usb_hid, usb_midi, etc.) plus the most common adafruit_* libraries plus neopixel and simpleio. The list lives in one Set at the top of the new file — easy to extend or trim.

Why this approach

  • ✅ No upstream maintenance burden — Python language stays stock, no fork of @codemirror/lang-python.
  • ✅ Only marks identifier nodes (VariableName), so strings and comments are never miscolored.
  • ✅ Cheap — decoration set is rebuilt only on doc/viewport/tree changes, and only visible ranges are walked.
  • ✅ Zero new dependencies; uses @codemirror/view and @codemirror/language already in the tree.

Trade-offs / future work

  • Limited to bare identifier matching for now. To highlight CircuitPython-specific attributes (e.g. board.D13) we'd extend the same overlay to PropertyName nodes — easy follow-up.
  • The module list is hand-maintained. Adding a name when a new core module ships is a one-line change.

Test

  • npm run build is clean.
  • New class tok-cp-module ships in dist/assets/index.css.
  • Verified the dev server starts and the editor renders Python files normally with the extension active.

CodeMirror 6 dropped the simple extra_keywords mechanism that CM5 had,
so instead of forking @codemirror/lang-python we layer a small
ViewPlugin on top of the existing Python syntax tree. It walks the
visible tree, finds VariableName nodes whose text matches a known
CircuitPython core module or common Adafruit library, and tags them
with a tok-cp-module class so the theme can color them distinctly.

This avoids:
- Forking lang-python and tracking upstream changes
- Re-tokenizing strings/comments (we only mark identifier nodes)
- Adding any per-keystroke parsing cost (decoration set is rebuilt
  only on doc/viewport/tree changes)

Adds a magenta accent (#FF79C6) for .tok-cp-module in the editor
theme so CircuitPython modules pop out from regular Python identifiers.

Closes circuitpython#363
@makermelissa-piclaw makermelissa-piclaw changed the base branch from main to beta April 29, 2026 22:13
Drops the hand-curated list of adafruit_* community libraries in favour
of a startsWith("adafruit_") check. New Adafruit CircuitPython libraries
will be highlighted automatically as they ship, with no maintenance
needed in this file. The core CircuitPython module set still uses an
explicit allowlist because those names don't share a distinguishing
prefix.
The CircuitPython Community Bundle ships ~10 libraries with a
`circuitpython_` prefix (circuitpython_csv, circuitpython_schedule,
circuitpython_functools, etc.). Same prefix-match approach as
adafruit_*: new community libraries are highlighted automatically.
Refreshed CIRCUITPYTHON_CORE_MODULES against the current contents of
adafruit/circuitpython:shared-bindings/. Added 15 modules that have
landed since the initial list was written: audiodelays, audiofilters,
audiofreeverb, audiospeed, aurora_epaper, camera, fourwire, gnss,
i2cioexpander, lvfontio, mcp4822, mipidsi, ps2io, qspibus, rclcpy.

Removed the deprecated paralleldisplay alias (paralleldisplaybus is the
modern name and is already listed) and the stray lsm6ds entry, which
isn't a shared binding and isn't in the community bundle either.

Standard-Python modules that CircuitPython also exposes (math, os, time,
random, struct, hashlib, ipaddress, locale, __future__) are intentionally
left out so we don't recolour those names in plain Python code.
Underscore-prefixed internal bindings (_bleio etc.) are also omitted;
users reach for the adafruit_ wrappers, which the prefix wildcard
already matches.
These are early Adafruit-maintained libraries that predate the
adafruit_ naming convention, not community-bundle modules.
When an identifier matches both classHighlighter's VariableName tag
and our CircuitPython overlay, CodeMirror renders nested mark spans.
The inner span (closer to the text) is what the browser uses for
`color`, and it's chosen by decoration precedence \u2014 so without an
explicit precedence wrapper, the syntax highlighter's blue stayed on
top and `neopixel` rendered the same color as any other variable.

Wrapping the ViewPlugin with Prec.highest puts the tok-cp-module span
inside the tok-variableName span, letting the pink override the blue
without touching the CSS or using !important.
Copy link
Copy Markdown
Collaborator

@makermelissa makermelissa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested and working

@makermelissa makermelissa merged commit 8a712b5 into circuitpython:beta Apr 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CircuitPython Types to Code Mirror

2 participants