persist code in local storage (#34)
Just a little frustrating to have code disapear on you, will probably need to be made less naive at some point
This commit is contained in:
105
src/App.tsx
105
src/App.tsx
@ -1,8 +1,8 @@
|
|||||||
import { useRef, useState, useEffect, useMemo } from 'react'
|
import { useRef, useState, useEffect } from 'react'
|
||||||
import { Canvas } from '@react-three/fiber'
|
import { Canvas } from '@react-three/fiber'
|
||||||
import { Allotment } from 'allotment'
|
import { Allotment } from 'allotment'
|
||||||
import { OrbitControls, OrthographicCamera } from '@react-three/drei'
|
import { OrbitControls, OrthographicCamera } from '@react-three/drei'
|
||||||
import { lexer } from './lang/tokeniser'
|
import { asyncLexer } from './lang/tokeniser'
|
||||||
import { abstractSyntaxTree } from './lang/abstractSyntaxTree'
|
import { abstractSyntaxTree } from './lang/abstractSyntaxTree'
|
||||||
import { executor, ExtrudeGroup, SketchGroup } from './lang/executor'
|
import { executor, ExtrudeGroup, SketchGroup } from './lang/executor'
|
||||||
import { recast } from './lang/recast'
|
import { recast } from './lang/recast'
|
||||||
@ -40,8 +40,6 @@ function App() {
|
|||||||
code,
|
code,
|
||||||
setCode,
|
setCode,
|
||||||
setAst,
|
setAst,
|
||||||
// formatCode,
|
|
||||||
ast,
|
|
||||||
setError,
|
setError,
|
||||||
errorState,
|
errorState,
|
||||||
setProgramMemory,
|
setProgramMemory,
|
||||||
@ -56,10 +54,8 @@ function App() {
|
|||||||
addLog: s.addLog,
|
addLog: s.addLog,
|
||||||
code: s.code,
|
code: s.code,
|
||||||
setCode: s.setCode,
|
setCode: s.setCode,
|
||||||
ast: s.ast,
|
|
||||||
setAst: s.setAst,
|
setAst: s.setAst,
|
||||||
lastGuiMode: s.lastGuiMode,
|
lastGuiMode: s.lastGuiMode,
|
||||||
// formatCode: s.formatCode,
|
|
||||||
setError: s.setError,
|
setError: s.setError,
|
||||||
errorState: s.errorState,
|
errorState: s.errorState,
|
||||||
setProgramMemory: s.setProgramMemory,
|
setProgramMemory: s.setProgramMemory,
|
||||||
@ -89,61 +85,60 @@ function App() {
|
|||||||
}
|
}
|
||||||
const [geoArray, setGeoArray] = useState<(ExtrudeGroup | SketchGroup)[]>([])
|
const [geoArray, setGeoArray] = useState<(ExtrudeGroup | SketchGroup)[]>([])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
const asyncWrap = async () => {
|
||||||
if (!code) {
|
try {
|
||||||
setGeoArray([])
|
if (!code) {
|
||||||
setAst(null)
|
setGeoArray([])
|
||||||
return
|
setAst(null)
|
||||||
}
|
return
|
||||||
const tokens = lexer(code)
|
}
|
||||||
const _ast = abstractSyntaxTree(tokens)
|
const tokens = await asyncLexer(code)
|
||||||
setAst(_ast)
|
const _ast = abstractSyntaxTree(tokens)
|
||||||
resetLogs()
|
console.log('setting ast')
|
||||||
const programMemory = executor(_ast, {
|
setAst(_ast)
|
||||||
root: {
|
resetLogs()
|
||||||
log: {
|
const programMemory = executor(_ast, {
|
||||||
type: 'userVal',
|
root: {
|
||||||
value: (a: any) => {
|
log: {
|
||||||
addLog(a)
|
type: 'userVal',
|
||||||
},
|
value: (a: any) => {
|
||||||
__meta: [
|
addLog(a)
|
||||||
{
|
|
||||||
pathToNode: [],
|
|
||||||
sourceRange: [0, 0],
|
|
||||||
},
|
},
|
||||||
],
|
__meta: [
|
||||||
|
{
|
||||||
|
pathToNode: [],
|
||||||
|
sourceRange: [0, 0],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
_sketch: [],
|
||||||
_sketch: [],
|
|
||||||
})
|
|
||||||
setProgramMemory(programMemory)
|
|
||||||
const geos = programMemory?.return
|
|
||||||
?.map(({ name }: { name: string }) => {
|
|
||||||
const artifact = programMemory?.root?.[name]
|
|
||||||
if (
|
|
||||||
artifact.type === 'extrudeGroup' ||
|
|
||||||
artifact.type === 'sketchGroup'
|
|
||||||
) {
|
|
||||||
return artifact
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
})
|
})
|
||||||
.filter((a) => a) as (ExtrudeGroup | SketchGroup)[]
|
setProgramMemory(programMemory)
|
||||||
|
const geos = programMemory?.return
|
||||||
|
?.map(({ name }: { name: string }) => {
|
||||||
|
const artifact = programMemory?.root?.[name]
|
||||||
|
if (
|
||||||
|
artifact.type === 'extrudeGroup' ||
|
||||||
|
artifact.type === 'sketchGroup'
|
||||||
|
) {
|
||||||
|
return artifact
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
.filter((a) => a) as (ExtrudeGroup | SketchGroup)[]
|
||||||
|
|
||||||
setGeoArray(geos)
|
setGeoArray(geos)
|
||||||
console.log(programMemory)
|
console.log(programMemory)
|
||||||
setError()
|
setError()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
setError('problem')
|
setError('problem')
|
||||||
console.log(e)
|
console.log(e)
|
||||||
addLog(e)
|
addLog(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
asyncWrap()
|
||||||
}, [code])
|
}, [code])
|
||||||
// const shouldFormat = useMemo(() => {
|
|
||||||
// if (!ast) return false
|
|
||||||
// const recastedCode = recast(ast)
|
|
||||||
// return recastedCode !== code
|
|
||||||
// }, [code, ast])
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen">
|
<div className="h-screen">
|
||||||
<Allotment snap={true}>
|
<Allotment snap={true}>
|
||||||
|
178
src/useStore.ts
178
src/useStore.ts
@ -1,4 +1,5 @@
|
|||||||
import create from 'zustand'
|
import create from 'zustand'
|
||||||
|
import { persist } from 'zustand/middleware'
|
||||||
import { addLineHighlight, EditorView } from './editor/highlightextension'
|
import { addLineHighlight, EditorView } from './editor/highlightextension'
|
||||||
import {
|
import {
|
||||||
Program,
|
Program,
|
||||||
@ -107,87 +108,100 @@ interface StoreState {
|
|||||||
setIsShiftDown: (isShiftDown: boolean) => void
|
setIsShiftDown: (isShiftDown: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useStore = create<StoreState>()((set, get) => ({
|
export const useStore = create<StoreState>()(
|
||||||
editorView: null,
|
persist(
|
||||||
setEditorView: (editorView) => {
|
(set, get) => ({
|
||||||
set({ editorView })
|
editorView: null,
|
||||||
},
|
setEditorView: (editorView) => {
|
||||||
highlightRange: [0, 0],
|
set({ editorView })
|
||||||
setHighlightRange: (highlightRange) => {
|
},
|
||||||
set({ highlightRange })
|
highlightRange: [0, 0],
|
||||||
const editorView = get().editorView
|
setHighlightRange: (highlightRange) => {
|
||||||
if (editorView) {
|
set({ highlightRange })
|
||||||
editorView.dispatch({ effects: addLineHighlight.of(highlightRange) })
|
const editorView = get().editorView
|
||||||
}
|
if (editorView) {
|
||||||
},
|
editorView.dispatch({ effects: addLineHighlight.of(highlightRange) })
|
||||||
setCursor: (ranges: Ranges) => {
|
}
|
||||||
const { editorView } = get()
|
},
|
||||||
if (!editorView) return
|
setCursor: (ranges: Ranges) => {
|
||||||
editorView.dispatch({
|
const { editorView } = get()
|
||||||
selection: EditorSelection.create(
|
if (!editorView) return
|
||||||
[...ranges.map(([start, end]) => EditorSelection.cursor(end))],
|
editorView.dispatch({
|
||||||
ranges.length - 1
|
selection: EditorSelection.create(
|
||||||
),
|
[...ranges.map(([start, end]) => EditorSelection.cursor(end))],
|
||||||
})
|
ranges.length - 1
|
||||||
},
|
),
|
||||||
selectionRanges: [[0, 0]],
|
})
|
||||||
setSelectionRanges: (selectionRanges) => {
|
},
|
||||||
set({ selectionRanges })
|
selectionRanges: [[0, 0]],
|
||||||
},
|
setSelectionRanges: (selectionRanges) => {
|
||||||
guiMode: { mode: 'default' },
|
set({ selectionRanges })
|
||||||
lastGuiMode: { mode: 'default' },
|
},
|
||||||
setGuiMode: (guiMode) => {
|
guiMode: { mode: 'default' },
|
||||||
set({ guiMode })
|
lastGuiMode: { mode: 'default' },
|
||||||
},
|
setGuiMode: (guiMode) => {
|
||||||
logs: [],
|
set({ guiMode })
|
||||||
addLog: (log) => {
|
},
|
||||||
if (Array.isArray(log)) {
|
logs: [],
|
||||||
const cleanLog: any = log.map(({ __geoMeta, ...rest }) => rest)
|
addLog: (log) => {
|
||||||
set((state) => ({ logs: [...state.logs, cleanLog] }))
|
if (Array.isArray(log)) {
|
||||||
} else {
|
const cleanLog: any = log.map(({ __geoMeta, ...rest }) => rest)
|
||||||
set((state) => ({ logs: [...state.logs, log] }))
|
set((state) => ({ logs: [...state.logs, cleanLog] }))
|
||||||
}
|
} else {
|
||||||
},
|
set((state) => ({ logs: [...state.logs, log] }))
|
||||||
resetLogs: () => {
|
}
|
||||||
set({ logs: [] })
|
},
|
||||||
},
|
resetLogs: () => {
|
||||||
ast: null,
|
set({ logs: [] })
|
||||||
setAst: (ast) => {
|
},
|
||||||
set({ ast })
|
ast: null,
|
||||||
},
|
setAst: (ast) => {
|
||||||
updateAst: async (ast, focusPath) => {
|
set({ ast })
|
||||||
const newCode = recast(ast)
|
},
|
||||||
const astWithUpdatedSource = abstractSyntaxTree(await asyncLexer(newCode))
|
updateAst: async (ast, focusPath) => {
|
||||||
|
const newCode = recast(ast)
|
||||||
|
const astWithUpdatedSource = abstractSyntaxTree(
|
||||||
|
await asyncLexer(newCode)
|
||||||
|
)
|
||||||
|
|
||||||
set({ ast: astWithUpdatedSource, code: newCode })
|
set({ ast: astWithUpdatedSource, code: newCode })
|
||||||
if (focusPath) {
|
if (focusPath) {
|
||||||
const { node } = getNodeFromPath<any>(astWithUpdatedSource, focusPath)
|
const { node } = getNodeFromPath<any>(astWithUpdatedSource, focusPath)
|
||||||
const { start, end } = node
|
const { start, end } = node
|
||||||
if (!start || !end) return
|
if (!start || !end) return
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
get().setCursor([[start, end]])
|
get().setCursor([[start, end]])
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
code: '',
|
||||||
|
setCode: (code) => {
|
||||||
|
set({ code })
|
||||||
|
},
|
||||||
|
formatCode: async () => {
|
||||||
|
const code = get().code
|
||||||
|
const ast = abstractSyntaxTree(await asyncLexer(code))
|
||||||
|
const newCode = recast(ast)
|
||||||
|
set({ code: newCode, ast })
|
||||||
|
},
|
||||||
|
errorState: {
|
||||||
|
isError: false,
|
||||||
|
error: '',
|
||||||
|
},
|
||||||
|
setError: (error = '') => {
|
||||||
|
set({ errorState: { isError: !!error, error } })
|
||||||
|
},
|
||||||
|
programMemory: { root: {}, _sketch: [] },
|
||||||
|
setProgramMemory: (programMemory) => set({ programMemory }),
|
||||||
|
isShiftDown: false,
|
||||||
|
setIsShiftDown: (isShiftDown) => set({ isShiftDown }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: 'store',
|
||||||
|
partialize: (state) =>
|
||||||
|
Object.fromEntries(
|
||||||
|
Object.entries(state).filter(([key]) => ['code'].includes(key))
|
||||||
|
),
|
||||||
}
|
}
|
||||||
},
|
)
|
||||||
code: '',
|
)
|
||||||
setCode: (code) => {
|
|
||||||
set({ code })
|
|
||||||
},
|
|
||||||
formatCode: async () => {
|
|
||||||
const code = get().code
|
|
||||||
const ast = abstractSyntaxTree(await asyncLexer(code))
|
|
||||||
const newCode = recast(ast)
|
|
||||||
set({ code: newCode, ast })
|
|
||||||
},
|
|
||||||
errorState: {
|
|
||||||
isError: false,
|
|
||||||
error: '',
|
|
||||||
},
|
|
||||||
setError: (error = '') => {
|
|
||||||
set({ errorState: { isError: !!error, error } })
|
|
||||||
},
|
|
||||||
programMemory: { root: {}, _sketch: [] },
|
|
||||||
setProgramMemory: (programMemory) => set({ programMemory }),
|
|
||||||
isShiftDown: false,
|
|
||||||
setIsShiftDown: (isShiftDown) => set({ isShiftDown }),
|
|
||||||
}))
|
|
||||||
|
Reference in New Issue
Block a user