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:
17
README.md
17
README.md
@ -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).
|
||||
|
@ -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
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
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
200
docs/kcl/profileStartY.md
Normal file
File diff suppressed because one or more lines are too long
2972
docs/kcl/std.json
2972
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
@ -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')
|
||||
|
20
src/wasm-lib/kcl/README.md
Normal file
20
src/wasm-lib/kcl/README.md
Normal 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.
|
@ -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),
|
||||
|
@ -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 |
Reference in New Issue
Block a user