Compare commits
22 Commits
remove-unu
...
pierremtb/
Author | SHA1 | Date | |
---|---|---|---|
0573801381 | |||
140e8b56fb | |||
4d203b0c0c | |||
223a4ad45d | |||
edf31ec1d3 | |||
04d6fcf0c4 | |||
30b2a765fc | |||
8ddbb488d6 | |||
1539557005 | |||
1d3ba4e3ac | |||
4110aa00db | |||
7eb52cda36 | |||
db82a54f27 | |||
077d1cfcef | |||
7872fb9cbd | |||
651181e62c | |||
38a245f2fc | |||
1b4289f93f | |||
d0697c24fd | |||
8c24e29081 | |||
2b9d26e2ff | |||
ab148a7654 |
15
.github/workflows/e2e-tests.yml
vendored
15
.github/workflows/e2e-tests.yml
vendored
@ -143,7 +143,7 @@ jobs:
|
|||||||
- name: Install browsers
|
- name: Install browsers
|
||||||
run: npm run playwright install --with-deps
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
- name: Capture snapshots
|
- name: Test snapshots
|
||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
with:
|
with:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -158,6 +158,17 @@ jobs:
|
|||||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
TARGET: web
|
TARGET: web
|
||||||
|
|
||||||
|
- name: Update snapshots
|
||||||
|
if: always()
|
||||||
|
run: npm run test:snapshots -- --last-failed --update-snapshots
|
||||||
|
env:
|
||||||
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
TAB_API_URL: ${{ secrets.TAB_API_URL }}
|
||||||
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
TARGET: web
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ !cancelled() && (success() || failure()) }}
|
if: ${{ !cancelled() && (success() || failure()) }}
|
||||||
with:
|
with:
|
||||||
@ -173,7 +184,7 @@ jobs:
|
|||||||
id: git-check
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||||
if git status | grep -q "Changes to be committed"
|
if git status | grep --quiet "Changes to be committed"
|
||||||
then echo "modified=true" >> $GITHUB_OUTPUT
|
then echo "modified=true" >> $GITHUB_OUTPUT
|
||||||
else echo "modified=false" >> $GITHUB_OUTPUT
|
else echo "modified=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
@ -27,9 +27,6 @@ import increment from "util.kcl"
|
|||||||
answer = increment(41)
|
answer = increment(41)
|
||||||
```
|
```
|
||||||
|
|
||||||
Imported files _must_ be in the same project so that units are uniform across
|
|
||||||
modules. This means that it must be in the same directory.
|
|
||||||
|
|
||||||
Import statements must be at the top-level of a file. It is not allowed to have
|
Import statements must be at the top-level of a file. It is not allowed to have
|
||||||
an `import` statement inside a function or in the body of an if‑else.
|
an `import` statement inside a function or in the body of an if‑else.
|
||||||
|
|
||||||
@ -58,6 +55,9 @@ Imported symbols can be renamed for convenience or to avoid name collisions.
|
|||||||
import increment as inc, decrement as dec from "util.kcl"
|
import increment as inc, decrement as dec from "util.kcl"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can import files from the current directory or from subdirectories, but if importing from a
|
||||||
|
subdirectory you can only import `main.kcl`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Functions vs `clone`
|
## Functions vs `clone`
|
||||||
@ -229,6 +229,19 @@ The final statement is what's important because it's the return value of the
|
|||||||
entire module. The module is expected to return a single object that can be used
|
entire module. The module is expected to return a single object that can be used
|
||||||
as a variable by the file that imports it.
|
as a variable by the file that imports it.
|
||||||
|
|
||||||
|
The name of the file or subdirectory is used as the name of the variable within the importing program.
|
||||||
|
If you want to use a different name, you can do so by using the `as` keyword:
|
||||||
|
|
||||||
|
```kcl,norun
|
||||||
|
import "cube.kcl" // Introduces a new variable called `cube`.
|
||||||
|
import "cube.kcl" as block // Introduces a new variable called `block`.
|
||||||
|
import "cube/main.kcl" // Introduces a new variable called `cube`.
|
||||||
|
import "cube/main.kcl" as block // Introduces a new variable called `block`.
|
||||||
|
```
|
||||||
|
|
||||||
|
If the filename includes hyphens (`-`) or starts with an underscore (`_`), then you must specify a
|
||||||
|
variable name.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Multiple instances of the same import
|
## Multiple instances of the same import
|
||||||
|
@ -684,4 +684,33 @@ c = 3 + a`
|
|||||||
highlightedHeaderArg: 'value',
|
highlightedHeaderArg: 'value',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Text-to-CAD command can be closed with escape while in prompt', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await homePage.expectState({
|
||||||
|
projectCards: [],
|
||||||
|
sortBy: 'last-modified-desc',
|
||||||
|
})
|
||||||
|
await homePage.textToCadBtn.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
commandName: 'Text-to-CAD Create',
|
||||||
|
currentArgKey: 'prompt',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Method: 'New project',
|
||||||
|
NewProjectName: 'untitled',
|
||||||
|
Prompt: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'prompt',
|
||||||
|
})
|
||||||
|
await page.keyboard.press('Escape')
|
||||||
|
await cmdBar.toBeClosed()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'commandBarClosed',
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -238,6 +238,26 @@ test.describe('when using the file tree to', () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
`create new folders and that doesn't trigger a navigation`,
|
||||||
|
{ tag: ['@electron', '@macos', '@windows'] },
|
||||||
|
async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await toolbar.openPane('files')
|
||||||
|
const { createNewFolder } = await getUtils(page, test)
|
||||||
|
|
||||||
|
await createNewFolder('folder')
|
||||||
|
|
||||||
|
await createNewFolder('folder.kcl')
|
||||||
|
|
||||||
|
await test.step(`Postcondition: folders are created and we didn't navigate`, async () => {
|
||||||
|
await toolbar.expectFileTreeState(['folder', 'folder.kcl', 'main.kcl'])
|
||||||
|
await expect(toolbar.fileName).toHaveText('main.kcl')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'deleting all files recreates a default main.kcl with no code',
|
'deleting all files recreates a default main.kcl with no code',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
|
@ -308,6 +308,11 @@ export class CmdBarFixture {
|
|||||||
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toBeClosed() {
|
||||||
|
// Check that the command bar is closed
|
||||||
|
await expect(this.cmdBarElement).not.toBeVisible({ timeout: 10_000 })
|
||||||
|
}
|
||||||
|
|
||||||
async expectArgValue(value: string) {
|
async expectArgValue(value: string) {
|
||||||
// Check the placeholder project name exists
|
// Check the placeholder project name exists
|
||||||
const actualArgument = await this.cmdBarElement
|
const actualArgument = await this.cmdBarElement
|
||||||
|
@ -26,6 +26,7 @@ export class HomePageFixture {
|
|||||||
sortByNameBtn!: Locator
|
sortByNameBtn!: Locator
|
||||||
appHeader!: Locator
|
appHeader!: Locator
|
||||||
tutorialBtn!: Locator
|
tutorialBtn!: Locator
|
||||||
|
textToCadBtn!: Locator
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page
|
this.page = page
|
||||||
@ -47,6 +48,7 @@ export class HomePageFixture {
|
|||||||
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
||||||
this.appHeader = this.page.getByTestId('app-header')
|
this.appHeader = this.page.getByTestId('app-header')
|
||||||
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
||||||
|
this.textToCadBtn = this.page.getByTestId('home-text-to-cad')
|
||||||
}
|
}
|
||||||
|
|
||||||
private _serialiseSortBy = async (): Promise<
|
private _serialiseSortBy = async (): Promise<
|
||||||
|
@ -2064,3 +2064,59 @@ test(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
'nested dir import works on windows',
|
||||||
|
{ tag: ['@electron', '@windows'] },
|
||||||
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
|
// Skip if on non-windows
|
||||||
|
if (process.platform !== 'win32') {
|
||||||
|
test.skip()
|
||||||
|
}
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
|
const nestedDir = path.join(bracketDir, 'nested')
|
||||||
|
await fsp.mkdir(nestedDir, { recursive: true })
|
||||||
|
|
||||||
|
await fsp.copyFile(
|
||||||
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
|
path.join(nestedDir, 'main.kcl')
|
||||||
|
)
|
||||||
|
await fsp.writeFile(
|
||||||
|
path.join(bracketDir, 'main.kcl'),
|
||||||
|
`import 'nested\\main.kcl' as thing
|
||||||
|
|
||||||
|
thing`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
const pointOnModel = { x: 630, y: 280 }
|
||||||
|
|
||||||
|
await test.step('Opening the bracket project should load the stream', async () => {
|
||||||
|
// expect to see the text bracket
|
||||||
|
await expect(page.getByText('bracket')).toBeVisible()
|
||||||
|
|
||||||
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
|
).toBeEnabled({
|
||||||
|
timeout: 20_000,
|
||||||
|
})
|
||||||
|
|
||||||
|
// gray at this pixel means the stream has loaded in the most
|
||||||
|
// user way we can verify it (pixel color)
|
||||||
|
await expect
|
||||||
|
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
||||||
|
timeout: 10_000,
|
||||||
|
})
|
||||||
|
.toBeLessThan(15)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
@ -557,6 +557,14 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
createNewFolder: async (name: string) => {
|
||||||
|
return test?.step(`Create a folder named ${name}`, async () => {
|
||||||
|
await page.getByTestId('create-folder-button').click()
|
||||||
|
await page.getByTestId('tree-input-field').fill(name)
|
||||||
|
await page.keyboard.press('Enter')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
cloneFile: async (name: string) => {
|
cloneFile: async (name: string) => {
|
||||||
return test?.step(`Cloning file '${name}'`, async () => {
|
return test?.step(`Cloning file '${name}'`, async () => {
|
||||||
await page
|
await page
|
||||||
|
@ -72,25 +72,25 @@ leftSpacerShape = boxModuleFn(width = leftSpacerWidth)
|
|||||||
|
|
||||||
// Module for power switch including front plate and red rocker button
|
// Module for power switch including front plate and red rocker button
|
||||||
switchPosition = leftSpacerPosition + leftSpacerWidth / 2 + moduleWidth / 2
|
switchPosition = leftSpacerPosition + leftSpacerWidth / 2 + moduleWidth / 2
|
||||||
swtichWidth = moduleWidth
|
switchWidth = moduleWidth
|
||||||
|
|
||||||
// Switch Body
|
// Switch Body
|
||||||
switchBody = boxModuleFn(width = moduleWidth)
|
switchBody = boxModuleFn(width = moduleWidth)
|
||||||
|
|
||||||
// Switch Plate
|
// Switch Plate
|
||||||
swtichPlateWidth = 20
|
switchPlateWidth = 20
|
||||||
switchPlateHeight = 30
|
switchPlateHeight = 30
|
||||||
switchPlateThickness = 3
|
switchPlateThickness = 3
|
||||||
switchPlateShape = startSketchOn(switchBody, face = END)
|
switchPlateShape = startSketchOn(switchBody, face = END)
|
||||||
|> startProfile(
|
|> startProfile(
|
||||||
%,
|
%,
|
||||||
at = [
|
at = [
|
||||||
-swtichPlateWidth / 2,
|
-switchPlateWidth / 2,
|
||||||
-switchPlateHeight / 2
|
-switchPlateHeight / 2
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|> yLine(length = switchPlateHeight)
|
|> yLine(length = switchPlateHeight)
|
||||||
|> xLine(length = swtichPlateWidth)
|
|> xLine(length = switchPlateWidth)
|
||||||
|> yLine(length = -switchPlateHeight)
|
|> yLine(length = -switchPlateHeight)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
@ -104,8 +104,8 @@ switchPlateBody = extrude(switchPlateShape, length = switchPlateThickness)
|
|||||||
|
|
||||||
// Switch Button
|
// Switch Button
|
||||||
switchButtonHeight = 26
|
switchButtonHeight = 26
|
||||||
swtichButtonWidth = 15
|
switchButtonWidth = 15
|
||||||
switchButtonShape = startSketchOn(offsetPlane(-YZ, offset = -swtichButtonWidth / 2))
|
switchButtonShape = startSketchOn(offsetPlane(-YZ, offset = -switchButtonWidth / 2))
|
||||||
|> startProfile(
|
|> startProfile(
|
||||||
%,
|
%,
|
||||||
at = [
|
at = [
|
||||||
@ -121,7 +121,7 @@ switchButtonShape = startSketchOn(offsetPlane(-YZ, offset = -swtichButtonWidth /
|
|||||||
])
|
])
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
switchButtonBody = extrude(switchButtonShape, length = swtichButtonWidth)
|
switchButtonBody = extrude(switchButtonShape, length = switchButtonWidth)
|
||||||
|> translate(
|
|> translate(
|
||||||
%,
|
%,
|
||||||
x = switchPosition,
|
x = switchPosition,
|
||||||
@ -132,7 +132,7 @@ switchButtonBody = extrude(switchButtonShape, length = swtichButtonWidth)
|
|||||||
|
|
||||||
// Spacer between switch and plug modules for layout alignment
|
// Spacer between switch and plug modules for layout alignment
|
||||||
secondSpacerWidth = moduleWidth / 2
|
secondSpacerWidth = moduleWidth / 2
|
||||||
secondSpacerPosition = switchPosition + swtichWidth / 2 + secondSpacerWidth / 2
|
secondSpacerPosition = switchPosition + switchWidth / 2 + secondSpacerWidth / 2
|
||||||
secondSpacerBody = boxModuleFn(width = secondSpacerWidth)
|
secondSpacerBody = boxModuleFn(width = secondSpacerWidth)
|
||||||
|> translate(
|
|> translate(
|
||||||
%,
|
%,
|
||||||
|
@ -53,8 +53,8 @@ baseSlab = boxFn(plane = XY, width = slabWidth, height = -baseThickness)
|
|||||||
|> appearance(%, color = "#dbd7d2")
|
|> appearance(%, color = "#dbd7d2")
|
||||||
|
|
||||||
// Create ground platform beneath the base
|
// Create ground platform beneath the base
|
||||||
goundSize = 50
|
groundSize = 50
|
||||||
groundBody = boxFn(plane = offsetPlane(XY, offset = -baseThickness), width = goundSize, height = -5)
|
groundBody = boxFn(plane = offsetPlane(XY, offset = -baseThickness), width = groundSize, height = -5)
|
||||||
|> appearance(%, color = "#3a3631")
|
|> appearance(%, color = "#3a3631")
|
||||||
|
|
||||||
// Create a single slab with handrail height to be reused with pattern
|
// Create a single slab with handrail height to be reused with pattern
|
||||||
|
@ -35,31 +35,28 @@ impl Default for TypedPath {
|
|||||||
|
|
||||||
impl From<&String> for TypedPath {
|
impl From<&String> for TypedPath {
|
||||||
fn from(path: &String) -> Self {
|
fn from(path: &String) -> Self {
|
||||||
#[cfg(target_arch = "wasm32")]
|
TypedPath::new(path)
|
||||||
{
|
|
||||||
TypedPath(typed_path::TypedPath::derive(path).to_path_buf())
|
|
||||||
}
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
{
|
|
||||||
TypedPath(std::path::PathBuf::from(path))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for TypedPath {
|
impl From<&str> for TypedPath {
|
||||||
fn from(path: &str) -> Self {
|
fn from(path: &str) -> Self {
|
||||||
|
TypedPath::new(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypedPath {
|
||||||
|
pub fn new(path: &str) -> Self {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
TypedPath(typed_path::TypedPath::derive(path).to_path_buf())
|
TypedPath(typed_path::TypedPath::derive(path).to_path_buf())
|
||||||
}
|
}
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
{
|
{
|
||||||
TypedPath(std::path::PathBuf::from(path))
|
TypedPath(normalise_import(path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl TypedPath {
|
|
||||||
pub fn extension(&self) -> Option<&str> {
|
pub fn extension(&self) -> Option<&str> {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
@ -85,6 +82,17 @@ impl TypedPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn join_typed(&self, path: &TypedPath) -> Self {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
TypedPath(self.0.join(path.0.to_path()))
|
||||||
|
}
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
{
|
||||||
|
TypedPath(self.0.join(&path.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parent(&self) -> Option<Self> {
|
pub fn parent(&self) -> Option<Self> {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
@ -206,3 +214,19 @@ impl schemars::JsonSchema for TypedPath {
|
|||||||
gen.subschema_for::<std::path::PathBuf>()
|
gen.subschema_for::<std::path::PathBuf>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turn `nested\foo\bar\main.kcl` or `nested/foo/bar/main.kcl`
|
||||||
|
/// into a PathBuf that works on the host OS.
|
||||||
|
///
|
||||||
|
/// * Does **not** touch `..` or symlinks – call `canonicalize()` if you need that.
|
||||||
|
/// * Returns an owned `PathBuf` only when normalisation was required.
|
||||||
|
fn normalise_import<S: AsRef<str>>(raw: S) -> std::path::PathBuf {
|
||||||
|
let s = raw.as_ref();
|
||||||
|
// On Unix we need to swap `\` → `/`. On Windows we leave it alone.
|
||||||
|
// (Windows happily consumes `/`)
|
||||||
|
if cfg!(unix) && s.contains('\\') {
|
||||||
|
std::path::PathBuf::from(s.replace('\\', "/"))
|
||||||
|
} else {
|
||||||
|
std::path::Path::new(s).to_path_buf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -185,9 +185,9 @@ impl ModulePath {
|
|||||||
match path {
|
match path {
|
||||||
ImportPath::Kcl { filename: path } | ImportPath::Foreign { path } => {
|
ImportPath::Kcl { filename: path } | ImportPath::Foreign { path } => {
|
||||||
let resolved_path = if let Some(project_dir) = project_directory {
|
let resolved_path = if let Some(project_dir) = project_directory {
|
||||||
project_dir.join(path)
|
project_dir.join_typed(path)
|
||||||
} else {
|
} else {
|
||||||
TypedPath::from(path)
|
path.clone()
|
||||||
};
|
};
|
||||||
ModulePath::Local { value: resolved_path }
|
ModulePath::Local { value: resolved_path }
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
parsing::{ast::digest::Digest, token::NumericSuffix, PIPE_OPERATOR},
|
parsing::{ast::digest::Digest, token::NumericSuffix, PIPE_OPERATOR},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
ModuleId,
|
ModuleId, TypedPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod condition;
|
mod condition;
|
||||||
@ -1741,8 +1741,8 @@ impl ImportSelector {
|
|||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum ImportPath {
|
pub enum ImportPath {
|
||||||
Kcl { filename: String },
|
Kcl { filename: TypedPath },
|
||||||
Foreign { path: String },
|
Foreign { path: TypedPath },
|
||||||
Std { path: Vec<String> },
|
Std { path: Vec<String> },
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1811,16 +1811,25 @@ impl ImportStatement {
|
|||||||
|
|
||||||
match &self.path {
|
match &self.path {
|
||||||
ImportPath::Kcl { filename: s } | ImportPath::Foreign { path: s } => {
|
ImportPath::Kcl { filename: s } | ImportPath::Foreign { path: s } => {
|
||||||
let mut parts = s.split('.');
|
let name = s.to_string_lossy();
|
||||||
let path = parts.next()?;
|
if name.ends_with("/main.kcl") || name.ends_with("\\main.kcl") {
|
||||||
let _ext = parts.next()?;
|
let name = &name[..name.len() - 9];
|
||||||
let rest = parts.next();
|
let start = name.rfind(['/', '\\']).map(|s| s + 1).unwrap_or(0);
|
||||||
|
return Some(name[start..].to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
if rest.is_some() {
|
let name = s.file_name().map(|f| f.to_string())?;
|
||||||
|
if name.contains('\\') || name.contains('/') {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
path.rsplit(&['/', '\\']).next().map(str::to_owned)
|
// Remove the extension if it exists.
|
||||||
|
let extension = s.extension();
|
||||||
|
Some(if let Some(extension) = extension {
|
||||||
|
name.trim_end_matches(extension).trim_end_matches('.').to_string()
|
||||||
|
} else {
|
||||||
|
name
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ImportPath::Std { path } => path.last().cloned(),
|
ImportPath::Std { path } => path.last().cloned(),
|
||||||
}
|
}
|
||||||
@ -4332,4 +4341,20 @@ startSketchOn(XY)
|
|||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn module_name() {
|
||||||
|
#[track_caller]
|
||||||
|
fn assert_mod_name(stmt: &str, name: &str) {
|
||||||
|
let tokens = crate::parsing::token::lex(stmt, ModuleId::default()).unwrap();
|
||||||
|
let stmt = crate::parsing::parser::import_stmt(&mut tokens.as_slice()).unwrap();
|
||||||
|
assert_eq!(stmt.module_name().unwrap(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_mod_name("import 'foo.kcl'", "foo");
|
||||||
|
assert_mod_name("import 'foo.kcl' as bar", "bar");
|
||||||
|
assert_mod_name("import 'main.kcl'", "main");
|
||||||
|
assert_mod_name("import 'foo/main.kcl'", "foo");
|
||||||
|
assert_mod_name("import 'foo\\bar\\main.kcl'", "bar");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ use crate::{
|
|||||||
token::{Token, TokenSlice, TokenType},
|
token::{Token, TokenSlice, TokenType},
|
||||||
PIPE_OPERATOR, PIPE_SUBSTITUTION_OPERATOR,
|
PIPE_OPERATOR, PIPE_SUBSTITUTION_OPERATOR,
|
||||||
},
|
},
|
||||||
SourceRange, IMPORT_FILE_EXTENSIONS,
|
SourceRange, TypedPath, IMPORT_FILE_EXTENSIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
@ -1729,7 +1729,7 @@ fn glob(i: &mut TokenSlice) -> PResult<Token> {
|
|||||||
.parse_next(i)
|
.parse_next(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_stmt(i: &mut TokenSlice) -> PResult<BoxNode<ImportStatement>> {
|
pub(super) fn import_stmt(i: &mut TokenSlice) -> PResult<BoxNode<ImportStatement>> {
|
||||||
let (visibility, visibility_token) = opt(terminated(item_visibility, whitespace))
|
let (visibility, visibility_token) = opt(terminated(item_visibility, whitespace))
|
||||||
.parse_next(i)?
|
.parse_next(i)?
|
||||||
.map_or((ItemVisibility::Default, None), |pair| (pair.0, Some(pair.1)));
|
.map_or((ItemVisibility::Default, None), |pair| (pair.0, Some(pair.1)));
|
||||||
@ -1862,18 +1862,50 @@ fn validate_path_string(path_string: String, var_name: bool, path_range: SourceR
|
|||||||
let path = if path_string.ends_with(".kcl") {
|
let path = if path_string.ends_with(".kcl") {
|
||||||
if path_string
|
if path_string
|
||||||
.chars()
|
.chars()
|
||||||
.any(|c| !c.is_ascii_alphanumeric() && c != '_' && c != '-' && c != '.')
|
.any(|c| !c.is_ascii_alphanumeric() && c != '_' && c != '-' && c != '.' && c != '/' && c != '\\')
|
||||||
{
|
{
|
||||||
return Err(ErrMode::Cut(
|
return Err(ErrMode::Cut(
|
||||||
CompilationError::fatal(
|
CompilationError::fatal(
|
||||||
path_range,
|
path_range,
|
||||||
"import path may only contain alphanumeric characters, underscore, hyphen, and period. KCL files in other directories are not yet supported.",
|
"import path may only contain alphanumeric characters, `_`, `-`, `.`, `/`, and `\\`.",
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportPath::Kcl { filename: path_string }
|
if path_string.starts_with("..") {
|
||||||
|
return Err(ErrMode::Cut(
|
||||||
|
CompilationError::fatal(
|
||||||
|
path_range,
|
||||||
|
"import path may not start with '..'. Cannot traverse to something outside the bounds of your project. If this path is inside your project please find a better way to reference it.",
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure they are not using an absolute path.
|
||||||
|
if path_string.starts_with('/') || path_string.starts_with('\\') {
|
||||||
|
return Err(ErrMode::Cut(
|
||||||
|
CompilationError::fatal(
|
||||||
|
path_range,
|
||||||
|
"import path may not start with '/' or '\\'. Cannot traverse to something outside the bounds of your project. If this path is inside your project please find a better way to reference it.",
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_string.contains('/') || path_string.contains('\\'))
|
||||||
|
&& !(path_string.ends_with("/main.kcl") || path_string.ends_with("\\main.kcl"))
|
||||||
|
{
|
||||||
|
return Err(ErrMode::Cut(
|
||||||
|
CompilationError::fatal(path_range, "import path to a subdirectory must only refer to main.kcl.")
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportPath::Kcl {
|
||||||
|
filename: TypedPath::new(&path_string),
|
||||||
|
}
|
||||||
} else if path_string.starts_with("std::") {
|
} else if path_string.starts_with("std::") {
|
||||||
ParseContext::warn(CompilationError::err(
|
ParseContext::warn(CompilationError::err(
|
||||||
path_range,
|
path_range,
|
||||||
@ -1910,7 +1942,9 @@ fn validate_path_string(path_string: String, var_name: bool, path_range: SourceR
|
|||||||
format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", IMPORT_FILE_EXTENSIONS.join(", ")),
|
format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", IMPORT_FILE_EXTENSIONS.join(", ")),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ImportPath::Foreign { path: path_string }
|
ImportPath::Foreign {
|
||||||
|
path: TypedPath::new(&path_string),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ErrMode::Cut(
|
return Err(ErrMode::Cut(
|
||||||
CompilationError::fatal(
|
CompilationError::fatal(
|
||||||
@ -4534,9 +4568,24 @@ e
|
|||||||
fn bad_imports() {
|
fn bad_imports() {
|
||||||
assert_err(
|
assert_err(
|
||||||
r#"import cube from "../cube.kcl""#,
|
r#"import cube from "../cube.kcl""#,
|
||||||
"import path may only contain alphanumeric characters, underscore, hyphen, and period. KCL files in other directories are not yet supported.",
|
"import path may not start with '..'. Cannot traverse to something outside the bounds of your project. If this path is inside your project please find a better way to reference it.",
|
||||||
[17, 30],
|
[17, 30],
|
||||||
);
|
);
|
||||||
|
assert_err(
|
||||||
|
r#"import cube from "/cube.kcl""#,
|
||||||
|
"import path may not start with '/' or '\\'. Cannot traverse to something outside the bounds of your project. If this path is inside your project please find a better way to reference it.",
|
||||||
|
[17, 28],
|
||||||
|
);
|
||||||
|
assert_err(
|
||||||
|
r#"import cube from "C:\cube.kcl""#,
|
||||||
|
"import path may only contain alphanumeric characters, `_`, `-`, `.`, `/`, and `\\`.",
|
||||||
|
[17, 30],
|
||||||
|
);
|
||||||
|
assert_err(
|
||||||
|
r#"import cube from "cube/cube.kcl""#,
|
||||||
|
"import path to a subdirectory must only refer to main.kcl.",
|
||||||
|
[17, 32],
|
||||||
|
);
|
||||||
assert_err(
|
assert_err(
|
||||||
r#"import * as foo from "dsfs""#,
|
r#"import * as foo from "dsfs""#,
|
||||||
"as is not the 'from' keyword",
|
"as is not the 'from' keyword",
|
||||||
|
@ -3276,3 +3276,45 @@ mod subtract_regression10 {
|
|||||||
super::execute(TEST_NAME, true).await
|
super::execute(TEST_NAME, true).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mod nested_main_kcl {
|
||||||
|
const TEST_NAME: &str = "nested_main_kcl";
|
||||||
|
|
||||||
|
/// Test parsing KCL.
|
||||||
|
#[test]
|
||||||
|
fn parse() {
|
||||||
|
super::parse(TEST_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that parsing and unparsing KCL produces the original KCL input.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn unparse() {
|
||||||
|
super::unparse(TEST_NAME).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that KCL is executed correctly.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_execute() {
|
||||||
|
super::execute(TEST_NAME, true).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod nested_windows_main_kcl {
|
||||||
|
const TEST_NAME: &str = "nested_windows_main_kcl";
|
||||||
|
|
||||||
|
/// Test parsing KCL.
|
||||||
|
#[test]
|
||||||
|
fn parse() {
|
||||||
|
super::parse(TEST_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that parsing and unparsing KCL produces the original KCL input.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn unparse() {
|
||||||
|
super::unparse(TEST_NAME).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that KCL is executed correctly.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_execute() {
|
||||||
|
super::execute(TEST_NAME, true).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ use crate::{
|
|||||||
args::{Args, TyF64},
|
args::{Args, TyF64},
|
||||||
utils::{
|
utils::{
|
||||||
arc_center_and_end, get_tangential_arc_to_info, get_x_component, get_y_component,
|
arc_center_and_end, get_tangential_arc_to_info, get_x_component, get_y_component,
|
||||||
intersection_with_parallel_line, point_to_len_unit, point_to_mm, untype_point, untyped_point_to_mm,
|
intersection_with_parallel_line, point_to_len_unit, point_to_mm, untyped_point_to_mm,
|
||||||
TangentialArcInfoInput,
|
TangentialArcInfoInput,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1396,12 +1396,14 @@ pub(crate) async fn inner_start_profile(
|
|||||||
])
|
])
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let (to, ty) = untype_point(at);
|
// Convert to the units of the module. This is what the frontend expects.
|
||||||
|
let units = exec_state.length_unit();
|
||||||
|
let to = point_to_len_unit(at, units);
|
||||||
let current_path = BasePath {
|
let current_path = BasePath {
|
||||||
from: to,
|
from: to,
|
||||||
to,
|
to,
|
||||||
tag: tag.clone(),
|
tag: tag.clone(),
|
||||||
units: ty.expect_length(),
|
units,
|
||||||
geo_meta: GeoMeta {
|
geo_meta: GeoMeta {
|
||||||
id: move_pen_id,
|
id: move_pen_id,
|
||||||
metadata: args.source_range.into(),
|
metadata: args.source_range.into(),
|
||||||
@ -1414,7 +1416,7 @@ pub(crate) async fn inner_start_profile(
|
|||||||
artifact_id: path_id.into(),
|
artifact_id: path_id.into(),
|
||||||
on: sketch_surface.clone(),
|
on: sketch_surface.clone(),
|
||||||
paths: vec![],
|
paths: vec![],
|
||||||
units: ty.expect_length(),
|
units,
|
||||||
mirror: Default::default(),
|
mirror: Default::default(),
|
||||||
meta: vec![args.source_range.into()],
|
meta: vec![args.source_range.into()],
|
||||||
tags: if let Some(tag) = &tag {
|
tags: if let Some(tag) = &tag {
|
||||||
|
@ -203,7 +203,7 @@ description: Artifact commands helium-tank.kcl
|
|||||||
"path": "[uuid]",
|
"path": "[uuid]",
|
||||||
"segment": {
|
"segment": {
|
||||||
"type": "tangential_arc",
|
"type": "tangential_arc",
|
||||||
"radius": 95.88500000000016,
|
"radius": 95.8850000000001,
|
||||||
"offset": {
|
"offset": {
|
||||||
"unit": "degrees",
|
"unit": "degrees",
|
||||||
"value": -90.0
|
"value": -90.0
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3271,7 +3271,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"id": {
|
"id": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichWidth",
|
"name": "switchWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -3385,7 +3385,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"id": {
|
"id": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichPlateWidth",
|
"name": "switchPlateWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -3586,7 +3586,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"name": {
|
"name": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichPlateWidth",
|
"name": "switchPlateWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -3768,7 +3768,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"name": {
|
"name": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichPlateWidth",
|
"name": "switchPlateWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -4257,7 +4257,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"id": {
|
"id": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichButtonWidth",
|
"name": "switchButtonWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -4339,7 +4339,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"name": {
|
"name": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichButtonWidth",
|
"name": "switchButtonWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -4994,7 +4994,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"name": {
|
"name": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichButtonWidth",
|
"name": "switchButtonWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -5329,7 +5329,7 @@ description: Result of parsing pdu-faceplate.kcl
|
|||||||
"name": {
|
"name": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "swtichWidth",
|
"name": "switchWidth",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
|
@ -17406,6 +17406,19 @@ description: Variables in memory after executing pdu-faceplate.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"switchButtonWidth": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 15.0,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Mm"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"switchPlateBody": {
|
"switchPlateBody": {
|
||||||
"type": "Solid",
|
"type": "Solid",
|
||||||
"value": {
|
"value": {
|
||||||
@ -18170,6 +18183,19 @@ description: Variables in memory after executing pdu-faceplate.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"switchPlateWidth": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 20.0,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "Mm"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"switchPosition": {
|
"switchPosition": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"value": -158.4,
|
"value": -158.4,
|
||||||
@ -18183,33 +18209,7 @@ description: Variables in memory after executing pdu-faceplate.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"swtichButtonWidth": {
|
"switchWidth": {
|
||||||
"type": "Number",
|
|
||||||
"value": 15.0,
|
|
||||||
"ty": {
|
|
||||||
"type": "Default",
|
|
||||||
"len": {
|
|
||||||
"type": "Mm"
|
|
||||||
},
|
|
||||||
"angle": {
|
|
||||||
"type": "Degrees"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"swtichPlateWidth": {
|
|
||||||
"type": "Number",
|
|
||||||
"value": 20.0,
|
|
||||||
"ty": {
|
|
||||||
"type": "Default",
|
|
||||||
"len": {
|
|
||||||
"type": "Mm"
|
|
||||||
},
|
|
||||||
"angle": {
|
|
||||||
"type": "Degrees"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"swtichWidth": {
|
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"value": 40.45,
|
"value": 40.45,
|
||||||
"ty": {
|
"ty": {
|
||||||
|
@ -148,7 +148,7 @@ description: Artifact commands router-template-cross-bar.kcl
|
|||||||
"segment": {
|
"segment": {
|
||||||
"type": "line",
|
"type": "line",
|
||||||
"end": {
|
"end": {
|
||||||
"x": 22.6312,
|
"x": 22.6313,
|
||||||
"y": -10.0,
|
"y": -10.0,
|
||||||
"z": 0.0
|
"z": 0.0
|
||||||
},
|
},
|
||||||
@ -182,7 +182,7 @@ description: Artifact commands router-template-cross-bar.kcl
|
|||||||
"segment": {
|
"segment": {
|
||||||
"type": "line",
|
"type": "line",
|
||||||
"end": {
|
"end": {
|
||||||
"x": 32.6312,
|
"x": 32.6313,
|
||||||
"y": 10.9406,
|
"y": 10.9406,
|
||||||
"z": 0.0
|
"z": 0.0
|
||||||
},
|
},
|
||||||
@ -199,7 +199,7 @@ description: Artifact commands router-template-cross-bar.kcl
|
|||||||
"segment": {
|
"segment": {
|
||||||
"type": "line",
|
"type": "line",
|
||||||
"end": {
|
"end": {
|
||||||
"x": 102.6312,
|
"x": 102.6313,
|
||||||
"y": 10.9406,
|
"y": 10.9406,
|
||||||
"z": 0.0
|
"z": 0.0
|
||||||
},
|
},
|
||||||
@ -233,7 +233,7 @@ description: Artifact commands router-template-cross-bar.kcl
|
|||||||
"segment": {
|
"segment": {
|
||||||
"type": "line",
|
"type": "line",
|
||||||
"end": {
|
"end": {
|
||||||
"x": 32.6312,
|
"x": 32.6313,
|
||||||
"y": 30.9406,
|
"y": 30.9406,
|
||||||
"z": 0.0
|
"z": 0.0
|
||||||
},
|
},
|
||||||
@ -250,7 +250,7 @@ description: Artifact commands router-template-cross-bar.kcl
|
|||||||
"segment": {
|
"segment": {
|
||||||
"type": "line",
|
"type": "line",
|
||||||
"end": {
|
"end": {
|
||||||
"x": 32.6312,
|
"x": 32.6313,
|
||||||
"y": 41.8813,
|
"y": 41.8813,
|
||||||
"z": 0.0
|
"z": 0.0
|
||||||
},
|
},
|
||||||
@ -284,7 +284,7 @@ description: Artifact commands router-template-cross-bar.kcl
|
|||||||
"segment": {
|
"segment": {
|
||||||
"type": "line",
|
"type": "line",
|
||||||
"end": {
|
"end": {
|
||||||
"x": -32.6312,
|
"x": -32.6313,
|
||||||
"y": 0.0,
|
"y": 0.0,
|
||||||
"z": 0.0
|
"z": 0.0
|
||||||
},
|
},
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -61,32 +61,32 @@ flowchart LR
|
|||||||
50[Solid2d]
|
50[Solid2d]
|
||||||
end
|
end
|
||||||
subgraph path13 [Path]
|
subgraph path13 [Path]
|
||||||
13["Path<br>[2227, 2279, 0]"]
|
13["Path<br>[2229, 2281, 0]"]
|
||||||
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
|
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
|
||||||
35["Segment<br>[2285, 2318, 0]"]
|
35["Segment<br>[2287, 2320, 0]"]
|
||||||
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
|
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
|
||||||
36["Segment<br>[2324, 2357, 0]"]
|
36["Segment<br>[2326, 2359, 0]"]
|
||||||
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
|
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
|
||||||
37["Segment<br>[2363, 2397, 0]"]
|
37["Segment<br>[2365, 2399, 0]"]
|
||||||
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
|
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
|
||||||
38["Segment<br>[2403, 2459, 0]"]
|
38["Segment<br>[2405, 2461, 0]"]
|
||||||
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
|
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
|
||||||
39["Segment<br>[2465, 2473, 0]"]
|
39["Segment<br>[2467, 2475, 0]"]
|
||||||
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
|
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
|
||||||
49[Solid2d]
|
49[Solid2d]
|
||||||
end
|
end
|
||||||
subgraph path14 [Path]
|
subgraph path14 [Path]
|
||||||
14["Path<br>[2803, 2858, 0]"]
|
14["Path<br>[2805, 2860, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 1 }]
|
||||||
40["Segment<br>[2864, 2893, 0]"]
|
40["Segment<br>[2866, 2895, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 2 }]
|
||||||
41["Segment<br>[2899, 2929, 0]"]
|
41["Segment<br>[2901, 2931, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 3 }]
|
||||||
42["Segment<br>[2935, 2969, 0]"]
|
42["Segment<br>[2937, 2971, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 4 }]
|
||||||
43["Segment<br>[2975, 3031, 0]"]
|
43["Segment<br>[2977, 3033, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 5 }]
|
||||||
44["Segment<br>[3037, 3045, 0]"]
|
44["Segment<br>[3039, 3047, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 6 }]
|
||||||
45[Solid2d]
|
45[Solid2d]
|
||||||
end
|
end
|
||||||
@ -94,17 +94,17 @@ flowchart LR
|
|||||||
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
||||||
2["Plane<br>[945, 965, 0]"]
|
2["Plane<br>[945, 965, 0]"]
|
||||||
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
||||||
3["Plane<br>[1713, 1753, 0]"]
|
3["Plane<br>[1714, 1754, 0]"]
|
||||||
%% [ProgramBodyItem { index: 21 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }, CallKwArg { index: 0 }]
|
%% [ProgramBodyItem { index: 21 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }, CallKwArg { index: 0 }]
|
||||||
4["Plane<br>[1937, 1990, 0]"]
|
4["Plane<br>[1939, 1992, 0]"]
|
||||||
%% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, CallKwArg { index: 0 }]
|
%% [ProgramBodyItem { index: 22 }, VariableDeclarationDeclaration, VariableDeclarationInit, CallKwArg { index: 0 }]
|
||||||
5["Plane<br>[2780, 2797, 0]"]
|
5["Plane<br>[2782, 2799, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
||||||
6["StartSketchOnPlane<br>[945, 965, 0]"]
|
6["StartSketchOnPlane<br>[945, 965, 0]"]
|
||||||
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
||||||
7["StartSketchOnPlane<br>[945, 965, 0]"]
|
7["StartSketchOnPlane<br>[945, 965, 0]"]
|
||||||
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 0 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
||||||
8["StartSketchOnFace<br>[2171, 2221, 0]"]
|
8["StartSketchOnFace<br>[2173, 2223, 0]"]
|
||||||
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
%% [ProgramBodyItem { index: 25 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
||||||
51["Sweep Extrusion<br>[1209, 1240, 0]"]
|
51["Sweep Extrusion<br>[1209, 1240, 0]"]
|
||||||
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit]
|
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit]
|
||||||
@ -114,9 +114,9 @@ flowchart LR
|
|||||||
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit]
|
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit]
|
||||||
54["Sweep Extrusion<br>[1209, 1240, 0]"]
|
54["Sweep Extrusion<br>[1209, 1240, 0]"]
|
||||||
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit]
|
%% [ProgramBodyItem { index: 16 }, VariableDeclarationDeclaration, VariableDeclarationInit, FunctionExpressionBody, FunctionExpressionBodyItem { index: 1 }, VariableDeclarationDeclaration, VariableDeclarationInit]
|
||||||
55["Sweep Extrusion<br>[2545, 2593, 0]"]
|
55["Sweep Extrusion<br>[2547, 2595, 0]"]
|
||||||
%% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
%% [ProgramBodyItem { index: 26 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 0 }]
|
||||||
56["Sweep Extrusion<br>[3051, 3082, 0]"]
|
56["Sweep Extrusion<br>[3053, 3084, 0]"]
|
||||||
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 7 }]
|
%% [ProgramBodyItem { index: 29 }, VariableDeclarationDeclaration, VariableDeclarationInit, PipeBodyItem { index: 7 }]
|
||||||
57[Wall]
|
57[Wall]
|
||||||
%% face_code_ref=Missing NodePath
|
%% face_code_ref=Missing NodePath
|
||||||
|
@ -1997,7 +1997,7 @@ description: Result of parsing spinning-highrise-tower.kcl
|
|||||||
"id": {
|
"id": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "goundSize",
|
"name": "groundSize",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -2138,7 +2138,7 @@ description: Result of parsing spinning-highrise-tower.kcl
|
|||||||
"name": {
|
"name": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "goundSize",
|
"name": "groundSize",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
|
@ -3936,19 +3936,6 @@ description: Variables in memory after executing spinning-highrise-tower.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"goundSize": {
|
|
||||||
"type": "Number",
|
|
||||||
"value": 50.0,
|
|
||||||
"ty": {
|
|
||||||
"type": "Default",
|
|
||||||
"len": {
|
|
||||||
"type": "M"
|
|
||||||
},
|
|
||||||
"angle": {
|
|
||||||
"type": "Degrees"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"groundBody": {
|
"groundBody": {
|
||||||
"type": "Solid",
|
"type": "Solid",
|
||||||
"value": {
|
"value": {
|
||||||
@ -4148,6 +4135,19 @@ description: Variables in memory after executing spinning-highrise-tower.kcl
|
|||||||
"sectional": false
|
"sectional": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"groundSize": {
|
||||||
|
"type": "Number",
|
||||||
|
"value": 50.0,
|
||||||
|
"ty": {
|
||||||
|
"type": "Default",
|
||||||
|
"len": {
|
||||||
|
"type": "M"
|
||||||
|
},
|
||||||
|
"angle": {
|
||||||
|
"type": "Degrees"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"handrailHeight": {
|
"handrailHeight": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"value": 1.2,
|
"value": 1.2,
|
||||||
|
184
rust/kcl-lib/tests/nested_main_kcl/artifact_commands.snap
Normal file
184
rust/kcl-lib/tests/nested_main_kcl/artifact_commands.snap
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Artifact commands nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "edge_lines_visible",
|
||||||
|
"hidden": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "make_plane",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"x_axis": {
|
||||||
|
"x": 1.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"y_axis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"size": 60.0,
|
||||||
|
"clobber": false,
|
||||||
|
"hide": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "close_path",
|
||||||
|
"path_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "enable_sketch_mode",
|
||||||
|
"entity_id": "[uuid]",
|
||||||
|
"ortho": false,
|
||||||
|
"animated": false,
|
||||||
|
"adjust_camera": false,
|
||||||
|
"planar_normal": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "arc",
|
||||||
|
"center": {
|
||||||
|
"x": 15.0,
|
||||||
|
"y": 0.0
|
||||||
|
},
|
||||||
|
"radius": 5.0,
|
||||||
|
"start": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 0.0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 360.0
|
||||||
|
},
|
||||||
|
"relative": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "move_path_pen",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"to": {
|
||||||
|
"x": 20.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "sketch_mode_disable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "start_path"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_bring_to_front",
|
||||||
|
"object_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "revolve",
|
||||||
|
"target": "[uuid]",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"axis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"axis_is_2d": true,
|
||||||
|
"angle": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 360.0
|
||||||
|
},
|
||||||
|
"tolerance": 0.0000001,
|
||||||
|
"opposite": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_adjacency_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_extrusion_face_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Artifact graph flowchart nested_main_kcl.kcl
|
||||||
|
extension: md
|
||||||
|
snapshot_kind: binary
|
||||||
|
---
|
@ -0,0 +1,23 @@
|
|||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph path2 [Path]
|
||||||
|
2["Path<br>[43, 81, 1]"]
|
||||||
|
3["Segment<br>[43, 81, 1]"]
|
||||||
|
4[Solid2d]
|
||||||
|
end
|
||||||
|
1["Plane<br>[18, 35, 1]"]
|
||||||
|
5["Sweep Revolve<br>[89, 142, 1]"]
|
||||||
|
6[Wall]
|
||||||
|
%% face_code_ref=Missing NodePath
|
||||||
|
7["SweepEdge Adjacent"]
|
||||||
|
1 --- 2
|
||||||
|
2 --- 3
|
||||||
|
2 --- 4
|
||||||
|
2 ---- 5
|
||||||
|
5 <--x 3
|
||||||
|
3 --- 6
|
||||||
|
3 --- 7
|
||||||
|
5 --- 6
|
||||||
|
5 --- 7
|
||||||
|
6 --- 7
|
||||||
|
```
|
73
rust/kcl-lib/tests/nested_main_kcl/ast.snap
Normal file
73
rust/kcl-lib/tests/nested_main_kcl/ast.snap
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of parsing nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"Ok": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"path": {
|
||||||
|
"type": "Kcl",
|
||||||
|
"filename": "nested/foo/bar/main.kcl"
|
||||||
|
},
|
||||||
|
"selector": {
|
||||||
|
"type": "None",
|
||||||
|
"alias": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "bar",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "ImportStatement",
|
||||||
|
"type": "ImportStatement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"expression": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "bar",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "NonCodeNode",
|
||||||
|
"value": {
|
||||||
|
"type": "newLine"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startNodes": []
|
||||||
|
},
|
||||||
|
"start": 0
|
||||||
|
}
|
||||||
|
}
|
3
rust/kcl-lib/tests/nested_main_kcl/input.kcl
Normal file
3
rust/kcl-lib/tests/nested_main_kcl/input.kcl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import "nested/foo/bar/main.kcl" as bar
|
||||||
|
|
||||||
|
bar
|
@ -0,0 +1,7 @@
|
|||||||
|
// A donut shape.
|
||||||
|
startSketchOn(XY)
|
||||||
|
|> circle( center = [15, 0], radius = 5 )
|
||||||
|
|> revolve(
|
||||||
|
angle = 360,
|
||||||
|
axis = Y,
|
||||||
|
)
|
18
rust/kcl-lib/tests/nested_main_kcl/ops.snap
Normal file
18
rust/kcl-lib/tests/nested_main_kcl/ops.snap
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Operations executed nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "GroupBegin",
|
||||||
|
"group": {
|
||||||
|
"type": "ModuleInstance",
|
||||||
|
"name": "main.kcl",
|
||||||
|
"moduleId": 0
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GroupEnd"
|
||||||
|
}
|
||||||
|
]
|
10
rust/kcl-lib/tests/nested_main_kcl/program_memory.snap
Normal file
10
rust/kcl-lib/tests/nested_main_kcl/program_memory.snap
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Variables in memory after executing nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"bar": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
}
|
BIN
rust/kcl-lib/tests/nested_main_kcl/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/nested_main_kcl/rendered_model.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
7
rust/kcl-lib/tests/nested_main_kcl/unparsed.snap
Normal file
7
rust/kcl-lib/tests/nested_main_kcl/unparsed.snap
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
import "nested/foo/bar/main.kcl" as bar
|
||||||
|
|
||||||
|
bar
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing tests/nested_main_kcl/nested/foo/bar/main.kcl
|
||||||
|
---
|
||||||
|
// A donut shape.
|
||||||
|
startSketchOn(XY)
|
||||||
|
|> circle(center = [15, 0], radius = 5)
|
||||||
|
|> revolve(angle = 360, axis = Y)
|
@ -0,0 +1,184 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Artifact commands nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "edge_lines_visible",
|
||||||
|
"hidden": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "make_plane",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"x_axis": {
|
||||||
|
"x": 1.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"y_axis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"size": 60.0,
|
||||||
|
"clobber": false,
|
||||||
|
"hide": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "close_path",
|
||||||
|
"path_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "enable_sketch_mode",
|
||||||
|
"entity_id": "[uuid]",
|
||||||
|
"ortho": false,
|
||||||
|
"animated": false,
|
||||||
|
"adjust_camera": false,
|
||||||
|
"planar_normal": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "arc",
|
||||||
|
"center": {
|
||||||
|
"x": 15.0,
|
||||||
|
"y": 0.0
|
||||||
|
},
|
||||||
|
"radius": 5.0,
|
||||||
|
"start": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 0.0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 360.0
|
||||||
|
},
|
||||||
|
"relative": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "move_path_pen",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"to": {
|
||||||
|
"x": 20.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "sketch_mode_disable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "start_path"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_bring_to_front",
|
||||||
|
"object_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "revolve",
|
||||||
|
"target": "[uuid]",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"axis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"axis_is_2d": true,
|
||||||
|
"angle": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 360.0
|
||||||
|
},
|
||||||
|
"tolerance": 0.0000001,
|
||||||
|
"opposite": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_adjacency_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_extrusion_face_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Artifact graph flowchart nested_main_kcl.kcl
|
||||||
|
extension: md
|
||||||
|
snapshot_kind: binary
|
||||||
|
---
|
@ -0,0 +1,23 @@
|
|||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph path2 [Path]
|
||||||
|
2["Path<br>[43, 81, 1]"]
|
||||||
|
3["Segment<br>[43, 81, 1]"]
|
||||||
|
4[Solid2d]
|
||||||
|
end
|
||||||
|
1["Plane<br>[18, 35, 1]"]
|
||||||
|
5["Sweep Revolve<br>[89, 142, 1]"]
|
||||||
|
6[Wall]
|
||||||
|
%% face_code_ref=Missing NodePath
|
||||||
|
7["SweepEdge Adjacent"]
|
||||||
|
1 --- 2
|
||||||
|
2 --- 3
|
||||||
|
2 --- 4
|
||||||
|
2 ---- 5
|
||||||
|
5 <--x 3
|
||||||
|
3 --- 6
|
||||||
|
3 --- 7
|
||||||
|
5 --- 6
|
||||||
|
5 --- 7
|
||||||
|
6 --- 7
|
||||||
|
```
|
67
rust/kcl-lib/tests/nested_windows_main_kcl/ast.snap
Normal file
67
rust/kcl-lib/tests/nested_windows_main_kcl/ast.snap
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of parsing nested_windows_main_kcl.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"Ok": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"path": {
|
||||||
|
"type": "Kcl",
|
||||||
|
"filename": "nested/foo/bar/main.kcl"
|
||||||
|
},
|
||||||
|
"selector": {
|
||||||
|
"type": "None",
|
||||||
|
"alias": null
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "ImportStatement",
|
||||||
|
"type": "ImportStatement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"expression": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "bar",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "NonCodeNode",
|
||||||
|
"value": {
|
||||||
|
"type": "newLine"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startNodes": []
|
||||||
|
},
|
||||||
|
"start": 0
|
||||||
|
}
|
||||||
|
}
|
3
rust/kcl-lib/tests/nested_windows_main_kcl/input.kcl
Normal file
3
rust/kcl-lib/tests/nested_windows_main_kcl/input.kcl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import "nested\foo\bar\main.kcl"
|
||||||
|
|
||||||
|
bar
|
@ -0,0 +1,7 @@
|
|||||||
|
// A donut shape.
|
||||||
|
startSketchOn(XY)
|
||||||
|
|> circle( center = [15, 0], radius = 5 )
|
||||||
|
|> revolve(
|
||||||
|
angle = 360,
|
||||||
|
axis = Y,
|
||||||
|
)
|
18
rust/kcl-lib/tests/nested_windows_main_kcl/ops.snap
Normal file
18
rust/kcl-lib/tests/nested_windows_main_kcl/ops.snap
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Operations executed nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "GroupBegin",
|
||||||
|
"group": {
|
||||||
|
"type": "ModuleInstance",
|
||||||
|
"name": "main.kcl",
|
||||||
|
"moduleId": 0
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GroupEnd"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Variables in memory after executing nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"bar": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
}
|
BIN
rust/kcl-lib/tests/nested_windows_main_kcl/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/nested_windows_main_kcl/rendered_model.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
7
rust/kcl-lib/tests/nested_windows_main_kcl/unparsed.snap
Normal file
7
rust/kcl-lib/tests/nested_windows_main_kcl/unparsed.snap
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing nested_windows_main_kcl.kcl
|
||||||
|
---
|
||||||
|
import "nested/foo/bar/main.kcl"
|
||||||
|
|
||||||
|
bar
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing tests/nested_windows_main_kcl/nested/foo/bar/main.kcl
|
||||||
|
---
|
||||||
|
// A donut shape.
|
||||||
|
startSketchOn(XY)
|
||||||
|
|> circle(center = [15, 0], radius = 5)
|
||||||
|
|> revolve(angle = 360, axis = Y)
|
@ -86,11 +86,11 @@ flowchart LR
|
|||||||
8 --- 18
|
8 --- 18
|
||||||
8 ---- 20
|
8 ---- 20
|
||||||
8 --- 21
|
8 --- 21
|
||||||
12 --- 22
|
12 <--x 22
|
||||||
12 <--x 23
|
12 --- 23
|
||||||
12 <--x 24
|
12 <--x 24
|
||||||
16 --- 25
|
16 <--x 25
|
||||||
16 <--x 26
|
16 --- 26
|
||||||
16 <--x 27
|
16 <--x 27
|
||||||
19 --- 22
|
19 --- 22
|
||||||
19 --- 23
|
19 --- 23
|
||||||
|
@ -94,7 +94,7 @@ function CommandBarHeader({ children }: React.PropsWithChildren<object>) {
|
|||||||
{selectedCommand.displayName || selectedCommand.name}
|
{selectedCommand.displayName || selectedCommand.name}
|
||||||
</span>
|
</span>
|
||||||
{selectedCommand.status === 'experimental' ? (
|
{selectedCommand.status === 'experimental' ? (
|
||||||
<span className="text-ml-black text-xs bg-ml-green rounded-full ml-2 px-2 py-1">
|
<span className="uppercase text-xs rounded-full ml-2 px-2 py-1 border border-ml-green dark:text-ml-green">
|
||||||
experimental
|
experimental
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
|
@ -86,6 +86,8 @@ function CommandBarTextareaInput({
|
|||||||
formRef.current?.dispatchEvent(
|
formRef.current?.dispatchEvent(
|
||||||
new Event('submit', { bubbles: true })
|
new Event('submit', { bubbles: true })
|
||||||
)
|
)
|
||||||
|
} else if (event.key === 'Escape') {
|
||||||
|
commandBarActor.send({ type: 'Close' })
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
autoFocus
|
autoFocus
|
||||||
@ -109,6 +111,8 @@ const useTextareaAutoGrow = (ref: RefObject<HTMLTextAreaElement>) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ref.current === null) return
|
if (ref.current === null) return
|
||||||
|
// Run initially to set all this stuff at the start
|
||||||
|
listener()
|
||||||
ref.current.addEventListener('input', listener)
|
ref.current.addEventListener('input', listener)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -654,7 +654,12 @@ export const useFileTreeOperations = () => {
|
|||||||
|
|
||||||
send({
|
send({
|
||||||
type: 'Create file',
|
type: 'Create file',
|
||||||
data: { name: args.name, makeDir: true, shouldSetToRename: false },
|
data: {
|
||||||
|
name: args.name,
|
||||||
|
makeDir: true,
|
||||||
|
silent: true,
|
||||||
|
shouldSetToRename: false,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ import {
|
|||||||
MAKE_TOAST_MESSAGES,
|
MAKE_TOAST_MESSAGES,
|
||||||
EXECUTION_TYPE_MOCK,
|
EXECUTION_TYPE_MOCK,
|
||||||
FILE_EXT,
|
FILE_EXT,
|
||||||
|
PROJECT_ENTRYPOINT,
|
||||||
} from '@src/lib/constants'
|
} from '@src/lib/constants'
|
||||||
import { exportMake } from '@src/lib/exportMake'
|
import { exportMake } from '@src/lib/exportMake'
|
||||||
import { exportSave } from '@src/lib/exportSave'
|
import { exportSave } from '@src/lib/exportSave'
|
||||||
@ -1759,7 +1760,8 @@ export const ModelingMachineProvider = ({
|
|||||||
)
|
)
|
||||||
let basePath = ''
|
let basePath = ''
|
||||||
if (isDesktop() && context?.project?.children) {
|
if (isDesktop() && context?.project?.children) {
|
||||||
basePath = context?.selectedDirectory?.path
|
// Use the entire project directory as the basePath for prompt to edit, do not use relative subdir paths
|
||||||
|
basePath = context?.project?.path
|
||||||
const filePromises: Promise<FileMeta | null>[] = []
|
const filePromises: Promise<FileMeta | null>[] = []
|
||||||
let uploadSize = 0
|
let uploadSize = 0
|
||||||
const recursivelyPushFilePromises = (files: FileEntry[]) => {
|
const recursivelyPushFilePromises = (files: FileEntry[]) => {
|
||||||
@ -1826,6 +1828,13 @@ export const ModelingMachineProvider = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let filePath = file?.path
|
||||||
|
// When prompt to edit finishes, try to route to the file they were in otherwise go to main.kcl
|
||||||
|
if (filePath) {
|
||||||
|
filePath = window.electron.path.relative(basePath, filePath)
|
||||||
|
} else {
|
||||||
|
filePath = PROJECT_ENTRYPOINT
|
||||||
|
}
|
||||||
return await promptToEditFlow({
|
return await promptToEditFlow({
|
||||||
projectFiles,
|
projectFiles,
|
||||||
prompt: input.prompt,
|
prompt: input.prompt,
|
||||||
@ -1833,6 +1842,7 @@ export const ModelingMachineProvider = ({
|
|||||||
token,
|
token,
|
||||||
artifactGraph: kclManager.artifactGraph,
|
artifactGraph: kclManager.artifactGraph,
|
||||||
projectName: context.project.name,
|
projectName: context.project.name,
|
||||||
|
filePath,
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
@ -35,6 +35,7 @@ import {
|
|||||||
} from '@src/machines/systemIO/utils'
|
} from '@src/machines/systemIO/utils'
|
||||||
import {
|
import {
|
||||||
useProjectDirectoryPath,
|
useProjectDirectoryPath,
|
||||||
|
useRequestedFileName,
|
||||||
useRequestedProjectName,
|
useRequestedProjectName,
|
||||||
} from '@src/machines/systemIO/hooks'
|
} from '@src/machines/systemIO/hooks'
|
||||||
import { commandBarActor } from '@src/lib/singletons'
|
import { commandBarActor } from '@src/lib/singletons'
|
||||||
@ -498,7 +499,14 @@ export function ToastPromptToEditCadSuccess({
|
|||||||
token?: string
|
token?: string
|
||||||
}) {
|
}) {
|
||||||
const modelId = data.id
|
const modelId = data.id
|
||||||
const requestedProjectName = useRequestedProjectName()
|
const possibleRequestedProjectName = useRequestedProjectName()
|
||||||
|
const possibleRequestedFileName = useRequestedFileName()
|
||||||
|
|
||||||
|
// Depends on navigation method
|
||||||
|
const requestedProjectName = {
|
||||||
|
name:
|
||||||
|
possibleRequestedProjectName.name || possibleRequestedFileName.project,
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-4 min-w-80">
|
<div className="flex gap-4 min-w-80">
|
||||||
@ -548,6 +556,7 @@ export function ToastPromptToEditCadSuccess({
|
|||||||
await writeOverFilesAndExecute({
|
await writeOverFilesAndExecute({
|
||||||
requestedFiles: requestedFiles,
|
requestedFiles: requestedFiles,
|
||||||
projectName: requestedProjectName.name,
|
projectName: requestedProjectName.name,
|
||||||
|
filePath: possibleRequestedFileName.file,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
codeManager.updateCodeEditor(oldCode)
|
codeManager.updateCodeEditor(oldCode)
|
||||||
@ -588,18 +597,32 @@ export function ToastPromptToEditCadSuccess({
|
|||||||
export const writeOverFilesAndExecute = async ({
|
export const writeOverFilesAndExecute = async ({
|
||||||
requestedFiles,
|
requestedFiles,
|
||||||
projectName,
|
projectName,
|
||||||
|
filePath,
|
||||||
}: {
|
}: {
|
||||||
requestedFiles: RequestedKCLFile[]
|
requestedFiles: RequestedKCLFile[]
|
||||||
projectName: string
|
projectName: string
|
||||||
|
filePath?: string | undefined
|
||||||
}) => {
|
}) => {
|
||||||
systemIOActor.send({
|
if (filePath) {
|
||||||
type: SystemIOMachineEvents.bulkCreateKCLFilesAndNavigateToProject,
|
systemIOActor.send({
|
||||||
data: {
|
type: SystemIOMachineEvents.bulkCreateKCLFilesAndNavigateToFile,
|
||||||
files: requestedFiles,
|
data: {
|
||||||
requestedProjectName: projectName,
|
files: requestedFiles,
|
||||||
override: true,
|
requestedProjectName: projectName,
|
||||||
},
|
requestedFileNameWithExtension: filePath,
|
||||||
})
|
override: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
systemIOActor.send({
|
||||||
|
type: SystemIOMachineEvents.bulkCreateKCLFilesAndNavigateToProject,
|
||||||
|
data: {
|
||||||
|
files: requestedFiles,
|
||||||
|
requestedProjectName: projectName,
|
||||||
|
override: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// to await the result of the send event above
|
// to await the result of the send event above
|
||||||
await waitForIdleState({ systemIOActor })
|
await waitForIdleState({ systemIOActor })
|
||||||
|
@ -14,8 +14,13 @@ import { IS_ML_EXPERIMENTAL, PROJECT_ENTRYPOINT } from '@src/lib/constants'
|
|||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { reportRejection } from '@src/lib/trap'
|
import { reportRejection } from '@src/lib/trap'
|
||||||
import { relevantFileExtensions } from '@src/lang/wasmUtils'
|
import { relevantFileExtensions } from '@src/lang/wasmUtils'
|
||||||
import { getStringAfterLastSeparator, webSafePathSplit } from '@src/lib/paths'
|
import {
|
||||||
|
getStringAfterLastSeparator,
|
||||||
|
joinOSPaths,
|
||||||
|
webSafePathSplit,
|
||||||
|
} from '@src/lib/paths'
|
||||||
import { FILE_EXT } from '@src/lib/constants'
|
import { FILE_EXT } from '@src/lib/constants'
|
||||||
|
import { getAllSubDirectoriesAtProjectRoot } from '@src/machines/systemIO/snapshotContext'
|
||||||
|
|
||||||
function onSubmitKCLSampleCreation({
|
function onSubmitKCLSampleCreation({
|
||||||
sample,
|
sample,
|
||||||
@ -87,6 +92,26 @@ function onSubmitKCLSampleCreation({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
/**
|
||||||
|
* When adding assemblies to an existing project create the assembly into a unique sub directory
|
||||||
|
*/
|
||||||
|
if (!isProjectNew) {
|
||||||
|
requestedFiles.forEach((requestedFile) => {
|
||||||
|
const subDirectoryName = projectPathPart
|
||||||
|
const firstLevelDirectories = getAllSubDirectoriesAtProjectRoot({
|
||||||
|
projectFolderName: requestedFile.requestedProjectName,
|
||||||
|
})
|
||||||
|
const uniqueSubDirectoryName = getUniqueProjectName(
|
||||||
|
subDirectoryName,
|
||||||
|
firstLevelDirectories
|
||||||
|
)
|
||||||
|
requestedFile.requestedProjectName = joinOSPaths(
|
||||||
|
requestedFile.requestedProjectName,
|
||||||
|
uniqueSubDirectoryName
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bulk create the assembly and navigate to the project
|
* Bulk create the assembly and navigate to the project
|
||||||
*/
|
*/
|
||||||
@ -278,10 +303,9 @@ export function createApplicationCommands({
|
|||||||
return value
|
return value
|
||||||
},
|
},
|
||||||
options: ({ argumentsToSubmit }) => {
|
options: ({ argumentsToSubmit }) => {
|
||||||
const samples =
|
const samples = isDesktop()
|
||||||
isDesktop() && argumentsToSubmit.method !== 'existingProject'
|
? everyKclSample
|
||||||
? everyKclSample
|
: kclSamplesManifestWithNoMultipleFiles
|
||||||
: kclSamplesManifestWithNoMultipleFiles
|
|
||||||
return samples.map((sample) => {
|
return samples.map((sample) => {
|
||||||
return {
|
return {
|
||||||
value: sample.pathFromProjectDirectoryToFirstFile,
|
value: sample.pathFromProjectDirectoryToFirstFile,
|
||||||
@ -296,17 +320,10 @@ export function createApplicationCommands({
|
|||||||
skip: true,
|
skip: true,
|
||||||
options: ({ argumentsToSubmit }, _) => {
|
options: ({ argumentsToSubmit }, _) => {
|
||||||
if (isDesktop() && typeof argumentsToSubmit.sample === 'string') {
|
if (isDesktop() && typeof argumentsToSubmit.sample === 'string') {
|
||||||
const kclSample = findKclSample(argumentsToSubmit.sample)
|
return [
|
||||||
if (kclSample && kclSample.files.length > 1) {
|
{ name: 'New project', value: 'newProject', isCurrent: true },
|
||||||
return [
|
{ name: 'Existing project', value: 'existingProject' },
|
||||||
{ name: 'New project', value: 'newProject', isCurrent: true },
|
]
|
||||||
]
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
{ name: 'New project', value: 'newProject', isCurrent: true },
|
|
||||||
{ name: 'Existing project', value: 'existingProject' },
|
|
||||||
]
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return [{ name: 'Overwrite', value: 'existingProject' }]
|
return [{ name: 'Overwrite', value: 'existingProject' }]
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import type { Selections } from '@src/lib/selections'
|
|||||||
import { codeManager, kclManager } from '@src/lib/singletons'
|
import { codeManager, kclManager } from '@src/lib/singletons'
|
||||||
import { err } from '@src/lib/trap'
|
import { err } from '@src/lib/trap'
|
||||||
import type { SketchTool, modelingMachine } from '@src/machines/modelingMachine'
|
import type { SketchTool, modelingMachine } from '@src/machines/modelingMachine'
|
||||||
|
import { isDesktop } from '../isDesktop'
|
||||||
|
|
||||||
type OutputFormat = Models['OutputFormat3d_type']
|
type OutputFormat = Models['OutputFormat3d_type']
|
||||||
type OutputTypeKey = OutputFormat['type']
|
type OutputTypeKey = OutputFormat['type']
|
||||||
@ -159,6 +160,10 @@ export type ModelingCommandSchema = {
|
|||||||
nodeToEdit?: PathToNode
|
nodeToEdit?: PathToNode
|
||||||
color: string
|
color: string
|
||||||
}
|
}
|
||||||
|
Insert: {
|
||||||
|
path: string
|
||||||
|
localName: string
|
||||||
|
}
|
||||||
Translate: {
|
Translate: {
|
||||||
nodeToEdit?: PathToNode
|
nodeToEdit?: PathToNode
|
||||||
selection: Selections
|
selection: Selections
|
||||||
@ -1011,6 +1016,74 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
|||||||
// Add more fields
|
// Add more fields
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Insert: {
|
||||||
|
description: 'Insert from a file in the current project directory',
|
||||||
|
icon: 'import',
|
||||||
|
hide: 'web',
|
||||||
|
needsReview: true,
|
||||||
|
args: {
|
||||||
|
path: {
|
||||||
|
inputType: 'options',
|
||||||
|
required: true,
|
||||||
|
// options
|
||||||
|
validation: async ({ data }) => {
|
||||||
|
const importExists = kclManager.ast.body.find(
|
||||||
|
(n) =>
|
||||||
|
n.type === 'ImportStatement' &&
|
||||||
|
((n.path.type === 'Kcl' && n.path.filename === data.path) ||
|
||||||
|
(n.path.type === 'Foreign' && n.path.path === data.path))
|
||||||
|
)
|
||||||
|
if (importExists) {
|
||||||
|
return 'This file is already imported, use the Clone command instead.'
|
||||||
|
// TODO: see if we can transition to the clone command, see #6515
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
localName: {
|
||||||
|
inputType: 'string',
|
||||||
|
required: true,
|
||||||
|
defaultValue: (context: CommandBarContext) => {
|
||||||
|
if (!context.argumentsToSubmit['path']) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = context.argumentsToSubmit['path'] as string
|
||||||
|
return getPathFilenameInVariableCase(path)
|
||||||
|
},
|
||||||
|
validation: async ({ data }) => {
|
||||||
|
const variableExists = kclManager.variables[data.localName]
|
||||||
|
if (variableExists) {
|
||||||
|
return 'This variable name is already in use.'
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// onSubmit: (data) => {
|
||||||
|
// if (!data) {
|
||||||
|
// return new Error('No input provided')
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const ast = kclManager.ast
|
||||||
|
// const { path, localName } = data
|
||||||
|
// const { modifiedAst, pathToNode } = addModuleImport({
|
||||||
|
// ast,
|
||||||
|
// path,
|
||||||
|
// localName,
|
||||||
|
// })
|
||||||
|
// updateModelingState(
|
||||||
|
// modifiedAst,
|
||||||
|
// EXECUTION_TYPE_REAL,
|
||||||
|
// { kclManager, editorManager, codeManager },
|
||||||
|
// {
|
||||||
|
// focusPath: [pathToNode],
|
||||||
|
// }
|
||||||
|
// ).catch(reportRejection)
|
||||||
|
// },
|
||||||
|
},
|
||||||
Translate: {
|
Translate: {
|
||||||
description: 'Set translation on solid or sketch.',
|
description: 'Set translation on solid or sketch.',
|
||||||
icon: 'move',
|
icon: 'move',
|
||||||
|
@ -89,76 +89,76 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: 'Insert',
|
// name: 'Insert',
|
||||||
description: 'Insert from a file in the current project directory',
|
// description: 'Insert from a file in the current project directory',
|
||||||
icon: 'import',
|
// icon: 'import',
|
||||||
groupId: 'code',
|
// groupId: 'code',
|
||||||
hide: 'web',
|
// hide: 'web',
|
||||||
needsReview: true,
|
// needsReview: true,
|
||||||
args: {
|
// args: {
|
||||||
path: {
|
// path: {
|
||||||
inputType: 'options',
|
// inputType: 'options',
|
||||||
required: true,
|
// required: true,
|
||||||
options: commandProps.specialPropsForInsertCommand.providedOptions,
|
// options: commandProps.specialPropsForInsertCommand.providedOptions,
|
||||||
validation: async ({ data }) => {
|
// validation: async ({ data }) => {
|
||||||
const importExists = kclManager.ast.body.find(
|
// const importExists = kclManager.ast.body.find(
|
||||||
(n) =>
|
// (n) =>
|
||||||
n.type === 'ImportStatement' &&
|
// n.type === 'ImportStatement' &&
|
||||||
((n.path.type === 'Kcl' && n.path.filename === data.path) ||
|
// ((n.path.type === 'Kcl' && n.path.filename === data.path) ||
|
||||||
(n.path.type === 'Foreign' && n.path.path === data.path))
|
// (n.path.type === 'Foreign' && n.path.path === data.path))
|
||||||
)
|
// )
|
||||||
if (importExists) {
|
// if (importExists) {
|
||||||
return 'This file is already imported, use the Clone command instead.'
|
// return 'This file is already imported, use the Clone command instead.'
|
||||||
// TODO: see if we can transition to the clone command, see #6515
|
// // TODO: see if we can transition to the clone command, see #6515
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true
|
// return true
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
localName: {
|
// localName: {
|
||||||
inputType: 'string',
|
// inputType: 'string',
|
||||||
required: true,
|
// required: true,
|
||||||
defaultValue: (context: CommandBarContext) => {
|
// defaultValue: (context: CommandBarContext) => {
|
||||||
if (!context.argumentsToSubmit['path']) {
|
// if (!context.argumentsToSubmit['path']) {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
const path = context.argumentsToSubmit['path'] as string
|
// const path = context.argumentsToSubmit['path'] as string
|
||||||
return getPathFilenameInVariableCase(path)
|
// return getPathFilenameInVariableCase(path)
|
||||||
},
|
// },
|
||||||
validation: async ({ data }) => {
|
// validation: async ({ data }) => {
|
||||||
const variableExists = kclManager.variables[data.localName]
|
// const variableExists = kclManager.variables[data.localName]
|
||||||
if (variableExists) {
|
// if (variableExists) {
|
||||||
return 'This variable name is already in use.'
|
// return 'This variable name is already in use.'
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true
|
// return true
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
onSubmit: (data) => {
|
// onSubmit: (data) => {
|
||||||
if (!data) {
|
// if (!data) {
|
||||||
return new Error('No input provided')
|
// return new Error('No input provided')
|
||||||
}
|
// }
|
||||||
|
|
||||||
const ast = kclManager.ast
|
// const ast = kclManager.ast
|
||||||
const { path, localName } = data
|
// const { path, localName } = data
|
||||||
const { modifiedAst, pathToNode } = addModuleImport({
|
// const { modifiedAst, pathToNode } = addModuleImport({
|
||||||
ast,
|
// ast,
|
||||||
path,
|
// path,
|
||||||
localName,
|
// localName,
|
||||||
})
|
// })
|
||||||
updateModelingState(
|
// updateModelingState(
|
||||||
modifiedAst,
|
// modifiedAst,
|
||||||
EXECUTION_TYPE_REAL,
|
// EXECUTION_TYPE_REAL,
|
||||||
{ kclManager, editorManager, codeManager },
|
// { kclManager, editorManager, codeManager },
|
||||||
{
|
// {
|
||||||
focusPath: [pathToNode],
|
// focusPath: [pathToNode],
|
||||||
}
|
// }
|
||||||
).catch(reportRejection)
|
// ).catch(reportRejection)
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: 'format-code',
|
name: 'format-code',
|
||||||
displayName: 'Format Code',
|
displayName: 'Format Code',
|
||||||
|
@ -415,6 +415,7 @@ export async function promptToEditFlow({
|
|||||||
token,
|
token,
|
||||||
artifactGraph,
|
artifactGraph,
|
||||||
projectName,
|
projectName,
|
||||||
|
filePath,
|
||||||
}: {
|
}: {
|
||||||
prompt: string
|
prompt: string
|
||||||
selections: Selections
|
selections: Selections
|
||||||
@ -422,6 +423,7 @@ export async function promptToEditFlow({
|
|||||||
token?: string
|
token?: string
|
||||||
artifactGraph: ArtifactGraph
|
artifactGraph: ArtifactGraph
|
||||||
projectName: string
|
projectName: string
|
||||||
|
filePath: string | undefined
|
||||||
}) {
|
}) {
|
||||||
const result = await doPromptEdit({
|
const result = await doPromptEdit({
|
||||||
prompt,
|
prompt,
|
||||||
@ -498,6 +500,7 @@ export async function promptToEditFlow({
|
|||||||
await writeOverFilesAndExecute({
|
await writeOverFilesAndExecute({
|
||||||
requestedFiles,
|
requestedFiles,
|
||||||
projectName,
|
projectName,
|
||||||
|
filePath,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
const newCode = result.outputs['main.kcl']
|
const newCode = result.outputs['main.kcl']
|
||||||
|
@ -427,6 +427,21 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
|||||||
{
|
{
|
||||||
id: 'ai',
|
id: 'ai',
|
||||||
array: [
|
array: [
|
||||||
|
{
|
||||||
|
id: 'prompt-to-edit',
|
||||||
|
onClick: () =>
|
||||||
|
commandBarActor.send({
|
||||||
|
type: 'Find and select command',
|
||||||
|
data: { name: 'Prompt-to-edit', groupId: 'modeling' },
|
||||||
|
}),
|
||||||
|
icon: 'sparkles',
|
||||||
|
iconColor: '#29FFA4',
|
||||||
|
alwaysDark: true,
|
||||||
|
status: IS_ML_EXPERIMENTAL ? 'experimental' : 'available',
|
||||||
|
title: 'Modify with Zoo Text-to-CAD',
|
||||||
|
description: 'Edit geometry with AI / ML.',
|
||||||
|
links: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'text-to-cad',
|
id: 'text-to-cad',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@ -457,21 +472,6 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'prompt-to-edit',
|
|
||||||
onClick: () =>
|
|
||||||
commandBarActor.send({
|
|
||||||
type: 'Find and select command',
|
|
||||||
data: { name: 'Prompt-to-edit', groupId: 'modeling' },
|
|
||||||
}),
|
|
||||||
icon: 'sparkles',
|
|
||||||
iconColor: '#29FFA4',
|
|
||||||
alwaysDark: true,
|
|
||||||
status: IS_ML_EXPERIMENTAL ? 'experimental' : 'available',
|
|
||||||
title: 'Modify with Zoo Text-to-CAD',
|
|
||||||
description: 'Edit geometry with AI / ML.',
|
|
||||||
links: [],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -47,6 +47,7 @@ import { updateModelingState } from '@src/lang/modelingWorkflows'
|
|||||||
import {
|
import {
|
||||||
addClone,
|
addClone,
|
||||||
addHelix,
|
addHelix,
|
||||||
|
addModuleImport,
|
||||||
addOffsetPlane,
|
addOffsetPlane,
|
||||||
addShell,
|
addShell,
|
||||||
insertNamedConstant,
|
insertNamedConstant,
|
||||||
@ -381,6 +382,7 @@ export type ModelingMachineEvent =
|
|||||||
data: ModelingCommandSchema['Delete selection']
|
data: ModelingCommandSchema['Delete selection']
|
||||||
}
|
}
|
||||||
| { type: 'Appearance'; data: ModelingCommandSchema['Appearance'] }
|
| { type: 'Appearance'; data: ModelingCommandSchema['Appearance'] }
|
||||||
|
| { type: 'Insert'; data: ModelingCommandSchema['Insert'] }
|
||||||
| { type: 'Translate'; data: ModelingCommandSchema['Translate'] }
|
| { type: 'Translate'; data: ModelingCommandSchema['Translate'] }
|
||||||
| { type: 'Rotate'; data: ModelingCommandSchema['Rotate'] }
|
| { type: 'Rotate'; data: ModelingCommandSchema['Rotate'] }
|
||||||
| { type: 'Clone'; data: ModelingCommandSchema['Clone'] }
|
| { type: 'Clone'; data: ModelingCommandSchema['Clone'] }
|
||||||
@ -2736,6 +2738,34 @@ export const modelingMachine = setup({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
insertAstMod: fromPromise(
|
||||||
|
async ({
|
||||||
|
input,
|
||||||
|
}: {
|
||||||
|
input: ModelingCommandSchema['Insert'] | undefined
|
||||||
|
}) => {
|
||||||
|
if (!input) {
|
||||||
|
return Promise.reject(new Error(NO_INPUT_PROVIDED_MESSAGE))
|
||||||
|
}
|
||||||
|
|
||||||
|
const ast = kclManager.ast
|
||||||
|
const { path, localName } = input
|
||||||
|
const { modifiedAst, pathToNode } = addModuleImport({
|
||||||
|
ast,
|
||||||
|
path,
|
||||||
|
localName,
|
||||||
|
})
|
||||||
|
|
||||||
|
await updateModelingState(
|
||||||
|
modifiedAst,
|
||||||
|
EXECUTION_TYPE_REAL,
|
||||||
|
{ kclManager, editorManager, codeManager },
|
||||||
|
{
|
||||||
|
focusPath: [pathToNode],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
translateAstMod: fromPromise(
|
translateAstMod: fromPromise(
|
||||||
async ({
|
async ({
|
||||||
input,
|
input,
|
||||||
@ -3269,6 +3299,12 @@ export const modelingMachine = setup({
|
|||||||
guard: 'no kcl errors',
|
guard: 'no kcl errors',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Insert: {
|
||||||
|
target: 'Applying insert',
|
||||||
|
reenter: true,
|
||||||
|
guard: 'no kcl errors',
|
||||||
|
},
|
||||||
|
|
||||||
Translate: {
|
Translate: {
|
||||||
target: 'Applying translate',
|
target: 'Applying translate',
|
||||||
reenter: true,
|
reenter: true,
|
||||||
@ -4738,6 +4774,22 @@ export const modelingMachine = setup({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'Applying insert': {
|
||||||
|
invoke: {
|
||||||
|
src: 'insertAstMod',
|
||||||
|
id: 'insertAstMod',
|
||||||
|
input: ({ event }) => {
|
||||||
|
if (event.type !== 'Insert') return undefined
|
||||||
|
return event.data
|
||||||
|
},
|
||||||
|
onDone: ['idle'],
|
||||||
|
onError: {
|
||||||
|
target: 'idle',
|
||||||
|
actions: 'toastError',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
'Applying translate': {
|
'Applying translate': {
|
||||||
invoke: {
|
invoke: {
|
||||||
src: 'translateAstMod',
|
src: 'translateAstMod',
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import type { FileEntry } from '@src/lib/project'
|
||||||
import { systemIOActor } from '@src/lib/singletons'
|
import { systemIOActor } from '@src/lib/singletons'
|
||||||
|
import { isArray } from '@src/lib/utils'
|
||||||
|
|
||||||
export const folderSnapshot = () => {
|
export const folderSnapshot = () => {
|
||||||
const { folders } = systemIOActor.getSnapshot().context
|
const { folders } = systemIOActor.getSnapshot().context
|
||||||
@ -9,3 +11,48 @@ export const defaultProjectFolderNameSnapshot = () => {
|
|||||||
const { defaultProjectFolderName } = systemIOActor.getSnapshot().context
|
const { defaultProjectFolderName } = systemIOActor.getSnapshot().context
|
||||||
return defaultProjectFolderName
|
return defaultProjectFolderName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From the application project directory go down to a project folder and list all the folders at that directory level
|
||||||
|
* application project directory: /home/documents/zoo-modeling-app-projects/
|
||||||
|
*
|
||||||
|
* /home/documents/zoo-modeling-app-projects/car-door/
|
||||||
|
* ├── handle
|
||||||
|
* ├── main.kcl
|
||||||
|
* └── window
|
||||||
|
*
|
||||||
|
* The two folders are handle and window
|
||||||
|
*
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {string} params.projectFolderName - The name with no path information.
|
||||||
|
* @returns {FileEntry[]} An array of subdirectory names found at the root level of the specified project folder.
|
||||||
|
*/
|
||||||
|
export const getAllSubDirectoriesAtProjectRoot = ({
|
||||||
|
projectFolderName,
|
||||||
|
}: { projectFolderName: string }): FileEntry[] => {
|
||||||
|
const subDirectories: FileEntry[] = []
|
||||||
|
const { folders } = systemIOActor.getSnapshot().context
|
||||||
|
|
||||||
|
const projectFolder = folders.find((folder) => {
|
||||||
|
return folder.name === projectFolderName
|
||||||
|
})
|
||||||
|
|
||||||
|
// Find the subdirectories
|
||||||
|
if (projectFolder) {
|
||||||
|
// 1st level
|
||||||
|
const children = projectFolder.children
|
||||||
|
if (children) {
|
||||||
|
children.forEach((childFileOrDirectory) => {
|
||||||
|
// 2nd level
|
||||||
|
const secondLevelChild = childFileOrDirectory.children
|
||||||
|
// if secondLevelChild is null then it is a file
|
||||||
|
if (secondLevelChild && isArray(secondLevelChild)) {
|
||||||
|
// this is a directory!
|
||||||
|
subDirectories.push(childFileOrDirectory)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return subDirectories
|
||||||
|
}
|
||||||
|
@ -102,6 +102,16 @@ export const systemIOMachine = setup({
|
|||||||
requestedSubRoute?: string
|
requestedSubRoute?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: SystemIOMachineEvents.bulkCreateKCLFilesAndNavigateToFile
|
||||||
|
data: {
|
||||||
|
files: RequestedKCLFile[]
|
||||||
|
requestedProjectName: string
|
||||||
|
requestedFileNameWithExtension: string
|
||||||
|
override?: boolean
|
||||||
|
requestedSubRoute?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
type: SystemIOMachineEvents.importFileFromURL
|
type: SystemIOMachineEvents.importFileFromURL
|
||||||
data: {
|
data: {
|
||||||
@ -339,6 +349,27 @@ export const systemIOMachine = setup({
|
|||||||
return { message: '', fileName: '', projectName: '', subRoute: '' }
|
return { message: '', fileName: '', projectName: '', subRoute: '' }
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
[SystemIOMachineActors.bulkCreateKCLFilesAndNavigateToFile]: fromPromise(
|
||||||
|
async ({
|
||||||
|
input,
|
||||||
|
}: {
|
||||||
|
input: {
|
||||||
|
context: SystemIOContext
|
||||||
|
files: RequestedKCLFile[]
|
||||||
|
rootContext: AppMachineContext
|
||||||
|
requestedProjectName: string
|
||||||
|
requestedFileNameWithExtension: string
|
||||||
|
requestedSubRoute?: string
|
||||||
|
}
|
||||||
|
}): Promise<{
|
||||||
|
message: string
|
||||||
|
fileName: string
|
||||||
|
projectName: string
|
||||||
|
subRoute: string
|
||||||
|
}> => {
|
||||||
|
return { message: '', fileName: '', projectName: '', subRoute: '' }
|
||||||
|
}
|
||||||
|
),
|
||||||
},
|
},
|
||||||
}).createMachine({
|
}).createMachine({
|
||||||
initial: SystemIOMachineStates.idle,
|
initial: SystemIOMachineStates.idle,
|
||||||
@ -414,6 +445,9 @@ export const systemIOMachine = setup({
|
|||||||
target:
|
target:
|
||||||
SystemIOMachineStates.bulkCreatingKCLFilesAndNavigateToProject,
|
SystemIOMachineStates.bulkCreatingKCLFilesAndNavigateToProject,
|
||||||
},
|
},
|
||||||
|
[SystemIOMachineEvents.bulkCreateKCLFilesAndNavigateToFile]: {
|
||||||
|
target: SystemIOMachineStates.bulkCreatingKCLFilesAndNavigateToFile,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[SystemIOMachineStates.readingFolders]: {
|
[SystemIOMachineStates.readingFolders]: {
|
||||||
@ -683,5 +717,53 @@ export const systemIOMachine = setup({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[SystemIOMachineStates.bulkCreatingKCLFilesAndNavigateToFile]: {
|
||||||
|
invoke: {
|
||||||
|
id: SystemIOMachineActors.bulkCreateKCLFilesAndNavigateToFile,
|
||||||
|
src: SystemIOMachineActors.bulkCreateKCLFilesAndNavigateToFile,
|
||||||
|
input: ({ context, event, self }) => {
|
||||||
|
assertEvent(
|
||||||
|
event,
|
||||||
|
SystemIOMachineEvents.bulkCreateKCLFilesAndNavigateToFile
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
context,
|
||||||
|
files: event.data.files,
|
||||||
|
rootContext: self.system.get('root').getSnapshot().context,
|
||||||
|
requestedProjectName: event.data.requestedProjectName,
|
||||||
|
override: event.data.override,
|
||||||
|
requestedFileNameWithExtension:
|
||||||
|
event.data.requestedFileNameWithExtension,
|
||||||
|
requestedSubRoute: event.data.requestedSubRoute,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDone: {
|
||||||
|
target: SystemIOMachineStates.readingFolders,
|
||||||
|
actions: [
|
||||||
|
assign({
|
||||||
|
requestedFileName: ({ event }) => {
|
||||||
|
assertEvent(
|
||||||
|
event,
|
||||||
|
SystemIOMachineEvents.done_bulkCreateKCLFilesAndNavigateToFile
|
||||||
|
)
|
||||||
|
// Gotcha: file could have an ending of .kcl...
|
||||||
|
const file = event.output.fileName.endsWith('.kcl')
|
||||||
|
? event.output.fileName
|
||||||
|
: event.output.fileName + '.kcl'
|
||||||
|
return {
|
||||||
|
project: event.output.projectName,
|
||||||
|
file,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
SystemIOMachineActions.toastSuccess,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
onError: {
|
||||||
|
target: SystemIOMachineStates.idle,
|
||||||
|
actions: [SystemIOMachineActions.toastError],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -370,5 +370,33 @@ export const systemIOMachineDesktop = systemIOMachine.provide({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
[SystemIOMachineActors.bulkCreateKCLFilesAndNavigateToFile]: fromPromise(
|
||||||
|
async ({
|
||||||
|
input,
|
||||||
|
}: {
|
||||||
|
input: {
|
||||||
|
context: SystemIOContext
|
||||||
|
files: RequestedKCLFile[]
|
||||||
|
rootContext: AppMachineContext
|
||||||
|
requestedProjectName: string
|
||||||
|
override?: boolean
|
||||||
|
requestedFileNameWithExtension: string
|
||||||
|
requestedSubRoute?: string
|
||||||
|
}
|
||||||
|
}) => {
|
||||||
|
const message = await sharedBulkCreateWorkflow({
|
||||||
|
input: {
|
||||||
|
...input,
|
||||||
|
override: input.override,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
...message,
|
||||||
|
projectName: input.requestedProjectName,
|
||||||
|
fileName: input.requestedFileNameWithExtension || '',
|
||||||
|
subRoute: input.requestedSubRoute || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -15,6 +15,7 @@ export enum SystemIOMachineActors {
|
|||||||
deleteKCLFile = 'delete kcl delete',
|
deleteKCLFile = 'delete kcl delete',
|
||||||
bulkCreateKCLFiles = 'bulk create kcl files',
|
bulkCreateKCLFiles = 'bulk create kcl files',
|
||||||
bulkCreateKCLFilesAndNavigateToProject = 'bulk create kcl files and navigate to project',
|
bulkCreateKCLFilesAndNavigateToProject = 'bulk create kcl files and navigate to project',
|
||||||
|
bulkCreateKCLFilesAndNavigateToFile = 'bulk create kcl files and navigate to file',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SystemIOMachineStates {
|
export enum SystemIOMachineStates {
|
||||||
@ -31,6 +32,7 @@ export enum SystemIOMachineStates {
|
|||||||
deletingKCLFile = 'deletingKCLFile',
|
deletingKCLFile = 'deletingKCLFile',
|
||||||
bulkCreatingKCLFiles = 'bulkCreatingKCLFiles',
|
bulkCreatingKCLFiles = 'bulkCreatingKCLFiles',
|
||||||
bulkCreatingKCLFilesAndNavigateToProject = 'bulkCreatingKCLFilesAndNavigateToProject',
|
bulkCreatingKCLFilesAndNavigateToProject = 'bulkCreatingKCLFilesAndNavigateToProject',
|
||||||
|
bulkCreatingKCLFilesAndNavigateToFile = 'bulkCreatingKCLFilesAndNavigateToFile',
|
||||||
}
|
}
|
||||||
|
|
||||||
const donePrefix = 'xstate.done.actor.'
|
const donePrefix = 'xstate.done.actor.'
|
||||||
@ -56,6 +58,9 @@ export enum SystemIOMachineEvents {
|
|||||||
deleteKCLFile = 'delete kcl file',
|
deleteKCLFile = 'delete kcl file',
|
||||||
bulkCreateKCLFiles = 'bulk create kcl files',
|
bulkCreateKCLFiles = 'bulk create kcl files',
|
||||||
bulkCreateKCLFilesAndNavigateToProject = 'bulk create kcl files and navigate to project',
|
bulkCreateKCLFilesAndNavigateToProject = 'bulk create kcl files and navigate to project',
|
||||||
|
bulkCreateKCLFilesAndNavigateToFile = 'bulk create kcl files and navigate to file',
|
||||||
|
done_bulkCreateKCLFilesAndNavigateToFile = donePrefix +
|
||||||
|
'bulk create kcl files and navigate to file',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SystemIOMachineActions {
|
export enum SystemIOMachineActions {
|
||||||
|
Reference in New Issue
Block a user