EzyCad scripting

EzyCad embeds script consoles that drive the live document through a public Python-first API under ezy. Lua mirrors the same namespaces (required for WebAssembly). Remote --listen clients use the same Python tree.

Use ezy.help() (or help()) in a console for a short built-in summary.

Availability

Lua

Python

Desktop (Windows)

Always (built-in Lua library)

Only if the app was built with Python enabled (EZYCAD_HAVE_PYTHON in CMake; needs Python development libraries). If the View -> Python Console item appears and works, your build includes it.

WebAssembly

Yes

No (not shipped in the browser build).

Opening the consoles

  • View -> Lua Console - Toggles the Lua console and script editor tabs.

  • View -> Python Console - Same layout for Python when the feature is compiled in.

Visibility is remembered with other panes (see usage.md -> Help and Settings).

Layout

  • Output / history - Results and errors from executed lines.

  • Input line - Enter a fragment and run it (same as a one-off at the interactive prompt).

  • Script tabs - Files under res/scripts/lua (*.lua) or res/scripts/python (*.py) are loaded as editable buffers; Lua scripts are also run on startup so you can define helpers (see basic.lua / basic.py).

Paths are relative to the app working directory on desktop; on WASM, Lua scripts are under the preloaded /res/scripts/lua tree.

Public API (Python)

Canonical surface (also available in Lua with the same names):

ezy.log / ezy.msg / ezy.help / ezy.get_mode / ezy.set_mode
ezy.save_occt_view_settings / ezy.occt_view_settings_json
ezy.view.*
ezy.view.curr_sketch.*   # same object as ezy.sketch
ezy.Shp

Aliases (compatibility): global view is ezy.view; global Shp is ezy.Shp; help() is ezy.help(). ezy.view.curr_sketch is the same object as ezy.sketch. Flat view.add_sketch / add_edge / finish_sketch_edges forward to view.curr_sketch.*.

print is redirected to ezy.log in both consoles.

ezy

Method

Purpose

ezy.log(msg)

Print to the console and the main Log pane

ezy.msg(text)

Status toast and append to the main Log pane

ezy.get_mode()

Current application mode name (string)

ezy.set_mode(name)

Switch mode by name

ezy.save_occt_view_settings()

Write settings JSON (including view colors)

ezy.occt_view_settings_json()

Settings JSON string

ezy.help()

Print binding summary

ezy.view

Method

Purpose

ezy.view.sketch_count()

Number of sketches

ezy.view.shape_count()

Number of 3D shapes

ezy.view.add_box(ox, oy, oz, w, l, h)

Add a box; returns Shp

ezy.view.add_sphere(ox, oy, oz, r)

Add a sphere; returns Shp

ezy.view.fuse(s1, s2, ...)

Boolean union of two or more Shp; returns Shp

ezy.view.cut(body, tool, ...)

Subtract tools from body; returns Shp

ezy.view.common(s1, s2, ...)

Boolean intersection; returns Shp

ezy.view.delete(s1, ...)

Remove one or more Shp from the document

ezy.view.get_shape(i)

Shape by 0-based index (raises IndexError)

ezy.view.get_selected()

List of selected document Shp (empty if none)

ezy.view.set_selected(s1, ...)

Replace the selection; accepts a list; no args clears

ezy.view.get_selected_indices()

0-based indices of selected document shapes

ezy.view.get_camera()

Camera vectors: eye, center, up

ezy.view.set_camera(ex, ey, ez, cx, cy, cz, ux, uy, uz)

Set camera vectors

ezy.view.curr_sketch

Current sketch API (same as ezy.sketch)

ezy.view.curr_sketch / ezy.sketch

Indices are 0-based in Python. Prefer view.curr_sketch for inspection; ezy.sketch is the same object and also used for creation helpers.

Method

Purpose

view.curr_sketch.name()

Name of the current sketch (curr_name() alias on ezy.sketch)

view.curr_sketch.node_count() / view.curr_sketch.node(i)

Read nodes (x, y) on the current sketch plane

view.curr_sketch.dim_count() / view.curr_sketch.dim(i)

Read length dimensions (distance in project display units)

view.curr_sketch.add(plane, offset, base_name)

New sketch on XY, XZ, or YZ (offset in project display units; optional name)

view.curr_sketch.add_edge(x1, y1, x2, y2)

Add a linear edge to the current sketch

view.curr_sketch.finish_edges()

Rebuild closed-face topology after bulk edge import

ezy.Shp

Method

Purpose

s.name() / s.set_name(s)

Shape name

s.visible() / s.set_visible(b)

Visibility

Lua notes

Lua exposes the same ezy / ezy.view / ezy.sketch layout. Differences:

Topic

Lua

Python

Shape index

1-based; out of range returns nil

0-based; raises IndexError

Selected idx

1-based in get_selected_indices()

0-based

Sketch index

1-based for node / dim

0-based

Methods

Prefer s:name() style on userdata

s.name()

WASM

Available

Not built

Sample scripts

  • res/scripts/python/basic.py - dump_view() using ezy.view (and a legacy view alias line).

  • res/scripts/python/sierpinski.py - Sierpinski triangle; call create_sierpinski_sketch().

  • res/scripts/lua/basic.lua - kv(obj) helper via ezy.log.

  • res/scripts/lua/sierpinski.lua - Same idea for Lua; call create_sierpinski_sketch().

Limitations

  • The API is small and may change between versions; prefer ezy.help() after upgrades.

  • Scripting is for automation and inspection, not a full replacement for the GUI workflow.

  • Heavy work on the UI thread can block the app; keep snippets short.

  • Only APIs under ezy (and documented aliases) are the supported public scripting contract.

Remote Python (--listen)

Desktop builds with embedded Python can accept console snippets over TCP while the GUI runs. The remote client talks to the same ezy tree as the in-app console.

Launch (default host is localhost when you pass only a port):

EzyCad.exe --listen 8765
EzyCad.exe --listen 127.0.0.1:8765

Bind 0.0.0.0 only if you intentionally expose the port on the network (no authentication).

Importable client (ezycad)

If scripts/ is already on your Python path (as in many IPython setups), just import ezycad. Otherwise::

import sys
sys.path.insert(0, r"C:\src\EzyCad\scripts")
import ezycad

Then (keep the connection open — avoid with in IPython if you will call app again later)::

import ezycad

app = ezycad.connect()  # 127.0.0.1:8765; EzyCad must be running with --listen
app.ezy.log("hello from remote")
print(app.view.sketch_count())
print(app.view.curr_sketch.node_count())
print(app.ezy.get_mode())
# app.close() when done

If you see a connection / socket error, EzyCad was closed or app was already closed — call ezycad.connect() again.

CLI

python scripts/ezycad_remote.py --port 8765
python scripts/ezycad_remote.py -c "ezy.log('hello')"

With scripts/ on PYTHONPATH, python -m ezycad works the same way.

Raw execute / eval still return a Result (ok / output / result / error). Typed methods raise ezycad.EzyCadError on failure and unwrap simple values (ints, tuples, dicts) from the remote repr.

For general application behavior, see usage.md.