made simple one-time move work

This commit is contained in:
Kevin Jahns
2021-12-06 13:23:01 +01:00
parent d314c3e1a6
commit fc5e36158f
7 changed files with 258 additions and 102 deletions

View File

@@ -36,7 +36,7 @@ const maxSearchMarker = 80
*/
export const useSearchMarker = (tr, yarray, index, f) => {
const searchMarker = yarray._searchMarker
if (searchMarker === null || yarray._start === null || index < 30) {
if (searchMarker === null || yarray._start === null || index < 5) {
return f(new ListIterator(yarray).forward(tr, index))
}
if (searchMarker.length === 0) {
@@ -48,26 +48,27 @@ export const useSearchMarker = (tr, yarray, index, f) => {
const sm = searchMarker.reduce(
(a, b, arrayIndex) => math.abs(index - a.index) < math.abs(index - b.index) ? a : b
)
const createFreshMarker = searchMarker.length < maxSearchMarker && math.abs(sm.index - index) > 30
const fsm = createFreshMarker ? sm.clone() : sm
const newIsCheaper = math.abs(sm.index - index) > index
const createFreshMarker = searchMarker.length < maxSearchMarker && (math.abs(sm.index - index) > 5 || newIsCheaper)
const fsm = createFreshMarker ? (newIsCheaper ? new ListIterator(yarray) : sm.clone()) : sm
const prevItem = /** @type {Item} */ (sm.nextItem)
if (createFreshMarker) {
searchMarker.push(fsm)
}
const diff = fsm.index - index
// @todo create fresh marker if diff > index
if (diff > 0) {
fsm.backward(tr, diff)
} else {
fsm.forward(tr, -diff)
}
// @todo remove this tests
/*
const otherTesting = new ListIterator(yarray)
otherTesting.forward(tr, index)
if (otherTesting.nextItem !== fsm.nextItem || otherTesting.index !== fsm.index || otherTesting.reachedEnd !== fsm.reachedEnd) {
throw new Error('udtirane')
}
*/
const result = f(fsm)
if (fsm.reachedEnd) {
fsm.reachedEnd = false
@@ -77,7 +78,7 @@ export const useSearchMarker = (tr, yarray, index, f) => {
}
fsm.rel = 0
}
if (!createFreshMarker && fsm.nextItem !== prevItem) {
if (!createFreshMarker) {
// reused old marker and we moved to a different position
prevItem.marker = false
}

View File

@@ -10,6 +10,7 @@ import {
transact,
ListIterator,
useSearchMarker,
createRelativePositionFromTypeIndex,
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
} from '../internals.js'
@@ -134,6 +135,32 @@ export class YArray extends AbstractType {
}
}
/**
* @param {number} start Inclusive move-start
* @param {number} end Inclusive move-end
* @param {number} target
* @param {number} assocStart >=0 if start should be associated with the right character. See relative-position assoc parameter.
* @param {number} assocEnd >= 0 if end should be associated with the right character.
*/
move (start, end, target, assocStart = 1, assocEnd = -1) {
if (start <= target && target <= end) {
// It doesn't make sense to move a range into the same range (it's basically a no-op).
return
}
if (this.doc !== null) {
transact(this.doc, transaction => {
useSearchMarker(transaction, this, target, walker => {
const left = createRelativePositionFromTypeIndex(this, start, assocStart)
const right = createRelativePositionFromTypeIndex(this, end + 1, assocEnd)
walker.insertMove(transaction, left, right)
})
})
} else {
const content = /** @type {Array<any>} */ (this._prelimContent).splice(start, end - start + 1)
;/** @type {Array<any>} */ (this._prelimContent).splice(target, 0, ...content)
}
}
/**
* Appends content to this YArray.
*