Files
modeling-app/src/lib/useCalculateKclExpression.ts
Kurt Hutten 59e0df7879 Selections Refactor (#4381)
* selection stuff

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* trigger CI

* fix bugs

* some edge cut stuff

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* fix sketch mode issues

* fix more tests, selection in sketch related

* more test fixing

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Trigger ci

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Trigger ci

* more sketch mode selection fixes

* fix unit tests

* rename function

* remove .only

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* lint

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* fix bad pathToNode issue

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* fix sketch on face

* migrate a more selections types

* migrate a more selections types

* fix code selection of fillets

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* migrate a more selections types

* fix bad path to node, looks like a race

* migrate a more selections types

* migrate a more selections types

* fix cmd bar selections

* fix cmd bar selections

* fix display issues

* migrate a more selections types

* Revert "migrate a more selections types"

This reverts commit 0d0e453bbb.

* migrate a more selections types

* clean up1

* clean up 2

* fix types after main merge

* review tweaks

* fix wall selection bug

* Update src/lang/std/engineConnection.ts

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>

* add franks TODO comment

* fix type after main merge, plus a touch of clean up

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2024-11-21 15:04:30 +11:00

137 lines
4.4 KiB
TypeScript

import { useModelingContext } from 'hooks/useModelingContext'
import { kclManager, engineCommandManager } from 'lib/singletons'
import { useKclContext } from 'lang/KclProvider'
import { findUniqueName } from 'lang/modifyAst'
import { PrevVariable, findAllPreviousVariables } from 'lang/queryAst'
import { ProgramMemory, Expr, parse } from 'lang/wasm'
import { useEffect, useRef, useState } from 'react'
import { executeAst } from 'lang/langHelpers'
import { err, trap } from 'lib/trap'
const isValidVariableName = (name: string) =>
/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)
/**
* Given a value and a possible variablename,
* return helpers for calculating the value and inserting it into the code
* as well as information about the variables that are available
*/
export function useCalculateKclExpression({
value,
initialVariableName: valueName = '',
}: {
value: string
initialVariableName?: string
}): {
inputRef: React.RefObject<HTMLInputElement>
valueNode: Expr | null
calcResult: string
prevVariables: PrevVariable<unknown>[]
newVariableName: string
isNewVariableNameUnique: boolean
newVariableInsertIndex: number
setNewVariableName: (a: string) => void
} {
const { programMemory, code } = useKclContext()
const { context } = useModelingContext()
const selectionRange:
| (typeof context)['selectionRanges']['graphSelections'][number]['codeRef']['range']
| undefined = context.selectionRanges.graphSelections[0]?.codeRef?.range
const inputRef = useRef<HTMLInputElement>(null)
const [availableVarInfo, setAvailableVarInfo] = useState<
ReturnType<typeof findAllPreviousVariables>
>({
variables: [],
insertIndex: 0,
bodyPath: [],
})
const [valueNode, setValueNode] = useState<Expr | null>(null)
const [calcResult, setCalcResult] = useState('NAN')
const [newVariableName, setNewVariableName] = useState('')
const [isNewVariableNameUnique, setIsNewVariableNameUnique] = useState(true)
useEffect(() => {
setTimeout(() => {
inputRef.current && inputRef.current.focus()
inputRef.current &&
inputRef.current.setSelectionRange(0, String(value).length)
}, 100)
setNewVariableName(findUniqueName(kclManager.ast, valueName))
}, [])
useEffect(() => {
if (
programMemory.has(newVariableName) ||
newVariableName === '' ||
!isValidVariableName(newVariableName)
) {
setIsNewVariableNameUnique(false)
} else {
setIsNewVariableNameUnique(true)
}
}, [programMemory, newVariableName])
useEffect(() => {
if (!programMemory || !selectionRange) return
const varInfo = findAllPreviousVariables(
kclManager.ast,
kclManager.programMemory,
selectionRange
)
setAvailableVarInfo(varInfo)
}, [kclManager.ast, kclManager.programMemory, selectionRange])
useEffect(() => {
const execAstAndSetResult = async () => {
const _code = `const __result__ = ${value}`
const ast = parse(_code)
if (err(ast)) return
if (trap(ast, { suppress: true })) return
const _programMem: ProgramMemory = ProgramMemory.empty()
for (const { key, value } of availableVarInfo.variables) {
const error = _programMem.set(key, {
type: 'String',
value,
__meta: [],
})
if (trap(error, { suppress: true })) return
}
const { execState } = await executeAst({
ast,
engineCommandManager,
useFakeExecutor: true,
programMemoryOverride: kclManager.programMemory.clone(),
idGenerator: kclManager.execState.idGenerator,
})
const resultDeclaration = ast.body.find(
(a) =>
a.type === 'VariableDeclaration' &&
a.declarations?.[0]?.id?.name === '__result__'
)
const init =
resultDeclaration?.type === 'VariableDeclaration' &&
resultDeclaration?.declarations?.[0]?.init
const result = execState.memory?.get('__result__')?.value
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
init && setValueNode(init)
}
if (!value) return
execAstAndSetResult().catch(() => {
setCalcResult('NAN')
setValueNode(null)
})
}, [value, availableVarInfo, code, kclManager.programMemory])
return {
valueNode,
calcResult,
prevVariables: availableVarInfo.variables,
newVariableInsertIndex: availableVarInfo.insertIndex,
newVariableName,
isNewVariableNameUnique,
setNewVariableName,
inputRef,
}
}