mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 21:01:37 +03:00
e0ba39ed3e
Introduce `SourceDocument`, a reactive source code representation that can be synced from a `MutableModule`. `SourceDocument` replaces various logic for tracking source code and spans--most importantly, `ReactiveModule`. There is no longer any reactively-tracked `Module`, per-se: Changes to the `MutableModule` attached to the synchronized `ydoc` are pushed as Y.Js events to the `SourceDocument` and `GraphDb`, which are reactively tracked. This avoids a problem in the upcoming text-synchronization (next PR) that was caused by a reactive back channel bypassing the `GraphDb` and resulting in observation of inconsistent states. Stacked on #8956. Part of #8238.
51 lines
1.4 KiB
Vue
51 lines
1.4 KiB
Vue
<script setup lang="ts">
|
|
import { useProjectStore } from '@/stores/project'
|
|
import { Ast } from '@/util/ast'
|
|
import { SourceDocument } from 'shared/ast/sourceDocument'
|
|
import { reactive, watch } from 'vue'
|
|
|
|
const props = defineProps<{ modelValue: string }>()
|
|
const emit = defineEmits<{ 'update:modelValue': [modelValue: string] }>()
|
|
|
|
const projectStore = useProjectStore()
|
|
const mod = projectStore.projectModel.createNewModule('Main.enso')
|
|
projectStore.setObservedFileName('Main.enso')
|
|
mod.doc.ydoc.emit('load', [])
|
|
let syncedCode: string | undefined
|
|
watch(
|
|
() => projectStore.module,
|
|
(mod) => {
|
|
if (!mod) return
|
|
const syncModule = new Ast.MutableModule(mod.doc.ydoc)
|
|
applyEdits(syncModule, props.modelValue)
|
|
const moduleSource = reactive(SourceDocument.Empty())
|
|
syncModule.observe((update) => moduleSource.applyUpdate(syncModule, update))
|
|
watch(
|
|
() => moduleSource.text,
|
|
(text) => {
|
|
if (text !== props.modelValue) {
|
|
syncedCode = text
|
|
emit('update:modelValue', text)
|
|
}
|
|
},
|
|
)
|
|
watch(
|
|
() => props.modelValue,
|
|
(modelValue) => applyEdits(syncModule, modelValue),
|
|
)
|
|
},
|
|
)
|
|
|
|
function applyEdits(syncModule: Ast.MutableModule, newText: string) {
|
|
if (newText !== syncedCode) {
|
|
syncModule.ydoc.transact(() => {
|
|
syncModule.syncRoot(Ast.parseBlock(newText, syncModule))
|
|
}, 'local')
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<slot></slot>
|
|
</template>
|