Add stdlib functions for getting sketch profile start and its components (#2373)

* Add stdlib functions for getting sketch profile start and its components

* Fix it up and actually generate snapshots

* cargo fmt

* Use `.to` instead of `.from`

* Update docs with EXPECTORATE=overwrite

* Add README

* fmt

* Update flow test to account for more autocompletion options when typing "start"

---------

Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
This commit is contained in:
Frank Noirot
2024-05-21 03:44:02 -04:00
committed by GitHub
parent 793b7407f6
commit 82b03a9d47
13 changed files with 3696 additions and 6 deletions

View File

@ -59,7 +59,9 @@ followed by:
```
yarn build:wasm-dev
```
or if you have the gh cli installed
```
./get-latest-wasm-bundle.sh # this will download the latest main wasm bundle
```
@ -100,6 +102,7 @@ yarn test
Which will run our suite of [Vitest unit](https://vitest.dev/) and [React Testing Library E2E](https://testing-library.com/docs/react-testing-library/intro/) tests, in interactive mode by default.
For running the rust (not tauri rust though) only, you can
```bash
cd src/wasm-lib
cargo test
@ -162,6 +165,7 @@ console.log(
- `)
)
```
grab the md list and delete any that are older than the last bump
2. Merge the PR
@ -191,23 +195,26 @@ $ cargo +nightly fuzz run parser
For more information on fuzzing you can check out
[this guide](https://rust-fuzz.github.io/book/cargo-fuzz.html).
### Playwright
First time running plawright locally, you'll need to add the secrets file
```bash
touch ./e2e/playwright/playwright-secrets.env
printf 'token="your-token"\nsnapshottoken="your-snapshot-token"' > ./e2e/playwright/playwright-secrets.env
```
then replace "your-token" with a dev token from dev.zoo.dev/account/api-tokens
then:
run playwright
```
yarn playwright test
```
run a specific test suite
```
yarn playwright test src/e2e-tests/example.spec.ts
```
@ -216,14 +223,17 @@ run a specific test change the test from `test('...` to `test.only('...`
(note if you commit this, the tests will instantly fail without running any of the tests)
run headed
```
yarn playwright test --headed
```
run with step through debugger
```
PWDEBUG=1 yarn playwright test
```
However, if you want a debugger I recommend using VSCode and the `playwright` extension, as the above command is a cruder debugger that steps into every function call which is annoying.
With the extension you can set a breakpoint after `waitForDefaultPlanesVisibilityChange` in order to skip app loading, then the vscode debugger's "step over" is much better for being able to stay at the right level of abstraction as you debug the code.
@ -268,7 +278,6 @@ Where `./store` should look like this
</details>
However because much of our tests involve clicking in the stream at specific locations, it's code-gen looks `await page.locator('video').click();` when really we need to use a pixel coord, so I think it's of limited use.
#### Some notes on CI
@ -299,3 +308,7 @@ PS: for the debug panel, the following JSON is useful for snapping the camera
```
</details>
## KCL
For how to contribute to KCL, [see our KCL README](https://github.com/KittyCAD/modeling-app/tree/main/src/wasm-lib/kcl).

View File

@ -56,6 +56,9 @@ layout: manual
* [`patternLinear3d`](kcl/patternLinear3d)
* [`pi`](kcl/pi)
* [`pow`](kcl/pow)
* [`profileStart`](kcl/profileStart)
* [`profileStartX`](kcl/profileStartX)
* [`profileStartY`](kcl/profileStartY)
* [`revolve`](kcl/revolve)
* [`segAng`](kcl/segAng)
* [`segEndX`](kcl/segEndX)

206
docs/kcl/profileStart.md Normal file

File diff suppressed because one or more lines are too long

201
docs/kcl/profileStartX.md Normal file

File diff suppressed because one or more lines are too long

200
docs/kcl/profileStartY.md Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -646,8 +646,8 @@ test('Auto complete works', async ({ page }) => {
await page.click('.cm-content')
await page.keyboard.type('const part001 = start')
// expect there to be three auto complete options
await expect(page.locator('.cm-completionLabel')).toHaveCount(3)
// expect there to be six auto complete options
await expect(page.locator('.cm-completionLabel')).toHaveCount(6)
await page.getByText('startSketchOn').click()
await page.keyboard.type("'XZ'")
await page.keyboard.press('Tab')

View File

@ -0,0 +1,20 @@
# KCL
Our language for defining geometry and working with our Geometry Engine efficiently. Short for KittyCAD Language, named after our Design API.
## Contributing a standard library function
We've built a lot of tooling to make contributing to KCL easier. If you are interested in contributing a new standard library function to KCL, here is the rough process:
1. Open just the wasm-lib folder in your editor of choice. VS Code, for example, struggles to run rust-analyzer on the entire modeling-app directory because it's such a turducken of TS and Rust code.
2. Find the definition for similar standard library functions in `./kcl/src/std` and place your new one near it or in the same category file.
3. Add your new code. A new standard library function consists of:
4. A `pub async` of the actual standard library function in Rust
5. A doc comment block containing at least one example using your new standard library function (the Rust compiler will error if you don't provide an example our teammates are dope)
6. A `stdlib` macro providing the name that will need to be written by KCL users to use the function (this is usually a camelCase version of your Rust implementation, which is named with snake_case)
7. An inner function that is published only to the crate
8. Add your new standard library function to [the long list of CORE_FNS in mod.rs](https://github.com/KittyCAD/modeling-app/blob/main/src/wasm-lib/kcl/src/std/mod.rs#L42)
9. Get a production Zoo dev token and run `export KITTYCAD_API_TOKEN=your-token-here` in a terminal
10. Run `TWENTY_TWENTY=overwrite cargo nextest run --workspace --no-fail-fast` to take snapshot tests of your example code running in the engine
11. Run `EXPECTORATE=overwrite cargo test --all generate_stdlib -- --nocapture` to generate new Markdown documentation for your function that will be used [to generate docs on our website](https://zoo.dev/docs/kcl).
12. Create a PR in GitHub.

View File

@ -68,6 +68,9 @@ lazy_static! {
Box::new(crate::std::sketch::StartSketchAt),
Box::new(crate::std::sketch::StartSketchOn),
Box::new(crate::std::sketch::StartProfileAt),
Box::new(crate::std::sketch::ProfileStartX),
Box::new(crate::std::sketch::ProfileStartY),
Box::new(crate::std::sketch::ProfileStart),
Box::new(crate::std::sketch::Close),
Box::new(crate::std::sketch::Arc),
Box::new(crate::std::sketch::TangentialArc),

View File

@ -12,7 +12,7 @@ use crate::{
errors::{KclError, KclErrorDetails},
executor::{
BasePath, ExtrudeGroup, ExtrudeSurface, Face, GeoMeta, MemoryItem, Path, Plane, PlaneType, Point2d, Point3d,
Position, Rotation, SketchGroup, SketchGroupSet, SketchSurface, SourceRange,
Position, Rotation, SketchGroup, SketchGroupSet, SketchSurface, SourceRange, UserVal,
},
std::{
utils::{
@ -1214,6 +1214,78 @@ pub(crate) async fn inner_start_profile_at(
Ok(Box::new(sketch_group))
}
/// Returns the X component of the sketch profile start point.
pub async fn profile_start_x(args: Args) -> Result<MemoryItem, KclError> {
let sketch_group: Box<SketchGroup> = args.get_sketch_group()?;
let x = inner_profile_start_x(sketch_group)?;
args.make_user_val_from_f64(x)
}
/// ```no_run
/// const sketch001 = startSketchOn('XY')
/// |> startProfileAt([5, 2], %)
/// |> angledLine([-26.6, 50], %)
/// |> angledLine([90, 50], %)
/// |> angledLineToX({ angle: 30, to: profileStartX(%) }, %)
/// ```
#[stdlib {
name = "profileStartX"
}]
pub(crate) fn inner_profile_start_x(sketch_group: Box<SketchGroup>) -> Result<f64, KclError> {
Ok(sketch_group.start.to[0])
}
/// Returns the Y component of the sketch profile start point.
pub async fn profile_start_y(args: Args) -> Result<MemoryItem, KclError> {
let sketch_group: Box<SketchGroup> = args.get_sketch_group()?;
let x = inner_profile_start_y(sketch_group)?;
args.make_user_val_from_f64(x)
}
/// ```no_run
/// const sketch001 = startSketchOn('XY')
/// |> startProfileAt([5, 2], %)
/// |> angledLine({ angle: -60, length: 14 }, %)
/// |> angledLineToY({ angle: 30, to: profileStartY(%) }, %)
/// ```
#[stdlib {
name = "profileStartY"
}]
pub(crate) fn inner_profile_start_y(sketch_group: Box<SketchGroup>) -> Result<f64, KclError> {
Ok(sketch_group.start.to[1])
}
/// Returns the sketch profile start point.
pub async fn profile_start(args: Args) -> Result<MemoryItem, KclError> {
let sketch_group: Box<SketchGroup> = args.get_sketch_group()?;
let point = inner_profile_start(sketch_group)?;
Ok(MemoryItem::UserVal(UserVal {
value: serde_json::to_value(point).map_err(|e| {
KclError::Type(KclErrorDetails {
message: format!("Failed to convert point to json: {}", e),
source_ranges: vec![args.source_range],
})
})?,
meta: Default::default(),
}))
}
/// ```no_run
/// const sketch001 = startSketchOn('XY')
/// |> startProfileAt([5, 2], %)
/// |> angledLine({ angle: 120, length: 50 }, %, 'seg01')
/// |> angledLine({ angle: segAng('seg01', %) + 120, length: 50 }, %)
/// |> lineTo(profileStart(%), %)
/// |> close(%)
/// |> extrude(20, %)
/// ```
#[stdlib {
name = "profileStart"
}]
pub(crate) fn inner_profile_start(sketch_group: Box<SketchGroup>) -> Result<[f64; 2], KclError> {
Ok(sketch_group.start.to)
}
/// Close the current sketch.
pub async fn close(args: Args) -> Result<MemoryItem, KclError> {
let (sketch_group, tag): (Box<SketchGroup>, Option<String>) = args.get_sketch_group_and_optional_tag()?;

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB