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:
Kurt Hutten
2023-02-21 14:50:22 +11:00
committed by GitHub
parent 4ec0401118
commit f70f0f7bc3
2 changed files with 146 additions and 137 deletions

View File

@ -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}>

View File

@ -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 }),
}))