Compare commits
7 Commits
v0.24.1
...
migrate-to
Author | SHA1 | Date | |
---|---|---|---|
6717543305 | |||
d822593f35 | |||
5a236577bb | |||
96346cfedf | |||
866dffbb46 | |||
e86c628118 | |||
28cd330fc2 |
@ -1175,11 +1175,11 @@ const part003 = startSketchOn('-XZ')
|
|||||||
|
|
||||||
fn yohey = (pos) => {
|
fn yohey = (pos) => {
|
||||||
const part004 = startSketchOn('-XZ')
|
const part004 = startSketchOn('-XZ')
|
||||||
${extrudeAndEditBlockedInFunction}
|
${extrudeAndEditBlockedInFunction}
|
||||||
|> line([27.55, -1.65], %)
|
|> line([27.55, -1.65], %)
|
||||||
|> line([4.95, -10.53], %)
|
|> line([4.95, -10.53], %)
|
||||||
|> line([-20.38, -8], %)
|
|> line([-20.38, -8], %)
|
||||||
|> line([-15.79, 17.08], %)
|
|> line([-15.79, 17.08], %)
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,7 +1189,7 @@ fn yohey = (pos) => {
|
|||||||
},
|
},
|
||||||
selectionsSnippets
|
selectionsSnippets
|
||||||
)
|
)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ test('exports of each format should work', async ({ page, context }) => {
|
|||||||
// FYI this test doesn't work with only engine running locally
|
// FYI this test doesn't work with only engine running locally
|
||||||
// And you will need to have the KittyCAD CLI installed
|
// And you will need to have the KittyCAD CLI installed
|
||||||
const u = getUtils(page)
|
const u = getUtils(page)
|
||||||
await context.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
;(window as any).playwrightSkipFilePicker = true
|
;(window as any).playwrightSkipFilePicker = true
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -79,6 +79,7 @@ const part001 = startSketchOn('-XZ')
|
|||||||
|> extrude(4, %)`
|
|> extrude(4, %)`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
@ -171,7 +171,7 @@ const FileTreeItem = ({
|
|||||||
|
|
||||||
if (fileOrDir.name?.endsWith(FILE_EXT) === false && project?.path) {
|
if (fileOrDir.name?.endsWith(FILE_EXT) === false && project?.path) {
|
||||||
// Import non-kcl files
|
// Import non-kcl files
|
||||||
kclManager.setCodeAndExecute(
|
kclManager.setCode(
|
||||||
`import("${fileOrDir.path.replace(project.path, '.')}")\n` +
|
`import("${fileOrDir.path.replace(project.path, '.')}")\n` +
|
||||||
kclManager.code
|
kclManager.code
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,7 @@ import {
|
|||||||
} from './Toolbar/SetAngleBetween'
|
} from './Toolbar/SetAngleBetween'
|
||||||
import { applyConstraintAngleLength } from './Toolbar/setAngleLength'
|
import { applyConstraintAngleLength } from './Toolbar/setAngleLength'
|
||||||
import { pathMapToSelections } from 'lang/util'
|
import { pathMapToSelections } from 'lang/util'
|
||||||
|
import { useLspContext } from 'components/LspProvider'
|
||||||
import { useStore } from 'useStore'
|
import { useStore } from 'useStore'
|
||||||
import {
|
import {
|
||||||
Selections,
|
Selections,
|
||||||
@ -86,6 +87,7 @@ export const ModelingMachineProvider = ({
|
|||||||
htmlRef,
|
htmlRef,
|
||||||
token
|
token
|
||||||
)
|
)
|
||||||
|
const { lspClients } = useLspContext()
|
||||||
useHotkeys('meta + shift + .', () => coreDump(coreDumpManager, true))
|
useHotkeys('meta + shift + .', () => coreDump(coreDumpManager, true))
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -116,6 +118,24 @@ export const ModelingMachineProvider = ({
|
|||||||
modelingMachine,
|
modelingMachine,
|
||||||
{
|
{
|
||||||
actions: {
|
actions: {
|
||||||
|
'disable lsp execution': async () => {
|
||||||
|
// Update the lsp server that we are in sketch mode, so we can turn off lsp execution.
|
||||||
|
for (const lspClient of lspClients) {
|
||||||
|
for (const plugin of lspClient.plugins) {
|
||||||
|
await plugin.updateCanExecute(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await kclManager.enterEditMode()
|
||||||
|
console.log('done with disabling lsp execution')
|
||||||
|
},
|
||||||
|
'enable lsp execution': async () => {
|
||||||
|
// Update the lsp server that we are done with sketch mode, so we can turn back on lsp execution.
|
||||||
|
for (const lspClient of lspClients) {
|
||||||
|
for (const plugin of lspClient.plugins) {
|
||||||
|
await plugin.updateCanExecute(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
'sketch exit execute': () => {
|
'sketch exit execute': () => {
|
||||||
try {
|
try {
|
||||||
kclManager.executeAst(parse(kclManager.code))
|
kclManager.executeAst(parse(kclManager.code))
|
||||||
|
@ -5,7 +5,7 @@ import { useCommandsContext } from 'hooks/useCommandsContext'
|
|||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
import { useConvertToVariable } from 'hooks/useToolbarGuards'
|
import { useConvertToVariable } from 'hooks/useToolbarGuards'
|
||||||
import { Themes, getSystemTheme } from 'lib/theme'
|
import { Themes, getSystemTheme } from 'lib/theme'
|
||||||
import { useEffect, useMemo, useRef } from 'react'
|
import { useMemo, useRef } from 'react'
|
||||||
import { useStore } from 'useStore'
|
import { useStore } from 'useStore'
|
||||||
import { processCodeMirrorRanges } from 'lib/selections'
|
import { processCodeMirrorRanges } from 'lib/selections'
|
||||||
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'
|
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'
|
||||||
@ -29,7 +29,7 @@ import {
|
|||||||
historyKeymap,
|
historyKeymap,
|
||||||
history,
|
history,
|
||||||
} from '@codemirror/commands'
|
} from '@codemirror/commands'
|
||||||
import { lintGutter, lintKeymap, linter } from '@codemirror/lint'
|
import { lintGutter, lintKeymap } from '@codemirror/lint'
|
||||||
import {
|
import {
|
||||||
foldGutter,
|
foldGutter,
|
||||||
foldKeymap,
|
foldKeymap,
|
||||||
@ -57,11 +57,6 @@ import {
|
|||||||
completionKeymap,
|
completionKeymap,
|
||||||
hasNextSnippetField,
|
hasNextSnippetField,
|
||||||
} from '@codemirror/autocomplete'
|
} from '@codemirror/autocomplete'
|
||||||
import {
|
|
||||||
NetworkHealthState,
|
|
||||||
useNetworkStatus,
|
|
||||||
} from 'components/NetworkHealthIndicator'
|
|
||||||
import { kclErrorsToDiagnostics } from 'lang/errors'
|
|
||||||
|
|
||||||
export const editorShortcutMeta = {
|
export const editorShortcutMeta = {
|
||||||
formatCode: {
|
formatCode: {
|
||||||
@ -86,20 +81,11 @@ export const KclEditorPane = () => {
|
|||||||
setEditorView: s.setEditorView,
|
setEditorView: s.setEditorView,
|
||||||
isShiftDown: s.isShiftDown,
|
isShiftDown: s.isShiftDown,
|
||||||
}))
|
}))
|
||||||
const { code, errors } = useKclContext()
|
const { code } = useKclContext()
|
||||||
const lastEvent = useRef({ event: '', time: Date.now() })
|
const lastEvent = useRef({ event: '', time: Date.now() })
|
||||||
const { copilotLSP, kclLSP } = useLspContext()
|
const { copilotLSP, kclLSP } = useLspContext()
|
||||||
const { overallState } = useNetworkStatus()
|
|
||||||
const isNetworkOkay = overallState === NetworkHealthState.Ok
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (typeof window === 'undefined') return
|
|
||||||
const onlineCallback = () => kclManager.setCodeAndExecute(kclManager.code)
|
|
||||||
window.addEventListener('online', onlineCallback)
|
|
||||||
return () => window.removeEventListener('online', onlineCallback)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useHotkeys('mod+z', (e) => {
|
useHotkeys('mod+z', (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (editorView) {
|
if (editorView) {
|
||||||
@ -136,8 +122,7 @@ export const KclEditorPane = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNetworkOkay) kclManager.setCodeAndExecute(newCode)
|
kclManager.setCode(newCode)
|
||||||
else kclManager.setCode(newCode)
|
|
||||||
}
|
}
|
||||||
const lastSelection = useRef('')
|
const lastSelection = useRef('')
|
||||||
const onUpdate = (viewUpdate: ViewUpdate) => {
|
const onUpdate = (viewUpdate: ViewUpdate) => {
|
||||||
@ -252,9 +237,6 @@ export const KclEditorPane = () => {
|
|||||||
if (!TEST) {
|
if (!TEST) {
|
||||||
extensions.push(
|
extensions.push(
|
||||||
lintGutter(),
|
lintGutter(),
|
||||||
linter((_view: EditorView) => {
|
|
||||||
return kclErrorsToDiagnostics(errors)
|
|
||||||
}),
|
|
||||||
lineNumbers(),
|
lineNumbers(),
|
||||||
highlightActiveLineGutter(),
|
highlightActiveLineGutter(),
|
||||||
highlightSpecialChars(),
|
highlightSpecialChars(),
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
} from 'xstate'
|
} from 'xstate'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
|
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
|
||||||
import { kclManager, sceneInfra, engineCommandManager } from 'lib/singletons'
|
import { sceneInfra, engineCommandManager } from 'lib/singletons'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
import { IndexLoaderData } from 'lib/types'
|
import { IndexLoaderData } from 'lib/types'
|
||||||
import { settings } from 'lib/settings/initialSettings'
|
import { settings } from 'lib/settings/initialSettings'
|
||||||
@ -138,7 +138,6 @@ export const SettingsAuthProviderBase = ({
|
|||||||
id: `${event.type}.success`,
|
id: `${event.type}.success`,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
'Execute AST': () => kclManager.executeAst(),
|
|
||||||
persistSettings: (context) =>
|
persistSettings: (context) =>
|
||||||
saveSettings(context, loadedProject?.project?.path),
|
saveSettings(context, loadedProject?.project?.path),
|
||||||
},
|
},
|
||||||
|
@ -12,7 +12,6 @@ import {
|
|||||||
CompletionTriggerKind,
|
CompletionTriggerKind,
|
||||||
} from 'vscode-languageserver-protocol'
|
} from 'vscode-languageserver-protocol'
|
||||||
|
|
||||||
import { deferExecution } from 'lib/utils'
|
|
||||||
import type {
|
import type {
|
||||||
Completion,
|
Completion,
|
||||||
CompletionContext,
|
CompletionContext,
|
||||||
@ -43,8 +42,6 @@ const CompletionItemKindMap = Object.fromEntries(
|
|||||||
Object.entries(CompletionItemKind).map(([key, value]) => [value, key])
|
Object.entries(CompletionItemKind).map(([key, value]) => [value, key])
|
||||||
) as Record<CompletionItemKind, string>
|
) as Record<CompletionItemKind, string>
|
||||||
|
|
||||||
const changesDelay = 600
|
|
||||||
|
|
||||||
export class LanguageServerPlugin implements PluginValue {
|
export class LanguageServerPlugin implements PluginValue {
|
||||||
public client: LanguageServerClient
|
public client: LanguageServerClient
|
||||||
public documentUri: string
|
public documentUri: string
|
||||||
@ -52,19 +49,6 @@ export class LanguageServerPlugin implements PluginValue {
|
|||||||
public workspaceFolders: LSP.WorkspaceFolder[]
|
public workspaceFolders: LSP.WorkspaceFolder[]
|
||||||
private documentVersion: number
|
private documentVersion: number
|
||||||
private foldingRanges: LSP.FoldingRange[] | null = null
|
private foldingRanges: LSP.FoldingRange[] | null = null
|
||||||
private _defferer = deferExecution((code: string) => {
|
|
||||||
try {
|
|
||||||
this.client.textDocumentDidChange({
|
|
||||||
textDocument: {
|
|
||||||
uri: this.documentUri,
|
|
||||||
version: this.documentVersion++,
|
|
||||||
},
|
|
||||||
contentChanges: [{ text: code }],
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
}, changesDelay)
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: LanguageServerClient,
|
client: LanguageServerClient,
|
||||||
@ -134,7 +118,17 @@ export class LanguageServerPlugin implements PluginValue {
|
|||||||
documentText = ''
|
documentText = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
this._defferer(documentText)
|
try {
|
||||||
|
this.client.textDocumentDidChange({
|
||||||
|
textDocument: {
|
||||||
|
uri: this.documentUri,
|
||||||
|
version: this.documentVersion++,
|
||||||
|
},
|
||||||
|
contentChanges: [{ text: documentText }],
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
requestDiagnostics(view: EditorView) {
|
requestDiagnostics(view: EditorView) {
|
||||||
@ -380,10 +374,10 @@ export class LanguageServerPlugin implements PluginValue {
|
|||||||
const params = notification.params as PublishDiagnosticsParams
|
const params = notification.params as PublishDiagnosticsParams
|
||||||
this.processDiagnostics(params)
|
this.processDiagnostics(params)
|
||||||
// Update the kcl errors pane.
|
// Update the kcl errors pane.
|
||||||
/*kclManager.kclErrors = lspDiagnosticsToKclErrors(
|
kclManager.kclErrors = lspDiagnosticsToKclErrors(
|
||||||
this.view.state.doc,
|
this.view.state.doc,
|
||||||
params.diagnostics
|
params.diagnostics
|
||||||
)*/
|
)
|
||||||
break
|
break
|
||||||
case 'window/logMessage':
|
case 'window/logMessage':
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -3,7 +3,7 @@ import { useStore } from '../useStore'
|
|||||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||||
import { deferExecution } from 'lib/utils'
|
import { deferExecution } from 'lib/utils'
|
||||||
import { Themes } from 'lib/theme'
|
import { Themes } from 'lib/theme'
|
||||||
import { makeDefaultPlanes, parse } from 'lang/wasm'
|
import { makeDefaultPlanes } from 'lang/wasm'
|
||||||
|
|
||||||
export function useSetupEngineManager(
|
export function useSetupEngineManager(
|
||||||
streamRef: React.RefObject<HTMLDivElement>,
|
streamRef: React.RefObject<HTMLDivElement>,
|
||||||
@ -40,10 +40,6 @@ export function useSetupEngineManager(
|
|||||||
setIsStreamReady,
|
setIsStreamReady,
|
||||||
width: quadWidth,
|
width: quadWidth,
|
||||||
height: quadHeight,
|
height: quadHeight,
|
||||||
executeCode: (code?: string) => {
|
|
||||||
const _ast = parse(code || kclManager.code)
|
|
||||||
return kclManager.executeAst(_ast, true)
|
|
||||||
},
|
|
||||||
token,
|
token,
|
||||||
theme,
|
theme,
|
||||||
makeDefaultPlanes: () => {
|
makeDefaultPlanes: () => {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { executeAst, executeCode } from 'useStore'
|
import { executeAst } from 'useStore'
|
||||||
import { Selections } from 'lib/selections'
|
import { Selections } from 'lib/selections'
|
||||||
import { KCLError } from './errors'
|
import { KCLError } from './errors'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
import { EngineCommandManager } from './std/engineConnection'
|
import { EngineCommandManager } from './std/engineConnection'
|
||||||
|
|
||||||
import { deferExecution } from 'lib/utils'
|
|
||||||
import {
|
import {
|
||||||
CallExpression,
|
CallExpression,
|
||||||
initPromise,
|
initPromise,
|
||||||
@ -47,19 +46,6 @@ export class KclManager {
|
|||||||
private _params: Params<string> = {}
|
private _params: Params<string> = {}
|
||||||
|
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
private _defferer = deferExecution((code: string) => {
|
|
||||||
const ast = this.safeParse(code)
|
|
||||||
if (!ast) return
|
|
||||||
try {
|
|
||||||
const fmtAndStringify = (ast: Program) =>
|
|
||||||
JSON.stringify(parse(recast(ast)))
|
|
||||||
const isAstTheSame = fmtAndStringify(ast) === fmtAndStringify(this._ast)
|
|
||||||
if (isAstTheSame) return
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
this.executeAst(ast)
|
|
||||||
}, 600)
|
|
||||||
|
|
||||||
private _isExecutingCallback: (arg: boolean) => void = () => {}
|
private _isExecutingCallback: (arg: boolean) => void = () => {}
|
||||||
private _codeCallBack: (arg: string) => void = () => {}
|
private _codeCallBack: (arg: string) => void = () => {}
|
||||||
@ -81,6 +67,9 @@ export class KclManager {
|
|||||||
get code() {
|
get code() {
|
||||||
return this._code
|
return this._code
|
||||||
}
|
}
|
||||||
|
// Calling set code will update the code in the codemirror editor.
|
||||||
|
// That will then trigger the lsp to update the ast and execute the code.
|
||||||
|
// DO NOT ALSO CALL execute/parseCode here, as that will cause the code to be executed twice.
|
||||||
set code(code) {
|
set code(code) {
|
||||||
this._code = code
|
this._code = code
|
||||||
this._codeCallBack(code)
|
this._codeCallBack(code)
|
||||||
@ -106,6 +95,12 @@ export class KclManager {
|
|||||||
set programMemory(programMemory) {
|
set programMemory(programMemory) {
|
||||||
this._programMemory = programMemory
|
this._programMemory = programMemory
|
||||||
this._programMemoryCallBack(programMemory)
|
this._programMemoryCallBack(programMemory)
|
||||||
|
// We only do this to help the playwright testes otherwise I would remove
|
||||||
|
// it. (@jessfraz wrote this comment)
|
||||||
|
this.engineCommandManager.addCommandLog({
|
||||||
|
type: 'execution-done',
|
||||||
|
data: null,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get logs() {
|
get logs() {
|
||||||
@ -208,7 +203,6 @@ export class KclManager {
|
|||||||
console.error('error parsing code', e)
|
console.error('error parsing code', e)
|
||||||
if (e instanceof KCLError) {
|
if (e instanceof KCLError) {
|
||||||
this.kclErrors = [e]
|
this.kclErrors = [e]
|
||||||
if (e.msg === 'file is empty') this.engineCommandManager?.endSession()
|
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -220,8 +214,9 @@ export class KclManager {
|
|||||||
if (this.wasmInitFailed) {
|
if (this.wasmInitFailed) {
|
||||||
this.wasmInitFailed = false
|
this.wasmInitFailed = false
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
this.wasmInitFailed = true
|
this.wasmInitFailed = true
|
||||||
|
throw new Error('error initializing wasm: ' + e.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +236,7 @@ export class KclManager {
|
|||||||
ast,
|
ast,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
})
|
})
|
||||||
enterEditMode(programMemory, this.engineCommandManager)
|
await enterEditMode(programMemory, this.engineCommandManager)
|
||||||
this.isExecuting = false
|
this.isExecuting = false
|
||||||
// Check the cancellation token for this execution before applying side effects
|
// Check the cancellation token for this execution before applying side effects
|
||||||
if (this._cancelTokens.get(currentExecutionId)) {
|
if (this._cancelTokens.get(currentExecutionId)) {
|
||||||
@ -276,7 +271,7 @@ export class KclManager {
|
|||||||
if (!newAst) return
|
if (!newAst) return
|
||||||
await this?.engineCommandManager?.waitForReady
|
await this?.engineCommandManager?.waitForReady
|
||||||
if (updates !== 'none') {
|
if (updates !== 'none') {
|
||||||
this.setCode(recast(ast))
|
this.setCode(newCode)
|
||||||
}
|
}
|
||||||
this._ast = { ...newAst }
|
this._ast = { ...newAst }
|
||||||
|
|
||||||
@ -308,41 +303,14 @@ export class KclManager {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
executeCode = async (code?: string, executionId?: number) => {
|
|
||||||
const currentExecutionId = executionId || Date.now()
|
|
||||||
this._cancelTokens.set(currentExecutionId, false)
|
|
||||||
if (this._cancelTokens.get(currentExecutionId)) {
|
|
||||||
this._cancelTokens.delete(currentExecutionId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await this.ensureWasmInit()
|
|
||||||
await this?.engineCommandManager?.waitForReady
|
|
||||||
const result = await executeCode({
|
|
||||||
engineCommandManager: this.engineCommandManager,
|
|
||||||
code: code || this._code,
|
|
||||||
lastAst: this._ast,
|
|
||||||
force: false,
|
|
||||||
})
|
|
||||||
// Check the cancellation token for this execution before applying side effects
|
|
||||||
if (this._cancelTokens.get(currentExecutionId)) {
|
|
||||||
this._cancelTokens.delete(currentExecutionId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!result.isChange) return
|
|
||||||
const { logs, errors, programMemory, ast } = result
|
|
||||||
enterEditMode(programMemory, this.engineCommandManager)
|
|
||||||
this.logs = logs
|
|
||||||
this.kclErrors = errors
|
|
||||||
this.programMemory = programMemory
|
|
||||||
this.ast = ast
|
|
||||||
if (code) this.code = code
|
|
||||||
this._cancelTokens.delete(currentExecutionId)
|
|
||||||
}
|
|
||||||
cancelAllExecutions() {
|
cancelAllExecutions() {
|
||||||
this._cancelTokens.forEach((_, key) => {
|
this._cancelTokens.forEach((_, key) => {
|
||||||
this._cancelTokens.set(key, true)
|
this._cancelTokens.set(key, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// Calling set code will update the code in the codemirror editor.
|
||||||
|
// That will then trigger the lsp to update the ast and execute the code.
|
||||||
|
// DO NOT ALSO CALL execute/parseCode here, as that will cause the code to be executed twice.
|
||||||
setCode(code: string, shouldWriteFile = true) {
|
setCode(code: string, shouldWriteFile = true) {
|
||||||
if (shouldWriteFile) {
|
if (shouldWriteFile) {
|
||||||
// use the normal code setter
|
// use the normal code setter
|
||||||
@ -352,27 +320,6 @@ export class KclManager {
|
|||||||
this._code = code
|
this._code = code
|
||||||
this._codeCallBack(code)
|
this._codeCallBack(code)
|
||||||
}
|
}
|
||||||
setCodeAndExecute(code: string, shouldWriteFile = true) {
|
|
||||||
this.setCode(code, shouldWriteFile)
|
|
||||||
if (code.trim()) {
|
|
||||||
this._defferer(code)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this._ast = {
|
|
||||||
body: [],
|
|
||||||
start: 0,
|
|
||||||
end: 0,
|
|
||||||
nonCodeMeta: {
|
|
||||||
nonCodeNodes: {},
|
|
||||||
start: [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
this._programMemory = {
|
|
||||||
root: {},
|
|
||||||
return: null,
|
|
||||||
}
|
|
||||||
this.engineCommandManager.endSession()
|
|
||||||
}
|
|
||||||
format() {
|
format() {
|
||||||
const ast = this.safeParse(this.code)
|
const ast = this.safeParse(this.code)
|
||||||
if (!ast) return
|
if (!ast) return
|
||||||
@ -440,6 +387,10 @@ export class KclManager {
|
|||||||
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, true)
|
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, true)
|
||||||
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xz, true)
|
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xz, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async enterEditMode() {
|
||||||
|
await enterEditMode(this.programMemory, this.engineCommandManager)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function safeLSGetItem(key: string) {
|
function safeLSGetItem(key: string) {
|
||||||
@ -452,7 +403,7 @@ function safteLSSetItem(key: string, value: string) {
|
|||||||
localStorage?.setItem(key, value)
|
localStorage?.setItem(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function enterEditMode(
|
async function enterEditMode(
|
||||||
programMemory: ProgramMemory,
|
programMemory: ProgramMemory,
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
) {
|
) {
|
||||||
@ -460,7 +411,7 @@ function enterEditMode(
|
|||||||
(node) => node.type === 'ExtrudeGroup' || node.type === 'SketchGroup'
|
(node) => node.type === 'ExtrudeGroup' || node.type === 'SketchGroup'
|
||||||
) as SketchGroup | ExtrudeGroup
|
) as SketchGroup | ExtrudeGroup
|
||||||
firstSketchOrExtrudeGroup &&
|
firstSketchOrExtrudeGroup &&
|
||||||
engineCommandManager.sendSceneCommand({
|
(await engineCommandManager.sendSceneCommand({
|
||||||
type: 'modeling_cmd_batch_req',
|
type: 'modeling_cmd_batch_req',
|
||||||
batch_id: uuidv4(),
|
batch_id: uuidv4(),
|
||||||
requests: [
|
requests: [
|
||||||
@ -479,5 +430,5 @@ function enterEditMode(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
@ -921,7 +921,6 @@ export class EngineCommandManager {
|
|||||||
setIsStreamReady,
|
setIsStreamReady,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
executeCode,
|
|
||||||
token,
|
token,
|
||||||
makeDefaultPlanes,
|
makeDefaultPlanes,
|
||||||
theme = Themes.Dark,
|
theme = Themes.Dark,
|
||||||
@ -930,7 +929,6 @@ export class EngineCommandManager {
|
|||||||
setIsStreamReady: (isStreamReady: boolean) => void
|
setIsStreamReady: (isStreamReady: boolean) => void
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
executeCode: (code?: string, force?: boolean) => void
|
|
||||||
token?: string
|
token?: string
|
||||||
makeDefaultPlanes: () => Promise<DefaultPlanes>
|
makeDefaultPlanes: () => Promise<DefaultPlanes>
|
||||||
theme?: Themes
|
theme?: Themes
|
||||||
@ -1005,7 +1003,6 @@ export class EngineCommandManager {
|
|||||||
this.initPlanes().then(() => {
|
this.initPlanes().then(() => {
|
||||||
this.resolveReady()
|
this.resolveReady()
|
||||||
setIsStreamReady(true)
|
setIsStreamReady(true)
|
||||||
executeCode(undefined, true)
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
|
@ -100,7 +100,7 @@ export const fileLoader: LoaderFunction = async ({
|
|||||||
const children = await invoke<FileEntry[]>('read_dir_recursive', {
|
const children = await invoke<FileEntry[]>('read_dir_recursive', {
|
||||||
path: projectPath,
|
path: projectPath,
|
||||||
})
|
})
|
||||||
kclManager.setCodeAndExecute(code, false)
|
kclManager.setCode(code, false)
|
||||||
|
|
||||||
// Set the file system manager to the project path
|
// Set the file system manager to the project path
|
||||||
// So that WASM gets an updated path for operations
|
// So that WASM gets an updated path for operations
|
||||||
|
@ -98,7 +98,6 @@ export async function executor(
|
|||||||
setMediaStream: () => {},
|
setMediaStream: () => {},
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
executeCode: () => {},
|
|
||||||
theme: Themes.Dark,
|
theme: Themes.Dark,
|
||||||
makeDefaultPlanes: () => {
|
makeDefaultPlanes: () => {
|
||||||
return new Promise((resolve) => resolve(defaultPlanes))
|
return new Promise((resolve) => resolve(defaultPlanes))
|
||||||
|
@ -192,7 +192,11 @@ export const modelingMachine = createMachine(
|
|||||||
Extrude: {
|
Extrude: {
|
||||||
target: 'idle',
|
target: 'idle',
|
||||||
cond: 'has valid extrude selection',
|
cond: 'has valid extrude selection',
|
||||||
actions: ['AST extrude'],
|
actions: [
|
||||||
|
'disable lsp execution',
|
||||||
|
'AST extrude',
|
||||||
|
'enable lsp execution',
|
||||||
|
],
|
||||||
internal: true,
|
internal: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -490,13 +494,18 @@ export const modelingMachine = createMachine(
|
|||||||
'tear down client sketch',
|
'tear down client sketch',
|
||||||
'remove sketch grid',
|
'remove sketch grid',
|
||||||
'engineToClient cam sync direction',
|
'engineToClient cam sync direction',
|
||||||
|
'enable lsp execution',
|
||||||
],
|
],
|
||||||
|
|
||||||
entry: ['add axis n grid', 'conditionally equip line tool'],
|
entry: ['add axis n grid', 'conditionally equip line tool'],
|
||||||
},
|
},
|
||||||
|
|
||||||
'Sketch no face': {
|
'Sketch no face': {
|
||||||
entry: ['show default planes', 'set selection filter to faces only'],
|
entry: [
|
||||||
|
'disable lsp execution',
|
||||||
|
'show default planes',
|
||||||
|
'set selection filter to faces only',
|
||||||
|
],
|
||||||
|
|
||||||
exit: ['hide default planes', 'set selection filter to defaults'],
|
exit: ['hide default planes', 'set selection filter to defaults'],
|
||||||
on: {
|
on: {
|
||||||
|
@ -45,7 +45,6 @@ export const settingsMachine = createMachine(
|
|||||||
'setSettingAtLevel',
|
'setSettingAtLevel',
|
||||||
'toastSuccess',
|
'toastSuccess',
|
||||||
'setClientSideSceneUnits',
|
'setClientSideSceneUnits',
|
||||||
'Execute AST',
|
|
||||||
'persistSettings',
|
'persistSettings',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -70,7 +69,6 @@ export const settingsMachine = createMachine(
|
|||||||
'setThemeClass',
|
'setThemeClass',
|
||||||
'setEngineTheme',
|
'setEngineTheme',
|
||||||
'setClientSideSceneUnits',
|
'setClientSideSceneUnits',
|
||||||
'Execute AST',
|
|
||||||
'persistSettings',
|
'persistSettings',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -83,7 +81,6 @@ export const settingsMachine = createMachine(
|
|||||||
'setThemeClass',
|
'setThemeClass',
|
||||||
'setEngineTheme',
|
'setEngineTheme',
|
||||||
'setClientSideSceneUnits',
|
'setClientSideSceneUnits',
|
||||||
'Execute AST',
|
|
||||||
'persistSettings',
|
'persistSettings',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -11,13 +11,8 @@ export default function FutureWork() {
|
|||||||
const dismiss = useDismiss()
|
const dismiss = useDismiss()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (kclManager.engineCommandManager.engineConnection?.isReady()) {
|
// Otherwise, just set the code and wait for the connection to complete
|
||||||
// If the engine is ready, promptly execute the loaded code
|
kclManager.setCode(bracket)
|
||||||
kclManager.setCodeAndExecute(bracket)
|
|
||||||
} else {
|
|
||||||
// Otherwise, just set the code and wait for the connection to complete
|
|
||||||
kclManager.setCode(bracket)
|
|
||||||
}
|
|
||||||
|
|
||||||
send({ type: 'Cancel' }) // in case the user hit 'Next' while still in sketch mode
|
send({ type: 'Cancel' }) // in case the user hit 'Next' while still in sketch mode
|
||||||
}, [send])
|
}, [send])
|
||||||
|
@ -70,7 +70,7 @@ function OnboardingWithNewFile() {
|
|||||||
className="mt-6"
|
className="mt-6"
|
||||||
dismiss={dismiss}
|
dismiss={dismiss}
|
||||||
next={() => {
|
next={() => {
|
||||||
kclManager.setCodeAndExecute(bracket)
|
kclManager.setCode(bracket)
|
||||||
next()
|
next()
|
||||||
}}
|
}}
|
||||||
nextText="Overwrite code and continue"
|
nextText="Overwrite code and continue"
|
||||||
|
@ -10,13 +10,7 @@ export default function Sketching() {
|
|||||||
const next = useNextClick(onboardingPaths.FUTURE_WORK)
|
const next = useNextClick(onboardingPaths.FUTURE_WORK)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (kclManager.engineCommandManager.engineConnection?.isReady()) {
|
kclManager.setCode('')
|
||||||
// If the engine is ready, promptly execute the loaded code
|
|
||||||
kclManager.setCodeAndExecute('')
|
|
||||||
} else {
|
|
||||||
// Otherwise, just set the code and wait for the connection to complete
|
|
||||||
kclManager.setCode('')
|
|
||||||
}
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -2,7 +2,6 @@ import { create } from 'zustand'
|
|||||||
import { persist } from 'zustand/middleware'
|
import { persist } from 'zustand/middleware'
|
||||||
import { addLineHighlight, EditorView } from './editor/highlightextension'
|
import { addLineHighlight, EditorView } from './editor/highlightextension'
|
||||||
import {
|
import {
|
||||||
parse,
|
|
||||||
Program,
|
Program,
|
||||||
_executor,
|
_executor,
|
||||||
ProgramMemory,
|
ProgramMemory,
|
||||||
@ -175,74 +174,6 @@ export const useStore = create<StoreState>()(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
export async function executeCode({
|
|
||||||
engineCommandManager,
|
|
||||||
code,
|
|
||||||
lastAst,
|
|
||||||
force,
|
|
||||||
}: {
|
|
||||||
code: string
|
|
||||||
lastAst: Program
|
|
||||||
engineCommandManager: EngineCommandManager
|
|
||||||
force?: boolean
|
|
||||||
}): Promise<
|
|
||||||
| {
|
|
||||||
logs: string[]
|
|
||||||
errors: KCLError[]
|
|
||||||
programMemory: ProgramMemory
|
|
||||||
ast: Program
|
|
||||||
isChange: true
|
|
||||||
}
|
|
||||||
| { isChange: false }
|
|
||||||
> {
|
|
||||||
let ast: Program
|
|
||||||
try {
|
|
||||||
ast = parse(code)
|
|
||||||
} catch (e) {
|
|
||||||
let errors: KCLError[] = []
|
|
||||||
let logs: string[] = [JSON.stringify(e)]
|
|
||||||
if (e instanceof KCLError) {
|
|
||||||
errors = [e]
|
|
||||||
logs = []
|
|
||||||
if (e.msg === 'file is empty') engineCommandManager.endSession()
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
isChange: true,
|
|
||||||
logs,
|
|
||||||
errors,
|
|
||||||
programMemory: {
|
|
||||||
root: {},
|
|
||||||
return: null,
|
|
||||||
},
|
|
||||||
ast: {
|
|
||||||
start: 0,
|
|
||||||
end: 0,
|
|
||||||
body: [],
|
|
||||||
nonCodeMeta: {
|
|
||||||
nonCodeNodes: {},
|
|
||||||
start: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if the ast we have is equal to the ast in the storage.
|
|
||||||
// If it is, we don't need to update the ast.
|
|
||||||
if (JSON.stringify(ast) === JSON.stringify(lastAst) && !force)
|
|
||||||
return { isChange: false }
|
|
||||||
|
|
||||||
const { logs, errors, programMemory } = await executeAst({
|
|
||||||
ast,
|
|
||||||
engineCommandManager,
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
ast,
|
|
||||||
logs,
|
|
||||||
errors,
|
|
||||||
programMemory,
|
|
||||||
isChange: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function executeAst({
|
export async function executeAst({
|
||||||
ast,
|
ast,
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
|
@ -223,8 +223,7 @@ pub async fn kcl_lsp_run(
|
|||||||
let engine = kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
let engine = kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("{:?}", e))?;
|
.map_err(|e| format!("{:?}", e))?;
|
||||||
// Turn off lsp execute for now
|
let executor_ctx = kcl_lib::executor::ExecutorContext {
|
||||||
let _executor_ctx = kcl_lib::executor::ExecutorContext {
|
|
||||||
engine: Arc::new(Box::new(engine)),
|
engine: Arc::new(Box::new(engine)),
|
||||||
fs: file_manager.clone(),
|
fs: file_manager.clone(),
|
||||||
stdlib: std::sync::Arc::new(stdlib),
|
stdlib: std::sync::Arc::new(stdlib),
|
||||||
@ -266,8 +265,8 @@ pub async fn kcl_lsp_run(
|
|||||||
semantic_tokens_map: Default::default(),
|
semantic_tokens_map: Default::default(),
|
||||||
zoo_client,
|
zoo_client,
|
||||||
can_send_telemetry: privacy_settings.can_train_on_data,
|
can_send_telemetry: privacy_settings.can_train_on_data,
|
||||||
executor_ctx: Default::default(),
|
executor_ctx: Arc::new(tokio::sync::RwLock::new(Some(executor_ctx))),
|
||||||
can_execute: Default::default(),
|
can_execute: Arc::new(tokio::sync::RwLock::new(true)),
|
||||||
|
|
||||||
is_initialized: Default::default(),
|
is_initialized: Default::default(),
|
||||||
current_handle: Default::default(),
|
current_handle: Default::default(),
|
||||||
|
Reference in New Issue
Block a user