Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit bea60c0

Browse files
author
Max Brunsfeld
authored
Merge pull request #273 from atom/mb-one-did-change-event-per-tx
Replace onDidChange with an enhanced version of onDidChangeText
2 parents 8aa6434 + 15ade70 commit bea60c0

File tree

7 files changed

+118
-126
lines changed

7 files changed

+118
-126
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "text-buffer",
3-
"version": "13.6.1",
3+
"version": "13.7.0-did-change-event-1",
44
"description": "A container for large mutable strings with annotated regions",
55
"main": "./lib/text-buffer",
66
"scripts": {

spec/marker-layer-spec.coffee

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ describe "MarkerLayer", ->
183183
displayLayerDidChange = false
184184

185185
changeCount = 0
186-
buffer.onDidChangeText ->
186+
buffer.onDidChange ->
187187
changeCount++
188188

189189
updateCount = 0

spec/text-buffer-io-spec.js

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -193,18 +193,12 @@ describe('TextBuffer IO', () => {
193193
fs.writeFileSync(filePath, 'abcdXefg', 'utf8')
194194

195195
{
196-
const subscription = buffer.onDidChange(() => {
197-
subscription.dispose()
198-
buffer.setText('')
199-
})
200-
}
201-
202-
{
203-
const subscription = buffer.onDidChangeText(({changes}) => {
196+
const subscription = buffer.onDidChange(({changes}) => {
204197
subscription.dispose()
205198
expect(changes.length).toBe(1)
206-
expect(changes[0].oldText).toBe('abcdefg')
207-
expect(changes[0].newText).toBe('')
199+
expect(changes[0].oldText).toBe('')
200+
expect(changes[0].newText).toBe('X')
201+
buffer.setText('')
208202
})
209203
}
210204

@@ -218,6 +212,9 @@ describe('TextBuffer IO', () => {
218212

219213
expect(buffer.getText()).toBe('')
220214

215+
buffer.undo()
216+
expect(buffer.getText()).toBe('abcdXefg')
217+
221218
buffer.undo()
222219
expect(buffer.getText()).toBe('abcdefg')
223220

@@ -257,7 +254,6 @@ describe('TextBuffer IO', () => {
257254
const changeEvents = []
258255
buffer.onWillChange(() => changeEvents.push(['will-change']))
259256
buffer.onDidChange((event) => changeEvents.push(['did-change', event]))
260-
buffer.onDidChangeText((event) => changeEvents.push(['did-change-text', event]))
261257

262258
buffer.save().then(() => {
263259
expect(buffer.isModified()).toBe(false)
@@ -881,11 +877,7 @@ describe('TextBuffer IO', () => {
881877
expect(buffer.getText()).toEqual('abcde')
882878
events.push(['will-change'])
883879
})
884-
buffer.onDidChange((event) => {
885-
expect(buffer.getText()).toEqual(newText)
886-
events.push(['did-change', event])
887-
})
888-
buffer.onDidChangeText((event) => events.push(['did-change-text', event]))
880+
buffer.onDidChange((event) => events.push(['did-change', event]))
889881
buffer.onDidReload((event) => events.push(['did-reload']))
890882

891883
const markerB = buffer.markRange(Range(Point(0, 1), Point(0, 2)))
@@ -915,12 +907,6 @@ describe('TextBuffer IO', () => {
915907
'did-change', {
916908
oldRange: Range(Point(0, 0), Point(0, 5)),
917909
newRange: Range(Point(0, 0), Point(0, newText.length)),
918-
oldText: 'abcde',
919-
newText: newText
920-
}
921-
],
922-
[
923-
'did-change-text', {
924910
changes: [
925911
{
926912
oldRange: Range(Point.ZERO, Point.ZERO),
@@ -952,7 +938,6 @@ describe('TextBuffer IO', () => {
952938
const events = []
953939
buffer.onWillChange(() => events.push(['will-change']))
954940
buffer.onDidChange((event) => events.push(['did-change', event]))
955-
buffer.onDidChangeText((event) => events.push(['did-change-text', event]))
956941

957942
const subscription = buffer.onDidReload(() => {
958943
subscription.dispose()
@@ -967,12 +952,6 @@ describe('TextBuffer IO', () => {
967952
'did-change', {
968953
oldRange: Range(Point(0, 3), Point(0, 5)),
969954
newRange: Range(Point(0, 3), Point(0, 7)),
970-
oldText: 'de',
971-
newText: ' de '
972-
}
973-
],
974-
[
975-
'did-change-text', {
976955
changes: [
977956
{
978957
oldRange: Range(Point(0, 3), Point(0, 3)),
@@ -1000,7 +979,6 @@ describe('TextBuffer IO', () => {
1000979
buffer.onWillReload((event) => events.push(event))
1001980
buffer.onDidReload((event) => events.push(event))
1002981
buffer.onDidChange((event) => events.push(event))
1003-
buffer.onDidChangeText((event) => events.push(event))
1004982
buffer.onDidConflict((event) => events.push(event))
1005983

1006984
fs.writeFileSync(buffer.getPath(), 'abcde')
@@ -1019,7 +997,6 @@ describe('TextBuffer IO', () => {
1019997
const changeEvents = []
1020998
buffer.onWillChange(() => changeEvents.push('will-change'))
1021999
buffer.onDidChange((event) => changeEvents.push('did-change'))
1022-
buffer.onDidChangeText((event) => changeEvents.push('did-change-text'))
10231000

10241001
// We debounce file system change events to avoid redundant loads. But
10251002
// for large files, another file system change event may occur *after* the
@@ -1049,9 +1026,9 @@ describe('TextBuffer IO', () => {
10491026
}, buffer.fileChangeDelay + 50)
10501027
}, buffer.fileChangeDelay + 50)
10511028

1052-
const subscription = buffer.onDidChangeText(() => {
1029+
const subscription = buffer.onDidChange(() => {
10531030
if (buffer.getText() === 'abcdef') {
1054-
expect(changeEvents).toEqual(['will-change', 'did-change', 'did-change-text'])
1031+
expect(changeEvents).toEqual(['will-change', 'did-change'])
10551032
subscription.dispose()
10561033
done()
10571034
}

spec/text-buffer-spec.coffee

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -97,22 +97,27 @@ describe "TextBuffer", ->
9797
expect(buffer.getText()).toEqual "hey\nyou're old\r\nhow are you doing?"
9898

9999
describe "after a change", ->
100-
it "notifies, in order, decoration layers, display layers, ::onDidChange observers and display layer ::onDidChangeSync observers with the relevant details", ->
100+
it "notifies, in order, decoration layers, display layers, and display layer ::onDidChangeSync observers with the relevant details", ->
101101
events = []
102-
textDecorationLayer1 = {bufferDidChange: (e) -> events.push({source: textDecorationLayer1, event: e})}
103-
textDecorationLayer2 = {bufferDidChange: (e) -> events.push({source: textDecorationLayer2, event: e})}
102+
textDecorationLayer1 = {
103+
bufferDidChange: (e) -> events.push({source: 'decoration-layer-1', event: e})
104+
}
105+
textDecorationLayer2 = {
106+
bufferDidChange: (e) -> events.push({source: 'decoration-layer-2', event: e}),
107+
jasmineToString: -> '<TextDecorationLayer2>'
108+
}
104109
displayLayer1 = buffer.addDisplayLayer()
105110
displayLayer2 = buffer.addDisplayLayer()
106111
spyOn(displayLayer1, 'bufferDidChange').and.callFake (e) ->
107-
events.push({source: displayLayer1, event: e})
112+
events.push({source: 'display-layer-1', event: e})
108113
DisplayLayer.prototype.bufferDidChange.call(displayLayer1, e)
109114
spyOn(displayLayer2, 'bufferDidChange').and.callFake (e) ->
110-
events.push({source: displayLayer2, event: e})
115+
events.push({source: 'display-layer-2', event: e})
111116
DisplayLayer.prototype.bufferDidChange.call(displayLayer2, e)
112-
buffer.onDidChange (e) -> events.push({source: buffer, event: e})
113117
buffer.registerTextDecorationLayer(textDecorationLayer1)
114118
buffer.registerTextDecorationLayer(textDecorationLayer1) # insert a duplicate decoration layer
115119
buffer.registerTextDecorationLayer(textDecorationLayer2)
120+
buffer.onDidChange (e) -> events.push({source: 'buffer', event: JSON.parse(JSON.stringify(e))})
116121

117122
disposable = displayLayer1.onDidChangeSync ->
118123
disposable.dispose()
@@ -128,17 +133,31 @@ describe "TextBuffer", ->
128133
oldText: "a", newText: "abc",
129134
}
130135
expect(events).toEqual [
131-
{source: textDecorationLayer1, event: changeEvent1},
132-
{source: textDecorationLayer2, event: changeEvent1},
133-
{source: displayLayer1, event: changeEvent1},
134-
{source: displayLayer2, event: changeEvent1},
135-
{source: buffer, event: changeEvent1},
136-
137-
{source: textDecorationLayer1, event: changeEvent2},
138-
{source: textDecorationLayer2, event: changeEvent2},
139-
{source: displayLayer1, event: changeEvent2},
140-
{source: displayLayer2, event: changeEvent2},
141-
{source: buffer, event: changeEvent2}
136+
{source: 'decoration-layer-1', event: changeEvent1},
137+
{source: 'decoration-layer-2', event: changeEvent1},
138+
{source: 'display-layer-1', event: changeEvent1},
139+
{source: 'display-layer-2', event: changeEvent1},
140+
141+
{source: 'decoration-layer-1', event: changeEvent2},
142+
{source: 'decoration-layer-2', event: changeEvent2},
143+
{source: 'display-layer-1', event: changeEvent2},
144+
{source: 'display-layer-2', event: changeEvent2},
145+
146+
{
147+
source: 'buffer',
148+
event: {
149+
oldRange: Range(Point(0, 2), Point(2, 3)),
150+
newRange: Range(Point(0, 2), Point(2, 4)),
151+
changes: [
152+
{
153+
oldRange: Range(Point(0, 2), Point(2, 3)),
154+
newRange: Range(Point(0, 2), Point(2, 4)),
155+
oldText: "llo\nworld\r\nhow",
156+
newText: "y there\r\ncabct\nwhat"
157+
}
158+
]
159+
}
160+
}
142161
]
143162

144163
it "returns the newRange of the change", ->
@@ -214,8 +233,8 @@ describe "TextBuffer", ->
214233
}])
215234

216235
it "still emits text change events (regression)", (done) ->
217-
didChangeTextEvents = []
218-
buffer.onDidChangeText (event) -> didChangeTextEvents.push(event)
236+
didChangeEvents = []
237+
buffer.onDidChange (event) -> didChangeEvents.push(event)
219238

220239
buffer.onDidStopChanging ({changes}) ->
221240
assertChangesEqual(changes, [{
@@ -227,17 +246,17 @@ describe "TextBuffer", ->
227246
done()
228247

229248
buffer.setTextInRange([[0, 0], [0, 1]], 'y', {undo: 'skip'})
230-
expect(didChangeTextEvents.length).toBe(1)
231-
assertChangesEqual(didChangeTextEvents[0].changes, [{
249+
expect(didChangeEvents.length).toBe(1)
250+
assertChangesEqual(didChangeEvents[0].changes, [{
232251
oldRange: [[0, 0], [0, 1]],
233252
newRange: [[0, 0], [0, 1]],
234253
oldText: 'h',
235254
newText: 'y'
236255
}])
237256

238257
buffer.transact -> buffer.setTextInRange([[0, 0], [0, 1]], 'z', {undo: 'skip'})
239-
expect(didChangeTextEvents.length).toBe(2)
240-
assertChangesEqual(didChangeTextEvents[1].changes, [{
258+
expect(didChangeEvents.length).toBe(2)
259+
assertChangesEqual(didChangeEvents[1].changes, [{
241260
oldRange: [[0, 0], [0, 1]],
242261
newRange: [[0, 0], [0, 1]],
243262
oldText: 'y',
@@ -266,28 +285,28 @@ describe "TextBuffer", ->
266285
expect(changeEvents[1].newText).toBe "ms\r\ndo you\r\nlike\r\ndirt"
267286

268287
buffer.setTextInRange([[5, 1], [5, 3]], '\r')
269-
expect(changeEvents[2]).toEqual({
288+
expect(changeEvents[2].changes).toEqual([{
270289
oldRange: [[5, 1], [5, 3]],
271290
newRange: [[5, 1], [6, 0]],
272291
oldText: 'ik',
273292
newText: '\r\n'
274-
})
293+
}])
275294

276295
buffer.undo()
277-
expect(changeEvents[3]).toEqual({
296+
expect(changeEvents[3].changes).toEqual([{
278297
oldRange: [[5, 1], [6, 0]],
279298
newRange: [[5, 1], [5, 3]],
280299
oldText: '\r\n',
281300
newText: 'ik'
282-
})
301+
}])
283302

284303
buffer.redo()
285-
expect(changeEvents[4]).toEqual({
304+
expect(changeEvents[4].changes).toEqual([{
286305
oldRange: [[5, 1], [5, 3]],
287306
newRange: [[5, 1], [6, 0]],
288307
oldText: 'ik',
289308
newText: '\r\n'
290-
})
309+
}])
291310

292311
describe "when the range's start row has no line ending (because it's the last line of the buffer)", ->
293312
describe "when the buffer contains no newlines", ->
@@ -2245,7 +2264,7 @@ describe "TextBuffer", ->
22452264
buffer.setText('\n')
22462265
expect(buffer.isEmpty()).toBeFalsy()
22472266

2248-
describe "::onWillChange", ->
2267+
describe "::onWillChange(callback)", ->
22492268
it "notifies observers before a transaction, an undo or a redo", ->
22502269
changeCount = 0
22512270
expectedText = ''
@@ -2282,14 +2301,14 @@ describe "TextBuffer", ->
22822301
buffer.revertToCheckpoint(checkpoint)
22832302
expect(changeCount).toBe(5)
22842303

2285-
describe "::onDidChangeText(callback)", ->
2304+
describe "::onDidChange(callback)", ->
22862305
beforeEach ->
22872306
filePath = require.resolve('./fixtures/sample.js')
22882307
buffer = TextBuffer.loadSync(filePath)
22892308

22902309
it "notifies observers after a transaction, an undo or a redo", ->
22912310
textChanges = []
2292-
buffer.onDidChangeText ({changes}) -> textChanges.push(changes...)
2311+
buffer.onDidChange ({changes}) -> textChanges.push(changes...)
22932312

22942313
buffer.insert([0, 0], "abc")
22952314
buffer.delete([[0, 0], [0, 1]])
@@ -2383,12 +2402,12 @@ describe "TextBuffer", ->
23832402

23842403
it "doesn't notify observers after an empty transaction", ->
23852404
didChangeTextSpy = jasmine.createSpy()
2386-
buffer.onDidChangeText(didChangeTextSpy)
2405+
buffer.onDidChange(didChangeTextSpy)
23872406
buffer.transact(->)
23882407
expect(didChangeTextSpy).not.toHaveBeenCalled()
23892408

23902409
it "doesn't throw an error when clearing the undo stack within a transaction", ->
2391-
buffer.onDidChangeText(didChangeTextSpy = jasmine.createSpy())
2410+
buffer.onDidChange(didChangeTextSpy = jasmine.createSpy())
23922411
expect(-> buffer.transact(-> buffer.clearUndoStack())).not.toThrowError()
23932412
expect(didChangeTextSpy).not.toHaveBeenCalled()
23942413

@@ -2457,8 +2476,8 @@ describe "TextBuffer", ->
24572476
])
24582477
done()
24592478

2460-
it "provides the correct changes when the buffer is mutated in the onDidChangeText callback", (done) ->
2461-
buffer.onDidChangeText ({changes}) ->
2479+
it "provides the correct changes when the buffer is mutated in the onDidChange callback", (done) ->
2480+
buffer.onDidChange ({changes}) ->
24622481
switch changes[0].newText
24632482
when 'a'
24642483
buffer.insert(changes[0].newRange.end, 'b')

src/helpers.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@ class TextChange {
9393
this.oldText = oldText
9494
this.newText = newText
9595
}
96+
97+
isEqual (other) {
98+
return (
99+
this.oldRange.isEqual(other.oldRange) &&
100+
this.newRange.isEqual(other.newRange) &&
101+
this.oldText === other.oldText &&
102+
this.newText === other.newText
103+
)
104+
}
96105
}
97106

98107
Object.defineProperty(TextChange.prototype, 'start', {

0 commit comments

Comments
 (0)