mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-20 15:37:46 +03:00
Avoid double computation of screen lines when opening files
Previously, instantiating a TextEditor would always compute compute screen lines twice: once when the DisplayBuffer was instantiated, and once when the 'invisibles' property was set on the DisplayBuffer.
This commit is contained in:
parent
fe2cfff7a6
commit
19d905606b
@ -36,23 +36,21 @@ describe "TextEditor", ->
|
||||
|
||||
it "preserves the invisibles setting", ->
|
||||
atom.config.set('editor.showInvisibles', true)
|
||||
previousInvisibles = editor.displayBuffer.invisibles
|
||||
previousInvisibles = editor.tokenizedLineForScreenRow(0).invisibles
|
||||
|
||||
editor2 = editor.testSerialization()
|
||||
|
||||
expect(editor2.displayBuffer.invisibles).toEqual previousInvisibles
|
||||
expect(editor2.displayBuffer.tokenizedBuffer.invisibles).toEqual previousInvisibles
|
||||
expect(previousInvisibles).toBeDefined()
|
||||
expect(editor2.displayBuffer.tokenizedLineForScreenRow(0).invisibles).toEqual previousInvisibles
|
||||
|
||||
it "updates invisibles if the settings have changed between serialization and deserialization", ->
|
||||
atom.config.set('editor.showInvisibles', true)
|
||||
previousInvisibles = editor.displayBuffer.invisibles
|
||||
|
||||
state = editor.serialize()
|
||||
atom.config.set('editor.invisibles', eol: '?')
|
||||
editor2 = TextEditor.deserialize(state)
|
||||
|
||||
expect(editor2.displayBuffer.invisibles.eol).toBe '?'
|
||||
expect(editor2.displayBuffer.tokenizedBuffer.invisibles.eol).toBe '?'
|
||||
expect(editor.tokenizedLineForScreenRow(0).invisibles.eol).toBe '?'
|
||||
|
||||
describe "when the editor is constructed with an initialLine option", ->
|
||||
it "positions the cursor on the specified line", ->
|
||||
|
@ -611,7 +611,8 @@ describe "TokenizedBuffer", ->
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
tokenizedBuffer.setInvisibles(space: 'S', tab: 'T')
|
||||
atom.config.set("editor.showInvisibles", true)
|
||||
atom.config.set("editor.invisibles", space: 'S', tab: 'T')
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe "SST Sa line with tabsTand T spacesSTS"
|
||||
@ -623,7 +624,7 @@ describe "TokenizedBuffer", ->
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
|
||||
atom.config.set('editor.showInvisibles', true)
|
||||
tokenizedBuffer.setInvisibles(cr: 'R', eol: 'N')
|
||||
atom.config.set("editor.invisibles", cr: 'R', eol: 'N')
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).endOfLineInvisibles).toEqual ['R', 'N']
|
||||
@ -634,7 +635,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(left.endOfLineInvisibles).toBe null
|
||||
expect(right.endOfLineInvisibles).toEqual ['R', 'N']
|
||||
|
||||
tokenizedBuffer.setInvisibles(cr: 'R', eol: false)
|
||||
atom.config.set("editor.invisibles", cr: 'R', eol: false)
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).endOfLineInvisibles).toEqual ['R']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).endOfLineInvisibles).toEqual []
|
||||
|
||||
@ -688,7 +689,8 @@ describe "TokenizedBuffer", ->
|
||||
it "sets leading and trailing whitespace correctly on a line with invisible characters that is copied", ->
|
||||
buffer.setText(" \t a line with tabs\tand \tspaces \t ")
|
||||
|
||||
tokenizedBuffer.setInvisibles(space: 'S', tab: 'T')
|
||||
atom.config.set("editor.showInvisibles", true)
|
||||
atom.config.set("editor.invisibles", space: 'S', tab: 'T')
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
line = tokenizedBuffer.tokenizedLineForRow(0).copy()
|
||||
@ -696,7 +698,8 @@ describe "TokenizedBuffer", ->
|
||||
expect(line.tokens[line.tokens.length - 1].firstTrailingWhitespaceIndex).toBe 0
|
||||
|
||||
it "sets the ::firstNonWhitespaceIndex and ::firstTrailingWhitespaceIndex correctly when tokens are split for soft-wrapping", ->
|
||||
tokenizedBuffer.setInvisibles(space: 'S')
|
||||
atom.config.set("editor.showInvisibles", true)
|
||||
atom.config.set("editor.invisibles", space: 'S')
|
||||
buffer.setText(" token ")
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
token = tokenizedBuffer.tokenizedLines[0].tokens[0]
|
||||
|
@ -24,13 +24,13 @@ class DisplayBuffer extends Model
|
||||
horizontalScrollMargin: 6
|
||||
scopedCharacterWidthsChangeCount: 0
|
||||
|
||||
constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, @invisibles}={}) ->
|
||||
constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer, ignoreInvisibles}={}) ->
|
||||
super
|
||||
|
||||
@emitter = new Emitter
|
||||
@disposables = new CompositeDisposable
|
||||
|
||||
@tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, @invisibles})
|
||||
@tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer, ignoreInvisibles})
|
||||
@buffer = @tokenizedBuffer.buffer
|
||||
@charWidthsByScope = {}
|
||||
@markers = {}
|
||||
@ -87,14 +87,13 @@ class DisplayBuffer extends Model
|
||||
scrollTop: @scrollTop
|
||||
scrollLeft: @scrollLeft
|
||||
tokenizedBuffer: @tokenizedBuffer.serialize()
|
||||
invisibles: _.clone(@invisibles)
|
||||
|
||||
deserializeParams: (params) ->
|
||||
params.tokenizedBuffer = TokenizedBuffer.deserialize(params.tokenizedBuffer)
|
||||
params
|
||||
|
||||
copy: ->
|
||||
newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength(), @invisibles})
|
||||
newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength()})
|
||||
newDisplayBuffer.setScrollTop(@getScrollTop())
|
||||
newDisplayBuffer.setScrollLeft(@getScrollLeft())
|
||||
|
||||
@ -429,8 +428,8 @@ class DisplayBuffer extends Model
|
||||
setTabLength: (tabLength) ->
|
||||
@tokenizedBuffer.setTabLength(tabLength)
|
||||
|
||||
setInvisibles: (@invisibles) ->
|
||||
@tokenizedBuffer.setInvisibles(@invisibles)
|
||||
setIgnoreInvisibles: (ignoreInvisibles) ->
|
||||
@tokenizedBuffer.setIgnoreInvisibles(ignoreInvisibles)
|
||||
|
||||
setSoftWrapped: (softWrapped) ->
|
||||
if softWrapped isnt @softWrapped
|
||||
|
@ -84,12 +84,10 @@ class TextEditor extends Model
|
||||
@selections = []
|
||||
|
||||
buffer ?= new TextBuffer
|
||||
@displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrapped})
|
||||
@displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrapped, ignoreInvisibles: @mini})
|
||||
@buffer = @displayBuffer.buffer
|
||||
@softTabs = @usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true
|
||||
|
||||
@updateInvisibles()
|
||||
|
||||
for marker in @findMarkers(@getSelectionMarkerAttributes())
|
||||
marker.setProperties(preserveFolds: true)
|
||||
@addSelection(marker)
|
||||
@ -170,21 +168,9 @@ class TextEditor extends Model
|
||||
@subscribe @displayBuffer.onDidAddDecoration (decoration) => @emit 'decoration-added', decoration
|
||||
@subscribe @displayBuffer.onDidRemoveDecoration (decoration) => @emit 'decoration-removed', decoration
|
||||
|
||||
@subscribeToScopedConfigSettings()
|
||||
|
||||
subscribeToScopedConfigSettings: ->
|
||||
@scopedConfigSubscriptions?.dispose()
|
||||
@scopedConfigSubscriptions = subscriptions = new CompositeDisposable
|
||||
|
||||
scopeDescriptor = @getRootScopeDescriptor()
|
||||
|
||||
subscriptions.add atom.config.onDidChange 'editor.showInvisibles', scope: scopeDescriptor, => @updateInvisibles()
|
||||
subscriptions.add atom.config.onDidChange 'editor.invisibles', scope: scopeDescriptor, => @updateInvisibles()
|
||||
|
||||
destroyed: ->
|
||||
@unsubscribe() if includeDeprecatedAPIs
|
||||
@disposables.dispose()
|
||||
@scopedConfigSubscriptions.dispose()
|
||||
selection.destroy() for selection in @getSelections()
|
||||
@buffer.release()
|
||||
@displayBuffer.destroy()
|
||||
@ -488,7 +474,7 @@ class TextEditor extends Model
|
||||
setMini: (mini) ->
|
||||
if mini isnt @mini
|
||||
@mini = mini
|
||||
@updateInvisibles()
|
||||
@displayBuffer.setIgnoreInvisibles(@mini)
|
||||
@emitter.emit 'did-change-mini', @mini
|
||||
@mini
|
||||
|
||||
@ -2779,15 +2765,6 @@ class TextEditor extends Model
|
||||
shouldAutoIndentOnPaste: ->
|
||||
atom.config.get("editor.autoIndentOnPaste", scope: @getRootScopeDescriptor())
|
||||
|
||||
shouldShowInvisibles: ->
|
||||
not @mini and atom.config.get('editor.showInvisibles', scope: @getRootScopeDescriptor())
|
||||
|
||||
updateInvisibles: ->
|
||||
if @shouldShowInvisibles()
|
||||
@displayBuffer.setInvisibles(atom.config.get('editor.invisibles', scope: @getRootScopeDescriptor()))
|
||||
else
|
||||
@displayBuffer.setInvisibles(null)
|
||||
|
||||
###
|
||||
Section: Event Handlers
|
||||
###
|
||||
@ -2796,8 +2773,6 @@ class TextEditor extends Model
|
||||
@softTabs = @usesSoftTabs() ? @softTabs
|
||||
|
||||
handleGrammarChange: ->
|
||||
@updateInvisibles()
|
||||
@subscribeToScopedConfigSettings()
|
||||
@unfoldAll()
|
||||
@emit 'grammar-changed' if includeDeprecatedAPIs
|
||||
@emitter.emit 'did-change-grammar', @getGrammar()
|
||||
|
@ -20,8 +20,9 @@ class TokenizedBuffer extends Model
|
||||
chunkSize: 50
|
||||
invalidRows: null
|
||||
visible: false
|
||||
configSettings: null
|
||||
|
||||
constructor: ({@buffer, @tabLength, @invisibles}) ->
|
||||
constructor: ({@buffer, @tabLength, @ignoreInvisibles}) ->
|
||||
@emitter = new Emitter
|
||||
@disposables = new CompositeDisposable
|
||||
|
||||
@ -39,7 +40,7 @@ class TokenizedBuffer extends Model
|
||||
serializeParams: ->
|
||||
bufferPath: @buffer.getPath()
|
||||
tabLength: @tabLength
|
||||
invisibles: _.clone(@invisibles)
|
||||
ignoreInvisibles: @ignoreInvisibles
|
||||
|
||||
deserializeParams: (params) ->
|
||||
params.buffer = atom.project.bufferForPathSync(params.bufferPath)
|
||||
@ -76,13 +77,28 @@ class TokenizedBuffer extends Model
|
||||
@grammarUpdateDisposable = @grammar.onDidUpdate => @retokenizeLines()
|
||||
@disposables.add(@grammarUpdateDisposable)
|
||||
|
||||
@configSettings = tabLength: atom.config.get('editor.tabLength', scope: @rootScopeDescriptor)
|
||||
scopeOptions = {scope: @rootScopeDescriptor}
|
||||
@configSettings =
|
||||
tabLength: atom.config.get('editor.tabLength', scopeOptions)
|
||||
invisibles: atom.config.get('editor.invisibles', scopeOptions)
|
||||
showInvisibles: atom.config.get('editor.showInvisibles', scopeOptions)
|
||||
|
||||
@grammarTabLengthSubscription?.dispose()
|
||||
@grammarTabLengthSubscription = atom.config.onDidChange 'editor.tabLength', scope: @rootScopeDescriptor, ({newValue}) =>
|
||||
if @configSubscriptions?
|
||||
@configSubscriptions.dispose()
|
||||
@disposables.remove(@configSubscriptions)
|
||||
@configSubscriptions = new CompositeDisposable
|
||||
@configSubscriptions.add atom.config.onDidChange 'editor.tabLength', scopeOptions, ({newValue}) =>
|
||||
@configSettings.tabLength = newValue
|
||||
@retokenizeLines()
|
||||
@disposables.add(@grammarTabLengthSubscription)
|
||||
@configSubscriptions.add atom.config.onDidChange 'editor.invisibles', scopeOptions, ({newValue}) =>
|
||||
oldInvisibles = @getInvisiblesToShow()
|
||||
@configSettings.invisibles = newValue
|
||||
@retokenizeLines() unless _.isEqual(@getInvisiblesToShow(), oldInvisibles)
|
||||
@configSubscriptions.add atom.config.onDidChange 'editor.showInvisibles', scopeOptions, ({newValue}) =>
|
||||
oldInvisibles = @getInvisiblesToShow()
|
||||
@configSettings.showInvisibles = newValue
|
||||
@retokenizeLines() unless _.isEqual(@getInvisiblesToShow(), oldInvisibles)
|
||||
@disposables.add(@configSubscriptions)
|
||||
|
||||
@retokenizeLines()
|
||||
|
||||
@ -123,10 +139,11 @@ class TokenizedBuffer extends Model
|
||||
@tabLength = tabLength
|
||||
@retokenizeLines()
|
||||
|
||||
setInvisibles: (invisibles) ->
|
||||
unless _.isEqual(invisibles, @invisibles)
|
||||
@invisibles = invisibles
|
||||
@retokenizeLines()
|
||||
setIgnoreInvisibles: (ignoreInvisibles) ->
|
||||
if ignoreInvisibles isnt @ignoreInvisibles
|
||||
@ignoreInvisibles = ignoreInvisibles
|
||||
if @configSettings.showInvisibles and @configSettings.invisibles?
|
||||
@retokenizeLines()
|
||||
|
||||
tokenizeInBackground: ->
|
||||
return if not @visible or @pendingChunk or not @isAlive()
|
||||
@ -302,7 +319,7 @@ class TokenizedBuffer extends Model
|
||||
tabLength = @getTabLength()
|
||||
indentLevel = @indentLevelForRow(row)
|
||||
lineEnding = @buffer.lineEndingForRow(row)
|
||||
new TokenizedLine({tokens, tabLength, indentLevel, @invisibles, lineEnding})
|
||||
new TokenizedLine({tokens, tabLength, indentLevel, invisibles: @getInvisiblesToShow(), lineEnding})
|
||||
|
||||
buildTokenizedLineForRow: (row, ruleStack) ->
|
||||
@buildTokenizedLineForRowWithText(row, @buffer.lineForRow(row), ruleStack)
|
||||
@ -312,7 +329,13 @@ class TokenizedBuffer extends Model
|
||||
tabLength = @getTabLength()
|
||||
indentLevel = @indentLevelForRow(row)
|
||||
{tokens, ruleStack} = @grammar.tokenizeLine(line, ruleStack, row is 0)
|
||||
new TokenizedLine({tokens, ruleStack, tabLength, lineEnding, indentLevel, @invisibles})
|
||||
new TokenizedLine({tokens, ruleStack, tabLength, lineEnding, indentLevel, invisibles: @getInvisiblesToShow()})
|
||||
|
||||
getInvisiblesToShow: ->
|
||||
if @configSettings.showInvisibles and not @ignoreInvisibles
|
||||
@configSettings.invisibles
|
||||
else
|
||||
null
|
||||
|
||||
tokenizedLineForRow: (bufferRow) ->
|
||||
@tokenizedLines[bufferRow]
|
||||
|
Loading…
Reference in New Issue
Block a user