Remove circular dependency, avoid adding 2 new ones

This commit is contained in:
Frank Noirot
2025-07-03 09:10:48 -04:00
parent 4b00d00977
commit 40388b80e7
13 changed files with 39 additions and 13 deletions

View File

@ -10,4 +10,3 @@
5) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts 5) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts
6) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts 6) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
7) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts 7) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts
8) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/setAngleLength.tsx -> src/components/SetAngleLengthModal.tsx -> src/lib/useCalculateKclExpression.ts

View File

@ -33,6 +33,7 @@ import { useSettings } from '@src/lib/singletons'
import { commandBarActor, useCommandBarState } from '@src/lib/singletons' import { commandBarActor, useCommandBarState } from '@src/lib/singletons'
import styles from './CommandBarKclInput.module.css' import styles from './CommandBarKclInput.module.css'
import { useModelingContext } from '@src/hooks/useModelingContext'
// TODO: remove the need for this selector once we decouple all actors from React // TODO: remove the need for this selector once we decouple all actors from React
const machineContextSelector = (snapshot?: SnapshotFrom<AnyStateMachine>) => const machineContextSelector = (snapshot?: SnapshotFrom<AnyStateMachine>) =>
@ -55,6 +56,9 @@ function CommandBarKclInput({
arg.name arg.name
] as KclCommandValue | undefined ] as KclCommandValue | undefined
const settings = useSettings() const settings = useSettings()
const {
context: { selectionRanges },
} = useModelingContext()
const argMachineContext = useSelector( const argMachineContext = useSelector(
arg.machineActor, arg.machineActor,
machineContextSelector machineContextSelector
@ -126,6 +130,7 @@ function CommandBarKclInput({
value, value,
initialVariableName, initialVariableName,
sourceRange: sourceRangeForPrevVariables, sourceRange: sourceRangeForPrevVariables,
selectionRanges,
}) })
const varMentionData: Completion[] = prevVariables.map((v) => { const varMentionData: Completion[] = prevVariables.map((v) => {

View File

@ -10,6 +10,7 @@ import {
} from '@src/components/AvailableVarsHelpers' } from '@src/components/AvailableVarsHelpers'
import type { Expr } from '@src/lang/wasm' import type { Expr } from '@src/lang/wasm'
import { useCalculateKclExpression } from '@src/lib/useCalculateKclExpression' import { useCalculateKclExpression } from '@src/lib/useCalculateKclExpression'
import type { Selections } from '@src/lib/selections'
type ModalResolve = { type ModalResolve = {
value: string value: string
@ -25,6 +26,7 @@ type SetAngleLengthModalProps = InstanceProps<ModalResolve, ModalReject> & {
value: number value: number
valueName: string valueName: string
shouldCreateVariable?: boolean shouldCreateVariable?: boolean
selectionRanges: Selections
} }
export const createSetAngleLengthModal = create< export const createSetAngleLengthModal = create<
@ -40,6 +42,7 @@ export const SetAngleLengthModal = ({
value: initialValue, value: initialValue,
valueName, valueName,
shouldCreateVariable: initialShouldCreateVariable = false, shouldCreateVariable: initialShouldCreateVariable = false,
selectionRanges,
}: SetAngleLengthModalProps) => { }: SetAngleLengthModalProps) => {
const [sign, setSign] = useState(Math.sign(Number(initialValue))) const [sign, setSign] = useState(Math.sign(Number(initialValue)))
const [value, setValue] = useState(String(initialValue * sign)) const [value, setValue] = useState(String(initialValue * sign))
@ -59,6 +62,7 @@ export const SetAngleLengthModal = ({
} = useCalculateKclExpression({ } = useCalculateKclExpression({
value, value,
initialVariableName: valueName, initialVariableName: valueName,
selectionRanges,
}) })
return ( return (

View File

@ -10,6 +10,7 @@ import {
} from '@src/components/AvailableVarsHelpers' } from '@src/components/AvailableVarsHelpers'
import type { Expr } from '@src/lang/wasm' import type { Expr } from '@src/lang/wasm'
import { useCalculateKclExpression } from '@src/lib/useCalculateKclExpression' import { useCalculateKclExpression } from '@src/lib/useCalculateKclExpression'
import type { Selections } from '@src/lib/selections'
type ModalResolve = { type ModalResolve = {
value: string value: string
@ -27,6 +28,7 @@ type GetInfoModalProps = InstanceProps<ModalResolve, ModalReject> & {
isSegNameEditable: boolean isSegNameEditable: boolean
value?: number value?: number
initialVariableName: string initialVariableName: string
selectionRanges: Selections
} }
export const createInfoModal = create< export const createInfoModal = create<
@ -43,6 +45,7 @@ export const GetInfoModal = ({
isSegNameEditable, isSegNameEditable,
value: initialValue, value: initialValue,
initialVariableName, initialVariableName,
selectionRanges,
}: GetInfoModalProps) => { }: GetInfoModalProps) => {
const [sign, setSign] = useState(Math.sign(Number(initialValue))) const [sign, setSign] = useState(Math.sign(Number(initialValue)))
const [segName, setSegName] = useState(initialSegName) const [segName, setSegName] = useState(initialSegName)
@ -60,7 +63,11 @@ export const GetInfoModal = ({
newVariableName, newVariableName,
isNewVariableNameUnique, isNewVariableNameUnique,
newVariableInsertIndex, newVariableInsertIndex,
} = useCalculateKclExpression({ value: value, initialVariableName }) } = useCalculateKclExpression({
value: value,
initialVariableName,
selectionRanges,
})
return ( return (
<Transition appear show={isOpen} as={Fragment}> <Transition appear show={isOpen} as={Fragment}>

View File

@ -6,11 +6,13 @@ import { type InstanceProps, create } from 'react-modal-promise'
import { ActionButton } from '@src/components/ActionButton' import { ActionButton } from '@src/components/ActionButton'
import { CreateNewVariable } from '@src/components/AvailableVarsHelpers' import { CreateNewVariable } from '@src/components/AvailableVarsHelpers'
import { useCalculateKclExpression } from '@src/lib/useCalculateKclExpression' import { useCalculateKclExpression } from '@src/lib/useCalculateKclExpression'
import type { Selections } from '@src/lib/selections'
type ModalResolve = { variableName: string } type ModalResolve = { variableName: string }
type ModalReject = boolean type ModalReject = boolean
type SetVarNameModalProps = InstanceProps<ModalResolve, ModalReject> & { type SetVarNameModalProps = InstanceProps<ModalResolve, ModalReject> & {
valueName: string valueName: string
selectionRanges: Selections
} }
export const createSetVarNameModal = create< export const createSetVarNameModal = create<
@ -24,9 +26,14 @@ export const SetVarNameModal = ({
onResolve, onResolve,
onReject, onReject,
valueName, valueName,
selectionRanges,
}: SetVarNameModalProps) => { }: SetVarNameModalProps) => {
const { isNewVariableNameUnique, newVariableName, setNewVariableName } = const { isNewVariableNameUnique, newVariableName, setNewVariableName } =
useCalculateKclExpression({ value: '', initialVariableName: valueName }) useCalculateKclExpression({
value: '',
initialVariableName: valueName,
selectionRanges,
})
return ( return (
<Transition appear show={isOpen} as={Fragment}> <Transition appear show={isOpen} as={Fragment}>

View File

@ -1,5 +1,4 @@
import type { Node } from '@rust/kcl-lib/bindings/Node' import type { Node } from '@rust/kcl-lib/bindings/Node'
import { removeDoubleNegatives } from '@src/components/AvailableVarsHelpers' import { removeDoubleNegatives } from '@src/components/AvailableVarsHelpers'
import { import {
GetInfoModal, GetInfoModal,
@ -167,6 +166,7 @@ export async function applyConstraintIntersect({
isSegNameEditable: !tagInfo?.isTagExisting, isSegNameEditable: !tagInfo?.isTagExisting,
value: valueUsedInTransform, value: valueUsedInTransform,
initialVariableName: 'offset', initialVariableName: 'offset',
selectionRanges,
}) })
if ( if (
!variableName && !variableName &&

View File

@ -113,6 +113,7 @@ export async function applyConstraintAbsDistance({
await getModalInfo({ await getModalInfo({
value: forceVal, value: forceVal,
valueName: constraint === 'yAbs' ? 'yDis' : 'xDis', valueName: constraint === 'yAbs' ? 'yDis' : 'xDis',
selectionRanges,
}) })
if (!isExprBinaryPart(valueNode)) if (!isExprBinaryPart(valueNode))
return Promise.reject('Invalid valueNode, is not a BinaryPart') return Promise.reject('Invalid valueNode, is not a BinaryPart')

View File

@ -117,7 +117,8 @@ export async function applyConstraintAngleBetween({
isSegNameEditable: !tagInfo?.isTagExisting, isSegNameEditable: !tagInfo?.isTagExisting,
value: valueUsedInTransform, value: valueUsedInTransform,
initialVariableName: 'angle', initialVariableName: 'angle',
} as any) selectionRanges,
})
if ( if (
segName === tagInfo?.tag && segName === tagInfo?.tag &&
Number(value) === valueUsedInTransform && Number(value) === valueUsedInTransform &&

View File

@ -123,7 +123,8 @@ export async function applyConstraintHorzVertDistance({
isSegNameEditable: !tagInfo?.isTagExisting, isSegNameEditable: !tagInfo?.isTagExisting,
value: valueUsedInTransform, value: valueUsedInTransform,
initialVariableName: constraint === 'setHorzDistance' ? 'xDis' : 'yDis', initialVariableName: constraint === 'setHorzDistance' ? 'xDis' : 'yDis',
} as any) selectionRanges,
})
if ( if (
!variableName && !variableName &&
segName === tagInfo?.tag && segName === tagInfo?.tag &&

View File

@ -143,6 +143,7 @@ export async function applyConstraintAngleLength({
value: forceVal, value: forceVal,
valueName: angleOrLength === 'setAngle' ? 'angle' : 'length', valueName: angleOrLength === 'setAngle' ? 'angle' : 'length',
shouldCreateVariable: true, shouldCreateVariable: true,
selectionRanges,
}) })
if (!isExprBinaryPart(valueNode)) if (!isExprBinaryPart(valueNode))
return Promise.reject('Invalid valueNode, is not a BinaryPart') return Promise.reject('Invalid valueNode, is not a BinaryPart')

View File

@ -52,6 +52,7 @@ export function useConvertToVariable(range?: SourceRange) {
try { try {
const { variableName } = await getVarNameModal({ const { variableName } = await getVarNameModal({
valueName: valueName || 'var', valueName: valueName || 'var',
selectionRanges: context.selectionRanges,
}) })
const { modifiedAst: _modifiedAst, pathToReplacedNode } = const { modifiedAst: _modifiedAst, pathToReplacedNode } =

View File

@ -1,6 +1,4 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useModelingContext } from '@src/hooks/useModelingContext'
import { useKclContext } from '@src/lang/KclProvider' import { useKclContext } from '@src/lang/KclProvider'
import { findUniqueName } from '@src/lang/create' import { findUniqueName } from '@src/lang/create'
import type { PrevVariable } from '@src/lang/queryAst' import type { PrevVariable } from '@src/lang/queryAst'
@ -12,6 +10,7 @@ import { getCalculatedKclExpressionValue } from '@src/lib/kclHelpers'
import { kclManager } from '@src/lib/singletons' import { kclManager } from '@src/lib/singletons'
import { err } from '@src/lib/trap' import { err } from '@src/lib/trap'
import { getInVariableCase } from '@src/lib/utils' import { getInVariableCase } from '@src/lib/utils'
import type { Selections } from '@src/lib/selections'
const isValidVariableName = (name: string) => const isValidVariableName = (name: string) =>
/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name) /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)
@ -25,10 +24,12 @@ export function useCalculateKclExpression({
value, value,
initialVariableName: valueName = '', initialVariableName: valueName = '',
sourceRange, sourceRange,
selectionRanges,
}: { }: {
value: string value: string
initialVariableName?: string initialVariableName?: string
sourceRange?: SourceRange sourceRange?: SourceRange
selectionRanges: Selections
}): { }): {
inputRef: React.RefObject<HTMLInputElement> inputRef: React.RefObject<HTMLInputElement>
valueNode: Expr | null valueNode: Expr | null
@ -45,12 +46,10 @@ export function useCalculateKclExpression({
// has completed // has completed
const [isExecuting, setIsExecuting] = useState(false) const [isExecuting, setIsExecuting] = useState(false)
const { variables, code } = useKclContext() const { variables, code } = useKclContext()
const { context } = useModelingContext()
// If there is no selection, use the end of the code // If there is no selection, use the end of the code
// so all variables are available // so all variables are available
const selectionRange: const selectionRange: SourceRange | undefined =
| (typeof context)['selectionRanges']['graphSelections'][number]['codeRef']['range'] selectionRanges.graphSelections[0]?.codeRef?.range
| undefined = context.selectionRanges.graphSelections[0]?.codeRef?.range
// If there is no selection, use the end of the code // If there is no selection, use the end of the code
// If we don't memoize this, we risk an infinite set/read state loop // If we don't memoize this, we risk an infinite set/read state loop
const endingSourceRange = useMemo( const endingSourceRange = useMemo(

View File

@ -29,7 +29,6 @@ import {
applyConstraintHorzVert, applyConstraintHorzVert,
horzVertInfo, horzVertInfo,
} from '@src/components/Toolbar/HorzVert' } from '@src/components/Toolbar/HorzVert'
import { intersectInfo } from '@src/components/Toolbar/Intersect'
import { import {
applyRemoveConstrainingValues, applyRemoveConstrainingValues,
removeConstrainingValuesInfo, removeConstrainingValuesInfo,
@ -155,6 +154,7 @@ import type { Plane } from '@rust/kcl-lib/bindings/Plane'
import type { Point3d } from '@rust/kcl-lib/bindings/ModelingCmd' import type { Point3d } from '@rust/kcl-lib/bindings/ModelingCmd'
import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils' import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils'
import { letEngineAnimateAndSyncCamAfter } from '@src/clientSideScene/CameraControls' import { letEngineAnimateAndSyncCamAfter } from '@src/clientSideScene/CameraControls'
import { intersectInfo } from '@src/components/Toolbar/Intersect'
export type SetSelections = export type SetSelections =
| { | {