Merge remote-tracking branch 'refs/remotes/origin/master' into wl-electron-35

This commit is contained in:
Wliu
2015-12-18 20:02:22 -05:00
17 changed files with 345 additions and 337 deletions

View File

@@ -1,5 +1,10 @@
'use strict'
// For now, we're not using babel or ES6 features like `let` and `const` in
// this file, because `apm` requires this file directly in order to pre-warm
// Atom's compile-cache when installing or updating packages, using an older
// version of node.js
var path = require('path')
var fs = require('fs-plus')
var CSON = null
@@ -159,8 +164,7 @@ require('source-map-support').install({
})
var prepareStackTraceWithSourceMapping = Error.prepareStackTrace
let prepareStackTrace = prepareStackTraceWithSourceMapping
var prepareStackTrace = prepareStackTraceWithSourceMapping
function prepareStackTraceWithRawStackAssignment (error, frames) {
if (error.rawStack) { // avoid infinite recursion

View File

@@ -13,8 +13,10 @@ class FileSystemBlobStore {
constructor (directory) {
this.inMemoryBlobs = new Map()
this.invalidationKeys = {}
this.blobFilename = path.join(directory, 'BLOB')
this.blobMapFilename = path.join(directory, 'MAP')
this.invalidationKeysFilename = path.join(directory, 'INVKEYS')
this.lockFilename = path.join(directory, 'LOCK')
this.storedBlob = new Buffer(0)
this.storedBlobMap = {}
@@ -27,14 +29,19 @@ class FileSystemBlobStore {
if (!fs.existsSync(this.blobFilename)) {
return
}
if (!fs.existsSync(this.invalidationKeysFilename)) {
return
}
this.storedBlob = fs.readFileSync(this.blobFilename)
this.storedBlobMap = JSON.parse(fs.readFileSync(this.blobMapFilename))
this.invalidationKeys = JSON.parse(fs.readFileSync(this.invalidationKeysFilename))
}
save () {
let dump = this.getDump()
let blobToStore = Buffer.concat(dump[0])
let mapToStore = JSON.stringify(dump[1])
let invalidationKeysToStore = JSON.stringify(this.invalidationKeys)
let acquiredLock = false
try {
@@ -43,6 +50,7 @@ class FileSystemBlobStore {
fs.writeFileSync(this.blobFilename, blobToStore)
fs.writeFileSync(this.blobMapFilename, mapToStore)
fs.writeFileSync(this.invalidationKeysFilename, invalidationKeysToStore)
} catch (error) {
// Swallow the exception silently only if we fail to acquire the lock.
if (error.code !== 'EEXIST') {
@@ -55,15 +63,20 @@ class FileSystemBlobStore {
}
}
has (key) {
return this.inMemoryBlobs.hasOwnProperty(key) || this.storedBlobMap.hasOwnProperty(key)
has (key, invalidationKey) {
let containsKey = this.inMemoryBlobs.has(key) || this.storedBlobMap.hasOwnProperty(key)
let isValid = this.invalidationKeys[key] === invalidationKey
return containsKey && isValid
}
get (key) {
return this.getFromMemory(key) || this.getFromStorage(key)
get (key, invalidationKey) {
if (this.has(key, invalidationKey)) {
return this.getFromMemory(key) || this.getFromStorage(key)
}
}
set (key, buffer) {
set (key, invalidationKey, buffer) {
this.invalidationKeys[key] = invalidationKey
return this.inMemoryBlobs.set(key, buffer)
}

View File

@@ -3,6 +3,11 @@
const Module = require('module')
const path = require('path')
const cachedVm = require('cached-run-in-this-context')
const crypto = require('crypto')
function computeHash (contents) {
return crypto.createHash('sha1').update(contents, 'utf8').digest('hex')
}
class NativeCompileCache {
constructor () {
@@ -14,6 +19,10 @@ class NativeCompileCache {
this.cacheStore = store
}
setV8Version (v8Version) {
this.v8Version = v8Version.toString()
}
install () {
this.savePreviousModuleCompile()
this.overrideModuleCompile()
@@ -28,20 +37,20 @@ class NativeCompileCache {
}
overrideModuleCompile () {
let cacheStore = this.cacheStore
let self = this
let resolvedArgv = null
// Here we override Node's module.js
// (https://github.com/atom/node/blob/atom/lib/module.js#L378), changing
// only the bits that affect compilation in order to use the cached one.
Module.prototype._compile = function (content, filename) {
let self = this
let moduleSelf = this
// remove shebang
content = content.replace(/^\#\!.*/, '')
function require (path) {
return self.require(path)
return moduleSelf.require(path)
}
require.resolve = function (request) {
return Module._resolveFilename(request, self)
return Module._resolveFilename(request, moduleSelf)
}
require.main = process.mainModule
@@ -54,18 +63,20 @@ class NativeCompileCache {
// create wrapper function
let wrapper = Module.wrap(content)
let cacheKey = filename
let invalidationKey = computeHash(wrapper + self.v8Version)
let compiledWrapper = null
if (cacheStore.has(filename)) {
let buffer = cacheStore.get(filename)
if (self.cacheStore.has(cacheKey, invalidationKey)) {
let buffer = self.cacheStore.get(cacheKey, invalidationKey)
let compilationResult = cachedVm.runInThisContextCached(wrapper, filename, buffer)
compiledWrapper = compilationResult.result
if (compilationResult.wasRejected) {
cacheStore.delete(filename)
self.cacheStore.delete(cacheKey)
}
} else {
let compilationResult = cachedVm.runInThisContext(wrapper, filename)
if (compilationResult.cacheBuffer) {
cacheStore.set(filename, compilationResult.cacheBuffer)
self.cacheStore.set(cacheKey, invalidationKey, compilationResult.cacheBuffer)
}
compiledWrapper = compilationResult.result
}
@@ -88,8 +99,8 @@ class NativeCompileCache {
global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0)
}
}
let args = [self.exports, require, self, filename, dirname, process, global]
return compiledWrapper.apply(self.exports, args)
let args = [moduleSelf.exports, require, moduleSelf, filename, dirname, process, global]
return compiledWrapper.apply(moduleSelf.exports, args)
}
}

View File

@@ -86,11 +86,7 @@ class TextEditorPresenter
@fetchDecorations()
@updateLineDecorations()
if @shouldUpdateLinesState or @shouldUpdateLineNumbersState
@updateTilesState()
@shouldUpdateLinesState = false
@shouldUpdateLineNumbersState = false
@shouldUpdateTilesState = true
@updateTilesState()
@updating = false
@state
@@ -104,105 +100,47 @@ class TextEditorPresenter
@clearPendingScrollPosition()
@updateRowsPerPage()
@updateFocusedState() if @shouldUpdateFocusedState
@updateHeightState() if @shouldUpdateHeightState
@updateVerticalScrollState() if @shouldUpdateVerticalScrollState
@updateHorizontalScrollState() if @shouldUpdateHorizontalScrollState
@updateScrollbarsState() if @shouldUpdateScrollbarsState
@updateHiddenInputState() if @shouldUpdateHiddenInputState
@updateContentState() if @shouldUpdateContentState
@updateFocusedState()
@updateHeightState()
@updateVerticalScrollState()
@updateHorizontalScrollState()
@updateScrollbarsState()
@updateHiddenInputState()
@updateContentState()
@updateHighlightDecorations() if @shouldUpdateDecorations
@updateTilesState() if @shouldUpdateTilesState
@updateCursorsState() if @shouldUpdateCursorsState
@updateOverlaysState() if @shouldUpdateOverlaysState
@updateLineNumberGutterState() if @shouldUpdateLineNumberGutterState
@updateGutterOrderState() if @shouldUpdateGutterOrderState
@updateCustomGutterDecorationState() if @shouldUpdateCustomGutterDecorationState
@updateTilesState()
@updateCursorsState()
@updateOverlaysState()
@updateLineNumberGutterState()
@updateGutterOrderState()
@updateCustomGutterDecorationState()
@updating = false
@resetTrackedUpdates()
@state
resetTrackedUpdates: ->
@shouldUpdateFocusedState = false
@shouldUpdateHeightState = false
@shouldUpdateVerticalScrollState = false
@shouldUpdateHorizontalScrollState = false
@shouldUpdateScrollbarsState = false
@shouldUpdateHiddenInputState = false
@shouldUpdateContentState = false
@shouldUpdateDecorations = false
@shouldUpdateLinesState = false
@shouldUpdateTilesState = false
@shouldUpdateCursorsState = false
@shouldUpdateOverlaysState = false
@shouldUpdateLineNumberGutterState = false
@shouldUpdateLineNumbersState = false
@shouldUpdateGutterOrderState = false
@shouldUpdateCustomGutterDecorationState = false
invalidateState: ->
@shouldUpdateFocusedState = true
@shouldUpdateHeightState = true
@shouldUpdateVerticalScrollState = true
@shouldUpdateHorizontalScrollState = true
@shouldUpdateScrollbarsState = true
@shouldUpdateHiddenInputState = true
@shouldUpdateContentState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@shouldUpdateTilesState = true
@shouldUpdateCursorsState = true
@shouldUpdateOverlaysState = true
@shouldUpdateLineNumberGutterState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateGutterOrderState = true
@shouldUpdateCustomGutterDecorationState = true
observeModel: ->
@disposables.add @model.onDidChange =>
@shouldUpdateHeightState = true
@shouldUpdateVerticalScrollState = true
@shouldUpdateHorizontalScrollState = true
@shouldUpdateScrollbarsState = true
@shouldUpdateContentState = true
@shouldUpdateDecorations = true
@shouldUpdateCursorsState = true
@shouldUpdateLinesState = true
@shouldUpdateLineNumberGutterState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateGutterOrderState = true
@shouldUpdateCustomGutterDecorationState = true
@emitDidUpdateState()
@disposables.add @model.onDidUpdateDecorations =>
@shouldUpdateLinesState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateDecorations = true
@shouldUpdateOverlaysState = true
@shouldUpdateCustomGutterDecorationState = true
@emitDidUpdateState()
@disposables.add @model.onDidChangeGrammar(@didChangeGrammar.bind(this))
@disposables.add @model.onDidChangePlaceholderText =>
@shouldUpdateContentState = true
@emitDidUpdateState()
@disposables.add @model.onDidChangePlaceholderText(@emitDidUpdateState.bind(this))
@disposables.add @model.onDidChangeMini =>
@shouldUpdateScrollbarsState = true
@shouldUpdateContentState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@shouldUpdateLineNumberGutterState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateGutterOrderState = true
@shouldUpdateCustomGutterDecorationState = true
@emitDidUpdateState()
@disposables.add @model.onDidChangeLineNumberGutterVisible =>
@shouldUpdateLineNumberGutterState = true
@shouldUpdateGutterOrderState = true
@emitDidUpdateState()
@disposables.add @model.onDidChangeLineNumberGutterVisible(@emitDidUpdateState.bind(this))
@disposables.add @model.onDidAddCursor(@didAddCursor.bind(this))
@disposables.add @model.onDidRequestAutoscroll(@requestAutoscroll.bind(this))
@@ -227,29 +165,19 @@ class TextEditorPresenter
@configDisposables.add @config.onDidChange 'editor.showIndentGuide', configParams, ({newValue}) =>
@showIndentGuide = newValue
@shouldUpdateContentState = true
@emitDidUpdateState()
@configDisposables.add @config.onDidChange 'editor.scrollPastEnd', configParams, ({newValue}) =>
@scrollPastEnd = newValue
@shouldUpdateVerticalScrollState = true
@shouldUpdateScrollbarsState = true
@updateScrollHeight()
@emitDidUpdateState()
@configDisposables.add @config.onDidChange 'editor.showLineNumbers', configParams, ({newValue}) =>
@showLineNumbers = newValue
@shouldUpdateLineNumberGutterState = true
@shouldUpdateGutterOrderState = true
@emitDidUpdateState()
didChangeGrammar: ->
@observeConfig()
@shouldUpdateContentState = true
@shouldUpdateLineNumberGutterState = true
@shouldUpdateGutterOrderState = true
@emitDidUpdateState()
buildState: ->
@@ -383,8 +311,6 @@ class TextEditorPresenter
return if not screenRows? or screenRows.length is 0
@screenRowsToMeasure = screenRows
@shouldUpdateLinesState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateDecorations = true
clearScreenRowsToMeasure: ->
@@ -425,8 +351,8 @@ class TextEditorPresenter
gutterTile.display = "block"
gutterTile.zIndex = zIndex
@updateLinesState(tile, rowsWithinTile) if @shouldUpdateLinesState
@updateLineNumbersState(gutterTile, rowsWithinTile) if @shouldUpdateLineNumbersState
@updateLinesState(tile, rowsWithinTile)
@updateLineNumbersState(gutterTile, rowsWithinTile)
visibleTiles[tileStartRow] = true
zIndex++
@@ -551,24 +477,15 @@ class TextEditorPresenter
didAddGutter: (gutter) ->
gutterDisposables = new CompositeDisposable
gutterDisposables.add gutter.onDidChangeVisible =>
@shouldUpdateGutterOrderState = true
@shouldUpdateCustomGutterDecorationState = true
@emitDidUpdateState()
gutterDisposables.add gutter.onDidChangeVisible => @emitDidUpdateState()
gutterDisposables.add gutter.onDidDestroy =>
@disposables.remove(gutterDisposables)
gutterDisposables.dispose()
@shouldUpdateGutterOrderState = true
@emitDidUpdateState()
# It is not necessary to @updateCustomGutterDecorationState here.
# The destroyed gutter will be removed from the list of gutters in @state,
# and thus will be removed from the DOM.
@disposables.add(gutterDisposables)
@shouldUpdateGutterOrderState = true
@shouldUpdateCustomGutterDecorationState = true
@emitDidUpdateState()
updateGutterOrderState: ->
@@ -861,26 +778,15 @@ class TextEditorPresenter
@startBlinkingCursors()
else
@stopBlinkingCursors(false)
@shouldUpdateFocusedState = true
@shouldUpdateHiddenInputState = true
@emitDidUpdateState()
setScrollTop: (scrollTop, overrideScroll=true) ->
setScrollTop: (scrollTop) ->
return unless scrollTop?
@pendingScrollLogicalPosition = null if overrideScroll
@pendingScrollLogicalPosition = null
@pendingScrollTop = scrollTop
@shouldUpdateVerticalScrollState = true
@shouldUpdateHiddenInputState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@shouldUpdateCursorsState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateCustomGutterDecorationState = true
@shouldUpdateOverlaysState = true
@emitDidUpdateState()
getScrollTop: ->
@@ -894,32 +800,19 @@ class TextEditorPresenter
clearTimeout(@stoppedScrollingTimeoutId)
@stoppedScrollingTimeoutId = null
@stoppedScrollingTimeoutId = setTimeout(@didStopScrolling.bind(this), @stoppedScrollingDelay)
@state.content.scrollingVertically = true
@emitDidUpdateState()
didStopScrolling: ->
@state.content.scrollingVertically = false
if @mouseWheelScreenRow?
@mouseWheelScreenRow = null
@shouldUpdateLinesState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateCustomGutterDecorationState = true
@emitDidUpdateState()
setScrollLeft: (scrollLeft, overrideScroll=true) ->
setScrollLeft: (scrollLeft) ->
return unless scrollLeft?
@pendingScrollLogicalPosition = null if overrideScroll
@pendingScrollLogicalPosition = null
@pendingScrollLeft = scrollLeft
@shouldUpdateHorizontalScrollState = true
@shouldUpdateHiddenInputState = true
@shouldUpdateCursorsState = true
@shouldUpdateOverlaysState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@emitDidUpdateState()
getScrollLeft: ->
@@ -941,13 +834,13 @@ class TextEditorPresenter
@contentFrameWidth - @verticalScrollbarWidth
getScrollBottom: -> @getScrollTop() + @getClientHeight()
setScrollBottom: (scrollBottom, overrideScroll) ->
@setScrollTop(scrollBottom - @getClientHeight(), overrideScroll)
setScrollBottom: (scrollBottom) ->
@setScrollTop(scrollBottom - @getClientHeight())
@getScrollBottom()
getScrollRight: -> @getScrollLeft() + @getClientWidth()
setScrollRight: (scrollRight, overrideScroll) ->
@setScrollLeft(scrollRight - @getClientWidth(), overrideScroll)
setScrollRight: (scrollRight) ->
@setScrollLeft(scrollRight - @getClientWidth())
@getScrollRight()
getScrollHeight: ->
@@ -967,43 +860,24 @@ class TextEditorPresenter
unless @measuredHorizontalScrollbarHeight is horizontalScrollbarHeight
oldHorizontalScrollbarHeight = @measuredHorizontalScrollbarHeight
@measuredHorizontalScrollbarHeight = horizontalScrollbarHeight
@shouldUpdateScrollbarsState = true
@shouldUpdateVerticalScrollState = true
@shouldUpdateHorizontalScrollState = true
@shouldUpdateCursorsState = true unless oldHorizontalScrollbarHeight?
@emitDidUpdateState()
setVerticalScrollbarWidth: (verticalScrollbarWidth) ->
unless @measuredVerticalScrollbarWidth is verticalScrollbarWidth
oldVerticalScrollbarWidth = @measuredVerticalScrollbarWidth
@measuredVerticalScrollbarWidth = verticalScrollbarWidth
@shouldUpdateScrollbarsState = true
@shouldUpdateVerticalScrollState = true
@shouldUpdateHorizontalScrollState = true
@shouldUpdateCursorsState = true unless oldVerticalScrollbarWidth?
@emitDidUpdateState()
setAutoHeight: (autoHeight) ->
unless @autoHeight is autoHeight
@autoHeight = autoHeight
@shouldUpdateHeightState = true
@emitDidUpdateState()
setExplicitHeight: (explicitHeight) ->
unless @explicitHeight is explicitHeight
@explicitHeight = explicitHeight
@updateHeight()
@shouldUpdateVerticalScrollState = true
@shouldUpdateScrollbarsState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@shouldUpdateCursorsState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateCustomGutterDecorationState = true
@emitDidUpdateState()
updateHeight: ->
@@ -1022,22 +896,12 @@ class TextEditorPresenter
@editorWidthInChars = null
@updateScrollbarDimensions()
@updateClientWidth()
@shouldUpdateVerticalScrollState = true
@shouldUpdateHorizontalScrollState = true
@shouldUpdateScrollbarsState = true
@shouldUpdateContentState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@shouldUpdateCursorsState = true unless oldContentFrameWidth?
@emitDidUpdateState()
setBoundingClientRect: (boundingClientRect) ->
unless @clientRectsEqual(@boundingClientRect, boundingClientRect)
@boundingClientRect = boundingClientRect
@shouldUpdateOverlaysState = true
@shouldUpdateContentState = true
@emitDidUpdateState()
clientRectsEqual: (clientRectA, clientRectB) ->
@@ -1051,25 +915,17 @@ class TextEditorPresenter
if @windowWidth isnt width or @windowHeight isnt height
@windowWidth = width
@windowHeight = height
@shouldUpdateOverlaysState = true
@emitDidUpdateState()
setBackgroundColor: (backgroundColor) ->
unless @backgroundColor is backgroundColor
@backgroundColor = backgroundColor
@shouldUpdateContentState = true
@shouldUpdateLineNumberGutterState = true
@shouldUpdateGutterOrderState = true
@emitDidUpdateState()
setGutterBackgroundColor: (gutterBackgroundColor) ->
unless @gutterBackgroundColor is gutterBackgroundColor
@gutterBackgroundColor = gutterBackgroundColor
@shouldUpdateLineNumberGutterState = true
@shouldUpdateGutterOrderState = true
@emitDidUpdateState()
setGutterWidth: (gutterWidth) ->
@@ -1085,18 +941,7 @@ class TextEditorPresenter
@lineHeight = lineHeight
@restoreScrollTopIfNeeded()
@model.setLineHeightInPixels(lineHeight)
@shouldUpdateHeightState = true
@shouldUpdateHorizontalScrollState = true
@shouldUpdateVerticalScrollState = true
@shouldUpdateScrollbarsState = true
@shouldUpdateHiddenInputState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@shouldUpdateCursorsState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateCustomGutterDecorationState = true
@shouldUpdateOverlaysState = true
@emitDidUpdateState()
setMouseWheelScreenRow: (screenRow) ->
@@ -1115,16 +960,7 @@ class TextEditorPresenter
@characterWidthsChanged()
characterWidthsChanged: ->
@shouldUpdateHorizontalScrollState = true
@shouldUpdateVerticalScrollState = true
@shouldUpdateScrollbarsState = true
@shouldUpdateHiddenInputState = true
@shouldUpdateContentState = true
@shouldUpdateDecorations = true
@shouldUpdateLinesState = true
@shouldUpdateCursorsState = true
@shouldUpdateOverlaysState = true
@emitDidUpdateState()
hasPixelPositionRequirements: ->
@@ -1365,20 +1201,16 @@ class TextEditorPresenter
overlayState.itemWidth = itemWidth
overlayState.itemHeight = itemHeight
overlayState.contentMargin = contentMargin
@shouldUpdateOverlaysState = true
@emitDidUpdateState()
observeCursor: (cursor) ->
didChangePositionDisposable = cursor.onDidChangePosition =>
@shouldUpdateHiddenInputState = true if cursor.isLastCursor()
@shouldUpdateCursorsState = true
@pauseCursorBlinking()
@emitDidUpdateState()
didChangeVisibilityDisposable = cursor.onDidChangeVisibility =>
@shouldUpdateCursorsState = true
@emitDidUpdateState()
@@ -1386,8 +1218,6 @@ class TextEditorPresenter
@disposables.remove(didChangePositionDisposable)
@disposables.remove(didChangeVisibilityDisposable)
@disposables.remove(didDestroyDisposable)
@shouldUpdateHiddenInputState = true
@shouldUpdateCursorsState = true
@emitDidUpdateState()
@@ -1397,8 +1227,6 @@ class TextEditorPresenter
didAddCursor: (cursor) ->
@observeCursor(cursor)
@shouldUpdateHiddenInputState = true
@shouldUpdateCursorsState = true
@pauseCursorBlinking()
@emitDidUpdateState()
@@ -1432,22 +1260,11 @@ class TextEditorPresenter
@pendingScrollLogicalPosition = position
@pendingScrollTop = null
@pendingScrollLeft = null
@shouldUpdateCursorsState = true
@shouldUpdateCustomGutterDecorationState = true
@shouldUpdateDecorations = true
@shouldUpdateHiddenInputState = true
@shouldUpdateHorizontalScrollState = true
@shouldUpdateLinesState = true
@shouldUpdateLineNumbersState = true
@shouldUpdateOverlaysState = true
@shouldUpdateScrollPosition = true
@shouldUpdateVerticalScrollState = true
@emitDidUpdateState()
didChangeFirstVisibleScreenRow: (screenRow) ->
@updateScrollTop(screenRow * @lineHeight)
@setScrollTop(screenRow * @lineHeight)
getVerticalScrollMarginInPixels: ->
Math.round(@model.getVerticalScrollMargin() * @lineHeight)
@@ -1482,14 +1299,14 @@ class TextEditorPresenter
if options?.reversed ? true
if desiredScrollBottom > @getScrollBottom()
@setScrollBottom(desiredScrollBottom, false)
@updateScrollTop(desiredScrollBottom - @getClientHeight())
if desiredScrollTop < @getScrollTop()
@setScrollTop(desiredScrollTop, false)
@updateScrollTop(desiredScrollTop)
else
if desiredScrollTop < @getScrollTop()
@setScrollTop(desiredScrollTop, false)
@updateScrollTop(desiredScrollTop)
if desiredScrollBottom > @getScrollBottom()
@setScrollBottom(desiredScrollBottom, false)
@updateScrollTop(desiredScrollBottom - @getClientHeight())
commitPendingLogicalScrollLeftPosition: ->
return unless @pendingScrollLogicalPosition?
@@ -1509,14 +1326,14 @@ class TextEditorPresenter
if options?.reversed ? true
if desiredScrollRight > @getScrollRight()
@setScrollRight(desiredScrollRight, false)
@updateScrollLeft(desiredScrollRight - @getClientWidth())
if desiredScrollLeft < @getScrollLeft()
@setScrollLeft(desiredScrollLeft, false)
@updateScrollLeft(desiredScrollLeft)
else
if desiredScrollLeft < @getScrollLeft()
@setScrollLeft(desiredScrollLeft, false)
@updateScrollLeft(desiredScrollLeft)
if desiredScrollRight > @getScrollRight()
@setScrollRight(desiredScrollRight, false)
@updateScrollLeft(desiredScrollRight - @getClientWidth())
commitPendingScrollLeftPosition: ->
if @pendingScrollLeft?

View File

@@ -57,11 +57,11 @@ isPairedCharacter = (string, index=0) ->
isVariationSequence(charCodeA, charCodeB) or
isCombinedCharacter(charCodeA, charCodeB)
isJapaneseCharacter = (charCode) ->
IsJapaneseKanaCharacter = (charCode) ->
0x3000 <= charCode <= 0x30FF
isCjkUnifiedIdeograph = (charCode) ->
0x4E00 <= charCode <= 0x9FAF
isCJKUnifiedIdeograph = (charCode) ->
0x4E00 <= charCode <= 0x9FFF
isFullWidthForm = (charCode) ->
0xFF01 <= charCode <= 0xFF5E or
@@ -70,8 +70,8 @@ isFullWidthForm = (charCode) ->
isDoubleWidthCharacter = (character) ->
charCode = character.charCodeAt(0)
isJapaneseCharacter(charCode) or
isCjkUnifiedIdeograph(charCode) or
IsJapaneseKanaCharacter(charCode) or
isCJKUnifiedIdeograph(charCode) or
isFullWidthForm(charCode)
isHalfWidthCharacter = (character) ->
@@ -89,6 +89,11 @@ isKoreanCharacter = (character) ->
0xA960 <= charCode <= 0xA97F or
0xD7B0 <= charCode <= 0xD7FF
isCJKCharacter = (character) ->
isDoubleWidthCharacter(character) or
isHalfWidthCharacter(character) or
isKoreanCharacter(character)
# Does the given string contain at least surrogate pair, variation sequence,
# or combined character?
#
@@ -102,4 +107,4 @@ hasPairedCharacter = (string) ->
index++
false
module.exports = {isPairedCharacter, hasPairedCharacter, isDoubleWidthCharacter, isHalfWidthCharacter, isKoreanCharacter}
module.exports = {isPairedCharacter, hasPairedCharacter, isDoubleWidthCharacter, isHalfWidthCharacter, isKoreanCharacter, isCJKCharacter}

View File

@@ -36,7 +36,7 @@ class TokenizedBuffer extends Model
constructor: (params) ->
{
@buffer, @tabLength, @ignoreInvisibles, @largeFileMode, @config,
@grammarRegistry, @packageManager, @assert
@grammarRegistry, @packageManager, @assert, grammarScopeName
} = params
@emitter = new Emitter
@@ -49,18 +49,26 @@ class TokenizedBuffer extends Model
@disposables.add @buffer.preemptDidChange (e) => @handleBufferChange(e)
@disposables.add @buffer.onDidChangePath (@bufferPath) => @reloadGrammar()
@reloadGrammar()
if grammar = @grammarRegistry.grammarForScopeName(grammarScopeName)
@setGrammar(grammar)
else
@reloadGrammar()
@grammarToRestoreScopeName = grammarScopeName
destroyed: ->
@disposables.dispose()
serialize: ->
deserializer: 'TokenizedBuffer'
bufferPath: @buffer.getPath()
bufferId: @buffer.getId()
tabLength: @tabLength
ignoreInvisibles: @ignoreInvisibles
largeFileMode: @largeFileMode
state = {
deserializer: 'TokenizedBuffer'
bufferPath: @buffer.getPath()
bufferId: @buffer.getId()
tabLength: @tabLength
ignoreInvisibles: @ignoreInvisibles
largeFileMode: @largeFileMode
}
state.grammarScopeName = @grammar?.scopeName unless @buffer.getPath()
state
observeGrammar: (callback) ->
callback(@grammar)
@@ -76,7 +84,9 @@ class TokenizedBuffer extends Model
@emitter.on 'did-tokenize', callback
grammarAddedOrUpdated: (grammar) =>
if grammar.injectionSelector?
if @grammarToRestoreScopeName is grammar.scopeName
@setGrammar(grammar)
else if grammar.injectionSelector?
@retokenizeLines() if @hasTokenForSelector(grammar.injectionSelector)
else
newScore = @grammarRegistry.getGrammarScore(grammar, @buffer.getPath(), @getGrammarSelectionContent())
@@ -89,6 +99,8 @@ class TokenizedBuffer extends Model
@rootScopeDescriptor = new ScopeDescriptor(scopes: [@grammar.scopeName])
@currentGrammarScore = score ? @grammarRegistry.getGrammarScore(grammar, @buffer.getPath(), @getGrammarSelectionContent())
@grammarToRestoreScopeName = null
@grammarUpdateDisposable?.dispose()
@grammarUpdateDisposable = @grammar.onDidUpdate => @retokenizeLines()
@disposables.add(@grammarUpdateDisposable)

View File

@@ -1,5 +1,5 @@
_ = require 'underscore-plus'
{isPairedCharacter} = require './text-utils'
{isPairedCharacter, isCJKCharacter} = require './text-utils'
Token = require './token'
{SoftTab, HardTab, PairedCharacter, SoftWrapIndent} = require './special-token-symbols'
@@ -322,15 +322,18 @@ class TokenizedLine
return unless @text.length > maxColumn
if /\s/.test(@text[maxColumn])
# search forward for the start of a word past the boundary
# search forward for the start of a word past the boundary
for column in [maxColumn..@text.length]
return column if /\S/.test(@text[column])
return @text.length
else if isCJKCharacter(@text[maxColumn])
maxColumn
else
# search backward for the start of the word on the boundary
for column in [maxColumn..@firstNonWhitespaceIndex]
return column + 1 if /\s/.test(@text[column])
if /\s/.test(@text[column]) or isCJKCharacter(@text[column])
return column + 1
return maxColumn