Fix to update the code in the editor before executing (#5976)

* Fix spelling

* Fix to update the code in the editor before executing
This commit is contained in:
Jonathan Tran
2025-03-25 05:06:27 -04:00
committed by GitHub
parent f7f7d9fa2c
commit 58dc3382eb
11 changed files with 192 additions and 134 deletions

View File

@ -123,6 +123,8 @@ import { Node } from '@rust/kcl-lib/bindings/Node'
import { radToDeg } from 'three/src/math/MathUtils' import { radToDeg } from 'three/src/math/MathUtils'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { getArtifactFromRange, codeRefFromRange } from 'lang/std/artifactGraph' import { getArtifactFromRange, codeRefFromRange } from 'lang/std/artifactGraph'
import { updateModelingState } from 'lang/modelingWorkflows'
import { EXECUTION_TYPE_MOCK } from 'lib/constants'
type DraftSegment = 'line' | 'tangentialArcTo' type DraftSegment = 'line' | 'tangentialArcTo'
@ -1075,7 +1077,11 @@ export class SceneEntities {
return return
} }
await kclManager.executeAstMock(modifiedAst) await updateModelingState(modifiedAst, EXECUTION_TYPE_MOCK, {
kclManager,
editorManager,
codeManager,
})
if (intersectsProfileStart) { if (intersectsProfileStart) {
sceneInfra.modelingSend({ type: 'Close sketch' }) sceneInfra.modelingSend({ type: 'Close sketch' })
@ -1090,8 +1096,6 @@ export class SceneEntities {
segmentName segmentName
) )
} }
await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst)
}, },
onMove: (args) => { onMove: (args) => {
const expressionIndex = Number(sketchEntryNodePath[1][0]) const expressionIndex = Number(sketchEntryNodePath[1][0])
@ -1303,13 +1307,16 @@ export class SceneEntities {
_ast = pResult.program _ast = pResult.program
// Update the primary AST and unequip the rectangle tool // Update the primary AST and unequip the rectangle tool
await kclManager.executeAstMock(_ast) //
sceneInfra.modelingSend({ type: 'Finish rectangle' })
// lee: I had this at the bottom of the function, but it's // lee: I had this at the bottom of the function, but it's
// possible sketchFromKclValue "fails" when sketching on a face, // possible sketchFromKclValue "fails" when sketching on a face,
// and this couldn't wouldn't run. // and this couldn't wouldn't run.
await codeManager.updateEditorWithAstAndWriteToFile(_ast) await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
kclManager,
editorManager,
codeManager,
})
sceneInfra.modelingSend({ type: 'Finish rectangle' })
}, },
}) })
return { return {
@ -1493,13 +1500,16 @@ export class SceneEntities {
_ast = pResult.program _ast = pResult.program
// Update the primary AST and unequip the rectangle tool // Update the primary AST and unequip the rectangle tool
await kclManager.executeAstMock(_ast) //
sceneInfra.modelingSend({ type: 'Finish center rectangle' })
// lee: I had this at the bottom of the function, but it's // lee: I had this at the bottom of the function, but it's
// possible sketchFromKclValue "fails" when sketching on a face, // possible sketchFromKclValue "fails" when sketching on a face,
// and this couldn't wouldn't run. // and this couldn't wouldn't run.
await codeManager.updateEditorWithAstAndWriteToFile(_ast) await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
kclManager,
editorManager,
codeManager,
})
sceneInfra.modelingSend({ type: 'Finish center rectangle' })
} }
}, },
}) })
@ -1678,9 +1688,12 @@ export class SceneEntities {
_ast = pResult.program _ast = pResult.program
// Update the primary AST and unequip the rectangle tool // Update the primary AST and unequip the rectangle tool
await kclManager.executeAstMock(_ast) await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
kclManager,
editorManager,
codeManager,
})
sceneInfra.modelingSend({ type: 'Finish circle three point' }) sceneInfra.modelingSend({ type: 'Finish circle three point' })
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
} }
}, },
}) })
@ -1912,9 +1925,12 @@ export class SceneEntities {
_ast = pResult.program _ast = pResult.program
// Update the primary AST and unequip the arc tool // Update the primary AST and unequip the arc tool
await kclManager.executeAstMock(_ast) await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
kclManager,
editorManager,
codeManager,
})
sceneInfra.modelingSend({ type: 'Finish arc' }) sceneInfra.modelingSend({ type: 'Finish arc' })
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
} }
}, },
}) })
@ -2166,13 +2182,16 @@ export class SceneEntities {
_ast = pResult.program _ast = pResult.program
// Update the primary AST and unequip the arc tool // Update the primary AST and unequip the arc tool
await kclManager.executeAstMock(_ast) await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
kclManager,
editorManager,
codeManager,
})
if (intersectsProfileStart) { if (intersectsProfileStart) {
sceneInfra.modelingSend({ type: 'Close sketch' }) sceneInfra.modelingSend({ type: 'Close sketch' })
} else { } else {
sceneInfra.modelingSend({ type: 'Finish arc' }) sceneInfra.modelingSend({ type: 'Finish arc' })
} }
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
} }
}, },
}) })
@ -2364,9 +2383,12 @@ export class SceneEntities {
_ast = pResult.program _ast = pResult.program
// Update the primary AST and unequip the rectangle tool // Update the primary AST and unequip the rectangle tool
await kclManager.executeAstMock(_ast) await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
kclManager,
editorManager,
codeManager,
})
sceneInfra.modelingSend({ type: 'Finish circle' }) sceneInfra.modelingSend({ type: 'Finish circle' })
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
} }
}, },
}) })

View File

@ -119,6 +119,8 @@ import { EXPORT_TOAST_MESSAGES, MAKE_TOAST_MESSAGES } from 'lib/constants'
import { exportMake } from 'lib/exportMake' import { exportMake } from 'lib/exportMake'
import { exportSave } from 'lib/exportSave' import { exportSave } from 'lib/exportSave'
import { Plane } from '@rust/kcl-lib/bindings/Plane' import { Plane } from '@rust/kcl-lib/bindings/Plane'
import { updateModelingState } from 'lang/modelingWorkflows'
import { EXECUTION_TYPE_MOCK } from 'lib/constants'
export const ModelingMachineContext = createContext( export const ModelingMachineContext = createContext(
{} as { {} as {
@ -1660,7 +1662,7 @@ export const ModelingMachineProvider = ({
sketchDetails.sketchEntryNodePath sketchDetails.sketchEntryNodePath
) )
if (err(doesNeedSplitting)) return reject(doesNeedSplitting) if (err(doesNeedSplitting)) return reject(doesNeedSplitting)
let moddedAst: Program = structuredClone(kclManager.ast) let moddedAst: Node<Program> = structuredClone(kclManager.ast)
let pathToProfile = sketchDetails.sketchEntryNodePath let pathToProfile = sketchDetails.sketchEntryNodePath
let updatedSketchNodePaths = sketchDetails.sketchNodePaths let updatedSketchNodePaths = sketchDetails.sketchNodePaths
if (doesNeedSplitting) { if (doesNeedSplitting) {
@ -1722,8 +1724,11 @@ export const ModelingMachineProvider = ({
indexToDelete >= 0 || indexToDelete >= 0 ||
isLastInPipeThreePointArc isLastInPipeThreePointArc
) { ) {
await kclManager.executeAstMock(moddedAst) await updateModelingState(moddedAst, EXECUTION_TYPE_MOCK, {
await codeManager.updateEditorWithAstAndWriteToFile(moddedAst) kclManager,
editorManager,
codeManager,
})
} }
return { return {
updatedEntryNodePath: pathToProfile, updatedEntryNodePath: pathToProfile,

View File

@ -2,12 +2,12 @@ import { executeAst, executeAstMock, lintAst } from 'lang/langHelpers'
import { handleSelectionBatch, Selections } from 'lib/selections' import { handleSelectionBatch, Selections } from 'lib/selections'
import { import {
KCLError, KCLError,
complilationErrorsToDiagnostics, compilationErrorsToDiagnostics,
kclErrorsToDiagnostics, kclErrorsToDiagnostics,
} from './errors' } from './errors'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
import { EngineCommandManager } from './std/engineConnection' import { EngineCommandManager } from './std/engineConnection'
import { err } from 'lib/trap' import { err, reportRejection } from 'lib/trap'
import { EXECUTE_AST_INTERRUPT_ERROR_MESSAGE } from 'lib/constants' import { EXECUTE_AST_INTERRUPT_ERROR_MESSAGE } from 'lib/constants'
import { import {
@ -295,8 +295,8 @@ export class KclManager {
this._astParseFailed = false this._astParseFailed = false
if (err(result)) { if (err(result)) {
const kclerror: KCLError = result as KCLError const kclError: KCLError = result as KCLError
this.diagnostics = kclErrorsToDiagnostics([kclerror]) this.diagnostics = kclErrorsToDiagnostics([kclError])
this._astParseFailed = true this._astParseFailed = true
await this.checkIfSwitchedFilesShouldClear() await this.checkIfSwitchedFilesShouldClear()
@ -310,8 +310,8 @@ export class KclManager {
this._kclErrorsCallBack([]) this._kclErrorsCallBack([])
this._logsCallBack([]) this._logsCallBack([])
this.addDiagnostics(complilationErrorsToDiagnostics(result.errors)) this.addDiagnostics(compilationErrorsToDiagnostics(result.errors))
this.addDiagnostics(complilationErrorsToDiagnostics(result.warnings)) this.addDiagnostics(compilationErrorsToDiagnostics(result.warnings))
if (result.errors.length > 0) { if (result.errors.length > 0) {
this._astParseFailed = true this._astParseFailed = true
@ -337,8 +337,8 @@ export class KclManager {
private _cancelTokens: Map<number, boolean> = new Map() private _cancelTokens: Map<number, boolean> = new Map()
// This NEVER updates the code, if you want to update the code DO NOT add to // This NEVER updates the code, if you want to update the code DO NOT add to
// this function, too many other things that don't want it exist. // this function, too many other things that don't want it exist. For that,
// just call to codeManager from wherever you want in other files. // use updateModelingState().
async executeAst(args: ExecuteArgs = {}): Promise<void> { async executeAst(args: ExecuteArgs = {}): Promise<void> {
if (this.isExecuting) { if (this.isExecuting) {
this.executeIsStale = args this.executeIsStale = args
@ -420,7 +420,7 @@ export class KclManager {
this.addDiagnostics(isInterrupted ? [] : kclErrorsToDiagnostics(errors)) this.addDiagnostics(isInterrupted ? [] : kclErrorsToDiagnostics(errors))
// Add warnings and non-fatal errors // Add warnings and non-fatal errors
this.addDiagnostics( this.addDiagnostics(
isInterrupted ? [] : complilationErrorsToDiagnostics(execState.errors) isInterrupted ? [] : compilationErrorsToDiagnostics(execState.errors)
) )
this.execState = execState this.execState = execState
if (!errors.length) { if (!errors.length) {
@ -460,7 +460,6 @@ export class KclManager {
markOnce('code/endExecuteAst') markOnce('code/endExecuteAst')
} }
// NOTE: this always updates the code state and editor.
// DO NOT CALL THIS from codemirror ever. // DO NOT CALL THIS from codemirror ever.
async executeAstMock(ast: Program) { async executeAstMock(ast: Program) {
await this.ensureWasmInit() await this.ensureWasmInit()
@ -472,7 +471,7 @@ export class KclManager {
} }
const newAst = await this.safeParse(newCode) const newAst = await this.safeParse(newCode)
if (!newAst) { if (!newAst) {
// By clearning the AST we indicate to our callers that there was an issue with execution and // By clearing the AST we indicate to our callers that there was an issue with execution and
// the pre-execution state should be restored. // the pre-execution state should be restored.
this.clearAst() this.clearAst()
return return
@ -501,7 +500,7 @@ export class KclManager {
const ast = await this.safeParse(codeManager.code) const ast = await this.safeParse(codeManager.code)
if (!ast) { if (!ast) {
// By clearning the AST we indicate to our callers that there was an issue with execution and // By clearing the AST we indicate to our callers that there was an issue with execution and
// the pre-execution state should be restored. // the pre-execution state should be restored.
this.clearAst() this.clearAst()
return return
@ -516,8 +515,8 @@ export class KclManager {
* This will override the zoom to fit to zoom into the model if the previous AST was empty. * This will override the zoom to fit to zoom into the model if the previous AST was empty.
* Workflows this improves, * Workflows this improves,
* When someone comments the entire file then uncomments the entire file it zooms to the model * When someone comments the entire file then uncomments the entire file it zooms to the model
* When someone CRTL+A and deletes the code then adds the code back it zooms to the model * When someone CTRL+A and deletes the code then adds the code back it zooms to the model
* When someone CRTL+A and copies new code into the editor it zooms to the model * When someone CTRL+A and copies new code into the editor it zooms to the model
*/ */
tryToZoomToFitOnCodeUpdate( tryToZoomToFitOnCodeUpdate(
ast: Node<Program>, ast: Node<Program>,
@ -555,12 +554,16 @@ export class KclManager {
codeManager.updateCodeStateEditor(code) codeManager.updateCodeStateEditor(code)
// Write back to the file system. // Write back to the file system.
void codeManager.writeToFile().then(() => this.executeCode()) void codeManager
.writeToFile()
.then(() => this.executeCode())
.catch(reportRejection)
} }
// There's overlapping responsibility between updateAst and executeAst. // There's overlapping responsibility between updateAst and executeAst.
// updateAst was added as it was used a lot before xState migration so makes the port easier. // updateAst was added as it was used a lot before xState migration so makes the port easier.
// but should probably have think about which of the function to keep // but should probably have think about which of the function to keep
// This always updates the code state and editor and writes to the file system. // This never updates the code state or editor and doesn't write to the file system.
async updateAst( async updateAst(
ast: Node<Program>, ast: Node<Program>,
execute: boolean, execute: boolean,
@ -627,7 +630,6 @@ export class KclManager {
// When we don't re-execute, we still want to update the program // When we don't re-execute, we still want to update the program
// memory with the new ast. So we will hit the mock executor // memory with the new ast. So we will hit the mock executor
// instead.. // instead..
// Execute ast mock will update the code state and editor.
await this.executeAstMock(astWithUpdatedSource) await this.executeAstMock(astWithUpdatedSource)
} }

View File

@ -165,10 +165,11 @@ export default class CodeManager {
} }
async updateEditorWithAstAndWriteToFile(ast: Program) { async updateEditorWithAstAndWriteToFile(ast: Program) {
// We clear the AST when there it cannot be parsed, so if we are trying to write an empty AST, its // We clear the AST when it cannot be parsed. If we are trying to write an
// probably because of an earlier error. That's a bad state to be in and it's not going to be // empty AST, it's probably because of an earlier error. That's a bad state
// pretty, but at the least, lets not permanently delete the user's code. // to be in, and it's not going to be pretty, but at the least, let's not
// If you want to clear the scene, call updateCodeStateEditor directly. // permanently delete the user's code. If you want to clear the scene, call
// updateCodeStateEditor directly.
if (ast.body.length === 0) return if (ast.body.length === 0) return
const newCode = recast(ast) const newCode = recast(ast)
if (err(newCode)) return if (err(newCode)) return

View File

@ -320,7 +320,7 @@ export function kclErrorsToDiagnostics(
}) })
} }
export function complilationErrorsToDiagnostics( export function compilationErrorsToDiagnostics(
errors: CompilationError[] errors: CompilationError[]
): CodeMirrorDiagnostic[] { ): CodeMirrorDiagnostic[] {
return errors return errors

View File

@ -8,6 +8,12 @@
import { Node } from '@rust/kcl-lib/bindings/Node' import { Node } from '@rust/kcl-lib/bindings/Node'
import { KclManager } from 'lang/KclSingleton' import { KclManager } from 'lang/KclSingleton'
import { ExecutionType } from 'lib/constants'
import {
EXECUTION_TYPE_MOCK,
EXECUTION_TYPE_NONE,
EXECUTION_TYPE_REAL,
} from 'lib/constants'
import { PathToNode, Program, SourceRange } from 'lang/wasm' import { PathToNode, Program, SourceRange } from 'lang/wasm'
import EditorManager from 'editor/manager' import EditorManager from 'editor/manager'
import CodeManager from 'lang/codeManager' import CodeManager from 'lang/codeManager'
@ -32,12 +38,13 @@ import CodeManager from 'lang/codeManager'
* regardless of geometric validity issues. * regardless of geometric validity issues.
* *
* @param ast - AST to commit * @param ast - AST to commit
* @param executionType - How to execute the AST
* @param dependencies - Required system components * @param dependencies - Required system components
* @param options - Optional parameters for focus, zoom, etc. * @param options - Optional parameters for focus, zoom, etc.
*/ */
export async function updateModelingState( export async function updateModelingState(
ast: Node<Program>, ast: Node<Program>,
executionType: ExecutionType,
dependencies: { dependencies: {
kclManager: KclManager kclManager: KclManager
editorManager: EditorManager editorManager: EditorManager
@ -55,6 +62,7 @@ export async function updateModelingState(
// Step 1: Update AST without executing (prepare selections) // Step 1: Update AST without executing (prepare selections)
const updatedAst = await dependencies.kclManager.updateAst( const updatedAst = await dependencies.kclManager.updateAst(
ast, ast,
// false == mock execution. Is this what we want?
false, // Execution handled separately for error resilience false, // Execution handled separately for error resilience
options options
) )
@ -69,14 +77,20 @@ export async function updateModelingState(
dependencies.editorManager.selectRange(updatedAst.selections) dependencies.editorManager.selectRange(updatedAst.selections)
} }
// Step 4: Try to execute the new code in the engine // Step 4: Try to execute the new code
// and continue regardless of errors // and continue regardless of errors
try { try {
await dependencies.kclManager.executeAst({ if (executionType === EXECUTION_TYPE_REAL) {
ast: updatedAst.newAst, await dependencies.kclManager.executeAst({
zoomToFit: options?.zoomToFit, ast: updatedAst.newAst,
zoomOnRangeAndType: options?.zoomOnRangeAndType, zoomToFit: options?.zoomToFit,
}) zoomOnRangeAndType: options?.zoomOnRangeAndType,
})
} else if (executionType === EXECUTION_TYPE_MOCK) {
await dependencies.kclManager.executeAstMock(updatedAst.newAst)
} else if (executionType === EXECUTION_TYPE_NONE) {
// No execution.
}
} catch (e) { } catch (e) {
console.error('Engine execution error (UI is still updated):', e) console.error('Engine execution error (UI is still updated):', e)
} }

View File

@ -673,7 +673,7 @@ export function sketchOnExtrudedFace(
sketchPathToNode: PathToNode, sketchPathToNode: PathToNode,
extrudePathToNode: PathToNode, extrudePathToNode: PathToNode,
info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' } info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' }
): { modifiedAst: Program; pathToNode: PathToNode } | Error { ): { modifiedAst: Node<Program>; pathToNode: PathToNode } | Error {
let _node = { ...node } let _node = { ...node }
const newSketchName = findUniqueName( const newSketchName = findUniqueName(
node, node,
@ -1375,7 +1375,7 @@ export function moveValueIntoNewVariablePath(
pathToNode: PathToNode, pathToNode: PathToNode,
variableName: string variableName: string
): { ): {
modifiedAst: Program modifiedAst: Node<Program>
pathToReplacedNode?: PathToNode pathToReplacedNode?: PathToNode
} { } {
const meta = isNodeSafeToReplacePath(ast, pathToNode) const meta = isNodeSafeToReplacePath(ast, pathToNode)
@ -1975,11 +1975,11 @@ making it safe for later code that uses part001 (the extrude in this example)
* *
*/ */
export function splitPipedProfile( export function splitPipedProfile(
ast: Program, ast: Node<Program>,
pathToPipe: PathToNode pathToPipe: PathToNode
): ):
| { | {
modifiedAst: Program modifiedAst: Node<Program>
pathToProfile: PathToNode pathToProfile: PathToNode
pathToPlane: PathToNode pathToPlane: PathToNode
} }

View File

@ -39,6 +39,7 @@ import { Artifact, getSweepArtifactFromSelection } from 'lang/std/artifactGraph'
import { Node } from '@rust/kcl-lib/bindings/Node' import { Node } from '@rust/kcl-lib/bindings/Node'
import { findKwArg } from 'lang/util' import { findKwArg } from 'lang/util'
import { KclManager } from 'lang/KclSingleton' import { KclManager } from 'lang/KclSingleton'
import { EXECUTION_TYPE_REAL } from 'lib/constants'
import { EngineCommandManager } from 'lang/std/engineConnection' import { EngineCommandManager } from 'lang/std/engineConnection'
import EditorManager from 'editor/manager' import EditorManager from 'editor/manager'
import CodeManager from 'lang/codeManager' import CodeManager from 'lang/codeManager'
@ -86,6 +87,7 @@ export async function applyEdgeTreatmentToSelection(
// 2. update ast // 2. update ast
await updateModelingState( await updateModelingState(
modifiedAst, modifiedAst,
EXECUTION_TYPE_REAL,
{ {
kclManager: dependencies.kclManager, kclManager: dependencies.kclManager,
editorManager: dependencies.editorManager, editorManager: dependencies.editorManager,

View File

@ -3,12 +3,15 @@ import { getFaceDetails } from 'clientSideScene/sceneEntities'
import { deleteFromSelection } from 'lang/modifyAst' import { deleteFromSelection } from 'lang/modifyAst'
import { import {
codeManager, codeManager,
editorManager,
engineCommandManager, engineCommandManager,
kclManager, kclManager,
rustContext, rustContext,
} from 'lib/singletons' } from 'lib/singletons'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { executeAstMock } from 'lang/langHelpers' import { executeAstMock } from 'lang/langHelpers'
import { updateModelingState } from 'lang/modelingWorkflows'
import { EXECUTION_TYPE_REAL } from 'lib/constants'
export const deletionErrorMessage = export const deletionErrorMessage =
'Unable to delete selection. Please edit manually in code pane.' 'Unable to delete selection. Please edit manually in code pane.'
@ -36,7 +39,9 @@ export async function deleteSelectionPromise(
if (testExecute.errors.length) { if (testExecute.errors.length) {
return new Error(deletionErrorMessage) return new Error(deletionErrorMessage)
} }
await updateModelingState(modifiedAst, EXECUTION_TYPE_REAL, {
await kclManager.updateAst(modifiedAst, true) kclManager,
await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst) editorManager,
codeManager,
})
} }

View File

@ -167,3 +167,17 @@ export const ZOO_STUDIO_PROTOCOL = 'zoo-studio'
* to "open in desktop app" when present in the URL * to "open in desktop app" when present in the URL
*/ */
export const ASK_TO_OPEN_QUERY_PARAM = 'ask-open-desktop' export const ASK_TO_OPEN_QUERY_PARAM = 'ask-open-desktop'
/** Real execution. */
export const EXECUTION_TYPE_REAL = 'real' as const
/** Mock execution. */
export const EXECUTION_TYPE_MOCK = 'mock' as const
/** No execution. */
export const EXECUTION_TYPE_NONE = 'none' as const
/**
* Enum of engine execution kinds.
*/
export type ExecutionType =
| typeof EXECUTION_TYPE_REAL
| typeof EXECUTION_TYPE_MOCK
| typeof EXECUTION_TYPE_NONE

View File

@ -102,6 +102,7 @@ import { setAppearance } from 'lang/modifyAst/setAppearance'
import { DRAFT_DASHED_LINE } from 'clientSideScene/sceneEntities' import { DRAFT_DASHED_LINE } from 'clientSideScene/sceneEntities'
import { Node } from '@rust/kcl-lib/bindings/Node' import { Node } from '@rust/kcl-lib/bindings/Node'
import { updateModelingState } from 'lang/modelingWorkflows' import { updateModelingState } from 'lang/modelingWorkflows'
import { EXECUTION_TYPE_REAL } from 'lib/constants'
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY' export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
@ -751,20 +752,23 @@ export const modelingMachine = setup({
if (trap(revolveSketchRes)) return if (trap(revolveSketchRes)) return
const { modifiedAst, pathToRevolveArg } = revolveSketchRes const { modifiedAst, pathToRevolveArg } = revolveSketchRes
const updatedAst = await kclManager.updateAst(modifiedAst, true, { await updateModelingState(
focusPath: [pathToRevolveArg], modifiedAst,
zoomToFit: true, EXECUTION_TYPE_REAL,
zoomOnRangeAndType: { {
range: selection.graphSelections[0]?.codeRef.range, kclManager,
type: 'path', editorManager,
codeManager,
}, },
}) {
focusPath: [pathToRevolveArg],
await codeManager.updateEditorWithAstAndWriteToFile(updatedAst.newAst) zoomToFit: true,
zoomOnRangeAndType: {
if (updatedAst?.selections) { range: selection.graphSelections[0]?.codeRef.range,
editorManager.selectRange(updatedAst?.selections) type: 'path',
} },
}
)
})().catch(reportRejection) })().catch(reportRejection)
}, },
'set selection filter to curves only': () => { 'set selection filter to curves only': () => {
@ -1797,20 +1801,23 @@ export const modelingMachine = setup({
pathToExtrudeArg[1][0]++ pathToExtrudeArg[1][0]++
} }
const updatedAst = await kclManager.updateAst(modifiedAst, true, { await updateModelingState(
focusPath: [pathToExtrudeArg], modifiedAst,
zoomToFit: true, EXECUTION_TYPE_REAL,
zoomOnRangeAndType: { {
range: selection.graphSelections[0]?.codeRef.range, kclManager,
type: 'path', editorManager,
codeManager,
}, },
}) {
focusPath: [pathToExtrudeArg],
await codeManager.updateEditorWithAstAndWriteToFile(updatedAst.newAst) zoomToFit: true,
zoomOnRangeAndType: {
if (updatedAst?.selections) { range: selection.graphSelections[0]?.codeRef.range,
editorManager.selectRange(updatedAst?.selections) type: 'path',
} },
}
)
}), }),
offsetPlaneAstMod: fromPromise( offsetPlaneAstMod: fromPromise(
async ({ async ({
@ -1880,21 +1887,18 @@ export const modelingMachine = setup({
offsetPlaneResult.pathToNode[1][0]++ offsetPlaneResult.pathToNode[1][0]++
} }
const updateAstResult = await kclManager.updateAst( await updateModelingState(
offsetPlaneResult.modifiedAst, offsetPlaneResult.modifiedAst,
true, EXECUTION_TYPE_REAL,
{
kclManager,
editorManager,
codeManager,
},
{ {
focusPath: [offsetPlaneResult.pathToNode], focusPath: [offsetPlaneResult.pathToNode],
} }
) )
await codeManager.updateEditorWithAstAndWriteToFile(
updateAstResult.newAst
)
if (updateAstResult?.selections) {
editorManager.selectRange(updateAstResult?.selections)
}
} }
), ),
helixAstMod: fromPromise( helixAstMod: fromPromise(
@ -1995,6 +1999,7 @@ export const modelingMachine = setup({
}) })
await updateModelingState( await updateModelingState(
modifiedAst, modifiedAst,
EXECUTION_TYPE_REAL,
{ {
kclManager, kclManager,
editorManager, editorManager,
@ -2088,6 +2093,7 @@ export const modelingMachine = setup({
}) })
await updateModelingState( await updateModelingState(
modifiedAst, modifiedAst,
EXECUTION_TYPE_REAL,
{ {
kclManager, kclManager,
editorManager, editorManager,
@ -2126,21 +2132,18 @@ export const modelingMachine = setup({
// Perform the loft // Perform the loft
const loftSketchesRes = loftSketches(ast, declarators) const loftSketchesRes = loftSketches(ast, declarators)
const updateAstResult = await kclManager.updateAst( await updateModelingState(
loftSketchesRes.modifiedAst, loftSketchesRes.modifiedAst,
true, EXECUTION_TYPE_REAL,
{
kclManager,
editorManager,
codeManager,
},
{ {
focusPath: [loftSketchesRes.pathToNode], focusPath: [loftSketchesRes.pathToNode],
} }
) )
await codeManager.updateEditorWithAstAndWriteToFile(
updateAstResult.newAst
)
if (updateAstResult?.selections) {
editorManager.selectRange(updateAstResult?.selections)
}
} }
), ),
shellAstMod: fromPromise( shellAstMod: fromPromise(
@ -2306,21 +2309,18 @@ export const modelingMachine = setup({
addResult.pathToNode[1][0]++ addResult.pathToNode[1][0]++
} }
const updateAstResult = await kclManager.updateAst( await updateModelingState(
addResult.modifiedAst, addResult.modifiedAst,
true, EXECUTION_TYPE_REAL,
{
kclManager,
editorManager,
codeManager,
},
{ {
focusPath: [addResult.pathToNode], focusPath: [addResult.pathToNode],
} }
) )
await codeManager.updateEditorWithAstAndWriteToFile(
updateAstResult.newAst
)
if (updateAstResult?.selections) {
editorManager.selectRange(updateAstResult?.selections)
}
} }
), ),
filletAstMod: fromPromise( filletAstMod: fromPromise(
@ -2372,15 +2372,11 @@ export const modelingMachine = setup({
node: kclManager.ast, node: kclManager.ast,
newExpression: value, newExpression: value,
}) })
const updateAstResult = await kclManager.updateAst(newAst, true) await updateModelingState(newAst, EXECUTION_TYPE_REAL, {
kclManager,
await codeManager.updateEditorWithAstAndWriteToFile( editorManager,
updateAstResult.newAst codeManager,
) })
if (updateAstResult?.selections) {
editorManager.selectRange(updateAstResult?.selections)
}
} }
), ),
'actor.parameter.edit': fromPromise( 'actor.parameter.edit': fromPromise(
@ -2409,7 +2405,7 @@ export const modelingMachine = setup({
// Mutate the variable's value // Mutate the variable's value
variableNode.node.init = value.valueAst variableNode.node.init = value.valueAst
await updateModelingState(newAst, { await updateModelingState(newAst, EXECUTION_TYPE_REAL, {
codeManager, codeManager,
editorManager, editorManager,
kclManager, kclManager,
@ -2575,21 +2571,18 @@ export const modelingMachine = setup({
return err(result) return err(result)
} }
const updateAstResult = await kclManager.updateAst( await updateModelingState(
result.modifiedAst, result.modifiedAst,
true, EXECUTION_TYPE_REAL,
{
kclManager,
editorManager,
codeManager,
},
{ {
focusPath: [result.pathToNode], focusPath: [result.pathToNode],
} }
) )
await codeManager.updateEditorWithAstAndWriteToFile(
updateAstResult.newAst
)
if (updateAstResult?.selections) {
editorManager.selectRange(updateAstResult?.selections)
}
} }
), ),
exportFromEngine: fromPromise( exportFromEngine: fromPromise(