Skip to content

Commit

Permalink
JS: Support multiple cursors
Browse files Browse the repository at this point in the history
  • Loading branch information
juharris committed Dec 9, 2024
1 parent 127b800 commit b46e03f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 13 deletions.
12 changes: 7 additions & 5 deletions js/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,12 @@ describe('Basin', () => {
basin.setCursor({ jsonPath: 'list[0]', p: -1 })
basin.setCursor({ jsonPath: 'list[1]', p: -1 }, '1')
basin.setCursor({ jsonPath: 'list[2]', p: -1 }, '2')
expect(basin.write("there")).to.deep.equal({ list: ["Hello there", "Hi ", "Hey "] })
expect(basin.write("guy", '1')).to.deep.equal({ list: ["Hello there", "Hi you", "Hey "] })
expect(basin.write("you", '2')).to.deep.equal({ list: ["Hello there", "Hi you", "Hey you"] })
expect(basin.write(".", '1')).to.deep.equal({ list: ["Hello there.", "Hi you.", "Hey you"] })
expect(basin.write("!", '2')).to.deep.equal({ list: ["Hello there.", "Hi you.", "Hey you!"] })
expect(basin.write("there")).to.deep.equal(["Hello there", "Hi ", "Hey "])
expect(basin.write("guy", '1')).to.deep.equal(["Hello there", "Hi guy", "Hey "])
expect(basin.write("you", '2')).to.deep.equal(["Hello there", "Hi guy", "Hey you"])
expect(basin.write(".")).to.deep.equal(["Hello there.", "Hi guy", "Hey you"] )
expect(basin.write(".", '1')).to.deep.equal(["Hello there.", "Hi guy.", "Hey you"] )
expect(basin.write("!", '2')).to.deep.equal(["Hello there.", "Hi guy.", "Hey you!"])
expect(basin.items).to.deep.equal({ list: ["Hello there.", "Hi guy.", "Hey you!"] })
})
})
18 changes: 10 additions & 8 deletions js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ export class BasinCursor {
* @typeparam T The type of values (top level) that will be modified.
*/
export class Basin<T> {
private _currentKey?: T
private readonly _cursors = new Map<string | null | undefined, BasinCursor>()
private readonly _keys = new Map<string | null | undefined, string>()

/**
* @param items The items to contain. If not provided, an empty object will be created.
* @param _cursor The cursor to use. If not provided, then it must be provided later by calling {@link setCursor}.
*/
public constructor(
public items: any = {},
private _cursor?: BasinCursor) {
if (_cursor !== undefined) {
this.setCursor(_cursor)
cursor?: BasinCursor) {
if (cursor !== undefined) {
this.setCursor(cursor)
}
}

Expand Down Expand Up @@ -86,7 +87,7 @@ export class Basin<T> {
* @param cursor The cursor to use.
*/
public setCursor(cursor: BasinCursor, label?: string): void {
this._cursor = cursor
this._cursors.set(label, cursor)
if (cursor.j !== undefined) {
cursor.jsonPath = cursor.j
delete cursor.j
Expand All @@ -103,7 +104,7 @@ export class Basin<T> {
const expressions = jp.parse(cursor.jsonPath!)
for (const expression of expressions) {
if (expression.expression.type !== 'root') {
this._currentKey = expression.expression.value
this._keys.set(label, expression.expression.value)
break
}
}
Expand All @@ -117,7 +118,7 @@ export class Basin<T> {
*/
public write(value?: any, cursorLabel?: string): T {
// For efficiency, assume the cursor is set.
const cursor = this._cursor!
const cursor = this._cursors.get(cursorLabel)!
const position = cursor.position
const jsonPath = cursor.jsonPath!
if (typeof position !== 'number') {
Expand Down Expand Up @@ -152,6 +153,7 @@ export class Basin<T> {
})
}

return this.items[this._currentKey]
const key = this._keys.get(cursorLabel)!
return this.items[key]
}
}

0 comments on commit b46e03f

Please sign in to comment.