Compare commits

...

74 Commits

Author SHA1 Message Date
3d19dfb800 Cut release v0.9.3 (#753) 2023-10-02 14:14:00 -04:00
d2a7b84292 Request a feature should open externally (#737)
Fixes #659
2023-10-02 13:26:23 -04:00
9e02bab155 Explicitly close the Engine Connection when ICE fails (#732)
This will avoid letting the stack think its ready until it times out,
and will hopefully help with faster retry logic in the future

Signed-off-by: Paul Tagliamonte <paul@kittycad.io>
2023-10-02 09:50:49 -04:00
7352de5a70 Bump vitest from 0.34.1 to 0.34.6 (#747)
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 0.34.1 to 0.34.6.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v0.34.6/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-30 12:24:39 +10:00
9797d0cb81 Fix pipe expression start (#746) 2023-09-29 22:19:20 -04:00
83907fa9db adds tangentalArc and tangentalArcTo to the stdlib (#748)
* start of tangental arc

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-29 14:41:14 -07:00
a367be4e2b add gizmo (#738)
* add gizmo

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixups

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix force ast execution

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-29 12:41:58 -07:00
056fa00adc Bump tauri from 1.4.1 to 1.5.0 in /src-tauri (#742)
Bumps [tauri](https://github.com/tauri-apps/tauri) from 1.4.1 to 1.5.0.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/tauri-v1.4.1...tauri-v1.5.0)

---
updated-dependencies:
- dependency-name: tauri
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 12:03:35 -07:00
4759fb2e6f Bump postcss from 8.4.27 to 8.4.31 (#743)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.27 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.27...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 11:12:08 -07:00
45f497d9cd Bump tauri-build from 1.4.0 to 1.4.1 in /src-tauri (#741)
Bumps [tauri-build](https://github.com/tauri-apps/tauri) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/tauri-build-v1.4...tauri-build-v1.4.1)

---
updated-dependencies:
- dependency-name: tauri-build
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 11:11:57 -07:00
dc61bdebdf Bump tauri-plugin-fs-extra from 3d27909 to 9af4c37 in /src-tauri (#740)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `3d27909` to `9af4c37`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](3d279094d4...9af4c3727c)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 11:11:42 -07:00
61943055e5 refactor a bit before more rust port (#739)
* partially there

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixups

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-29 11:11:01 -07:00
416fe0f644 Bump clap from 4.4.5 to 4.4.6 in /src/wasm-lib (#744)
Bumps [clap](https://github.com/clap-rs/clap) from 4.4.5 to 4.4.6.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.4.5...v4.4.6)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 12:41:22 -04:00
708465d818 Bump kittycad from 0.2.27 to 0.2.28 in /src-tauri (#734)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.27 to 0.2.28.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.27...v0.2.28)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-28 18:09:56 -07:00
e706fb02d6 Bump openapitor from d3e98c4 to fa0345c in /src/wasm-lib (#733)
Bumps [openapitor](https://github.com/KittyCAD/kittycad.rs) from `d3e98c4` to `fa0345c`.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](d3e98c4ec0...fa0345c514)

---
updated-dependencies:
- dependency-name: openapitor
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-28 18:09:46 -07:00
1bf7daa474 Bump tauri-plugin-fs-extra from 6c7a4c0 to 3d27909 in /src-tauri (#735)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `6c7a4c0` to `3d27909`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](6c7a4c0984...3d279094d4)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-28 18:09:31 -07:00
ffc47f8f40 actually use the units the user sets (#727)
* actually use the units the user sets

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update kittycad lib

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* next

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix bug

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix types

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-27 15:42:16 -07:00
768aaa84f6 Bump clap from 4.4.4 to 4.4.5 in /src/wasm-lib (#711)
Bumps [clap](https://github.com/clap-rs/clap) from 4.4.4 to 4.4.5.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.4.4...v4.4.5)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 09:10:07 -07:00
f3a700eec8 Bump expectorate from 1.0.7 to 1.1.0 in /src/wasm-lib (#712)
Bumps [expectorate](https://github.com/oxidecomputer/expectorate) from 1.0.7 to 1.1.0.
- [Release notes](https://github.com/oxidecomputer/expectorate/releases)
- [Commits](https://github.com/oxidecomputer/expectorate/compare/v1.0.7...v1.1.0)

---
updated-dependencies:
- dependency-name: expectorate
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:39:16 -07:00
c853637a9a Bump thiserror from 1.0.48 to 1.0.49 in /src/wasm-lib (#721)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.48 to 1.0.49.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.48...1.0.49)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:39:03 -07:00
9af30d9ef6 Bump kittycad from 0.2.26 to 0.2.27 in /src/wasm-lib (#722)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.26 to 0.2.27.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.26...v0.2.27)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:49 -07:00
6164714a6b Bump openapitor from 61a1605 to d3e98c4 in /src/wasm-lib (#723)
Bumps [openapitor](https://github.com/KittyCAD/kittycad.rs) from `61a1605` to `d3e98c4`.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](61a16059b3...d3e98c4ec0)

---
updated-dependencies:
- dependency-name: openapitor
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:37 -07:00
64ceb98eba Bump toml from 0.8.0 to 0.8.1 in /src-tauri (#724)
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.0 to 0.8.1.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.0...toml-v0.8.1)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:25 -07:00
2cbf260900 Bump tauri-plugin-fs-extra from b04bde3 to 6c7a4c0 in /src-tauri (#725)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `b04bde3` to `6c7a4c0`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](b04bde3461...6c7a4c0984)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:14 -07:00
cfaaedf602 Bump kittycad from 0.2.26 to 0.2.27 in /src-tauri (#726)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.26 to 0.2.27.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.26...v0.2.27)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:37:54 -07:00
12b3717eb5 Cut release v0.9.2 (#714) 2023-09-26 20:39:05 -04:00
0bc685b0c4 Bump tungstenite from 0.20.0 to 0.20.1 in /src/wasm-lib/kcl/fuzz (#709)
Bumps [tungstenite](https://github.com/snapview/tungstenite-rs) from 0.20.0 to 0.20.1.
- [Changelog](https://github.com/snapview/tungstenite-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/snapview/tungstenite-rs/compare/v0.20.0...v0.20.1)

---
updated-dependencies:
- dependency-name: tungstenite
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 20:49:16 -07:00
9ee032771a unused dep (#710) 2023-09-26 03:22:05 +00:00
c307ddd1b1 resize (#706)
* start of resize

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* refactor

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* check if 0

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* will work w new lib

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* new types

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* handle resize effect

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
2023-09-25 19:49:53 -07:00
a30818ff2b fixes negative args in function (#707)
* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-25 15:25:58 -07:00
53e763d938 fix close arc (#704)
* fix close arc

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* much bigger radius

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-25 12:14:41 -07:00
8f74cd1d0c Bump tauri-plugin-fs-extra from 0190f68 to b04bde3 in /src-tauri (#702)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `0190f68` to `b04bde3`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](0190f68f1d...b04bde3461)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 09:33:53 -07:00
c271942897 remove errors (#703) 2023-09-25 07:28:03 +00:00
a03d09b41d Restructure tokenizer module (#700)
* Remove duplicated tests

These tests already were copied to tokeniser2.rs, so removing them doesn't affect code coverage.

* Move tokeniser to its own module

Now there's a module for tokens, and the tokenizer/lexer implementation is private within the token module.
2023-09-24 20:01:17 -05:00
2971b7752b Bump rust websocket libraries (#701)
Changelog: https://github.com/snapview/tokio-tungstenite/blob/master/CHANGELOG.md#0201
2023-09-24 21:34:31 +00:00
70e99eb00b Refactor is_code_token into a method (#699)
* Refactor is_code_token into a method

* Fix typos, use Parser as it was imported
2023-09-24 21:11:36 +00:00
5c66af59d2 New tokenizer based on winnow (#697)
* New tokenizer, using Winnow instead of regexes.

Between 1.3x and 4.4x speedup on lexer benchmarks :)

* Use dispatch instead of alt

Most of the time, if you know the first character of a token, you can narrow down its potential possible token types, instead of just trying each token type until one succeeds.

This further speeds up the lexer. Compared to main, this branch is now between 3x and 12x faster than main.
2023-09-22 21:57:39 -05:00
6dda6daeef Use separate benchmarks for lexing and parsing (#698) 2023-09-23 02:01:18 +00:00
b5387f1220 Cut release v0.9.1 (#693)
* bump to ️v0.9.1️

* update bump instructions

* readme update

* read me again

* change pr convention
2023-09-22 10:38:17 +10:00
fd5921b366 Convert the lexer to be iterative not recursive (#691)
This is often more memory-efficient (does not create a bunch of stack
frames)
2023-09-21 19:19:08 -05:00
716ad938fc stop gap for large files making editor slow (#690)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-21 16:13:22 -07:00
40136eb392 Bump kittycad from 0.2.25 to 0.2.26 in /src-tauri (#680)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.25 to 0.2.26.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.25...v0.2.26)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 14:05:55 -07:00
8d2b89fcd1 Bump openapitor from 0d121f6 to 61a1605 in /src/wasm-lib (#679)
Bumps [openapitor](https://github.com/KittyCAD/kittycad.rs) from `0d121f6` to `61a1605`.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](0d121f6881...61a16059b3)

---
updated-dependencies:
- dependency-name: openapitor
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 15:22:04 -05:00
ad9fba3390 Bump tauri-plugin-fs-extra from 76832e6 to 0190f68 in /src-tauri (#681)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `76832e6` to `0190f68`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](76832e60bf...0190f68f1d)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 15:21:08 -05:00
911c43af50 Bump phonenumber from 0.3.2+8.13.9 to 0.3.3+8.13.9 in /src-tauri (#687)
Bumps [phonenumber](https://github.com/whisperfish/rust-phonenumber) from 0.3.2+8.13.9 to 0.3.3+8.13.9.
- [Commits](https://github.com/whisperfish/rust-phonenumber/commits)

---
updated-dependencies:
- dependency-name: phonenumber
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 15:02:37 -05:00
ab4e04f6c2 Bump phonenumber from 0.3.2+8.13.9 to 0.3.3+8.13.9 in /src/wasm-lib (#685)
Bumps [phonenumber](https://github.com/whisperfish/rust-phonenumber) from 0.3.2+8.13.9 to 0.3.3+8.13.9.
- [Commits](https://github.com/whisperfish/rust-phonenumber/commits)

---
updated-dependencies:
- dependency-name: phonenumber
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 15:02:23 -05:00
94aef05f74 Bump phonenumber from 0.3.2+8.13.9 to 0.3.3+8.13.9 in /src/wasm-lib/kcl/fuzz (#686)
Bump phonenumber in /src/wasm-lib/kcl/fuzz

Bumps [phonenumber](https://github.com/whisperfish/rust-phonenumber) from 0.3.2+8.13.9 to 0.3.3+8.13.9.
- [Commits](https://github.com/whisperfish/rust-phonenumber/commits)

---
updated-dependencies:
- dependency-name: phonenumber
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 15:02:10 -05:00
d820cf2446 Tokenizer is accidentally quadratic (#689)
* Add comments and rename a function

* Typo: paran -> paren

* Use bytes, not string, for the tokenizer

* Fix typo
2023-09-21 14:18:42 -05:00
0c724c4971 Start to restructure the Engine's connection to the backend (#674)
* Start to restructure the Engine's connectio to the backend

1) Add in a tearDown stub for when the Engine is torn down. This is now
   distinct from a 'close', which will not stop connect from trying
   again. Running tearDown will mark the connection to not be retried
   and close active connections.

2) Move the retry logic out of connect and into the constructor. It will
   attempt to reconnect at the same rate as we had previously.

3) The timeout will now only close the connection, not restart it.

Signed-off-by: Paul Tagliamonte <paul@kittycad.io>

* Don't continue on dead conn & setTimeout on init only

* Clean up extra setTimeout

* Keep track of connection timeouts and clear on close

* Fix tsc by defining Timeout

Signed-off-by: Paul Tagliamonte <paul@kittycad.io>

* appease the format gods

---------

Signed-off-by: Paul Tagliamonte <paul@kittycad.io>
Co-authored-by: Adam Sunderland <adam@kittycad.io>
2023-09-21 12:07:47 -04:00
b54ac4a694 improve getNodePathFromSourceRange and therefore the ast explorer aswell (#683)
improve getNodePathFromSourceRange and therefore the ast explorer as well
2023-09-21 05:40:41 +00:00
27227092b1 app stuck on blur when engine errors (#682)
* temp fix for when engine returns error

* don't add extrued to show function
2023-09-21 04:32:47 +00:00
04e1b92a5b Add a benchmark for parsing pipes-on-pipes (#678) 2023-09-21 03:13:07 +00:00
0553cd4621 tests for big files (#675)
* shit;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* u[dates;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* still ignore the big one

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Add big kitt SVG to benchmarks

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Adam Chalmers <adam.s.chalmers@gmail.com>
2023-09-20 19:35:37 -07:00
61a0c88af4 Add IDE dirs to .gitignore (#676) 2023-09-21 02:03:09 +00:00
d5b0544437 Bump tauri-plugin-fs-extra from 5b814f5 to 76832e6 in /src-tauri (#657)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `5b814f5` to `76832e6`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](5b814f56e6...76832e60bf)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-20 18:47:38 -07:00
6cc8af5c23 make stdlib functions async (#672)
* wip

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

closer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* closer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* closer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* compiles

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* connection

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix wasm

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* timeout

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* remove the drop

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* drop handle

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-20 18:27:08 -07:00
888104080e bump v0.9.0 (#673) 2023-09-21 10:38:40 +10:00
b6769889e3 Handle relative paths at kcl level (#506)
* handle relative paths at kcl level

* fmt

* update kittycad

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* bump

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2023-09-21 10:36:26 +10:00
a32258dac4 Engine manager can be cloned (#671) 2023-09-20 16:22:47 -07:00
18dbbad244 Use an actor to manage the Tokio engine connection (#669)
* Use an actor to manage the Tokio engine connection

This means EngineManager trait's methods take &self not &mut self, and the tokio implementation can be cloned.

* Clean up code
2023-09-20 16:59:03 -05:00
b67c16cc9d Benchmark for KCL parser (#664)
* KCL benchmarks

* CI for benchmarks

* More specific name for benchmark

* Benchmark the right directory

* Format
2023-09-20 13:15:28 -05:00
ad482641ef Unit test for zero-param programs (#663) 2023-09-20 10:51:49 -05:00
9ee24845a1 Bump to v0.8.2 (#656)
Co-authored-by: Frank Noirot <frank@kittycad.io>
2023-09-20 14:41:23 +00:00
e69d263252 Revert swapping setCode for deferredSetCode in App (#662)
This fix was implemented in https://github.com/KittyCAD/modeling-app/pull/649
to try and address https://github.com/KittyCAD/modeling-app/issues/545.
However, we need to run `setCode` to execute immediately here or else
files will not render in the 3D view when opened, as reported by @pierremtb.

Reverting for now to allow for a timely release https://github.com/KittyCAD/modeling-app/pull/656

Signed-off-by: Frank Noirot <frank@kittycad.io>
2023-09-20 10:32:36 -04:00
111738f38e Fix the debug panel overflow (#653) 2023-09-20 05:36:29 -04:00
e34501cc5a Ast fixes (#650)
* allow using member expressions for memory items

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes pi in binary expressions

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-19 16:05:53 -07:00
c767c1c3a6 Replace setCode with deferredSetCode in App (#649)
* Replace `setCode` with `deferredSetCode` in App

* Remove unused OpenFileButton component
2023-09-19 22:07:54 +00:00
e399a8f938 Franknoirot/ux papercuts 4 (#640)
* Add Cmd + / to support windows, update walkthrough

* Fix #628 dark mode <select> bg color

* Fix #621 by narrowing margins and moving to left

---------

Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2023-09-19 18:06:13 -04:00
59d5f2524a fix function inside show not executing (#641)
* start of heap changes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix show bug

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* new images

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-19 14:20:14 -07:00
b47ebd14d2 Bump to v0.8.1 (#637)
Signed-off-by: Frank Noirot <frank@kittycad.io>
2023-09-19 15:55:55 -04:00
e74bcd0695 make it so the lsp server doesnt vom on restart (#636)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-19 15:17:34 -04:00
22161ec386 Variables needs to scroll (#624)
* Variables needs to scroll
Fixes #609

* Run yarn fmt

---------

Co-authored-by: Frank Noirot <frank@kittycad.io>
2023-09-19 18:29:22 +00:00
ada46c4317 Fix Tauri auth in development (#635)
* Fix Tauri auth in development

* Fix Rust formatting
2023-09-19 14:08:26 -04:00
6675fa8d1e UX Papercuts 3: use absolute paths, add error page with buttons to help refresh, etc (#615)
* Fix #593: don't prevent default on link click

* Use absolute/explicit path for settings
Trying to test fix for #594

* Broken: replace almost all relative URLs with absolute

* Clean up to use clean useDismiss with absolute path

* Merge branch 'main' into franknoirot/ux-papercuts-3a

* Add buttons to home, reload, clear, and bug report on error screen
2023-09-19 14:06:56 -04:00
148 changed files with 8046 additions and 2598 deletions

View File

@ -54,4 +54,4 @@ jobs:
- name: Run clippy
run: |
cd "${{ matrix.dir }}"
cargo clippy --all --tests -- -D warnings
cargo clippy --all --tests --benches -- -D warnings

37
.github/workflows/cargo-criterion.yml vendored Normal file
View File

@ -0,0 +1,37 @@
on:
push:
branches:
- main
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-criterion.yml
pull_request:
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-criterion.yml
workflow_dispatch:
permissions: read-all
name: cargo criterion
jobs:
cargocriterion:
name: cargo criterion
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
cargo install cargo-criterion
- name: Rust Cache
uses: Swatinem/rust-cache@v2.6.1
- name: Benchmark kcl library
shell: bash
run: |-
cd src/wasm-lib/kcl; cargo criterion

View File

@ -58,4 +58,5 @@ jobs:
cargo nextest run --workspace --no-fail-fast -P ci
env:
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
RUST_MIN_STACK: 10485760000

5
.gitignore vendored
View File

@ -22,6 +22,11 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea
.vscode
src/wasm-lib/.idea
src/wasm-lib/.vscode
# rust
src/wasm-lib/target
src/wasm-lib/bindings

View File

@ -123,13 +123,24 @@ Before you submit a contribution PR to this repo, please ensure that:
## Release a new version
1. Bump the versions in the .json files by creating a `Bump to v{x}.{y}.{z}` PR, committing the changes from
1. Bump the versions in the .json files by creating a `Cut release v{x}.{y}.{z}` PR, committing the changes from
```bash
VERSION=x.y.z yarn run bump-jsons
```
The PR may serve as a place to discuss the human-readable changelog and extra QA.
The PR may serve as a place to discuss the human-readable changelog and extra QA. A quick way of getting PR's merged since the last bump is to [use this PR filter](https://github.com/KittyCAD/modeling-app/pulls?q=is%3Apr+sort%3Aupdated-desc+is%3Amerged+), open up the browser console and past in the following
```typescript
console.log(
'- ' +
Array.from(
document.querySelectorAll('[data-hovercard-type="pull_request"]')
).map((a) => `[${a.innerText}](${a.href})`).join(`
- `)
)
```
grab the md list and delete any that are older than the last bump
2. Merge the PR

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,8 @@
* [`sqrt`](#sqrt)
* [`startSketchAt`](#startSketchAt)
* [`tan`](#tan)
* [`tangentalArc`](#tangentalArc)
* [`tangentalArcTo`](#tangentalArcTo)
* [`tau`](#tau)
* [`xLine`](#xLine)
* [`xLineTo`](#xLineTo)
@ -3234,6 +3236,320 @@ tan(num: number) -> number
### tangentalArc
Draw an arc.
```
tangentalArc(data: TangentalArcData, sketch_group: SketchGroup) -> SketchGroup
```
#### Arguments
* `data`: `TangentalArcData` - Data to draw a tangental arc.
```
{
// Offset of the arc, in degrees.
offset: number,
// Radius of the arc. Not to be confused with Raiders of the Lost Ark.
radius: number,
} |
{
// The tag.
tag: string,
// Where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
to: [number],
} |
[number]
```
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
#### Returns
* `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
### tangentalArcTo
Draw an arc.
```
tangentalArcTo(data: TangentalArcToData, sketch_group: SketchGroup) -> SketchGroup
```
#### Arguments
* `data`: `TangentalArcToData` - Data to draw a tangental arc to a specific point.
```
{
// The tag.
tag: string,
// Where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
to: [number],
} |
[number]
```
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
#### Returns
* `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
### tau
Return the value of `tau`. The full circle constant (τ). Equal to 2π.

View File

@ -1,6 +1,6 @@
{
"name": "untitled-app",
"version": "0.8.0",
"version": "0.9.3",
"private": true,
"dependencies": {
"@codemirror/autocomplete": "^6.9.0",
@ -10,7 +10,7 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.13",
"@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "^0.0.37",
"@kittycad/lib": "^0.0.40",
"@lezer/javascript": "^1.4.7",
"@open-rpc/client-js": "^1.8.1",
"@react-hook/resize-observer": "^1.2.6",
@ -27,6 +27,7 @@
"@uiw/react-codemirror": "^4.21.13",
"@xstate/react": "^3.2.2",
"crypto-js": "^4.1.1",
"debounce-promise": "^3.1.2",
"formik": "^2.4.3",
"fuse.js": "^6.6.2",
"http-server": "^14.1.1",
@ -47,7 +48,7 @@
"ts-node": "^10.9.1",
"typescript": "^4.4.2",
"uuid": "^9.0.0",
"vitest": "^0.34.1",
"vitest": "^0.34.6",
"vscode-jsonrpc": "^8.1.0",
"vscode-languageserver-protocol": "^3.17.3",
"wasm-pack": "^0.12.1",
@ -65,7 +66,7 @@
"pretest": "yarn remove-importmeta",
"test": "vitest --mode development",
"test:nowatch": "vitest run --mode development",
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests)",
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)",
"test:cov": "vitest run --coverage --mode development",
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",
@ -101,7 +102,7 @@
"@babel/preset-env": "^7.22.9",
"@tauri-apps/cli": "^1.3.1",
"@types/crypto-js": "^4.1.1",
"@types/debounce": "^1.2.1",
"@types/debounce-promise": "^3.1.6",
"@types/isomorphic-fetch": "^0.0.36",
"@types/react-modal": "^3.16.0",
"@types/uuid": "^9.0.1",
@ -115,7 +116,7 @@
"eslint-plugin-css-modules": "^2.11.0",
"happy-dom": "^10.8.0",
"husky": "^8.0.3",
"postcss": "^8.4.19",
"postcss": "^8.4.31",
"prettier": "^2.8.0",
"setimmediate": "^1.0.5",
"tailwindcss": "^3.2.4",

220
src-tauri/Cargo.lock generated
View File

@ -84,7 +84,7 @@ dependencies = [
"tauri-build",
"tauri-plugin-fs-extra",
"tokio",
"toml 0.8.0",
"toml 0.8.1",
]
[[package]]
@ -155,6 +155,20 @@ version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "bigdecimal"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "454bca3db10617b88b566f205ed190aedb0e0e6dd4cad61d3988a72e8c5594cb"
dependencies = [
"autocfg",
"libm",
"num-bigint",
"num-integer",
"num-traits",
"serde",
]
[[package]]
name = "bincode"
version = "1.3.3"
@ -1295,7 +1309,21 @@ checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148"
dependencies = [
"log",
"mac",
"markup5ever",
"markup5ever 0.10.1",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "html5ever"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
dependencies = [
"log",
"mac",
"markup5ever 0.11.0",
"proc-macro2",
"quote",
"syn 1.0.109",
@ -1630,13 +1658,14 @@ dependencies = [
[[package]]
name = "kittycad"
version = "0.2.25"
version = "0.2.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9cf962b1e81a0b4eb923a727e761b40672cbacc7f5f0b75e13579d346352bc7"
checksum = "35b2f9302648dbb06fd7121687f9505fc3179eba84111a06d76b246e3158f5dc"
dependencies = [
"anyhow",
"async-trait",
"base64 0.21.2",
"bigdecimal",
"bytes",
"chrono",
"data-encoding",
@ -1671,7 +1700,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358"
dependencies = [
"cssparser",
"html5ever",
"html5ever 0.25.2",
"matches",
"selectors",
]
[[package]]
name = "kuchikiki"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8"
dependencies = [
"cssparser",
"html5ever 0.26.0",
"indexmap 1.9.3",
"matches",
"selectors",
]
@ -1688,6 +1730,12 @@ version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]]
name = "libm"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]]
name = "line-wrap"
version = "0.1.1"
@ -1727,9 +1775,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.18"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
dependencies = [
"serde",
]
@ -1781,7 +1829,21 @@ checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd"
dependencies = [
"log",
"phf 0.8.0",
"phf_codegen",
"phf_codegen 0.8.0",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
name = "markup5ever"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
dependencies = [
"log",
"phf 0.10.1",
"phf_codegen 0.10.0",
"string_cache",
"string_cache_codegen",
"tendril",
@ -1959,6 +2021,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
@ -1982,9 +2055,9 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [
"autocfg",
]
@ -2182,6 +2255,17 @@ dependencies = [
"thiserror",
]
[[package]]
name = "os_info"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e"
dependencies = [
"log",
"serde",
"winapi",
]
[[package]]
name = "overload"
version = "0.1.1"
@ -2331,6 +2415,16 @@ dependencies = [
"phf_shared 0.8.0",
]
[[package]]
name = "phf_codegen"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
dependencies = [
"phf_generator 0.10.0",
"phf_shared 0.10.0",
]
[[package]]
name = "phf_generator"
version = "0.8.0"
@ -2399,9 +2493,9 @@ dependencies = [
[[package]]
name = "phonenumber"
version = "0.3.2+8.13.9"
version = "0.3.3+8.13.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34749f64ea9d76f10cdc8a859588b57775f59177c7dd91f744d620bd62982d6f"
checksum = "635f3e6288e4f01c049d89332a031bd74f25d64b6fb94703ca966e819488cd06"
dependencies = [
"bincode",
"either",
@ -2414,6 +2508,7 @@ dependencies = [
"regex-cache",
"serde",
"serde_derive",
"strum",
"thiserror",
]
@ -3010,10 +3105,11 @@ dependencies = [
[[package]]
name = "schemars"
version = "0.8.13"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "763f8cd0d4c71ed8389c90cb8100cba87e763bd01a8e614d4f0af97bcd50a161"
checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c"
dependencies = [
"bigdecimal",
"bytes",
"chrono",
"dyn-clone",
@ -3026,9 +3122,9 @@ dependencies = [
[[package]]
name = "schemars_derive"
version = "0.8.13"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0f696e21e10fa546b7ffb1c9672c6de8fbc7a81acf59524386d8639bf12737"
checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c"
dependencies = [
"proc-macro2",
"quote",
@ -3094,7 +3190,7 @@ dependencies = [
"log",
"matches",
"phf 0.8.0",
"phf_codegen",
"phf_codegen 0.8.0",
"precomputed-hash",
"servo_arc",
"smallvec",
@ -3447,6 +3543,28 @@ dependencies = [
"syn 2.0.33",
]
[[package]]
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck 0.4.1",
"proc-macro2",
"quote",
"rustversion",
"syn 1.0.109",
]
[[package]]
name = "syn"
version = "1.0.109"
@ -3469,6 +3587,19 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sys-locale"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee"
dependencies = [
"js-sys",
"libc",
"wasm-bindgen",
"web-sys",
"windows-sys 0.45.0",
]
[[package]]
name = "system-deps"
version = "5.0.0"
@ -3581,9 +3712,9 @@ dependencies = [
[[package]]
name = "tauri"
version = "1.4.1"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e"
checksum = "72aee3277d0a0df01472cc704ab5934a51a1f25348838df17bfb3c5cb727880c"
dependencies = [
"anyhow",
"base64 0.21.2",
@ -3604,6 +3735,7 @@ dependencies = [
"objc",
"once_cell",
"open",
"os_info",
"percent-encoding",
"rand 0.8.5",
"raw-window-handle",
@ -3616,6 +3748,7 @@ dependencies = [
"serde_repr",
"serialize-to-javascript",
"state",
"sys-locale",
"tar",
"tauri-macros",
"tauri-runtime",
@ -3635,12 +3768,13 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b"
checksum = "6a62b3327886e7ef2978adc668432f1cc53f14e1d46e7ae04f730f4d48584623"
dependencies = [
"anyhow",
"cargo_toml",
"dirs-next",
"heck 0.4.1",
"json-patch",
"semver",
@ -3648,13 +3782,14 @@ dependencies = [
"serde_json",
"tauri-utils",
"tauri-winres",
"walkdir",
]
[[package]]
name = "tauri-codegen"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a"
checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb"
dependencies = [
"base64 0.21.2",
"brotli",
@ -3678,9 +3813,9 @@ dependencies = [
[[package]]
name = "tauri-macros"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7"
checksum = "613740228de92d9196b795ac455091d3a5fbdac2654abb8bb07d010b62ab43af"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@ -3693,7 +3828,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-fs-extra"
version = "0.0.0"
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#5b814f56e6368fdec46c4ddb04a07e0923ff995a"
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#9af4c3727c0d9c7a88b27cb80a6482a5aa461fc5"
dependencies = [
"log",
"serde",
@ -3704,9 +3839,9 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "0.14.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769"
checksum = "07f8e9e53e00e9f41212c115749e87d5cd2a9eebccafca77a19722eeecd56d43"
dependencies = [
"gtk",
"http",
@ -3725,9 +3860,9 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
version = "0.14.0"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7aa256a1407a3a091b5d843eccc1a5042289baf0a43d1179d9f0fcfea37c1b"
checksum = "8141d72b6b65f2008911e9ef5b98a68d1e3413b7a1464e8f85eb3673bb19a895"
dependencies = [
"cocoa",
"gtk",
@ -3745,19 +3880,20 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "1.4.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03fc02bb6072bb397e1d473c6f76c953cda48b4a2d0cce605df284aa74a12e84"
checksum = "34d55e185904a84a419308d523c2c6891d5e2dbcee740c4997eb42e75a7b0f46"
dependencies = [
"brotli",
"ctor",
"dunce",
"glob",
"heck 0.4.1",
"html5ever",
"html5ever 0.26.0",
"infer",
"json-patch",
"kuchiki",
"kuchikiki",
"log",
"memchr",
"phf 0.10.1",
"proc-macro2",
@ -3942,14 +4078,14 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c226a7bba6d859b63c92c4b4fe69c5b6b72d0cb897dbc8e6012298e6154cb56e"
checksum = "1bc1433177506450fe920e46a4f9812d0c211f5dd556da10e731a0a3dfa151f0"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.20.0",
"toml_edit 0.20.1",
]
[[package]]
@ -3976,9 +4112,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.20.0"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ff63e60a958cefbb518ae1fd6566af80d9d4be430a33f3723dfc47d1d411d95"
checksum = "ca676d9ba1a322c1b64eb8045a5ec5c0cfb0c9d08e15e9ff622589ad5221c8fe"
dependencies = [
"indexmap 2.0.0",
"serde",
@ -4773,9 +4909,9 @@ dependencies = [
[[package]]
name = "wry"
version = "0.24.3"
version = "0.24.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33748f35413c8a98d45f7a08832d848c0c5915501803d1faade5a4ebcd258cea"
checksum = "88ef04bdad49eba2e01f06e53688c8413bd6a87b0bc14b72284465cf96e3578e"
dependencies = [
"base64 0.13.1",
"block",
@ -4787,7 +4923,7 @@ dependencies = [
"gio",
"glib",
"gtk",
"html5ever",
"html5ever 0.25.2",
"http",
"kuchiki",
"libc",

View File

@ -12,18 +12,18 @@ rust-version = "1.60"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1.4.0", features = [] }
tauri-build = { version = "1.4.1", features = [] }
[dependencies]
anyhow = "1"
kittycad = "0.2.25"
kittycad = "0.2.28"
oauth2 = "4.4.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tauri = { version = "1.4.1", features = ["dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
tauri = { version = "1.5.0", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tokio = { version = "1.32.0", features = ["time"] }
toml = "0.8.0"
toml = "0.8.1"
[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.

View File

@ -6,6 +6,7 @@ use std::io::Read;
use anyhow::Result;
use oauth2::TokenResponse;
use tauri::{InvokeError, Manager};
const DEFAULT_HOST: &str = "https://api.kittycad.io";
/// This command returns the a json string parse from a toml file at the path.
#[tauri::command]
@ -88,11 +89,34 @@ async fn login(app: tauri::AppHandle, host: &str) -> Result<String, InvokeError>
///This command returns the KittyCAD user info given a token.
/// The string returned from this method is the user info as a json string.
#[tauri::command]
async fn get_user(token: Option<String>) -> Result<kittycad::types::User, InvokeError> {
async fn get_user(
token: Option<String>,
hostname: &str,
) -> Result<kittycad::types::User, InvokeError> {
// Use the host passed in if it's set.
// Otherwise, use the default host.
let host = if hostname.is_empty() {
DEFAULT_HOST.to_string()
} else {
hostname.to_string()
};
// Change the baseURL to the one we want.
let mut baseurl = host.to_string();
if !host.starts_with("http://") && !host.starts_with("https://") {
baseurl = format!("https://{host}");
if host.starts_with("localhost") {
baseurl = format!("http://{host}")
}
}
println!("Getting user info...");
// use kittycad library to fetch the user info from /user/me
let client = kittycad::Client::new(token.unwrap());
let mut client = kittycad::Client::new(token.unwrap());
if baseurl != DEFAULT_HOST {
client.set_base_url(&baseurl);
}
let user_info: kittycad::types::User = client
.users()

View File

@ -8,7 +8,7 @@
},
"package": {
"productName": "kittycad-modeling",
"version": "0.8.0"
"version": "0.9.3"
},
"tauri": {
"allowlist": {
@ -36,6 +36,9 @@
"https://api.dev.kittycad.io/*"
]
},
"os": {
"all": true
},
"shell": {
"open": true
},

View File

@ -31,6 +31,7 @@ import { TextEditor } from 'components/TextEditor'
import { Themes, getSystemTheme } from 'lib/theme'
import { useSetupEngineManager } from 'hooks/useSetupEngineManager'
import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubscriptions'
import { engineCommandManager } from './lang/std/engineConnection'
export function App() {
const { code: loadedCode, project } = useLoaderData() as IndexLoaderData
@ -39,7 +40,6 @@ export function App() {
useHotKeyListener()
const {
setCode,
engineCommandManager,
buttonDownInStream,
openPanes,
setOpenPanes,
@ -52,7 +52,6 @@ export function App() {
guiMode: s.guiMode,
setGuiMode: s.setGuiMode,
setCode: s.setCode,
engineCommandManager: s.engineCommandManager,
buttonDownInStream: s.buttonDownInStream,
openPanes: s.openPanes,
setOpenPanes: s.setOpenPanes,
@ -91,12 +90,12 @@ export function App() {
if (guiMode.sketchMode === 'sketchEdit') {
// TODO: share this with Toolbar's "Exit sketch" button
// exiting sketch should be done consistently across all exits
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: { type: 'edit_mode_exit' },
})
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: { type: 'default_camera_disable_sketch_mode' },
@ -107,7 +106,7 @@ export function App() {
// when exiting sketch mode in the future
executeAst()
} else {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
@ -156,7 +155,7 @@ export function App() {
useEngineConnectionSubscriptions()
const debounceSocketSend = throttle<EngineCommand>((message) => {
engineCommandManager?.sendSceneCommand(message)
engineCommandManager.sendSceneCommand(message)
}, 16)
const handleMouseMove: MouseEventHandler<HTMLDivElement> = (e) => {
e.nativeEvent.preventDefault()
@ -216,7 +215,6 @@ export function App() {
} else if (interactionGuards.zoom.dragCallback(eWithButton)) {
interaction = 'zoom'
} else {
console.log('none')
return
}

View File

@ -6,9 +6,9 @@ export const Auth = ({ children }: React.PropsWithChildren) => {
const {
auth: { state },
} = useGlobalStateContext()
const isLoggedIn = state.matches('checkIfLoggedIn')
const isLoggingIn = state.matches('checkIfLoggedIn')
return isLoggedIn ? (
return isLoggingIn ? (
<Loading>Loading KittyCAD Modeling App...</Loading>
) : (
<>{children}</>

View File

@ -130,6 +130,7 @@ const router = createBrowserRouter(
path: paths.INDEX,
loader: () =>
isTauri() ? redirect(paths.HOME) : redirect(paths.FILE + '/new'),
errorElement: <ErrorPage />,
},
{
path: paths.FILE + '/:id',
@ -140,7 +141,6 @@ const router = createBrowserRouter(
{!isTauri() && import.meta.env.PROD && <DownloadAppBanner />}
</Auth>
),
errorElement: <ErrorPage />,
id: paths.FILE,
loader: async ({
request,

View File

@ -18,6 +18,7 @@ import styles from './Toolbar.module.css'
import { v4 as uuidv4 } from 'uuid'
import { useAppMode } from 'hooks/useAppMode'
import { ActionIcon } from 'components/ActionIcon'
import { engineCommandManager } from './lang/std/engineConnection'
export const sketchButtonClassnames = {
background:
@ -50,7 +51,6 @@ export const Toolbar = () => {
ast,
updateAst,
programMemory,
engineCommandManager,
executeAst,
} = useStore((s) => ({
guiMode: s.guiMode,
@ -59,15 +59,10 @@ export const Toolbar = () => {
ast: s.ast,
updateAst: s.updateAst,
programMemory: s.programMemory,
engineCommandManager: s.engineCommandManager,
executeAst: s.executeAst,
}))
useAppMode()
useEffect(() => {
console.log('guiMode', guiMode)
}, [guiMode])
function ToolbarButtons({ className }: React.HTMLAttributes<HTMLElement>) {
return (
<span className={styles.toolbarButtons + ' ' + className}>
@ -173,12 +168,12 @@ export const Toolbar = () => {
{guiMode.mode === 'sketch' && (
<button
onClick={() => {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: { type: 'edit_mode_exit' },
})
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: { type: 'default_camera_disable_sketch_mode' },
@ -214,7 +209,7 @@ export const Toolbar = () => {
<button
key={sketchFnName}
onClick={() => {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {

View File

@ -23,10 +23,7 @@ type ActionButtonAsLink = BaseActionButtonProps &
}
type ActionButtonAsExternal = BaseActionButtonProps &
Omit<
React.AnchorHTMLAttributes<HTMLAnchorElement>,
keyof BaseActionButtonProps
> & {
Omit<LinkProps, keyof BaseActionButtonProps> & {
Element: 'externalLink'
}
@ -69,12 +66,17 @@ export const ActionButton = (props: ActionButtonProps) => {
)
}
case 'externalLink': {
const { Element, icon, children, className, ...rest } = props
const { Element, to, icon, children, className, ...rest } = props
return (
<a className={classNames} {...rest}>
<Link
to={to || paths.INDEX}
className={classNames}
{...rest}
target="_blank"
>
{icon && <ActionIcon {...icon} />}
{children}
</a>
</Link>
)
}
default: {

View File

@ -1,7 +1,5 @@
import { useEffect, useState, useRef } from 'react'
import { parser_wasm } from '../lang/abstractSyntaxTree'
import { BinaryPart, Value } from '../lang/abstractSyntaxTreeTypes'
import { executor } from '../lang/executor'
import { parse, BinaryPart, Value, executor } from '../lang/wasm'
import {
createIdentifier,
createLiteral,
@ -10,6 +8,7 @@ import {
} from '../lang/modifyAst'
import { findAllPreviousVariables, PrevVariable } from '../lang/queryAst'
import { useStore } from '../useStore'
import { engineCommandManager } from '../lang/std/engineConnection'
export const AvailableVars = ({
onVarClick,
@ -92,14 +91,11 @@ export function useCalc({
newVariableInsertIndex: number
setNewVariableName: (a: string) => void
} {
const { ast, programMemory, selectionRange, engineCommandManager } = useStore(
(s) => ({
ast: s.ast,
programMemory: s.programMemory,
selectionRange: s.selectionRanges.codeBasedSelections[0].range,
engineCommandManager: s.engineCommandManager,
})
)
const { ast, programMemory, selectionRange } = useStore((s) => ({
ast: s.ast,
programMemory: s.programMemory,
selectionRange: s.selectionRanges.codeBasedSelections[0].range,
}))
const inputRef = useRef<HTMLInputElement>(null)
const [availableVarInfo, setAvailableVarInfo] = useState<
ReturnType<typeof findAllPreviousVariables>
@ -140,10 +136,9 @@ export function useCalc({
}, [ast, programMemory, selectionRange])
useEffect(() => {
if (!engineCommandManager) return
try {
const code = `const __result__ = ${value}\nshow(__result__)`
const ast = parser_wasm(code)
const ast = parse(code)
const _programMem: any = { root: {}, return: null }
availableVarInfo.variables.forEach(({ key, value }) => {
_programMem.root[key] = { type: 'userVal', value, __meta: [] }

View File

@ -62,7 +62,7 @@ export const CommandBarProvider = ({
const CommandBar = () => {
const { commands, commandBarOpen, setCommandBarOpen } = useCommandsContext()
useHotkeys('meta+k', () => {
useHotkeys(['meta+k', 'meta+/'], () => {
if (commands.length === 0) return
setCommandBarOpen(!commandBarOpen)
})
@ -221,10 +221,10 @@ const CommandBar = () => {
<Combobox
value={selectedCommand}
onChange={handleCommandSelection}
className="rounded relative mx-auto p-2 bg-chalkboard-10 dark:bg-chalkboard-100 border dark:border-chalkboard-70 max-w-xl w-full shadow-lg"
className="relative w-full max-w-xl p-2 mx-auto border rounded shadow-lg bg-chalkboard-10 dark:bg-chalkboard-100 dark:border-chalkboard-70"
as="div"
>
<div className="flex gap-2 items-center">
<div className="flex items-center gap-2">
<ActionIcon icon={faSearch} size="xl" className="rounded-sm" />
<div>
{inSubCommand && (
@ -235,7 +235,7 @@ const CommandBar = () => {
)}
<Combobox.Input
onChange={(event) => setQuery(event.target.value)}
className="bg-transparent focus:outline-none w-full"
className="w-full bg-transparent focus:outline-none"
onKeyDown={(event) => {
if (event.metaKey && event.key === 'k')
setCommandBarOpen(false)
@ -264,12 +264,12 @@ const CommandBar = () => {
/>
</div>
</div>
<Combobox.Options static className="max-h-96 overflow-y-auto">
<Combobox.Options static className="overflow-y-auto max-h-96">
{filteredCommands?.map((commandResult) => (
<Combobox.Option
key={commandResult.item.name}
value={commandResult}
className="my-2 first:mt-4 last:mb-4 ui-active:bg-liquid-10 dark:ui-active:bg-liquid-90 py-1 px-2"
className="px-2 py-1 my-2 first:mt-4 last:mb-4 ui-active:bg-liquid-10 dark:ui-active:bg-liquid-90"
>
<p>{commandResult.item.name}</p>
{(commandResult.item as SubCommand).description && (

View File

@ -1,5 +1,4 @@
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
import { useStore } from '../useStore'
import { v4 as uuidv4 } from 'uuid'
import { EngineCommand } from '../lang/std/engineConnection'
import { useState } from 'react'
@ -7,6 +6,7 @@ import { ActionButton } from '../components/ActionButton'
import { faCheck } from '@fortawesome/free-solid-svg-icons'
import { isReducedMotion } from 'lang/util'
import { AstExplorer } from './AstExplorer'
import { engineCommandManager } from '../lang/std/engineConnection'
type SketchModeCmd = Extract<
Extract<EngineCommand, { type: 'modeling_cmd_req' }>['cmd'],
@ -14,9 +14,6 @@ type SketchModeCmd = Extract<
>
export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
const { engineCommandManager } = useStore((s) => ({
engineCommandManager: s.engineCommandManager,
}))
const [sketchModeCmd, setSketchModeCmd] = useState<SketchModeCmd>({
type: 'default_camera_enable_sketch_mode',
origin: { x: 0, y: 0, z: 0 },
@ -30,7 +27,11 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
return (
<CollapsiblePanel
{...props}
className={'!absolute !h-auto bottom-5 right-5 ' + className}
className={
'!absolute overflow-hidden !h-auto bottom-5 right-5 ' + className
}
// header height, top-5, and bottom-5
style={{ maxHeight: 'calc(100% - 3rem - 1.25rem - 1.25rem)' }}
>
<section className="p-4 flex flex-col gap-4">
<Xyz
@ -66,19 +67,18 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
className="w-16"
type="checkbox"
checked={sketchModeCmd.ortho}
onChange={(a) => {
console.log(a, (a as any).checked)
onChange={(a) =>
setSketchModeCmd({
...sketchModeCmd,
ortho: a.target.checked,
})
}}
}
/>
</div>
<ActionButton
Element="button"
onClick={() => {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: sketchModeCmd,
cmd_id: uuidv4(),

View File

@ -1,4 +1,12 @@
import { useRouteError } from 'react-router-dom'
import { isTauri } from 'lib/isTauri'
import { useRouteError, isRouteErrorResponse } from 'react-router-dom'
import { ActionButton } from './ActionButton'
import {
faBug,
faHome,
faRefresh,
faTrash,
} from '@fortawesome/free-solid-svg-icons'
export const ErrorPage = () => {
let error = useRouteError()
@ -11,7 +19,43 @@ export const ErrorPage = () => {
<h1 className="text-4xl mb-8 font-bold">
An unexpected error occurred
</h1>
<p>{String(error)}</p>
{isRouteErrorResponse(error) && (
<p className="mb-8">
{error.status}: {error.data}
</p>
)}
<div className="flex justify-between gap-2 mt-6">
{isTauri() && (
<ActionButton Element="link" to={'/'} icon={{ icon: faHome }}>
Go Home
</ActionButton>
)}
<ActionButton
Element="button"
icon={{ icon: faRefresh }}
onClick={() => window.location.reload()}
>
Reload
</ActionButton>
<ActionButton
Element="button"
icon={{ icon: faTrash }}
onClick={() => {
window.localStorage.clear()
}}
>
Clear storage
</ActionButton>
<ActionButton
Element="link"
icon={{ icon: faBug }}
target="_blank"
rel="noopener noreferrer"
to="https://discord.com/channels/915388055236509727/1138967922614743060"
>
Report Bug
</ActionButton>
</div>
</section>
</div>
)

View File

@ -1,13 +1,17 @@
import { v4 as uuidv4 } from 'uuid'
import { useStore } from '../useStore'
import { faFileExport, faXmark } from '@fortawesome/free-solid-svg-icons'
import { ActionButton } from './ActionButton'
import Modal from 'react-modal'
import React from 'react'
import { useFormik } from 'formik'
import { Models } from '@kittycad/lib'
import { engineCommandManager } from '../lang/std/engineConnection'
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
type OutputFormat = Models['OutputFormat_type']
type OutputTypeKey = OutputFormat['type']
type ExtractStorageTypes<T> = T extends { storage: infer U } ? U : never
type StorageUnion = ExtractStorageTypes<OutputFormat>
interface ExportButtonProps extends React.PropsWithChildren {
className?: {
@ -18,14 +22,19 @@ interface ExportButtonProps extends React.PropsWithChildren {
}
export const ExportButton = ({ children, className }: ExportButtonProps) => {
const { engineCommandManager } = useStore((s) => ({
engineCommandManager: s.engineCommandManager,
}))
const [modalIsOpen, setIsOpen] = React.useState(false)
const {
settings: {
state: {
context: { baseUnit },
},
},
} = useGlobalStateContext()
const defaultType = 'gltf'
const [type, setType] = React.useState(defaultType)
const [type, setType] = React.useState<OutputTypeKey>(defaultType)
const defaultStorage = 'embedded'
const [storage, setStorage] = React.useState<StorageUnion>(defaultStorage)
function openModal() {
setIsOpen(true)
@ -38,7 +47,7 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
// Default to gltf and embedded.
const initialValues: OutputFormat = {
type: defaultType,
storage: 'embedded',
storage: defaultStorage,
presentation: 'pretty',
}
const formik = useFormik({
@ -66,7 +75,18 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
},
}
}
engineCommandManager?.sendSceneCommand({
if (values.type === 'obj' || values.type === 'stl') {
values.units = baseUnit
}
if (
values.type === 'ply' ||
values.type === 'stl' ||
values.type === 'gltf'
) {
// Set the storage type.
values.storage = storage
}
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'export',
@ -75,6 +95,7 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
// in the scene to export. In that case, you'd pass the IDs thru here.
entity_ids: [],
format: values,
source_unit: baseUnit,
},
cmd_id: uuidv4(),
})
@ -109,7 +130,17 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
id="type"
name="type"
onChange={(e) => {
setType(e.target.value)
setType(e.target.value as OutputTypeKey)
if (e.target.value === 'gltf') {
// Set default to embedded.
setStorage('embedded')
} else if (e.target.value === 'ply') {
// Set default to ascii.
setStorage('ascii')
} else if (e.target.value === 'stl') {
// Set default to ascii.
setStorage('ascii')
}
formik.handleChange(e)
}}
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
@ -127,10 +158,10 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
<select
id="storage"
name="storage"
onChange={formik.handleChange}
value={
'storage' in formik.values ? formik.values.storage : ''
}
onChange={(e) => {
setStorage(e.target.value as StorageUnion)
formik.handleChange(e)
}}
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
>
{type === 'gltf' && (

View File

@ -1,7 +1,6 @@
import { processMemory } from './MemoryPanel'
import { parser_wasm } from '../lang/abstractSyntaxTree'
import { enginelessExecutor } from '../lib/testHelpers'
import { initPromise } from '../lang/rust'
import { initPromise, parse } from '../lang/wasm'
beforeAll(() => initPromise)
@ -26,7 +25,7 @@ describe('processMemory', () => {
|> lineTo([2.15, 4.32], %)
// |> rx(90, %)
show(theExtrude, theSketch)`
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast, {
root: {},
return: null,

View File

@ -2,7 +2,7 @@ import ReactJson from 'react-json-view'
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
import { useStore } from '../useStore'
import { useMemo } from 'react'
import { ProgramMemory, Path, ExtrudeSurface } from '../lang/executor'
import { ProgramMemory, Path, ExtrudeSurface } from '../lang/wasm'
import { Themes } from '../lib/theme'
interface MemoryPanelProps extends CollapsiblePanelProps {
@ -24,7 +24,11 @@ export const MemoryPanel = ({
<CollapsiblePanel {...props}>
<div className="h-full relative">
<div className="absolute inset-0 flex flex-col items-start">
<div className=" h-full console-tile w-full">
<div
className="overflow-y-auto h-full console-tile w-full"
style={{ marginBottom: 36 }}
>
{/* 36px is the height of PanelHeader */}
<ReactJson
src={ProcessedMemory}
collapsed={1}
@ -46,7 +50,7 @@ export const MemoryPanel = ({
export const processMemory = (programMemory: ProgramMemory) => {
const processedMemory: any = {}
Object.keys(programMemory.root).forEach((key) => {
Object.keys(programMemory?.root || {}).forEach((key) => {
const val = programMemory.root[key]
if (typeof val.value !== 'function') {
if (val.type === 'SketchGroup') {

View File

@ -1,42 +0,0 @@
import { invoke } from '@tauri-apps/api/tauri'
import { open } from '@tauri-apps/api/dialog'
import { useStore } from '../useStore'
export const OpenFileButton = () => {
const { setCode } = useStore((s) => ({
setCode: s.setCode,
}))
const handleClick = async () => {
const selected = await open({
multiple: false,
directory: false,
filters: [
{
name: 'CAD',
extensions: ['toml'],
},
],
})
if (Array.isArray(selected)) {
// User selected multiple files
// We should not get here, since multiple is false.
} else if (selected === null) {
// User cancelled the selection
// Do nothing.
} else {
// User selected a single file
// We want to invoke our command to read the file.
const json: string = await invoke('read_toml', { path: selected })
const packageDetails = JSON.parse(json).package
if (packageDetails.main) {
const absPath = [
...selected.split('/').slice(0, -1),
packageDetails.main,
].join('/')
const file: string = await invoke('read_txt_file', { path: absPath })
setCode(file)
}
}
}
return <button onClick={() => handleClick()}>Open File</button>
}

View File

@ -2,6 +2,8 @@ import { fireEvent, render, screen } from '@testing-library/react'
import { BrowserRouter } from 'react-router-dom'
import ProjectSidebarMenu from './ProjectSidebarMenu'
import { ProjectWithEntryPointMetadata } from '../Router'
import { GlobalStateProvider } from './GlobalStateProvider'
import CommandBarProvider from './CommandBar'
const now = new Date()
const projectWellFormed = {
@ -38,7 +40,11 @@ describe('ProjectSidebarMenu tests', () => {
test('Renders the project name', () => {
render(
<BrowserRouter>
<ProjectSidebarMenu project={projectWellFormed} />
<CommandBarProvider>
<GlobalStateProvider>
<ProjectSidebarMenu project={projectWellFormed} />
</GlobalStateProvider>
</CommandBarProvider>
</BrowserRouter>
)
@ -55,7 +61,11 @@ describe('ProjectSidebarMenu tests', () => {
test('Renders app name if given no project', () => {
render(
<BrowserRouter>
<ProjectSidebarMenu />
<CommandBarProvider>
<GlobalStateProvider>
<ProjectSidebarMenu />
</GlobalStateProvider>
</CommandBarProvider>
</BrowserRouter>
)
@ -69,7 +79,14 @@ describe('ProjectSidebarMenu tests', () => {
test('Renders as a link if set to do so', () => {
render(
<BrowserRouter>
<ProjectSidebarMenu project={projectWellFormed} renderAsLink={true} />
<CommandBarProvider>
<GlobalStateProvider>
<ProjectSidebarMenu
project={projectWellFormed}
renderAsLink={true}
/>
</GlobalStateProvider>
</CommandBarProvider>
</BrowserRouter>
)

View File

@ -1,6 +1,6 @@
import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react'
import { Value } from '../lang/abstractSyntaxTreeTypes'
import { Value } from '../lang/wasm'
import {
AvailableVars,
addToInputHelper,

View File

@ -1,6 +1,6 @@
import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react'
import { Value } from '../lang/abstractSyntaxTreeTypes'
import { Value } from '../lang/wasm'
import {
AvailableVars,
addToInputHelper,

View File

@ -20,11 +20,15 @@ import {
compareVec2Epsilon,
} from 'lang/std/sketch'
import { getNodeFromPath } from 'lang/queryAst'
import { Program, VariableDeclarator } from 'lang/abstractSyntaxTreeTypes'
import { modify_ast_for_sketch } from '../wasm-lib/pkg/wasm_lib'
import {
Program,
VariableDeclarator,
rangeTypeFix,
modifyAstForSketch,
} from 'lang/wasm'
import { KCLError } from 'lang/errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import { rangeTypeFix } from 'lang/abstractSyntaxTree'
import { engineCommandManager } from '../lang/std/engineConnection'
export const Stream = ({ className = '' }) => {
const [isLoading, setIsLoading] = useState(true)
@ -32,7 +36,6 @@ export const Stream = ({ className = '' }) => {
const videoRef = useRef<HTMLVideoElement>(null)
const {
mediaStream,
engineCommandManager,
setButtonDownInStream,
didDragInStream,
setDidDragInStream,
@ -45,7 +48,6 @@ export const Stream = ({ className = '' }) => {
programMemory,
} = useStore((s) => ({
mediaStream: s.mediaStream,
engineCommandManager: s.engineCommandManager,
setButtonDownInStream: s.setButtonDownInStream,
fileId: s.fileId,
didDragInStream: s.didDragInStream,
@ -73,7 +75,7 @@ export const Stream = ({ className = '' }) => {
if (!videoRef.current) return
if (!mediaStream) return
videoRef.current.srcObject = mediaStream
}, [mediaStream, engineCommandManager])
}, [mediaStream])
const handleMouseDown: MouseEventHandler<HTMLVideoElement> = (e) => {
if (!videoRef.current) return
@ -107,7 +109,7 @@ export const Stream = ({ className = '' }) => {
}
if (guiMode.mode === 'sketch' && guiMode.sketchMode === ('move' as any)) {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'handle_mouse_drag_start',
@ -121,7 +123,7 @@ export const Stream = ({ className = '' }) => {
guiMode.sketchMode === ('sketch_line' as any)
)
) {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'camera_drag_start',
@ -139,7 +141,7 @@ export const Stream = ({ className = '' }) => {
const handleScroll: WheelEventHandler<HTMLVideoElement> = (e) => {
if (!cameraMouseDragGuards[cameraControls].zoom.scrollCallback(e)) return
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'default_camera_zoom',
@ -177,7 +179,7 @@ export const Stream = ({ className = '' }) => {
}
if (!didDragInStream) {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'select_with_point',
@ -214,7 +216,7 @@ export const Stream = ({ className = '' }) => {
window: { x, y },
}
}
engineCommandManager?.sendSceneCommand(command).then(async (resp) => {
engineCommandManager.sendSceneCommand(command).then(async (resp) => {
if (!(guiMode.mode === 'sketch')) return
if (guiMode.sketchMode === 'selectFace') return
@ -240,9 +242,6 @@ export const Stream = ({ className = '' }) => {
) {
// Let's get the updated ast.
if (sketchGroupId === '') return
console.log('guiMode.pathId', guiMode.pathId)
// We have a problem if we do not have an id for the sketch group.
if (
guiMode.pathId === undefined ||
@ -253,26 +252,14 @@ export const Stream = ({ className = '' }) => {
let engineId = guiMode.pathId
try {
const updatedAst: Program = await modify_ast_for_sketch(
engineCommandManager,
JSON.stringify(ast),
variableName,
engineId
)
const updatedAst: Program = await modifyAstForSketch(
engineCommandManager,
ast,
variableName,
engineId
)
updateAst(updatedAst, false)
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
updateAst(updatedAst, false)
return
}
@ -285,7 +272,7 @@ export const Stream = ({ className = '' }) => {
guiMode.waitingFirstClick &&
!isEditingExistingSketch
) {
const curve = await engineCommandManager?.sendSceneCommand({
const curve = await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
@ -326,7 +313,7 @@ export const Stream = ({ className = '' }) => {
resp?.data?.data?.entities_modified?.length &&
(!guiMode.waitingFirstClick || isEditingExistingSketch)
) {
const curve = await engineCommandManager?.sendSceneCommand({
const curve = await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
@ -371,12 +358,12 @@ export const Stream = ({ className = '' }) => {
setGuiMode({
mode: 'default',
})
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: { type: 'edit_mode_exit' },
})
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: { type: 'default_camera_disable_sketch_mode' },

View File

@ -30,6 +30,7 @@ import { isOverlap, roundOff } from 'lib/utils'
import { kclErrToDiagnostic } from 'lang/errors'
import { CSSRuleObject } from 'tailwindcss/types/config'
import interact from '@replit/codemirror-interact'
import { engineCommandManager } from '../lang/std/engineConnection'
export const editorShortcutMeta = {
formatCode: {
@ -52,7 +53,6 @@ export const TextEditor = ({
code,
deferredSetCode,
editorView,
engineCommandManager,
formatCode,
isLSPServerReady,
selectionRanges,
@ -64,7 +64,6 @@ export const TextEditor = ({
code: s.code,
deferredSetCode: s.deferredSetCode,
editorView: s.editorView,
engineCommandManager: s.engineCommandManager,
formatCode: s.formatCode,
isLSPServerReady: s.isLSPServerReady,
selectionRanges: s.selectionRanges,
@ -173,7 +172,7 @@ export const TextEditor = ({
const idBasedSelections = codeBasedSelections
.map(({ type, range }) => {
const hasOverlap = Object.entries(
engineCommandManager?.sourceRangeMap || {}
engineCommandManager.sourceRangeMap || {}
).filter(([_, sourceRange]) => {
return isOverlap(sourceRange, range)
})
@ -186,7 +185,7 @@ export const TextEditor = ({
})
.filter(Boolean) as any
engineCommandManager?.cusorsSelected({
engineCommandManager.cusorsSelected({
otherSelections: [],
idBasedSelections,
})

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore'
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTreeTypes'
import { Value, VariableDeclarator } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore'
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTreeTypes'
import { Value, VariableDeclarator } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes'
import { Value } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,

View File

@ -1,11 +1,7 @@
import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore'
import {
BinaryPart,
Value,
VariableDeclarator,
} from '../../lang/abstractSyntaxTreeTypes'
import { BinaryPart, Value, VariableDeclarator } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes'
import { Value } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes'
import { Value } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
@ -133,7 +133,7 @@ export const SetAbsDistance = ({ buttonType }: { buttonType: ButtonType }) => {
callBack: updateCursors(setCursor, selectionRanges, pathToNodeMap),
})
} catch (e) {
console.log('e', e)
console.log('error', e)
}
}}
disabled={!enableAngLen}

View File

@ -1,11 +1,7 @@
import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore'
import {
BinaryPart,
Value,
VariableDeclarator,
} from '../../lang/abstractSyntaxTreeTypes'
import { BinaryPart, Value, VariableDeclarator } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,

View File

@ -1,11 +1,7 @@
import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore'
import {
BinaryPart,
Value,
VariableDeclarator,
} from '../../lang/abstractSyntaxTreeTypes'
import { BinaryPart, Value, VariableDeclarator } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
@ -21,8 +17,6 @@ import { GetInfoModal } from '../SetHorVertDistanceModal'
import { createLiteral, createVariableDeclaration } from '../../lang/modifyAst'
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { updateCursors } from '../../lang/util'
import { ActionIcon } from 'components/ActionIcon'
import { sketchButtonClassnames } from 'Toolbar'
const getModalInfo = create(GetInfoModal as any)

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes'
import { Value } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
@ -147,7 +147,7 @@ export const SetAngleLength = ({
callBack: updateCursors(setCursor, selectionRanges, pathToNodeMap),
})
} catch (e) {
console.log('e', e)
console.log('erorr', e)
}
}}
disabled={!enableAngLen}

View File

@ -137,7 +137,7 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
Settings
</ActionButton>
<ActionButton
Element="link"
Element="externalLink"
to="https://github.com/KittyCAD/modeling-app/discussions"
icon={{ icon: faGithub }}
className="border-transparent dark:border-transparent dark:hover:border-liquid-60"

View File

@ -109,7 +109,6 @@ export default class Client extends jsrpc.JSONRPCServerAndClient {
}
}
messageString += message
// console.log(messageString)
return
})

View File

@ -13,6 +13,7 @@ import {
CompletionItemKind,
CompletionTriggerKind,
} from 'vscode-languageserver-protocol'
import debounce from 'debounce-promise'
import type {
Completion,
@ -53,14 +54,11 @@ export class LanguageServerPlugin implements PluginValue {
private languageId: string
private documentVersion: number
private changesTimeout: number
constructor(private view: EditorView, private allowHTMLContent: boolean) {
this.client = this.view.state.facet(client)
this.documentUri = this.view.state.facet(documentUri)
this.languageId = this.view.state.facet(languageId)
this.documentVersion = 0
this.changesTimeout = 0
this.client.attachPlugin(this)
@ -71,12 +69,10 @@ export class LanguageServerPlugin implements PluginValue {
update({ docChanged }: ViewUpdate) {
if (!docChanged) return
if (this.changesTimeout) clearTimeout(this.changesTimeout)
this.changesTimeout = window.setTimeout(() => {
this.sendChange({
documentText: this.view.state.doc.toString(),
})
}, changesDelay)
this.sendChange({
documentText: this.view.state.doc.toString(),
})
}
destroy() {
@ -99,14 +95,32 @@ export class LanguageServerPlugin implements PluginValue {
async sendChange({ documentText }: { documentText: string }) {
if (!this.client.ready) return
if (documentText.length > 5000) {
// Clear out the text it thinks we have, large documents will throw a stack error.
// This is obviously not a good fix but it works for now til we figure
// out the stack limits in wasm and also rewrite the parser.
// Since this is only for hover and completions it will be fine,
// completions will still work for stdlib but hover will not.
// That seems like a fine trade-off for a working editor for the time
// being.
documentText = ''
}
try {
await this.client.textDocumentDidChange({
textDocument: {
uri: this.documentUri,
version: this.documentVersion++,
debounce(
() => {
return this.client.textDocumentDidChange({
textDocument: {
uri: this.documentUri,
version: this.documentVersion++,
},
contentChanges: [{ text: documentText }],
})
},
contentChanges: [{ text: documentText }],
})
changesDelay,
{ leading: true }
)
} catch (e) {
console.error(e)
}

View File

@ -5,8 +5,6 @@ import init, {
} from '../../wasm-lib/pkg/wasm_lib'
import { FromServer, IntoServer } from './codec'
let server: null | Server
export default class Server {
readonly initOutput: InitOutput
readonly #intoServer: IntoServer
@ -26,12 +24,8 @@ export default class Server {
intoServer: IntoServer,
fromServer: FromServer
): Promise<Server> {
if (null == server) {
const initOutput = await init()
server = new Server(initOutput, intoServer, fromServer)
} else {
console.warn('Server already initialized; ignoring')
}
const initOutput = await init()
const server = new Server(initOutput, intoServer, fromServer)
return server
}

View File

@ -8,6 +8,7 @@ import { ArtifactMap, EngineCommandManager } from 'lang/std/engineConnection'
import { Models } from '@kittycad/lib/dist/types/src'
import { isReducedMotion } from 'lang/util'
import { isOverlap } from 'lib/utils'
import { engineCommandManager } from '../lang/std/engineConnection'
interface DefaultPlanes {
xy: string
@ -17,19 +18,13 @@ interface DefaultPlanes {
}
export function useAppMode() {
const {
guiMode,
setGuiMode,
selectionRanges,
engineCommandManager,
selectionRangeTypeMap,
} = useStore((s) => ({
guiMode: s.guiMode,
setGuiMode: s.setGuiMode,
selectionRanges: s.selectionRanges,
engineCommandManager: s.engineCommandManager,
selectionRangeTypeMap: s.selectionRangeTypeMap,
}))
const { guiMode, setGuiMode, selectionRanges, selectionRangeTypeMap } =
useStore((s) => ({
guiMode: s.guiMode,
setGuiMode: s.setGuiMode,
selectionRanges: s.selectionRanges,
selectionRangeTypeMap: s.selectionRangeTypeMap,
}))
const [defaultPlanes, setDefaultPlanes] = useState<DefaultPlanes | null>(null)
useEffect(() => {
if (
@ -65,7 +60,7 @@ export function useAppMode() {
setDefaultPlanesHidden(engineCommandManager, localDefaultPlanes, true)
// TODO figure out the plane to use based on the sketch
// maybe it's easier to make a new plane than rely on the defaults
await engineCommandManager?.sendSceneCommand({
await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
@ -135,7 +130,7 @@ export function useAppMode() {
])
useEffect(() => {
const unSub = engineCommandManager?.subscribeTo({
const unSub = engineCommandManager.subscribeTo({
event: 'select_with_point',
callback: async ({ data }) => {
if (!data.entity_id) return
@ -144,18 +139,16 @@ export function useAppMode() {
// user clicked something else in the scene
return
}
const sketchModeResponse = await engineCommandManager?.sendSceneCommand(
{
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'sketch_mode_enable',
plane_id: data.entity_id,
ortho: true,
animated: !isReducedMotion(),
},
}
)
const sketchModeResponse = await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'sketch_mode_enable',
plane_id: data.entity_id,
ortho: true,
animated: !isReducedMotion(),
},
})
setDefaultPlanesHidden(engineCommandManager, defaultPlanes, true)
const sketchUuid = uuidv4()
const proms: any[] = []
@ -178,8 +171,7 @@ export function useAppMode() {
},
})
)
const res = await Promise.all(proms)
console.log('res', res)
await Promise.all(proms)
setGuiMode({
mode: 'sketch',
sketchMode: 'sketchEdit',
@ -209,7 +201,7 @@ async function createPlane(
}
) {
const planeId = uuidv4()
await engineCommandManager?.sendSceneCommand({
await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'make_plane',
@ -221,7 +213,7 @@ async function createPlane(
},
cmd_id: planeId,
})
await engineCommandManager?.sendSceneCommand({
await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'plane_set_color',
@ -234,12 +226,12 @@ async function createPlane(
}
function setDefaultPlanesHidden(
engineCommandManager: EngineCommandManager | undefined,
engineCommandManager: EngineCommandManager,
defaultPlanes: DefaultPlanes,
hidden: boolean
) {
Object.values(defaultPlanes).forEach((planeId) => {
engineCommandManager?.sendSceneCommand({
engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {

View File

@ -1,14 +1,9 @@
import { useEffect } from 'react'
import { useStore } from 'useStore'
import { engineCommandManager } from '../lang/std/engineConnection'
export function useEngineConnectionSubscriptions() {
const {
engineCommandManager,
setCursor2,
setHighlightRange,
highlightRange,
} = useStore((s) => ({
engineCommandManager: s.engineCommandManager,
const { setCursor2, setHighlightRange, highlightRange } = useStore((s) => ({
setCursor2: s.setCursor2,
setHighlightRange: s.setHighlightRange,
highlightRange: s.highlightRange,

View File

@ -1,53 +1,89 @@
import { useLayoutEffect } from 'react'
import { _executor } from '../lang/executor'
import { useLayoutEffect, useEffect, useRef } from 'react'
import { _executor } from '../lang/wasm'
import { useStore } from '../useStore'
import { EngineCommandManager } from '../lang/std/engineConnection'
import { engineCommandManager } from '../lang/std/engineConnection'
import { deferExecution } from 'lib/utils'
import { v4 as uuidv4 } from 'uuid'
export function useSetupEngineManager(
streamRef: React.RefObject<HTMLDivElement>,
token?: string
) {
const {
setEngineCommandManager,
setMediaStream,
setIsStreamReady,
setStreamDimensions,
streamDimensions,
executeCode,
} = useStore((s) => ({
setEngineCommandManager: s.setEngineCommandManager,
setMediaStream: s.setMediaStream,
setIsStreamReady: s.setIsStreamReady,
setStreamDimensions: s.setStreamDimensions,
streamDimensions: s.streamDimensions,
executeCode: s.executeCode,
}))
const streamWidth = streamRef?.current?.offsetWidth
const streamHeight = streamRef?.current?.offsetHeight
const hasSetNonZeroDimensions = useRef<boolean>(false)
useLayoutEffect(() => {
// Load the engine command manager once with the initial width and height,
// then we do not want to reload it.
const { width: quadWidth, height: quadHeight } = getDimensions(
streamWidth,
streamHeight
)
if (!hasSetNonZeroDimensions.current && quadHeight && quadWidth) {
engineCommandManager.start({
setMediaStream,
setIsStreamReady,
width: quadWidth,
height: quadHeight,
executeCode,
token,
})
setStreamDimensions({
streamWidth: quadWidth,
streamHeight: quadHeight,
})
hasSetNonZeroDimensions.current = true
}
}, [streamRef?.current?.offsetWidth, streamRef?.current?.offsetHeight])
useEffect(() => {
const handleResize = deferExecution(() => {
const { width, height } = getDimensions(
streamRef?.current?.offsetWidth,
streamRef?.current?.offsetHeight
)
if (
streamDimensions.streamWidth !== width ||
streamDimensions.streamHeight !== height
) {
engineCommandManager.handleResize({
streamWidth: width,
streamHeight: height,
})
setStreamDimensions({
streamWidth: width,
streamHeight: height,
})
}
}, 500)
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
}
function getDimensions(streamWidth?: number, streamHeight?: number) {
const width = streamWidth ? streamWidth : 0
const quadWidth = Math.round(width / 4) * 4
const height = streamHeight ? streamHeight : 0
const quadHeight = Math.round(height / 4) * 4
useLayoutEffect(() => {
setStreamDimensions({
streamWidth: quadWidth,
streamHeight: quadHeight,
})
if (!width || !height) return
const eng = new EngineCommandManager({
setMediaStream,
setIsStreamReady,
width: quadWidth,
height: quadHeight,
token,
})
setEngineCommandManager(eng)
eng.waitForReady.then(() => {
executeCode()
})
return () => {
eng?.tearDown()
}
}, [quadWidth, quadHeight])
return { width: quadWidth, height: quadHeight }
}

View File

@ -48,7 +48,7 @@ export function useConvertToVariable() {
updateAst(_modifiedAst, true)
} catch (e) {
console.log('e', e)
console.log('error', e)
}
}

View File

@ -31,6 +31,14 @@ body.dark {
@apply text-chalkboard-10;
}
select {
@apply bg-chalkboard-20;
}
.dark select {
@apply bg-chalkboard-90;
}
::-webkit-scrollbar {
@apply w-2 h-2 rounded-sm;
@apply bg-chalkboard-20;

View File

@ -1,12 +1,11 @@
import { parser_wasm } from './abstractSyntaxTree'
import { KCLError } from './errors'
import { initPromise } from './rust'
import { initPromise, parse } from './wasm'
beforeAll(() => initPromise)
describe('testing AST', () => {
test('5 + 6', () => {
const result = parser_wasm('5 +6')
const result = parse('5 +6')
delete (result as any).nonCodeMeta
expect(result.body).toEqual([
{
@ -37,7 +36,7 @@ describe('testing AST', () => {
])
})
test('const myVar = 5', () => {
const { body } = parser_wasm('const myVar = 5')
const { body } = parse('const myVar = 5')
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -71,7 +70,7 @@ describe('testing AST', () => {
const code = `const myVar = 5
const newVar = myVar + 1
`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -143,7 +142,7 @@ const newVar = myVar + 1
describe('testing function declaration', () => {
test('fn funcN = () => {}', () => {
const { body } = parser_wasm('fn funcN = () => {}')
const { body } = parse('fn funcN = () => {}')
delete (body[0] as any).declarations[0].init.body.nonCodeMeta
expect(body).toEqual([
{
@ -179,7 +178,7 @@ describe('testing function declaration', () => {
])
})
test('fn funcN = (a, b) => {return a + b}', () => {
const { body } = parser_wasm(
const { body } = parse(
['fn funcN = (a, b) => {', ' return a + b', '}'].join('\n')
)
delete (body[0] as any).declarations[0].init.body.nonCodeMeta
@ -256,7 +255,7 @@ describe('testing function declaration', () => {
test('call expression assignment', () => {
const code = `fn funcN = (a, b) => { return a + b }
const myVar = funcN(1, 2)`
const { body } = parser_wasm(code)
const { body } = parse(code)
delete (body[0] as any).declarations[0].init.body.nonCodeMeta
expect(body).toEqual([
{
@ -388,7 +387,7 @@ describe('testing pipe operator special', () => {
|> lineTo([1, 1], %)
|> rx(45, %)
`
const { body } = parser_wasm(code)
const { body } = parse(code)
delete (body[0] as any).declarations[0].init.nonCodeMeta
expect(body).toEqual([
{
@ -404,7 +403,7 @@ describe('testing pipe operator special', () => {
id: { type: 'Identifier', start: 6, end: 14, name: 'mySketch' },
init: {
type: 'PipeExpression',
start: 15,
start: 17,
end: 145,
body: [
{
@ -624,7 +623,7 @@ describe('testing pipe operator special', () => {
})
test('pipe operator with binary expression', () => {
let code = `const myVar = 5 + 6 |> myFunc(45, %)`
const { body } = parser_wasm(code)
const { body } = parse(code)
delete (body as any)[0].declarations[0].init.nonCodeMeta
expect(body).toEqual([
{
@ -645,7 +644,7 @@ describe('testing pipe operator special', () => {
},
init: {
type: 'PipeExpression',
start: 12,
start: 14,
end: 36,
body: [
{
@ -706,7 +705,7 @@ describe('testing pipe operator special', () => {
})
test('array expression', () => {
let code = `const yo = [1, '2', three, 4 + 5]`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -781,7 +780,7 @@ describe('testing pipe operator special', () => {
'const three = 3',
"const yo = {aStr: 'str', anum: 2, identifier: three, binExp: 4 + 5}",
].join('\n')
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -925,7 +924,7 @@ describe('testing pipe operator special', () => {
const code = `const yo = {key: {
key2: 'value'
}}`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -993,7 +992,7 @@ describe('testing pipe operator special', () => {
})
test('object expression with array ast', () => {
const code = `const yo = {key: [1, '2']}`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -1057,7 +1056,7 @@ describe('testing pipe operator special', () => {
})
test('object memberExpression simple', () => {
const code = `const prop = yo.one.two`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -1112,7 +1111,7 @@ describe('testing pipe operator special', () => {
})
test('object memberExpression with square braces', () => {
const code = `const prop = yo.one["two"]`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -1168,7 +1167,7 @@ describe('testing pipe operator special', () => {
})
test('object memberExpression with two square braces literal and identifier', () => {
const code = `const prop = yo["one"][two]`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body).toEqual([
{
type: 'VariableDeclaration',
@ -1227,7 +1226,7 @@ describe('testing pipe operator special', () => {
describe('nests binary expressions correctly', () => {
it('works with the simple case', () => {
const code = `const yo = 1 + 2`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body[0]).toEqual({
type: 'VariableDeclaration',
start: 0,
@ -1271,7 +1270,7 @@ describe('nests binary expressions correctly', () => {
it('should nest according to precedence with multiply first', () => {
// should be binExp { binExp { lit-1 * lit-2 } + lit}
const code = `const yo = 1 * 2 + 3`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body[0]).toEqual({
type: 'VariableDeclaration',
start: 0,
@ -1328,7 +1327,7 @@ describe('nests binary expressions correctly', () => {
it('should nest according to precedence with sum first', () => {
// should be binExp { lit-1 + binExp { lit-2 * lit-3 } }
const code = `const yo = 1 + 2 * 3`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect(body[0]).toEqual({
type: 'VariableDeclaration',
start: 0,
@ -1384,7 +1383,7 @@ describe('nests binary expressions correctly', () => {
})
it('should nest properly with two opperators of equal precedence', () => {
const code = `const yo = 1 + 2 - 3`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect((body[0] as any).declarations[0].init).toEqual({
type: 'BinaryExpression',
start: 11,
@ -1421,7 +1420,7 @@ describe('nests binary expressions correctly', () => {
})
it('should nest properly with two opperators of equal (but higher) precedence', () => {
const code = `const yo = 1 * 2 / 3`
const { body } = parser_wasm(code)
const { body } = parse(code)
expect((body[0] as any).declarations[0].init).toEqual({
type: 'BinaryExpression',
start: 11,
@ -1458,7 +1457,7 @@ describe('nests binary expressions correctly', () => {
})
it('should nest properly with longer example', () => {
const code = `const yo = 1 + 2 * (3 - 4) / 5 + 6`
const { body } = parser_wasm(code)
const { body } = parse(code)
const init = (body[0] as any).declarations[0].init
expect(init).toEqual({
type: 'BinaryExpression',
@ -1520,14 +1519,12 @@ const key = 'c'`
value: 'this is a comment',
},
}
const { nonCodeMeta } = parser_wasm(code)
const { nonCodeMeta } = parse(code)
expect(nonCodeMeta.nonCodeNodes[0]).toEqual(nonCodeMetaInstance)
// extra whitespace won't change it's position (0) or value (NB the start end would have changed though)
const codeWithExtraStartWhitespace = '\n\n\n' + code
const { nonCodeMeta: nonCodeMeta2 } = parser_wasm(
codeWithExtraStartWhitespace
)
const { nonCodeMeta: nonCodeMeta2 } = parse(codeWithExtraStartWhitespace)
expect(nonCodeMeta2.nonCodeNodes[0].value).toStrictEqual(
nonCodeMetaInstance.value
)
@ -1545,7 +1542,7 @@ const key = 'c'`
|> close(%)
`
const { body } = parser_wasm(code)
const { body } = parse(code)
const indexOfSecondLineToExpression = 2
const sketchNonCodeMeta = (body as any)[0].declarations[0].init.nonCodeMeta
.nonCodeNodes
@ -1569,7 +1566,7 @@ const key = 'c'`
' |> rx(90, %)',
].join('\n')
const { body } = parser_wasm(code)
const { body } = parse(code)
const sketchNonCodeMeta = (body[0] as any).declarations[0].init.nonCodeMeta
.nonCodeNodes
expect(sketchNonCodeMeta[3]).toEqual({
@ -1587,7 +1584,7 @@ const key = 'c'`
describe('test UnaryExpression', () => {
it('should parse a unary expression in simple var dec situation', () => {
const code = `const myVar = -min(4, 100)`
const { body } = parser_wasm(code)
const { body } = parse(code)
const myVarInit = (body?.[0] as any).declarations[0]?.init
expect(myVarInit).toEqual({
type: 'UnaryExpression',
@ -1613,7 +1610,7 @@ describe('test UnaryExpression', () => {
describe('testing nested call expressions', () => {
it('callExp in a binExp in a callExp', () => {
const code = 'const myVar = min(100, 1 + legLen(5, 3))'
const { body } = parser_wasm(code)
const { body } = parse(code)
const myVarInit = (body?.[0] as any).declarations[0]?.init
expect(myVarInit).toEqual({
type: 'CallExpression',
@ -1651,7 +1648,7 @@ describe('testing nested call expressions', () => {
describe('should recognise callExpresions in binaryExpressions', () => {
const code = "xLineTo(segEndX('seg02', %) + 1, %)"
it('should recognise the callExp', () => {
const { body } = parser_wasm(code)
const { body } = parse(code)
const callExpArgs = (body?.[0] as any).expression?.arguments
expect(callExpArgs).toEqual([
{
@ -1690,8 +1687,7 @@ describe('parsing errors', () => {
let _theError
try {
const result = expect(parser_wasm(code))
console.log('result', result)
const result = expect(parse(code))
} catch (e) {
_theError = e
}

View File

@ -1,48 +0,0 @@
import { Program } from './abstractSyntaxTreeTypes'
import { parse_js } from '../wasm-lib/pkg/wasm_lib'
import { initPromise } from './rust'
import { Token } from './tokeniser'
import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
export const rangeTypeFix = (ranges: number[][]): [number, number][] =>
ranges.map(([start, end]) => [start, end])
export const parser_wasm = (code: string): Program => {
try {
const program: Program = parse_js(code)
return program
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export async function asyncParser(code: string): Promise<Program> {
await initPromise
try {
const program: Program = parse_js(code)
return program
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export function rangeOfToken(token: Token | undefined): [number, number][] {
return token === undefined ? [] : [[token.start, token.end]]
}

View File

@ -1,37 +0,0 @@
export type { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Value } from '../wasm-lib/kcl/bindings/Value'
export type { ObjectExpression } from '../wasm-lib/kcl/bindings/ObjectExpression'
export type { MemberExpression } from '../wasm-lib/kcl/bindings/MemberExpression'
export type { PipeExpression } from '../wasm-lib/kcl/bindings/PipeExpression'
export type { VariableDeclaration } from '../wasm-lib/kcl/bindings/VariableDeclaration'
export type { PipeSubstitution } from '../wasm-lib/kcl/bindings/PipeSubstitution'
export type { Identifier } from '../wasm-lib/kcl/bindings/Identifier'
export type { UnaryExpression } from '../wasm-lib/kcl/bindings/UnaryExpression'
export type { BinaryExpression } from '../wasm-lib/kcl/bindings/BinaryExpression'
export type { ReturnStatement } from '../wasm-lib/kcl/bindings/ReturnStatement'
export type { ExpressionStatement } from '../wasm-lib/kcl/bindings/ExpressionStatement'
export type { CallExpression } from '../wasm-lib/kcl/bindings/CallExpression'
export type { VariableDeclarator } from '../wasm-lib/kcl/bindings/VariableDeclarator'
export type { BinaryPart } from '../wasm-lib/kcl/bindings/BinaryPart'
export type { Literal } from '../wasm-lib/kcl/bindings/Literal'
export type { ArrayExpression } from '../wasm-lib/kcl/bindings/ArrayExpression'
export type SyntaxType =
| 'Program'
| 'ExpressionStatement'
| 'BinaryExpression'
| 'CallExpression'
| 'Identifier'
| 'ReturnStatement'
| 'VariableDeclaration'
| 'VariableDeclarator'
| 'MemberExpression'
| 'ArrayExpression'
| 'ObjectExpression'
| 'ObjectProperty'
| 'FunctionExpression'
| 'PipeExpression'
| 'PipeSubstitution'
| 'Literal'
| 'NonCodeNode'
| 'UnaryExpression'

View File

@ -1,5 +1,4 @@
import { parser_wasm } from './abstractSyntaxTree'
import { initPromise } from './rust'
import { parse, initPromise } from './wasm'
import { enginelessExecutor } from '../lib/testHelpers'
beforeAll(() => initPromise)
@ -13,7 +12,7 @@ const mySketch001 = startSketchAt([0, 0])
|> lineTo([0.46, -5.82], %)
// |> rx(45, %)
show(mySketch001)`
const programMemory = await enginelessExecutor(parser_wasm(code))
const programMemory = await enginelessExecutor(parse(code))
// @ts-ignore
const shown = programMemory?.return?.map(
// @ts-ignore
@ -69,7 +68,7 @@ const mySketch001 = startSketchAt([0, 0])
// |> rx(45, %)
|> extrude(2, %)
show(mySketch001)`
const programMemory = await enginelessExecutor(parser_wasm(code))
const programMemory = await enginelessExecutor(parse(code))
// @ts-ignore
const shown = programMemory?.return?.map(
// @ts-ignore
@ -109,7 +108,7 @@ const sk2 = startSketchAt([0, 0])
show(theExtrude, sk2)`
const programMemory = await enginelessExecutor(parser_wasm(code))
const programMemory = await enginelessExecutor(parse(code))
// @ts-ignore
const geos = programMemory?.return?.map(
// @ts-ignore

View File

@ -1,10 +1,7 @@
import fs from 'node:fs'
import { parser_wasm } from './abstractSyntaxTree'
import { ProgramMemory, SketchGroup } from './executor'
import { initPromise } from './rust'
import { parse, ProgramMemory, SketchGroup, initPromise } from './wasm'
import { enginelessExecutor } from '../lib/testHelpers'
import { vi } from 'vitest'
import { KCLError } from './errors'
beforeAll(() => initPromise)
@ -403,7 +400,7 @@ async function exe(
code: string,
programMemory: ProgramMemory = { root: {}, return: null }
) {
const ast = parser_wasm(code)
const ast = parse(code)
const result = await enginelessExecutor(ast, programMemory)
return result

View File

@ -1,81 +0,0 @@
import { Program } from './abstractSyntaxTreeTypes'
import {
EngineCommandManager,
ArtifactMap,
SourceRangeMap,
} from './std/engineConnection'
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
import { execute_wasm } from '../wasm-lib/pkg/wasm_lib'
import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import { rangeTypeFix } from './abstractSyntaxTree'
export type { SourceRange } from '../wasm-lib/kcl/bindings/SourceRange'
export type { Position } from '../wasm-lib/kcl/bindings/Position'
export type { Rotation } from '../wasm-lib/kcl/bindings/Rotation'
export type { Path } from '../wasm-lib/kcl/bindings/Path'
export type { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
export type { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface'
export type PathToNode = [string | number, string][]
interface Memory {
[key: string]: MemoryItem
}
export interface ProgramMemory {
root: Memory
return: ProgramReturn | null
}
export const executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager,
// work around while the gemotry is still be stored on the frontend
// will be removed when the stream UI is added.
tempMapCallback: (a: {
artifactMap: ArtifactMap
sourceRangeMap: SourceRangeMap
}) => void = () => {}
): Promise<ProgramMemory> => {
engineCommandManager.startNewSession()
const _programMemory = await _executor(
node,
programMemory,
engineCommandManager
)
const { artifactMap, sourceRangeMap } =
await engineCommandManager.waitForAllCommands(node, _programMemory)
tempMapCallback({ artifactMap, sourceRangeMap })
engineCommandManager.endSession()
return _programMemory
}
export const _executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager
): Promise<ProgramMemory> => {
try {
const memory: ProgramMemory = await execute_wasm(
JSON.stringify(node),
JSON.stringify(programMemory),
engineCommandManager
)
return memory
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}

View File

@ -1,6 +1,5 @@
import { getNodePathFromSourceRange, getNodeFromPath } from './queryAst'
import { parser_wasm } from './abstractSyntaxTree'
import { initPromise } from './rust'
import { Identifier, parse, initPromise } from './wasm'
beforeAll(() => initPromise)
@ -20,11 +19,88 @@ const sk3 = startSketchAt([0, 0])
lineToSubstringIndex + subStr.length,
]
const ast = parser_wasm(code)
const ast = parse(code)
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const { node } = getNodeFromPath<any>(ast, nodePath)
expect([node.start, node.end]).toEqual(sourceRange)
expect(node.type).toBe('CallExpression')
})
it('gets path right for function definition params', () => {
const code = `fn cube = (pos, scale) => {
const sg = startSketchAt(pos)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
return sg
}
const b1 = cube([0,0], 10)`
const subStr = 'pos, scale'
const subStrIndex = code.indexOf(subStr)
const sourceRange: [number, number] = [
subStrIndex,
subStrIndex + 'pos'.length,
]
const ast = parse(code)
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const node = getNodeFromPath<Identifier>(ast, nodePath).node
expect(nodePath).toEqual([
['body', ''],
[0, 'index'],
['declarations', 'VariableDeclaration'],
[0, 'index'],
['init', ''],
['params', 'FunctionExpression'],
[0, 'index'],
])
expect(node.type).toBe('Identifier')
expect(node.name).toBe('pos')
})
it('gets path right for deep within function definition body', () => {
const code = `fn cube = (pos, scale) => {
const sg = startSketchAt(pos)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
return sg
}
const b1 = cube([0,0], 10)`
const subStr = 'scale, 0'
const subStrIndex = code.indexOf(subStr)
const sourceRange: [number, number] = [
subStrIndex,
subStrIndex + 'scale'.length,
]
const ast = parse(code)
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const node = getNodeFromPath<Identifier>(ast, nodePath).node
expect(nodePath).toEqual([
['body', ''],
[0, 'index'],
['declarations', 'VariableDeclaration'],
[0, 'index'],
['init', ''],
['body', 'FunctionExpression'],
['body', 'FunctionExpression'],
[0, 'index'],
['declarations', 'VariableDeclaration'],
[0, 'index'],
['init', ''],
['body', 'PipeExpression'],
[2, 'index'],
['arguments', 'CallExpression'],
[0, 'index'],
['elements', 'ArrayExpression'],
[0, 'index'],
])
expect(node.type).toBe('Identifier')
expect(node.name).toBe('scale')
})
})

View File

@ -1,4 +1,4 @@
import { parser_wasm } from './abstractSyntaxTree'
import { parse, recast, initPromise } from './wasm'
import {
createLiteral,
createIdentifier,
@ -13,8 +13,6 @@ import {
giveSketchFnCallTag,
moveValueIntoNewVariable,
} from './modifyAst'
import { recast } from './recast'
import { initPromise } from './rust'
import { enginelessExecutor } from '../lib/testHelpers'
beforeAll(() => initPromise)
@ -126,7 +124,7 @@ function giveSketchFnCallTagTestHelper(
// giveSketchFnCallTag inputs and outputs an ast, which is very verbose for testing
// this wrapper changes the input and output to code
// making it more of an integration test, but easier to read the test intention is the goal
const ast = parser_wasm(code)
const ast = parse(code)
const start = code.indexOf(searchStr)
const range: [number, number] = [start, start + searchStr.length]
const { modifiedAst, tag, isTagExisting } = giveSketchFnCallTag(ast, range)
@ -197,7 +195,7 @@ const part001 = startSketchAt([-1.2, 4.83])
const yo2 = hmm([identifierGuy + 5])
show(part001)`
it('should move a binary expression into a new variable', async () => {
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('100 + 100') + 1
const { modifiedAst } = moveValueIntoNewVariable(
@ -211,7 +209,7 @@ show(part001)`
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
})
it('should move a value into a new variable', async () => {
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('2.8') + 1
const { modifiedAst } = moveValueIntoNewVariable(
@ -225,7 +223,7 @@ show(part001)`
expect(newCode).toContain(`line([newVar, 0], %)`)
})
it('should move a callExpression into a new variable', async () => {
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('def(')
const { modifiedAst } = moveValueIntoNewVariable(
@ -239,7 +237,7 @@ show(part001)`
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
})
it('should move a binary expression with call expression into a new variable', async () => {
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('jkl(') + 1
const { modifiedAst } = moveValueIntoNewVariable(
@ -253,7 +251,7 @@ show(part001)`
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
})
it('should move a identifier into a new variable', async () => {
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('identifierGuy +') + 1
const { modifiedAst } = moveValueIntoNewVariable(

View File

@ -14,14 +14,15 @@ import {
ObjectExpression,
UnaryExpression,
BinaryExpression,
} from './abstractSyntaxTreeTypes'
PathToNode,
ProgramMemory,
} from './wasm'
import {
findAllPreviousVariables,
getNodeFromPath,
getNodePathFromSourceRange,
isNodeSafeToReplace,
} from './queryAst'
import { PathToNode, ProgramMemory } from './executor'
import {
addTagForSketchOnFace,
getFirstArg,
@ -321,7 +322,7 @@ export function extrudeSketch(
[0, 'index'],
]
return {
modifiedAst: addToShow(_node, name),
modifiedAst: node,
pathToNode: [...pathToNode.slice(0, -1), [showCallIndex, 'index']],
pathToExtrudeArg,
}

View File

@ -1,11 +1,10 @@
import { parser_wasm } from './abstractSyntaxTree'
import { parse, recast, initPromise } from './wasm'
import {
findAllPreviousVariables,
isNodeSafeToReplace,
isTypeInValue,
getNodePathFromSourceRange,
} from './queryAst'
import { initPromise } from './rust'
import { enginelessExecutor } from '../lib/testHelpers'
import {
createArrayExpression,
@ -13,7 +12,6 @@ import {
createLiteral,
createPipeSubstitution,
} from './modifyAst'
import { recast } from './recast'
beforeAll(() => initPromise)
@ -36,7 +34,7 @@ const variableBelowShouldNotBeIncluded = 3
show(part001)`
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const { variables, bodyPath, insertIndex } = findAllPreviousVariables(
@ -70,7 +68,7 @@ const yo = 5 + 6
const yo2 = hmm([identifierGuy + 5])
show(part001)`
it('find a safe binaryExpression', () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('100 + 100') + 2
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true)
@ -84,7 +82,7 @@ show(part001)`
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
})
it('find a safe Identifier', () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('abc')
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true)
@ -92,7 +90,7 @@ show(part001)`
expect(code.slice(result.value.start, result.value.end)).toBe('abc')
})
it('find a safe CallExpression', () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('def')
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true)
@ -106,7 +104,7 @@ show(part001)`
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
})
it('find an UNsafe CallExpression, as it has a PipeSubstitution', () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('ghi')
const range: [number, number] = [rangeStart, rangeStart]
const result = isNodeSafeToReplace(ast, range)
@ -115,7 +113,7 @@ show(part001)`
expect(code.slice(result.value.start, result.value.end)).toBe('ghi(%)')
})
it('find an UNsafe Identifier, as it is a callee', () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('ine([2.8,')
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(false)
@ -125,7 +123,7 @@ show(part001)`
)
})
it("find a safe BinaryExpression that's assigned to a variable", () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('5 + 6') + 1
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true)
@ -139,7 +137,7 @@ show(part001)`
expect(outCode).toContain(`const yo = replaceName`)
})
it('find a safe BinaryExpression that has a CallExpression within', () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('jkl') + 1
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true)
@ -155,7 +153,7 @@ show(part001)`
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
})
it('find a safe BinaryExpression within a CallExpression', () => {
const ast = parser_wasm(code)
const ast = parse(code)
const rangeStart = code.indexOf('identifierGuy') + 1
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true)
@ -203,7 +201,7 @@ show(part001)`
it('finds the second line when cursor is put at the end', () => {
const searchLn = `line([0.94, 2.61], %)`
const sourceIndex = code.indexOf(searchLn) + searchLn.length
const ast = parser_wasm(code)
const ast = parse(code)
const result = getNodePathFromSourceRange(ast, [sourceIndex, sourceIndex])
expect(result).toEqual([
['body', ''],
@ -218,7 +216,7 @@ show(part001)`
it('finds the last line when cursor is put at the end', () => {
const searchLn = `line([-0.21, -1.4], %)`
const sourceIndex = code.indexOf(searchLn) + searchLn.length
const ast = parser_wasm(code)
const ast = parse(code)
const result = getNodePathFromSourceRange(ast, [sourceIndex, sourceIndex])
const expected = [
['body', ''],

View File

@ -1,4 +1,3 @@
import { PathToNode, ProgramMemory, SketchGroup, SourceRange } from './executor'
import { Selection, ToolTip } from '../useStore'
import {
BinaryExpression,
@ -10,7 +9,11 @@ import {
VariableDeclaration,
ReturnStatement,
ArrayExpression,
} from './abstractSyntaxTreeTypes'
PathToNode,
ProgramMemory,
SketchGroup,
SourceRange,
} from './wasm'
import { createIdentifier, splitPathAtLastIndex } from './modifyAst'
import { getSketchSegmentFromSourceRange } from './std/sketchConstraints'
import { getAngle } from '../lib/utils'
@ -239,7 +242,29 @@ function moreNodePathFromSourceRange(
}
return path
}
console.error('not implemented')
if (_node.type === 'FunctionExpression' && isInRange) {
for (let i = 0; i < _node.params.length; i++) {
const param = _node.params[i]
if (param.start <= start && param.end >= end) {
path.push(['params', 'FunctionExpression'])
path.push([i, 'index'])
return moreNodePathFromSourceRange(param, sourceRange, path)
}
}
if (_node.body.start <= start && _node.body.end >= end) {
path.push(['body', 'FunctionExpression'])
const fnBody = _node.body.body
for (let i = 0; i < fnBody.length; i++) {
const statement = fnBody[i]
if (statement.start <= start && statement.end >= end) {
path.push(['body', 'FunctionExpression'])
path.push([i, 'index'])
return moreNodePathFromSourceRange(statement, sourceRange, path)
}
}
}
}
console.error('not implemented: ' + node.type)
return path
}

View File

@ -1,8 +1,5 @@
import { recast } from './recast'
import { parser_wasm } from './abstractSyntaxTree'
import { Program } from './abstractSyntaxTreeTypes'
import { parse, Program, recast, initPromise } from './wasm'
import fs from 'node:fs'
import { initPromise } from './rust'
beforeAll(() => initPromise)
@ -366,6 +363,6 @@ describe('it recasts binary expression using brackets where needed', () => {
// helpers
function code2ast(code: string): { ast: Program } {
const ast = parser_wasm(code)
const ast = parse(code)
return { ast }
}

View File

@ -1,13 +0,0 @@
import { Program } from './abstractSyntaxTreeTypes'
import { recast_wasm } from '../wasm-lib/pkg/wasm_lib'
export const recast = (ast: Program): string => {
try {
const s: string = recast_wasm(JSON.stringify(ast))
return s
} catch (e) {
// TODO: do something real with the error.
console.log('recast', e)
throw e
}
}

View File

@ -1,20 +0,0 @@
import init from '../wasm-lib/pkg/wasm_lib'
const initialise = async () => {
const baseUrl =
typeof window === 'undefined'
? 'http://127.0.0.1:3000'
: window.location.origin.includes('tauri://localhost')
? 'tauri://localhost'
: window.location.origin.includes('localhost')
? 'http://localhost:3000'
: window.location.origin && window.location.origin !== 'null'
? window.location.origin
: 'http://localhost:3000'
const fullUrl = baseUrl + '/wasm_lib_bg.wasm'
const input = await fetch(fullUrl)
const buffer = await input.arrayBuffer()
return init(buffer)
}
export const initPromise = initialise()

View File

@ -1,4 +1,9 @@
import { ProgramMemory, SourceRange } from 'lang/executor'
import {
ProgramMemory,
SourceRange,
Program,
VariableDeclarator,
} from 'lang/wasm'
import { Selections } from 'useStore'
import { VITE_KC_API_WS_MODELING_URL, VITE_KC_CONNECTION_TIMEOUT_MS } from 'env'
import { Models } from '@kittycad/lib'
@ -6,7 +11,6 @@ import { exportSave } from 'lib/exportSave'
import { v4 as uuidv4 } from 'uuid'
import * as Sentry from '@sentry/react'
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
import { Program, VariableDeclarator } from 'lang/abstractSyntaxTreeTypes'
let lastMessage = ''
@ -23,6 +27,10 @@ interface ResultCommand extends CommandInfo {
data: any
raw: WebSocketResponse
}
interface FailedCommand extends CommandInfo {
type: 'failed'
errors: Models['FailureWebSocketResponse_type']['errors']
}
interface PendingCommand extends CommandInfo {
type: 'pending'
promise: Promise<any>
@ -30,7 +38,7 @@ interface PendingCommand extends CommandInfo {
}
export interface ArtifactMap {
[key: string]: ResultCommand | PendingCommand
[key: string]: ResultCommand | PendingCommand | FailedCommand
}
export interface SourceRangeMap {
[key: string]: SourceRange
@ -41,6 +49,11 @@ interface NewTrackArgs {
mediaStream: MediaStream
}
// This looks funny, I know. This is needed because node and the browser
// disagree as to the type. In a browser it's a number, but in node it's a
// "Timeout".
type Timeout = ReturnType<typeof setTimeout>
type ClientMetrics = Models['ClientMetrics_type']
// EngineConnection encapsulates the connection(s) to the Engine
@ -52,6 +65,9 @@ export class EngineConnection {
unreliableDataChannel?: RTCDataChannel
private ready: boolean
private connecting: boolean
private dead: boolean
private failedConnTimeout: Timeout | null
readonly url: string
private readonly token?: string
@ -87,6 +103,9 @@ export class EngineConnection {
this.url = url
this.token = token
this.ready = false
this.connecting = false
this.dead = false
this.failedConnTimeout = null
this.onWebsocketOpen = onWebsocketOpen
this.onDataChannelOpen = onDataChannelOpen
this.onEngineConnectionOpen = onEngineConnectionOpen
@ -97,7 +116,10 @@ export class EngineConnection {
// TODO(paultag): This ought to be tweakable.
const pingIntervalMs = 10000
setInterval(() => {
let pingInterval = setInterval(() => {
if (this.dead) {
clearInterval(pingInterval)
}
if (this.isReady()) {
// When we're online, every 10 seconds, we'll attempt to put a 'ping'
// command through the WebSocket connection. This will help both ends
@ -106,6 +128,24 @@ export class EngineConnection {
this.send({ type: 'ping' })
}
}, pingIntervalMs)
const connectionTimeoutMs = VITE_KC_CONNECTION_TIMEOUT_MS
let connectInterval = setInterval(() => {
if (this.dead) {
clearInterval(connectInterval)
return
}
if (this.isReady()) {
return
}
console.log('connecting via retry')
this.connect()
}, connectionTimeoutMs)
}
// isConnecting will return true when connect has been called, but the full
// WebRTC is not online.
isConnecting() {
return this.connecting
}
// isReady will return true only when the WebRTC *and* WebSocket connection
// are connected. During setup, the WebSocket connection comes online first,
@ -114,6 +154,10 @@ export class EngineConnection {
isReady() {
return this.ready
}
tearDown() {
this.dead = true
this.close()
}
// shouldTrace will return true when Sentry should be used to instrument
// the Engine.
shouldTrace() {
@ -125,8 +169,10 @@ export class EngineConnection {
// This will attempt the full handshake, and retry if the connection
// did not establish.
connect() {
// TODO(paultag): make this safe to call multiple times, and figure out
// when a connection is in progress (state: connecting or something).
console.log('connect was called')
if (this.isConnecting() || this.isReady()) {
return
}
// Information on the connect transaction
@ -314,6 +360,11 @@ export class EngineConnection {
if (this.shouldTrace()) {
iceSpan.resolve?.()
}
} else if (this.pc?.iceConnectionState === 'failed') {
// failed is a terminal state; let's explicitly kill the
// connection to the server at this point.
console.log('failed to negotiate ice connection; restarting')
this.close()
}
})
@ -358,20 +409,6 @@ export class EngineConnection {
})
})
}
// TODO(paultag): This ought to be both controllable, as well as something
// like exponential backoff to have some grace on the backend, as well as
// fix responsiveness for clients that had a weird network hiccup.
const connectionTimeoutMs = VITE_KC_CONNECTION_TIMEOUT_MS
setTimeout(() => {
if (this.isReady()) {
return
}
console.log('engine connection timeout on connection, retrying')
this.close()
this.connect()
}, connectionTimeoutMs)
})
this.pc.addEventListener('track', (event) => {
@ -459,8 +496,11 @@ export class EngineConnection {
this.onDataChannelOpen(this)
this.onEngineConnectionOpen(this)
this.ready = true
this.connecting = false
// Do this after we set the connection is ready to avoid errors when
// we try to send messages before the connection is ready.
this.onEngineConnectionOpen(this)
})
this.unreliableDataChannel.addEventListener('close', (event) => {
@ -474,6 +514,22 @@ export class EngineConnection {
})
})
const connectionTimeoutMs = VITE_KC_CONNECTION_TIMEOUT_MS
if (this.failedConnTimeout) {
console.log('clearing timeout before set')
clearTimeout(this.failedConnTimeout)
this.failedConnTimeout = null
}
console.log('timeout set')
this.failedConnTimeout = setTimeout(() => {
if (this.isReady()) {
return
}
console.log('engine connection timeout on connection, closing')
this.close()
}, connectionTimeoutMs)
this.onConnectionStarted(this)
}
unreliableSend(message: object | string) {
@ -498,9 +554,15 @@ export class EngineConnection {
this.pc = undefined
this.unreliableDataChannel = undefined
this.webrtcStatsCollector = undefined
if (this.failedConnTimeout) {
console.log('closed timeout in close')
clearTimeout(this.failedConnTimeout)
this.failedConnTimeout = null
}
this.onClose(this)
this.ready = false
this.connecting = false
}
}
@ -531,6 +593,9 @@ export class EngineCommandManager {
outSequence = 1
inSequence = 1
engineConnection?: EngineConnection
// Folks should realize that wait for ready does not get called _everytime_
// the connection resets and restarts, it only gets called the first time.
// Be careful what you put here.
waitForReady: Promise<void> = new Promise(() => {})
private resolveReady = () => {}
@ -544,19 +609,36 @@ export class EngineCommandManager {
[localUnsubscribeId: string]: (a: any) => void
}
} = {} as any
constructor({
constructor() {
this.engineConnection = undefined
}
start({
setMediaStream,
setIsStreamReady,
width,
height,
executeCode,
token,
}: {
setMediaStream: (stream: MediaStream) => void
setIsStreamReady: (isStreamReady: boolean) => void
width: number
height: number
executeCode: (code?: string, force?: boolean) => void
token?: string
}) {
if (width === 0 || height === 0) {
return
}
// If we already have an engine connection, just need to resize the stream.
if (this.engineConnection) {
this.handleResize({ streamWidth: width, streamHeight: height })
return
}
this.waitForReady = new Promise((resolve) => {
this.resolveReady = resolve
})
@ -567,6 +649,32 @@ export class EngineCommandManager {
onEngineConnectionOpen: () => {
this.resolveReady()
setIsStreamReady(true)
// Make the axis gizmo.
// We do this after the connection opened to avoid a race condition.
// Connected opened is the last thing that happens when the stream
// is ready.
// We also do this here because we want to ensure we create the gizmo
// and execute the code everytime the stream is restarted.
const gizmoId = uuidv4()
this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: gizmoId,
cmd: {
type: 'make_axes_gizmo',
clobber: false,
// If true, axes gizmo will be placed in the corner of the screen.
// If false, it will be placed at the origin of the scene.
gizmo_mode: true,
},
})
// We execute the code here to make sure if the stream was to
// restart in a session, we want to make sure to execute the code.
// We force it to re-execute the code because we want to make sure
// the code is executed everytime the stream is restarted.
// We pass undefined for the code so it reads from the current state.
executeCode(undefined, true)
},
onClose: () => {
setIsStreamReady(false)
@ -617,6 +725,8 @@ export class EngineCommandManager {
message.request_id
) {
this.handleModelingCommand(message.resp, message.request_id)
} else if (!message.success && message.request_id) {
this.handleFailedModelingCommand(message)
}
}
})
@ -636,6 +746,30 @@ export class EngineCommandManager {
this.engineConnection?.connect()
}
handleResize({
streamWidth,
streamHeight,
}: {
streamWidth: number
streamHeight: number
}) {
console.log('handleResize', streamWidth, streamHeight)
if (!this.engineConnection?.isReady()) {
return
}
const resizeCmd: EngineCommand = {
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'reconfigure_stream',
width: streamWidth,
height: streamHeight,
fps: 60,
},
}
this.engineConnection?.send(resizeCmd)
}
handleModelingCommand(message: WebSocketResponse, id: string) {
if (message.type !== 'modeling') {
return
@ -673,8 +807,40 @@ export class EngineCommandManager {
}
}
}
handleFailedModelingCommand({
request_id,
errors,
}: Models['FailureWebSocketResponse_type']) {
const id = request_id
if (!id) return
const command = this.artifactMap[id]
if (command && command.type === 'pending') {
const resolve = command.resolve
this.artifactMap[id] = {
type: 'failed',
range: command.range,
commandType: command.commandType,
parentId: command.parentId ? command.parentId : undefined,
errors,
}
resolve({
id,
commandType: command.commandType,
range: command.range,
errors,
})
} else {
this.artifactMap[id] = {
type: 'failed',
range: command.range,
commandType: command.commandType,
parentId: command.parentId ? command.parentId : undefined,
errors,
}
}
}
tearDown() {
this.engineConnection?.close()
this.engineConnection?.tearDown()
}
startNewSession() {
this.artifactMap = {}
@ -769,6 +935,14 @@ export class EngineCommandManager {
})
}
sendSceneCommand(command: EngineCommand): Promise<any> {
if (this.engineConnection === undefined) {
return Promise.resolve()
}
if (!this.engineConnection?.isReady()) {
return Promise.resolve()
}
if (
command.type === 'modeling_cmd_req' &&
command.cmd.type !== lastMessage
@ -776,10 +950,6 @@ export class EngineCommandManager {
console.log('sending command', command.cmd.type)
lastMessage = command.cmd.type
}
if (!this.engineConnection?.isReady()) {
console.log('socket not ready')
return Promise.resolve()
}
if (command.type !== 'modeling_cmd_req') return Promise.resolve()
const cmd = command.cmd
if (
@ -821,10 +991,12 @@ export class EngineCommandManager {
range: SourceRange
command: EngineCommand | string
}): Promise<any> {
if (this.engineConnection === undefined) {
return Promise.resolve()
}
this.sourceRangeMap[id] = range
if (!this.engineConnection?.isReady()) {
console.log('socket not ready')
return Promise.resolve()
}
this.engineConnection?.send(command)
@ -867,6 +1039,9 @@ export class EngineCommandManager {
rangeStr: string,
commandStr: string
): Promise<any> {
if (this.engineConnection === undefined) {
return Promise.resolve()
}
if (id === undefined) {
throw new Error('id is undefined')
}
@ -890,6 +1065,8 @@ export class EngineCommandManager {
}
if (command.type === 'result') {
return command.data
} else if (command.type === 'failed') {
return Promise.resolve(command.errors)
}
return command.promise
}
@ -915,6 +1092,9 @@ export class EngineCommandManager {
}
}
private async fixIdMappings(ast: Program, programMemory: ProgramMemory) {
if (this.engineConnection === undefined) {
return
}
/* This is a temporary solution since the cmd_ids that are sent through when
sending 'extend_path' ids are not used as the segment ids.
@ -994,3 +1174,5 @@ export class EngineCommandManager {
})
}
}
export const engineCommandManager = new EngineCommandManager()

View File

@ -6,13 +6,9 @@ import {
getXComponent,
addCloseToPipe,
} from './sketch'
import { parser_wasm } from '../abstractSyntaxTree'
import { parse, recast, initPromise } from '../wasm'
import { getNodePathFromSourceRange } from '../queryAst'
import { recast } from '../recast'
import { enginelessExecutor } from '../../lib/testHelpers'
import { initPromise } from '../rust'
beforeAll(() => initPromise)
const eachQuad: [number, [number, number]][] = [
[-315, [1, 1]],
@ -29,6 +25,8 @@ const eachQuad: [number, [number, number]][] = [
[675, [1, -1]],
]
beforeAll(() => initPromise)
describe('testing getYComponent', () => {
it('should return the vertical component of a vector correctly when given angles in each quadrant (and with angles < 0, or > 360)', () => {
const expected: [number, number][] = []
@ -106,7 +104,7 @@ show(mySketch001)
`
const code = genCode(lineToChange)
const expectedCode = genCode(lineAfterChange)
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const sourceStart = code.indexOf(lineToChange)
const { modifiedAst } = changeSketchArguments(
@ -144,7 +142,7 @@ const mySketch001 = startSketchAt([0, 0])
|> lineTo([-1.59, -1.54], %)
|> lineTo([0.46, -5.82], %)
show(mySketch001)`
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const sourceStart = code.indexOf(lineToChange)
expect(sourceStart).toBe(66)
@ -205,7 +203,7 @@ describe('testing addTagForSketchOnFace', () => {
show(mySketch001)
`
const code = genCode(originalLine)
const ast = parser_wasm(code)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
const sourceStart = code.indexOf(originalLine)
const sourceRange: [number, number] = [

View File

@ -4,9 +4,6 @@ import {
SketchGroup,
SourceRange,
PathToNode,
MemoryItem,
} from '../executor'
import {
Program,
PipeExpression,
CallExpression,
@ -14,7 +11,7 @@ import {
Value,
Literal,
VariableDeclaration,
} from '../abstractSyntaxTreeTypes'
} from '../wasm'
import {
getNodeFromPath,
getNodeFromPathCurry,
@ -38,7 +35,6 @@ import {
findUniqueName,
} from '../modifyAst'
import { roundOff, getLength, getAngle } from '../../lib/utils'
import { getSketchSegmentFromSourceRange } from './sketchConstraints'
import { perpendicularDistance } from 'sketch-helpers'
export type Coords2d = [number, number]

View File

@ -1,12 +1,9 @@
import { parser_wasm } from '../abstractSyntaxTree'
import { SketchGroup } from '../executor'
import { parse, SketchGroup, recast, initPromise } from '../wasm'
import {
ConstraintType,
getTransformInfos,
transformAstSketchLines,
} from './sketchcombos'
import { recast } from '../recast'
import { initPromise } from '../rust'
import { getSketchSegmentFromSourceRange } from './sketchConstraints'
import { Selection } from '../../useStore'
import { enginelessExecutor } from '../../lib/testHelpers'
@ -31,7 +28,7 @@ async function testingSwapSketchFnCall({
type: 'default',
range: [startIndex, startIndex + callToSwap.length],
}
const ast = parser_wasm(inputCode)
const ast = parse(inputCode)
const programMemory = await enginelessExecutor(ast)
const selections = {
codeBasedSelections: [range],
@ -381,7 +378,7 @@ const part001 = startSketchAt([0, 0.04]) // segment-in-start
|> xLine(3.54, %)
show(part001)`
it('normal case works', async () => {
const programMemory = await enginelessExecutor(parser_wasm(code))
const programMemory = await enginelessExecutor(parse(code))
const index = code.indexOf('// normal-segment') - 7
const { __geoMeta, ...segment } = getSketchSegmentFromSourceRange(
programMemory.root['part001'] as SketchGroup,
@ -395,7 +392,7 @@ show(part001)`
})
})
it('verify it works when the segment is in the `start` property', async () => {
const programMemory = await enginelessExecutor(parser_wasm(code))
const programMemory = await enginelessExecutor(parse(code))
const index = code.indexOf('// segment-in-start') - 7
const { __geoMeta, ...segment } = getSketchSegmentFromSourceRange(
programMemory.root['part001'] as SketchGroup,

View File

@ -3,8 +3,10 @@ import {
Program,
VariableDeclarator,
CallExpression,
} from '../abstractSyntaxTreeTypes'
import { SketchGroup, SourceRange, Path } from '../executor'
SketchGroup,
SourceRange,
Path,
} from '../wasm'
export function getSketchSegmentFromSourceRange(
sketchGroup: SketchGroup,

View File

@ -1,5 +1,4 @@
import { parser_wasm } from '../abstractSyntaxTree'
import { Value } from '../abstractSyntaxTreeTypes'
import { parse, Value, recast, initPromise } from '../wasm'
import {
getConstraintType,
getTransformInfos,
@ -8,10 +7,8 @@ import {
ConstraintType,
getConstraintLevelFromSourceRange,
} from './sketchcombos'
import { initPromise } from '../rust'
import { Selections, ToolTip } from '../../useStore'
import { enginelessExecutor } from '../../lib/testHelpers'
import { recast } from '../../lang/recast'
beforeAll(() => initPromise)
@ -63,7 +60,7 @@ describe('testing getConstraintType', () => {
function getConstraintTypeFromSourceHelper(
code: string
): ReturnType<typeof getConstraintType> {
const ast = parser_wasm(code)
const ast = parse(code)
const args = (ast.body[0] as any).expression.arguments[0].elements as [
Value,
Value
@ -74,7 +71,7 @@ function getConstraintTypeFromSourceHelper(
function getConstraintTypeFromSourceHelper2(
code: string
): ReturnType<typeof getConstraintType> {
const ast = parser_wasm(code)
const ast = parse(code)
const arg = (ast.body[0] as any).expression.arguments[0] as Value
const fnName = (ast.body[0] as any).expression.callee.name as ToolTip
return getConstraintType(arg, fnName)
@ -199,7 +196,7 @@ const part001 = startSketchAt([0, 0])
show(part001)
`
it('should transform the ast', async () => {
const ast = parser_wasm(inputScript)
const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n')
.filter((ln) => ln.includes('//'))
@ -286,7 +283,7 @@ const part001 = startSketchAt([0, 0])
|> angledLineToY([301, myVar], %) // select for vertical constraint 10
show(part001)
`
const ast = parser_wasm(inputScript)
const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n')
.filter((ln) => ln.includes('// select for horizontal constraint'))
@ -344,7 +341,7 @@ const part001 = startSketchAt([0, 0])
|> yLineTo(myVar, %) // select for vertical constraint 10
show(part001)
`
const ast = parser_wasm(inputScript)
const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n')
.filter((ln) => ln.includes('// select for vertical constraint'))
@ -435,7 +432,7 @@ async function helperThing(
linesOfInterest: string[],
constraint: ConstraintType
): Promise<string> {
const ast = parser_wasm(inputScript)
const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n')
.filter((ln) =>
@ -498,7 +495,7 @@ const part001 = startSketchAt([-0.01, -0.05])
|> xLine(-3.43 + 0, %) // full
|> angledLineOfXLength([243 + 0, 1.2 + 0], %) // full
show(part001)`
const ast = parser_wasm(code)
const ast = parse(code)
const constraintLevels: ReturnType<
typeof getConstraintLevelFromSourceRange
>[] = ['full', 'partial', 'free']

View File

@ -6,7 +6,9 @@ import {
Value,
BinaryPart,
VariableDeclarator,
} from '../abstractSyntaxTreeTypes'
PathToNode,
ProgramMemory,
} from '../wasm'
import {
getNodeFromPath,
getNodeFromPathCurry,
@ -25,10 +27,8 @@ import {
giveSketchFnCallTag,
} from '../modifyAst'
import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch'
import { PathToNode, ProgramMemory } from '../executor'
import { getSketchSegmentFromSourceRange } from './sketchConstraints'
import { getAngle, roundOff, normaliseAngle } from '../../lib/utils'
import { MemoryItem } from 'wasm-lib/kcl/bindings/MemoryItem'
type LineInputsType =
| 'xAbsolute'
@ -1279,7 +1279,7 @@ export function getTransformInfos(
}) as TransformInfo[]
return theTransforms
} catch (error) {
console.log(error)
console.log('error', error)
return []
}
}

View File

@ -1,6 +1,5 @@
import { parser_wasm } from '../abstractSyntaxTree'
import { parse, initPromise } from '../wasm'
import { enginelessExecutor } from '../../lib/testHelpers'
import { initPromise } from '../rust'
beforeAll(() => initPromise)
@ -17,9 +16,9 @@ describe('testing angledLineThatIntersects', () => {
}, %)
const intersect = segEndX('yo2', part001)
show(part001)`
const { root } = await enginelessExecutor(parser_wasm(code('-1')))
const { root } = await enginelessExecutor(parse(code('-1')))
expect(root.intersect.value).toBe(1 + Math.sqrt(2))
const { root: noOffset } = await enginelessExecutor(parser_wasm(code('0')))
const { root: noOffset } = await enginelessExecutor(parse(code('0')))
expect(noOffset.intersect.value).toBeCloseTo(1)
})
})

View File

@ -1,7 +1,12 @@
import { ProgramMemory, Path, SourceRange } from '../executor'
import { Program, Value } from '../abstractSyntaxTreeTypes'
import {
ProgramMemory,
Path,
SourceRange,
Program,
Value,
PathToNode,
} from '../wasm'
import { ToolTip } from '../../useStore'
import { PathToNode } from '../executor'
import { EngineCommandManager } from './engineConnection'
export interface InternalFirstArg {

View File

@ -1,5 +1,4 @@
import { lexer, asyncLexer } from './tokeniser'
import { initPromise } from './rust'
import { lexer, initPromise } from './wasm'
beforeAll(() => initPromise)
@ -10,9 +9,9 @@ describe('testing lexer', () => {
const code3 = `const yo = 45 /* this is a comment
const ya = 6 */
const yi=45`
expect(await asyncLexer(code)).toEqual(lexer(code))
expect(await asyncLexer(code2)).toEqual(lexer(code2))
expect(await asyncLexer(code3)).toEqual(lexer(code3))
expect(lexer(code)).toEqual(lexer(code))
expect(lexer(code2)).toEqual(lexer(code2))
expect(lexer(code3)).toEqual(lexer(code3))
})
it('test lexer', () => {
expect(stringSummaryLexer('1 + 2')).toEqual([

View File

@ -1,28 +0,0 @@
import { lexer_js } from '../wasm-lib/pkg/wasm_lib'
import { initPromise } from './rust'
import { Token } from '../wasm-lib/kcl/bindings/Token'
export type { Token } from '../wasm-lib/kcl/bindings/Token'
export async function asyncLexer(str: string): Promise<Token[]> {
await initPromise
try {
const tokens: Token[] = lexer_js(str)
return tokens
} catch (e) {
// TODO: do something real with the error.
console.log('lexer', e)
throw e
}
}
export function lexer(str: string): Token[] {
try {
const tokens: Token[] = lexer_js(str)
return tokens
} catch (e) {
// TODO: do something real with the error.
console.log('lexer', e)
throw e
}
}

View File

@ -1,6 +1,5 @@
import { Selections, StoreState } from '../useStore'
import { Program } from './abstractSyntaxTreeTypes'
import { PathToNode } from './executor'
import { Program, PathToNode } from './wasm'
import { getNodeFromPath } from './queryAst'
export function updateCursors(

215
src/lang/wasm.ts Normal file
View File

@ -0,0 +1,215 @@
import init, {
parse_wasm,
recast_wasm,
execute_wasm,
lexer_wasm,
modify_ast_for_sketch_wasm,
} from '../wasm-lib/pkg/wasm_lib'
import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import {
EngineCommandManager,
ArtifactMap,
SourceRangeMap,
} from './std/engineConnection'
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
import type { Program } from '../wasm-lib/kcl/bindings/Program'
import type { Token } from '../wasm-lib/kcl/bindings/Token'
export type { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Value } from '../wasm-lib/kcl/bindings/Value'
export type { ObjectExpression } from '../wasm-lib/kcl/bindings/ObjectExpression'
export type { MemberExpression } from '../wasm-lib/kcl/bindings/MemberExpression'
export type { PipeExpression } from '../wasm-lib/kcl/bindings/PipeExpression'
export type { VariableDeclaration } from '../wasm-lib/kcl/bindings/VariableDeclaration'
export type { PipeSubstitution } from '../wasm-lib/kcl/bindings/PipeSubstitution'
export type { Identifier } from '../wasm-lib/kcl/bindings/Identifier'
export type { UnaryExpression } from '../wasm-lib/kcl/bindings/UnaryExpression'
export type { BinaryExpression } from '../wasm-lib/kcl/bindings/BinaryExpression'
export type { ReturnStatement } from '../wasm-lib/kcl/bindings/ReturnStatement'
export type { ExpressionStatement } from '../wasm-lib/kcl/bindings/ExpressionStatement'
export type { CallExpression } from '../wasm-lib/kcl/bindings/CallExpression'
export type { VariableDeclarator } from '../wasm-lib/kcl/bindings/VariableDeclarator'
export type { BinaryPart } from '../wasm-lib/kcl/bindings/BinaryPart'
export type { Literal } from '../wasm-lib/kcl/bindings/Literal'
export type { ArrayExpression } from '../wasm-lib/kcl/bindings/ArrayExpression'
export type SyntaxType =
| 'Program'
| 'ExpressionStatement'
| 'BinaryExpression'
| 'CallExpression'
| 'Identifier'
| 'ReturnStatement'
| 'VariableDeclaration'
| 'VariableDeclarator'
| 'MemberExpression'
| 'ArrayExpression'
| 'ObjectExpression'
| 'ObjectProperty'
| 'FunctionExpression'
| 'PipeExpression'
| 'PipeSubstitution'
| 'Literal'
| 'NonCodeNode'
| 'UnaryExpression'
export type { SourceRange } from '../wasm-lib/kcl/bindings/SourceRange'
export type { Position } from '../wasm-lib/kcl/bindings/Position'
export type { Rotation } from '../wasm-lib/kcl/bindings/Rotation'
export type { Path } from '../wasm-lib/kcl/bindings/Path'
export type { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
export type { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface'
// Initialise the wasm module.
const initialise = async () => {
const baseUrl =
typeof window === 'undefined'
? 'http://127.0.0.1:3000'
: window.location.origin.includes('tauri://localhost')
? 'tauri://localhost'
: window.location.origin.includes('localhost')
? 'http://localhost:3000'
: window.location.origin && window.location.origin !== 'null'
? window.location.origin
: 'http://localhost:3000'
const fullUrl = baseUrl + '/wasm_lib_bg.wasm'
const input = await fetch(fullUrl)
const buffer = await input.arrayBuffer()
return init(buffer)
}
export const initPromise = initialise()
export const rangeTypeFix = (ranges: number[][]): [number, number][] =>
ranges.map(([start, end]) => [start, end])
export const parse = (code: string): Program => {
try {
const program: Program = parse_wasm(code)
return program
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export type PathToNode = [string | number, string][]
interface Memory {
[key: string]: MemoryItem
}
export interface ProgramMemory {
root: Memory
return: ProgramReturn | null
}
export const executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager,
// work around while the gemotry is still be stored on the frontend
// will be removed when the stream UI is added.
tempMapCallback: (a: {
artifactMap: ArtifactMap
sourceRangeMap: SourceRangeMap
}) => void = () => {}
): Promise<ProgramMemory> => {
engineCommandManager.startNewSession()
const _programMemory = await _executor(
node,
programMemory,
engineCommandManager
)
const { artifactMap, sourceRangeMap } =
await engineCommandManager.waitForAllCommands(node, _programMemory)
tempMapCallback({ artifactMap, sourceRangeMap })
engineCommandManager.endSession()
return _programMemory
}
export const _executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager
): Promise<ProgramMemory> => {
try {
const memory: ProgramMemory = await execute_wasm(
JSON.stringify(node),
JSON.stringify(programMemory),
engineCommandManager
)
return memory
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export const recast = (ast: Program): string => {
try {
const s: string = recast_wasm(JSON.stringify(ast))
return s
} catch (e) {
// TODO: do something real with the error.
console.log('recast error', e)
throw e
}
}
export function lexer(str: string): Token[] {
try {
const tokens: Token[] = lexer_wasm(str)
return tokens
} catch (e) {
// TODO: do something real with the error.
console.log('lexer error', e)
throw e
}
}
export const modifyAstForSketch = async (
engineCommandManager: EngineCommandManager,
ast: Program,
variableName: string,
engineId: string
): Promise<Program> => {
try {
const updatedAst: Program = await modify_ast_for_sketch_wasm(
engineCommandManager,
JSON.stringify(ast),
variableName,
engineId
)
return updatedAst
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}

View File

@ -39,6 +39,6 @@ export async function exportSave(data: ArrayBuffer) {
}
} catch (e) {
// TODO: do something real with the error.
console.log('export', e)
console.log('export error', e)
}
}

View File

@ -36,7 +36,7 @@ export async function initializeProjectDirectory(directory: string) {
try {
docDirectory = await documentDir()
} catch (e) {
console.log(e)
console.log('error', e)
docDirectory = await homeDir() // seems to work better on Linux
}

View File

@ -1,10 +1,11 @@
import { Program } from '../lang/abstractSyntaxTreeTypes'
import { ProgramMemory, _executor } from '../lang/executor'
import { Program, ProgramMemory, _executor, SourceRange } from '../lang/wasm'
import {
EngineCommandManager,
EngineCommand,
} from '../lang/std/engineConnection'
import { SourceRange } from 'lang/executor'
import { Models } from '@kittycad/lib'
type WebSocketResponse = Models['OkWebSocketResponseData_type']
class MockEngineCommandManager {
constructor(mockParams: {
@ -23,7 +24,13 @@ class MockEngineCommandManager {
range: SourceRange
command: EngineCommand
}): Promise<any> {
return Promise.resolve()
const response: WebSocketResponse = {
type: 'modeling',
data: {
modeling_response: { type: 'empty' },
},
}
return Promise.resolve(JSON.stringify(response))
}
sendModelingCommandFromWasm(
id: string,
@ -66,11 +73,13 @@ export async function executor(
ast: Program,
pm: ProgramMemory = { root: {}, return: null }
): Promise<ProgramMemory> {
const engineCommandManager = new EngineCommandManager({
const engineCommandManager = new EngineCommandManager()
engineCommandManager.start({
setIsStreamReady: () => {},
setMediaStream: () => {},
width: 100,
height: 100,
width: 0,
height: 0,
executeCode: () => {},
})
await engineCommandManager.waitForReady
engineCommandManager.startNewSession()

View File

@ -1,5 +1,5 @@
import { isOverlap, roundOff } from './utils'
import { SourceRange } from '../lang/executor'
import { SourceRange } from '../lang/wasm'
describe('testing isOverlapping', () => {
testBothOrders([0, 3], [3, 10])

View File

@ -1,4 +1,4 @@
import { SourceRange } from '../lang/executor'
import { SourceRange } from '../lang/wasm'
export function isOverlap(a: SourceRange, b: SourceRange) {
const [startingRange, secondRange] = a[0] < b[0] ? [a, b] : [b, a]

View File

@ -4,6 +4,7 @@ import withBaseURL from '../lib/withBaseURL'
import { CommandBarMeta } from '../lib/commands'
import { isTauri } from 'lib/isTauri'
import { invoke } from '@tauri-apps/api'
import { VITE_KC_API_BASE_URL } from 'env'
const SKIP_AUTH =
import.meta.env.VITE_KC_SKIP_AUTH === 'true' && import.meta.env.DEV
@ -132,6 +133,7 @@ async function getUser(context: UserContext) {
.catch((err) => console.error('error from Browser getUser', err))
: invoke<Models['User_type'] | Record<'error_code', unknown>>('get_user', {
token: context.token,
hostname: VITE_KC_API_BASE_URL,
}).catch((err) => console.error('error from Tauri getUser', err))
const user = await userPromise

View File

@ -2,6 +2,7 @@ import { assign, createMachine } from 'xstate'
import { CommandBarMeta } from '../lib/commands'
import { Themes, getSystemTheme, setThemeClass } from '../lib/theme'
import { CameraSystem, cameraSystems } from 'lib/cameraControls'
import { Models } from '@kittycad/lib'
export const DEFAULT_PROJECT_NAME = 'project-$nnn'
@ -11,11 +12,11 @@ export enum UnitSystem {
}
export const baseUnits = {
imperial: ['in', 'ft'],
imperial: ['in', 'ft', 'yd'],
metric: ['mm', 'cm', 'm'],
} as const
export type BaseUnit = 'in' | 'ft' | 'mm' | 'cm' | 'm'
export type BaseUnit = Models['UnitLength_type']
export const baseUnitsUnion = Object.values(baseUnits).flatMap((v) => v)

View File

@ -9,7 +9,6 @@ import {
cameraMouseDragGuards,
cameraSystems,
} from 'lib/cameraControls'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function Units() {
const { buttonDownInStream } = useStore((s) => ({
@ -25,10 +24,9 @@ export default function Units() {
},
},
} = useGlobalStateContext()
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
<div className="fixed inset-0 z-50 grid items-end justify-start px-4 pointer-events-none">
<div
className={
'max-w-2xl flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded' +
@ -38,10 +36,11 @@ export default function Units() {
<SettingsSection
title="Camera Controls"
description="How you want to control the camera in the 3D view. Try them out above and choose the one that feels most comfortable to you."
className="my-4 last-of-type:mb-12"
>
<select
id="camera-controls"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={cameraControls}
onChange={(e) => {
send({
@ -56,7 +55,7 @@ export default function Units() {
</option>
))}
</select>
<ul className="text-sm my-2 mx-4 leading-relaxed">
<ul className="mx-4 my-2 text-sm leading-relaxed">
<li>
<strong>Pan:</strong>{' '}
{cameraMouseDragGuards[cameraControls].pan.description}
@ -74,7 +73,7 @@ export default function Units() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -2,7 +2,8 @@ import { faArrowRight, faXmark } from '@fortawesome/free-solid-svg-icons'
import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
import { Platform, platform } from '@tauri-apps/api/os'
import { useEffect, useState } from 'react'
export default function CmdK() {
const { buttonDownInStream } = useStore((s) => ({
@ -10,10 +11,17 @@ export default function CmdK() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.USER_MENU)
const dotDotSlash = useDotDotSlash()
const [platformName, setPlatformName] = useState<Platform | ''>('')
useEffect(() => {
async function getPlatform() {
setPlatformName(await platform())
}
getPlatform()
}, [setPlatformName])
return (
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
<div className="fixed inset-0 z-50 grid items-end justify-center pointer-events-none">
<div
className={
'max-w-full xl:max-w-4xl flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded' +
@ -22,8 +30,17 @@ export default function CmdK() {
>
<h2 className="text-2xl">Command Bar</h2>
<p className="my-4">
Press <kbd>Cmd/Win</kbd> + <kbd>K</kbd> to open the command bar. Try
changing your theme with it.
Press{' '}
{platformName === 'win32' ? (
<>
<kbd>Win</kbd> + <kbd>/</kbd>
</>
) : (
<>
<kbd>OS</kbd> + <kbd>K</kbd>
</>
)}{' '}
to open the command bar. Try changing your theme with it.
</p>
<p className="my-4">
We are working on a command bar that will allow you to quickly see and
@ -43,7 +60,7 @@ export default function CmdK() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -3,7 +3,6 @@ import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { useBackdropHighlight } from 'hooks/useBackdropHighlight'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function CodeEditor() {
const { buttonDownInStream } = useStore((s) => ({
@ -11,7 +10,6 @@ export default function CodeEditor() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.PARAMETRIC_MODELING)
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
@ -62,7 +60,7 @@ export default function CodeEditor() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -2,7 +2,6 @@ import { faArrowRight, faXmark } from '@fortawesome/free-solid-svg-icons'
import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function Export() {
const { buttonDownInStream } = useStore((s) => ({
@ -10,7 +9,6 @@ export default function Export() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.SKETCHING)
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
@ -42,7 +40,7 @@ export default function Export() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -4,14 +4,12 @@ import { useDismiss } from '.'
import { useEffect } from 'react'
import { useStore } from 'useStore'
import { bracket } from 'lib/exampleKcl'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function FutureWork() {
const dismiss = useDismiss()
const { deferredSetCode } = useStore((s) => ({
deferredSetCode: s.deferredSetCode,
}))
const dotDotSlash = useDotDotSlash()
useEffect(() => {
deferredSetCode(bracket)
@ -36,7 +34,7 @@ export default function FutureWork() {
<div className="flex justify-between mt-6">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',
@ -49,7 +47,7 @@ export default function FutureWork() {
</ActionButton>
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{ icon: faArrowRight }}
>
Finish

View File

@ -3,7 +3,6 @@ import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { useBackdropHighlight } from 'hooks/useBackdropHighlight'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function InteractiveNumbers() {
const { buttonDownInStream } = useStore((s) => ({
@ -11,7 +10,6 @@ export default function InteractiveNumbers() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.COMMAND_K)
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
@ -102,7 +100,7 @@ export default function InteractiveNumbers() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -15,15 +15,13 @@ import { isTauri } from 'lib/isTauri'
import { useNavigate } from 'react-router-dom'
import { paths } from 'Router'
import { useEffect } from 'react'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
function OnboardingWithNewFile() {
const navigate = useNavigate()
const dotDotSlash = useDotDotSlash()
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.INDEX)
const { setCode } = useStore((s) => ({
setCode: s.setCode,
const { deferredSetCode } = useStore((s) => ({
deferredSetCode: s.deferredSetCode,
}))
const {
settings: {
@ -53,7 +51,7 @@ function OnboardingWithNewFile() {
<div className="flex justify-between mt-6">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash())}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',
@ -67,7 +65,7 @@ function OnboardingWithNewFile() {
<ActionButton
Element="button"
onClick={() => {
setCode(bracket)
deferredSetCode(bracket)
next()
}}
icon={{ icon: faArrowRight }}
@ -91,7 +89,7 @@ function OnboardingWithNewFile() {
<div className="flex justify-between mt-6">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash())}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',
@ -118,9 +116,9 @@ function OnboardingWithNewFile() {
}
export default function Introduction() {
const { setCode, code } = useStore((s) => ({
const { deferredSetCode, code } = useStore((s) => ({
code: s.code,
setCode: s.setCode,
deferredSetCode: s.deferredSetCode,
}))
const {
settings: {
@ -136,11 +134,10 @@ export default function Introduction() {
: ''
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.CAMERA)
const dotDotSlash = useDotDotSlash()
useEffect(() => {
if (code === '') setCode(bracket)
}, [code, setCode])
if (code === '') deferredSetCode(bracket)
}, [code, deferredSetCode])
return !(code !== '' && code !== bracket) ? (
<div className="fixed grid place-content-center inset-0 bg-chalkboard-110/50 z-50">
@ -180,7 +177,7 @@ export default function Introduction() {
<div className="flex justify-between mt-6">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash())}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -5,7 +5,6 @@ import { useStore } from '../../useStore'
import { useBackdropHighlight } from 'hooks/useBackdropHighlight'
import { Themes, getSystemTheme } from 'lib/theme'
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function ParametricModeling() {
const { buttonDownInStream } = useStore((s) => ({
@ -23,7 +22,6 @@ export default function ParametricModeling() {
: ''
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.INTERACTIVE_NUMBERS)
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
@ -62,7 +60,7 @@ export default function ParametricModeling() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -3,7 +3,6 @@ import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { isTauri } from 'lib/isTauri'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function ProjectMenu() {
const { buttonDownInStream } = useStore((s) => ({
@ -11,7 +10,6 @@ export default function ProjectMenu() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.EXPORT)
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
@ -33,7 +31,7 @@ export default function ProjectMenu() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -3,7 +3,6 @@ import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from 'useStore'
import { useEffect } from 'react'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function Sketching() {
const { deferredSetCode, buttonDownInStream } = useStore((s) => ({
@ -16,7 +15,6 @@ export default function Sketching() {
useEffect(() => {
deferredSetCode('')
}, [deferredSetCode])
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
@ -40,7 +38,7 @@ export default function Sketching() {
<div className="flex justify-between mt-6">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -2,7 +2,6 @@ import { faArrowRight, faXmark } from '@fortawesome/free-solid-svg-icons'
import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function Streaming() {
const { buttonDownInStream } = useStore((s) => ({
@ -10,7 +9,6 @@ export default function Streaming() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.EDITOR)
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-start items-center inset-0 z-50 pointer-events-none">
@ -43,7 +41,7 @@ export default function Streaming() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -6,7 +6,6 @@ import { Toggle } from '../../components/Toggle/Toggle'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
import { UnitSystem } from 'machines/settingsMachine'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function Units() {
const dismiss = useDismiss()
@ -17,7 +16,6 @@ export default function Units() {
context: { unitSystem, baseUnit },
},
} = useGlobalStateContext()
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid place-content-center inset-0 bg-chalkboard-110/50 z-50">
@ -68,7 +66,7 @@ export default function Units() {
<div className="flex justify-between mt-6">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -2,7 +2,6 @@ import { faArrowRight, faXmark } from '@fortawesome/free-solid-svg-icons'
import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { useDotDotSlash } from 'hooks/useDotDotSlash'
export default function UserMenu() {
const { buttonDownInStream } = useStore((s) => ({
@ -10,7 +9,6 @@ export default function UserMenu() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.PROJECT_MENU)
const dotDotSlash = useDotDotSlash()
return (
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
@ -30,7 +28,7 @@ export default function UserMenu() {
<div className="flex justify-between">
<ActionButton
Element="button"
onClick={() => dismiss(dotDotSlash(2))}
onClick={dismiss}
icon={{
icon: faXmark,
bgClassName: 'bg-destroy-80',

View File

@ -1,5 +1,5 @@
import { useHotkeys } from 'react-hotkeys-hook'
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import { Outlet, useRouteLoaderData, useNavigate } from 'react-router-dom'
import Introduction from './Introduction'
import Camera from './Camera'
import Sketching from './Sketching'
@ -15,6 +15,7 @@ import UserMenu from './UserMenu'
import ProjectMenu from './ProjectMenu'
import Export from './Export'
import FutureWork from './FutureWork'
import { IndexLoaderData, paths } from 'Router'
export const onboardingPaths = {
INDEX: '/',
@ -89,42 +90,44 @@ export function useNextClick(newStatus: string) {
settings: { send },
} = useGlobalStateContext()
const navigate = useNavigate()
const location = useLocation()
const lastSlashIndex = location.pathname.lastIndexOf('/')
const { project } = useRouteLoaderData(paths.FILE) as IndexLoaderData
return useCallback(() => {
send({
type: 'Set Onboarding Status',
data: { onboardingStatus: newStatus },
})
navigate(location.pathname.slice(0, lastSlashIndex) + newStatus)
}, [location, lastSlashIndex, newStatus, send, navigate])
navigate(
paths.FILE +
'/' +
encodeURIComponent(project?.path || 'new') +
paths.ONBOARDING.INDEX.slice(0, -1) +
newStatus
)
}, [project, newStatus, send, navigate])
}
export function useDismiss() {
const routeData = useRouteLoaderData(paths.FILE) as IndexLoaderData
const {
settings: { send },
} = useGlobalStateContext()
const navigate = useNavigate()
return useCallback(
(path: string) => {
send({
type: 'Set Onboarding Status',
data: { onboardingStatus: 'dismissed' },
})
console.log('yoyo', window.location.pathname, path)
navigate(path)
},
[send, navigate]
)
return useCallback(() => {
send({
type: 'Set Onboarding Status',
data: { onboardingStatus: 'dismissed' },
})
navigate(
paths.FILE + '/' + encodeURIComponent(routeData?.project?.path || 'new')
)
}, [send, navigate, routeData])
}
const Onboarding = () => {
const location = useLocation()
const dismiss = useDismiss()
const lastSlashIndex = location.pathname.lastIndexOf('/')
useHotkeys('esc', () => dismiss(location.pathname.slice(0, lastSlashIndex)))
useHotkeys('esc', dismiss)
return (
<>

View File

@ -64,7 +64,7 @@ export const Settings = () => {
}
return (
<div className="body-bg fixed inset-0 z-40 overflow-auto">
<div className="fixed inset-0 z-40 overflow-auto body-bg">
<AppHeader showToolbar={false} project={loaderData?.project}>
<ActionButton
Element="link"
@ -80,9 +80,9 @@ export const Settings = () => {
Close
</ActionButton>
</AppHeader>
<div className="my-24 max-w-5xl mx-auto">
<div className="max-w-5xl mx-auto my-24">
<h1 className="text-4xl font-bold">User Settings</h1>
<p className="mt-6 max-w-2xl">
<p className="max-w-2xl mt-6">
Don't see the feature you want? Check to see if it's on{' '}
<a
href="https://github.com/KittyCAD/modeling-app/discussions"
@ -100,7 +100,7 @@ export const Settings = () => {
>
<select
id="camera-controls"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={cameraControls}
onChange={(e) => {
send({
@ -115,7 +115,7 @@ export const Settings = () => {
</option>
))}
</select>
<ul className="text-sm my-2 mx-4 leading-relaxed">
<ul className="mx-4 my-2 text-sm leading-relaxed">
<li>
<strong>Pan:</strong>{' '}
{cameraMouseDragGuards[cameraControls].pan.description}
@ -136,7 +136,7 @@ export const Settings = () => {
title="Default Directory"
description="Where newly-created projects are saved on your local computer"
>
<div className="w-full flex gap-4 p-1 rounded border border-chalkboard-30">
<div className="flex w-full gap-4 p-1 border rounded border-chalkboard-30">
<input
className="flex-1 px-2 bg-transparent"
value={defaultDirectory}
@ -163,7 +163,7 @@ export const Settings = () => {
description="Name template for new projects. Use $n to include an incrementing index"
>
<input
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
defaultValue={defaultProjectName}
onBlur={(e) => {
const newValue = e.target.value.trim() || DEFAULT_PROJECT_NAME
@ -207,7 +207,7 @@ export const Settings = () => {
>
<select
id="base-unit"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={baseUnit}
onChange={(e) => {
send({
@ -241,7 +241,7 @@ export const Settings = () => {
>
<select
id="settings-theme"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={theme}
onChange={(e) => {
send({
@ -285,15 +285,22 @@ export const Settings = () => {
interface SettingsSectionProps extends React.PropsWithChildren {
title: string
description?: string
className?: string
}
export function SettingsSection({
title,
description,
className,
children,
}: SettingsSectionProps) {
return (
<section className="my-16 last-of-type:mb-24 grid grid-cols-2 gap-12 items-start">
<section
className={
'my-16 last-of-type:mb-24 grid grid-cols-2 gap-12 items-start ' +
className
}
>
<div className="w-80">
<h2 className="text-2xl">{title}</h2>
<p className="mt-2 text-sm">{description}</p>

View File

@ -1,24 +1,25 @@
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import { addLineHighlight, EditorView } from './editor/highlightextension'
import { parser_wasm } from './lang/abstractSyntaxTree'
import { Program } from './lang/abstractSyntaxTreeTypes'
import { getNodeFromPath } from './lang/queryAst'
import { enginelessExecutor } from './lib/testHelpers'
import {
parse,
Program,
_executor,
recast,
ProgramMemory,
Position,
PathToNode,
Rotation,
SourceRange,
} from './lang/executor'
import { recast } from './lang/recast'
} from './lang/wasm'
import { getNodeFromPath } from './lang/queryAst'
import { enginelessExecutor } from './lib/testHelpers'
import { EditorSelection } from '@codemirror/state'
import { EngineCommandManager } from './lang/std/engineConnection'
import { KCLError } from './lang/errors'
import { deferExecution } from 'lib/utils'
import { _executor } from './lang/executor'
import { bracket } from 'lib/exampleKcl'
import { engineCommandManager } from './lang/std/engineConnection'
export type Selection = {
type: 'default' | 'line-end' | 'line-mid'
@ -156,14 +157,12 @@ export interface StoreState {
code: string
setCode: (code: string) => void
deferredSetCode: (code: string) => void
executeCode: (code?: string) => void
executeCode: (code?: string, force?: boolean) => void
formatCode: () => void
programMemory: ProgramMemory
setProgramMemory: (programMemory: ProgramMemory) => void
isShiftDown: boolean
setIsShiftDown: (isShiftDown: boolean) => void
engineCommandManager?: EngineCommandManager
setEngineCommandManager: (engineCommandManager: EngineCommandManager) => void
mediaStream?: MediaStream
setMediaStream: (mediaStream: MediaStream) => void
isStreamReady: boolean
@ -222,11 +221,12 @@ export const useStore = create<StoreState>()(
editorView.dispatch({ effects: addLineHighlight.of(selection) })
}
},
executeCode: async (code) => {
executeCode: async (code, force) => {
const result = await executeCode({
code: code || get().code,
lastAst: get().ast,
engineCommandManager: get().engineCommandManager,
engineCommandManager: engineCommandManager,
force,
})
if (!result.isChange) {
return
@ -332,8 +332,6 @@ export const useStore = create<StoreState>()(
executeAst: async (ast) => {
const _ast = ast || get().ast
if (!get().isStreamReady) return
const engineCommandManager = get().engineCommandManager!
if (!engineCommandManager) return
set({ isExecuting: true })
const { logs, errors, programMemory } = await executeAst({
@ -350,8 +348,6 @@ export const useStore = create<StoreState>()(
executeAstMock: async (ast) => {
const _ast = ast || get().ast
if (!get().isStreamReady) return
const engineCommandManager = get().engineCommandManager!
if (!engineCommandManager) return
const { logs, errors, programMemory } = await executeAst({
ast: _ast,
@ -371,7 +367,7 @@ export const useStore = create<StoreState>()(
{ focusPath, callBack = () => {} } = {}
) => {
const newCode = recast(ast)
const astWithUpdatedSource = parser_wasm(newCode)
const astWithUpdatedSource = parse(newCode)
callBack(astWithUpdatedSource)
set({
@ -427,7 +423,7 @@ export const useStore = create<StoreState>()(
},
formatCode: async () => {
const code = get().code
const ast = parser_wasm(code)
const ast = parse(code)
const newCode = recast(ast)
set({ code: newCode, ast })
},
@ -435,8 +431,6 @@ export const useStore = create<StoreState>()(
setProgramMemory: (programMemory) => set({ programMemory }),
isShiftDown: false,
setIsShiftDown: (isShiftDown) => set({ isShiftDown }),
setEngineCommandManager: (engineCommandManager) =>
set({ engineCommandManager }),
setMediaStream: (mediaStream) => set({ mediaStream }),
isStreamReady: false,
setIsStreamReady: (isStreamReady) => set({ isStreamReady }),
@ -454,7 +448,9 @@ export const useStore = create<StoreState>()(
fileId: '',
setFileId: (fileId) => set({ fileId }),
streamDimensions: { streamWidth: 1280, streamHeight: 720 },
setStreamDimensions: (streamDimensions) => set({ streamDimensions }),
setStreamDimensions: (streamDimensions) => {
set({ streamDimensions })
},
isExecuting: false,
setIsExecuting: (isExecuting) => set({ isExecuting }),
@ -516,10 +512,12 @@ async function executeCode({
engineCommandManager,
code,
lastAst,
force,
}: {
code: string
lastAst: Program
engineCommandManager?: EngineCommandManager
engineCommandManager: EngineCommandManager
force?: boolean
}): Promise<
| {
logs: string[]
@ -532,14 +530,14 @@ async function executeCode({
> {
let ast: Program
try {
ast = parser_wasm(code)
ast = parse(code)
} catch (e) {
let errors: KCLError[] = []
let logs: string[] = [JSON.stringify(e)]
if (e instanceof KCLError) {
errors = [e]
logs = []
if (e.msg === 'file is empty') engineCommandManager?.endSession()
if (e.msg === 'file is empty') engineCommandManager.endSession()
}
return {
isChange: true,
@ -562,7 +560,7 @@ async function executeCode({
}
// Check if the ast we have is equal to the ast in the storage.
// If it is, we don't need to update the ast.
if (!engineCommandManager || JSON.stringify(ast) === JSON.stringify(lastAst))
if (JSON.stringify(ast) === JSON.stringify(lastAst) && !force)
return { isChange: false }
const { logs, errors, programMemory } = await executeAst({

View File

@ -6,10 +6,10 @@
serial-integration = { max-threads = 4 }
[profile.default]
slow-timeout = { period = "10s", terminate-after = 1 }
slow-timeout = { period = "60s", terminate-after = 1 }
[profile.ci]
slow-timeout = { period = "60s", terminate-after = 10 }
slow-timeout = { period = "120s", terminate-after = 10 }
[[profile.default.overrides]]
filter = "test(serial_test_)"

248
src/wasm-lib/Cargo.lock generated
View File

@ -64,10 +64,16 @@ dependencies = [
]
[[package]]
name = "anstream"
version = "0.5.0"
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6cd65a4b849ace0b7f6daeebcc1a1d111282227ca745458c61dbf670e52a597"
dependencies = [
"anstyle",
"anstyle-parse",
@ -103,9 +109,9 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
version = "2.1.0"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
checksum = "0238ca56c96dfa37bdf7c373c8886dd591322500aceeeccdb2216fe06dc2f796"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
@ -142,6 +148,17 @@ dependencies = [
"thiserror",
]
[[package]]
name = "async-recursion"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.37",
]
[[package]]
name = "async-trait"
version = "0.1.73"
@ -211,13 +228,16 @@ checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
[[package]]
name = "bigdecimal"
version = "0.3.1"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa"
checksum = "454bca3db10617b88b566f205ed190aedb0e0e6dd4cad61d3988a72e8c5594cb"
dependencies = [
"autocfg",
"libm",
"num-bigint",
"num-integer",
"num-traits",
"serde",
]
[[package]]
@ -337,6 +357,12 @@ dependencies = [
"serde",
]
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.0.83"
@ -374,6 +400,33 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "ciborium"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
[[package]]
name = "ciborium-ll"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
dependencies = [
"ciborium-io",
"half 1.8.2",
]
[[package]]
name = "clang-sys"
version = "1.6.1"
@ -387,9 +440,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.4.4"
version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
dependencies = [
"clap_builder",
"clap_derive",
@ -397,9 +450,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.4.4"
version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
dependencies = [
"anstream",
"anstyle",
@ -507,6 +560,42 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools 0.10.5",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools 0.10.5",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
@ -593,7 +682,7 @@ checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
[[package]]
name = "derive-docs"
version = "0.1.3"
version = "0.1.4"
dependencies = [
"convert_case",
"expectorate",
@ -608,9 +697,9 @@ dependencies = [
[[package]]
name = "derive-docs"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe5c5ea065cfabc5a7c5e8ed616e369fbf108c4be01e0e5609bc9846a732664"
checksum = "c357dec14992ba88803535217ed83d6f6cd80efcb8fa8e3f8a30a9b84fadc1c7"
dependencies = [
"convert_case",
"proc-macro2",
@ -713,9 +802,9 @@ dependencies = [
[[package]]
name = "expectorate"
version = "1.0.7"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "710ab6a2d57038a835d66f78d5af3fa5d27c1ec4682f823b9203c48826cb0591"
checksum = "de6f19b25bdfa2747ae775f37cd109c31f1272d4e4c83095be0727840aa1d75f"
dependencies = [
"console",
"newline-converter",
@ -730,7 +819,7 @@ checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8"
dependencies = [
"bit_field",
"flume",
"half",
"half 2.2.1",
"lebe",
"miniz_oxide",
"rayon-core",
@ -997,6 +1086,12 @@ dependencies = [
"tracing",
]
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "half"
version = "2.2.1"
@ -1295,14 +1390,16 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.1.30"
version = "0.1.32"
dependencies = [
"anyhow",
"async-recursion",
"async-trait",
"bson",
"clap",
"criterion",
"dashmap",
"derive-docs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-docs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"expectorate",
"futures",
"itertools 0.11.0",
@ -1311,7 +1408,6 @@ dependencies = [
"lazy_static",
"parse-display",
"pretty_assertions",
"regex",
"reqwest",
"schemars",
"serde",
@ -1325,17 +1421,19 @@ dependencies = [
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winnow",
]
[[package]]
name = "kittycad"
version = "0.2.25"
version = "0.2.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9cf962b1e81a0b4eb923a727e761b40672cbacc7f5f0b75e13579d346352bc7"
checksum = "35b2f9302648dbb06fd7121687f9505fc3179eba84111a06d76b246e3158f5dc"
dependencies = [
"anyhow",
"async-trait",
"base64 0.21.4",
"bigdecimal",
"bytes",
"chrono",
"data-encoding",
@ -1397,6 +1495,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "libm"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
@ -1620,10 +1724,16 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2"
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "openapitor"
version = "0.0.9"
source = "git+https://github.com/KittyCAD/kittycad.rs?branch=main#0d121f6881da91b4a30bee18bbfe50e4a2096073"
source = "git+https://github.com/KittyCAD/kittycad.rs?branch=main#fa0345c514fcc9ae6cd74ae35c8e5c2800fec34f"
dependencies = [
"Inflector",
"anyhow",
@ -1797,14 +1907,14 @@ dependencies = [
[[package]]
name = "phonenumber"
version = "0.3.2+8.13.9"
version = "0.3.3+8.13.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34749f64ea9d76f10cdc8a859588b57775f59177c7dd91f744d620bd62982d6f"
checksum = "635f3e6288e4f01c049d89332a031bd74f25d64b6fb94703ca966e819488cd06"
dependencies = [
"bincode",
"either",
"fnv",
"itertools 0.10.5",
"itertools 0.11.0",
"lazy_static",
"nom",
"quick-xml",
@ -1812,6 +1922,7 @@ dependencies = [
"regex-cache",
"serde",
"serde_derive",
"strum",
"thiserror",
]
@ -1853,6 +1964,34 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "plotters"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
[[package]]
name = "plotters-svg"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
dependencies = [
"plotters-backend",
]
[[package]]
name = "png"
version = "0.17.10"
@ -2710,6 +2849,28 @@ dependencies = [
"syn 2.0.37",
]
[[package]]
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn 1.0.109",
]
[[package]]
name = "syn"
version = "1.0.109"
@ -2798,18 +2959,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.48"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.48"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
dependencies = [
"proc-macro2",
"quote",
@ -2867,6 +3028,16 @@ dependencies = [
"time-core",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
@ -2924,9 +3095,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
version = "0.20.0"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2"
checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
dependencies = [
"futures-util",
"log",
@ -3146,9 +3317,9 @@ dependencies = [
[[package]]
name = "tungstenite"
version = "0.20.0"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e862a1c4128df0112ab625f55cd5c934bcb4312ba80b39ae4b4835a3fd58e649"
checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9"
dependencies = [
"byteorder",
"bytes",
@ -3635,6 +3806,15 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "winnow"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
dependencies = [
"memchr",
]
[[package]]
name = "winreg"
version = "0.50.0"

Some files were not shown because too many files have changed in this diff Show More