mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-21 07:58:04 +03:00
Merge branch 'dev' of github.com:github/atom into ci-testing
This commit is contained in:
commit
beb000ceaf
@ -17,4 +17,3 @@ Requirements
|
||||
1. gh-setup atom
|
||||
|
||||
2. cd ~/github/atom && `rake install`
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Getting Started
|
||||
|
||||
Welcome to Atom. This documentation is intented to offer a basic introduction
|
||||
Welcome to Atom. This documentation is intended to offer a basic introduction
|
||||
of how to get productive with this editor. Then we'll delve into more details
|
||||
about configuring, theming, and extending Atom.
|
||||
|
||||
|
@ -27,7 +27,8 @@ namespace v8_extensions {
|
||||
"exists", "read", "write", "absolute", "getAllFilePathsAsync", "traverseTree", "isDirectory",
|
||||
"isFile", "remove", "writeToPasteboard", "readFromPasteboard", "quit", "watchPath", "unwatchPath",
|
||||
"getWatchedPaths", "unwatchAllPaths", "makeDirectory", "move", "moveToTrash", "reload", "lastModified",
|
||||
"md5ForPath", "exec", "getPlatform", "setWindowState", "getWindowState"
|
||||
"md5ForPath", "exec", "getPlatform", "setWindowState", "getWindowState", "isMisspelled",
|
||||
"getCorrectionsForMisspelling"
|
||||
};
|
||||
|
||||
CefRefPtr<CefV8Value> nativeObject = CefV8Value::CreateObject(NULL);
|
||||
@ -521,6 +522,29 @@ namespace v8_extensions {
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (name == "isMisspelled") {
|
||||
NSString *word = stringFromCefV8Value(arguments[0]);
|
||||
NSRange range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:word startingAt:0];
|
||||
retval = CefV8Value::CreateBool(range.length > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (name == "getCorrectionsForMisspelling") {
|
||||
NSString *misspelling = stringFromCefV8Value(arguments[0]);
|
||||
NSSpellChecker *spellchecker = [NSSpellChecker sharedSpellChecker];
|
||||
NSString *language = [spellchecker language];
|
||||
NSRange range;
|
||||
range.location = 0;
|
||||
range.length = [misspelling length];
|
||||
NSArray *guesses = [spellchecker guessesForWordRange:range inString:misspelling language:language inSpellDocumentWithTag:0];
|
||||
CefRefPtr<CefV8Value> v8Guesses = CefV8Value::CreateArray([guesses count]);
|
||||
for (int i = 0; i < [guesses count]; i++) {
|
||||
v8Guesses->SetValue(i, CefV8Value::CreateString([[guesses objectAtIndex:i] UTF8String]));
|
||||
}
|
||||
retval = v8Guesses;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -741,6 +741,7 @@ describe 'Buffer', ->
|
||||
oldTailPosition: [4, 20]
|
||||
newTailPosition: [4, 20]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
@ -751,6 +752,7 @@ describe 'Buffer', ->
|
||||
oldHeadPosition: [6, 2]
|
||||
newHeadPosition: [6, 5]
|
||||
bufferChanged: true
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "calls the given callback when the marker's tail position changes", ->
|
||||
@ -762,6 +764,7 @@ describe 'Buffer', ->
|
||||
oldTailPosition: [4, 20]
|
||||
newTailPosition: [6, 2]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
@ -773,6 +776,7 @@ describe 'Buffer', ->
|
||||
oldTailPosition: [6, 2]
|
||||
newTailPosition: [6, 5]
|
||||
bufferChanged: true
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "calls the callback when the selection's tail is cleared", ->
|
||||
@ -784,6 +788,7 @@ describe 'Buffer', ->
|
||||
oldTailPosition: [4, 20]
|
||||
newTailPosition: [4, 23]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "only calls the callback once when both the marker's head and tail positions change due to the same operation", ->
|
||||
@ -795,6 +800,7 @@ describe 'Buffer', ->
|
||||
oldHeadPosition: [4, 23]
|
||||
newHeadPosition: [4, 26]
|
||||
bufferChanged: true
|
||||
valid: true
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
@ -806,6 +812,31 @@ describe 'Buffer', ->
|
||||
oldHeadPosition: [4, 26]
|
||||
newHeadPosition: [1, 1]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "calls the callback with the valid flag set to false when the marker is invalidated", ->
|
||||
buffer.deleteRow(4)
|
||||
expect(observeHandler.callCount).toBe 1
|
||||
expect(observeHandler.argsForCall[0][0]).toEqual {
|
||||
oldTailPosition: [4, 20]
|
||||
newTailPosition: [4, 20]
|
||||
oldHeadPosition: [4, 23]
|
||||
newHeadPosition: [4, 23]
|
||||
bufferChanged: true
|
||||
valid: false
|
||||
}
|
||||
|
||||
observeHandler.reset()
|
||||
buffer.undo()
|
||||
expect(observeHandler.callCount).toBe 1
|
||||
expect(observeHandler.argsForCall[0][0]).toEqual {
|
||||
oldTailPosition: [4, 20]
|
||||
newTailPosition: [4, 20]
|
||||
oldHeadPosition: [4, 23]
|
||||
newHeadPosition: [4, 23]
|
||||
bufferChanged: true
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "allows the observation subscription to be cancelled", ->
|
||||
@ -830,19 +861,20 @@ describe 'Buffer', ->
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker)).toBeUndefined()
|
||||
|
||||
# even "stayValid" markers get destroyed properly
|
||||
marker2 = buffer.markRange([[4, 20], [4, 23]], stayValid: true)
|
||||
# even "invalidationStrategy: never" markers get destroyed properly
|
||||
marker2 = buffer.markRange([[4, 20], [4, 23]], invalidationStrategy: 'never')
|
||||
buffer.delete([[4, 15], [4, 25]])
|
||||
buffer.destroyMarker(marker2)
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker2)).toBeUndefined()
|
||||
|
||||
describe "marker updates due to buffer changes", ->
|
||||
[marker1, marker2] = []
|
||||
[marker1, marker2, marker3] = []
|
||||
|
||||
beforeEach ->
|
||||
marker1 = buffer.markRange([[4, 20], [4, 23]])
|
||||
marker2 = buffer.markRange([[4, 20], [4, 23]], stayValid: true)
|
||||
marker2 = buffer.markRange([[4, 20], [4, 23]], invalidationStrategy: 'never')
|
||||
marker3 = buffer.markRange([[4, 20], [4, 23]], invalidationStrategy: 'between')
|
||||
|
||||
describe "when the buffer changes due to a new operation", ->
|
||||
describe "when the change precedes the marker range", ->
|
||||
@ -874,20 +906,37 @@ describe 'Buffer', ->
|
||||
buffer.insert([4, 20], '...')
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 26]]
|
||||
|
||||
describe "when the invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.insert([4, 20], '...')
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
|
||||
describe "when the change is an insertion at the end of the marker range", ->
|
||||
it "moves the end point", ->
|
||||
buffer.insert([4, 23], '...')
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 26]]
|
||||
|
||||
describe "when the invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.insert([4, 23], '...')
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
|
||||
describe "when the change surrounds the marker range", ->
|
||||
describe "when the marker was created with stayValid: false (the default)", ->
|
||||
describe "when the marker's invalidation strategy is 'contains' (the default)", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 15], [4, 25]])
|
||||
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker was created with stayValid: true", ->
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 15], [4, 25]])
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
it "does not invalidate the marker, but sets it to an empty range at the end of the change", ->
|
||||
buffer.change([[4, 15], [4, 25]], "...")
|
||||
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 18], [4, 18]]
|
||||
@ -895,14 +944,21 @@ describe 'Buffer', ->
|
||||
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the change straddles the start of the marker range", ->
|
||||
describe "when the marker was created with stayValid: false (the default)", ->
|
||||
describe "when the marker's invalidation strategy is 'contains' (the default)", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 15], [4, 22]])
|
||||
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker was created with stayValid: true", ->
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 15], [4, 22]])
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
it "moves the start of the marker range to the end of the change", ->
|
||||
buffer.delete([[4, 15], [4, 22]])
|
||||
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 15], [4, 16]]
|
||||
@ -910,20 +966,49 @@ describe 'Buffer', ->
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the change straddles the end of the marker range", ->
|
||||
describe "when the marker was created with stayValid: false (the default)", ->
|
||||
describe "when the marker's invalidation strategy is 'contains' (the default)", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 22], [4, 25]])
|
||||
expect(buffer.getMarkerRange(marker1)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker was created with stayValid: true", ->
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.delete([[4, 22], [4, 25]])
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
it "moves the end of the marker range to the start of the change", ->
|
||||
buffer.delete([[4, 22], [4, 25]])
|
||||
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 22]]
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the change is between the start and the end of the marker range", ->
|
||||
describe "when the marker's invalidation strategy is 'contains' (the default)", ->
|
||||
it "does not invalidate the marker", ->
|
||||
buffer.insert([4, 21], 'x')
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 24]]
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'between'", ->
|
||||
it "invalidates the marker", ->
|
||||
buffer.insert([4, 21], 'x')
|
||||
expect(buffer.getMarkerRange(marker3)).toBeUndefined()
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker3)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the marker's invalidation strategy is 'never'", ->
|
||||
it "moves the end of the marker range to the start of the change", ->
|
||||
buffer.insert([4, 21], 'x')
|
||||
expect(buffer.getMarkerRange(marker2)).toEqual [[4, 20], [4, 24]]
|
||||
buffer.undo()
|
||||
expect(buffer.getMarkerRange(marker1)).toEqual [[4, 20], [4, 23]]
|
||||
|
||||
describe "when the buffer changes due to the undo or redo of a previous operation", ->
|
||||
it "restores invalidated markers when undoing/redoing in the other direction", ->
|
||||
buffer.change([[4, 21], [4, 24]], "foo")
|
||||
|
@ -661,6 +661,7 @@ describe "DisplayBuffer", ->
|
||||
newTailScreenPosition: [5, 4]
|
||||
newTailBufferPosition: [8, 4]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
@ -676,6 +677,7 @@ describe "DisplayBuffer", ->
|
||||
newTailScreenPosition: [5, 4]
|
||||
newTailBufferPosition: [8, 4]
|
||||
bufferChanged: true
|
||||
valid: true
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
@ -691,6 +693,7 @@ describe "DisplayBuffer", ->
|
||||
newTailScreenPosition: [8, 4]
|
||||
newTailBufferPosition: [8, 4]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
@ -706,6 +709,7 @@ describe "DisplayBuffer", ->
|
||||
newTailScreenPosition: [5, 4]
|
||||
newTailBufferPosition: [8, 4]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "calls the callback whenever the marker tail's position changes in the buffer or on screen", ->
|
||||
@ -721,6 +725,7 @@ describe "DisplayBuffer", ->
|
||||
newTailScreenPosition: [8, 20]
|
||||
newTailBufferPosition: [11, 20]
|
||||
bufferChanged: false
|
||||
valid: true
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
@ -736,6 +741,40 @@ describe "DisplayBuffer", ->
|
||||
newTailScreenPosition: [8, 23]
|
||||
newTailBufferPosition: [11, 23]
|
||||
bufferChanged: true
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "calls the callback whenever the marker is invalidated or revalidated", ->
|
||||
buffer.deleteRow(8)
|
||||
expect(observeHandler).toHaveBeenCalled()
|
||||
expect(observeHandler.argsForCall[0][0]).toEqual {
|
||||
oldHeadScreenPosition: [5, 10]
|
||||
oldHeadBufferPosition: [8, 10]
|
||||
newHeadScreenPosition: [5, 10]
|
||||
newHeadBufferPosition: [8, 10]
|
||||
oldTailScreenPosition: [5, 4]
|
||||
oldTailBufferPosition: [8, 4]
|
||||
newTailScreenPosition: [5, 4]
|
||||
newTailBufferPosition: [8, 4]
|
||||
bufferChanged: true
|
||||
valid: false
|
||||
}
|
||||
|
||||
observeHandler.reset()
|
||||
buffer.undo()
|
||||
|
||||
expect(observeHandler).toHaveBeenCalled()
|
||||
expect(observeHandler.argsForCall[0][0]).toEqual {
|
||||
oldHeadScreenPosition: [5, 10]
|
||||
oldHeadBufferPosition: [8, 10]
|
||||
newHeadScreenPosition: [5, 10]
|
||||
newHeadBufferPosition: [8, 10]
|
||||
oldTailScreenPosition: [5, 4]
|
||||
oldTailBufferPosition: [8, 4]
|
||||
newTailScreenPosition: [5, 4]
|
||||
newTailBufferPosition: [8, 4]
|
||||
bufferChanged: true
|
||||
valid: true
|
||||
}
|
||||
|
||||
it "does not call the callback for screen changes that don't change the position of the marker", ->
|
||||
|
@ -3,13 +3,13 @@ OnigRegExp = require 'onig-reg-exp'
|
||||
describe "OnigRegExp", ->
|
||||
describe ".search(string, index)", ->
|
||||
it "returns an array of the match and all capture groups", ->
|
||||
regex = new OnigRegExp("\\w(\\d+)")
|
||||
regex = OnigRegExp.create("\\w(\\d+)")
|
||||
result = regex.search("----a123----")
|
||||
expect(result).toEqual ["a123", "123"]
|
||||
expect(result.index).toBe 4
|
||||
expect(result.indices).toEqual [4, 5]
|
||||
|
||||
it "returns null if it does not match", ->
|
||||
regex = new OnigRegExp("\\w(\\d+)")
|
||||
regex = OnigRegExp.create("\\w(\\d+)")
|
||||
result = regex.search("--------")
|
||||
expect(result).toBeNull()
|
||||
|
@ -107,5 +107,4 @@ class BufferChangeOperation
|
||||
if validMarker = @buffer.validMarkers[id]
|
||||
validMarker.setRange(previousRange)
|
||||
else if invalidMarker = @buffer.invalidMarkers[id]
|
||||
@buffer.validMarkers[id] = invalidMarker
|
||||
|
||||
invalidMarker.revalidate()
|
||||
|
@ -8,9 +8,10 @@ class BufferMarker
|
||||
headPosition: null
|
||||
tailPosition: null
|
||||
suppressObserverNotification: false
|
||||
stayValid: false
|
||||
invalidationStrategy: null
|
||||
|
||||
constructor: ({@id, @buffer, range, @stayValid, noTail, reverse}) ->
|
||||
constructor: ({@id, @buffer, range, @invalidationStrategy, noTail, reverse}) ->
|
||||
@invalidationStrategy ?= 'contains'
|
||||
@setRange(range, {noTail, reverse})
|
||||
|
||||
setRange: (range, options={}) ->
|
||||
@ -71,23 +72,30 @@ class BufferMarker
|
||||
newTailPosition = @getTailPosition()
|
||||
@notifyObservers({oldTailPosition, newTailPosition, bufferChanged: false})
|
||||
|
||||
tryToInvalidate: (oldRange) ->
|
||||
containsStart = oldRange.containsPoint(@getStartPosition(), exclusive: true)
|
||||
containsEnd = oldRange.containsPoint(@getEndPosition(), exclusive: true)
|
||||
return unless containsEnd or containsStart
|
||||
tryToInvalidate: (changedRange) ->
|
||||
betweenStartAndEnd = @getRange().containsRange(changedRange, exclusive: false)
|
||||
containsStart = changedRange.containsPoint(@getStartPosition(), exclusive: true)
|
||||
containsEnd = changedRange.containsPoint(@getEndPosition(), exclusive: true)
|
||||
|
||||
if @stayValid
|
||||
previousRange = @getRange()
|
||||
if containsStart and containsEnd
|
||||
@setRange([oldRange.end, oldRange.end])
|
||||
else if containsStart
|
||||
@setRange([oldRange.end, @getEndPosition()])
|
||||
else
|
||||
@setRange([@getStartPosition(), oldRange.start])
|
||||
[@id, previousRange]
|
||||
else
|
||||
@invalidate()
|
||||
[@id]
|
||||
switch @invalidationStrategy
|
||||
when 'between'
|
||||
if betweenStartAndEnd or containsStart or containsEnd
|
||||
@invalidate()
|
||||
[@id]
|
||||
when 'contains'
|
||||
if containsStart or containsEnd
|
||||
@invalidate()
|
||||
[@id]
|
||||
when 'never'
|
||||
if containsStart or containsEnd
|
||||
previousRange = @getRange()
|
||||
if containsStart and containsEnd
|
||||
@setRange([changedRange.end, changedRange.end])
|
||||
else if containsStart
|
||||
@setRange([changedRange.end, @getEndPosition()])
|
||||
else
|
||||
@setRange([@getStartPosition(), changedRange.start])
|
||||
[@id, previousRange]
|
||||
|
||||
handleBufferChange: (bufferChange) ->
|
||||
@consolidateObserverNotifications true, =>
|
||||
@ -113,23 +121,31 @@ class BufferMarker
|
||||
[newRow, newColumn]
|
||||
|
||||
observe: (callback) ->
|
||||
@on 'position-changed', callback
|
||||
@on 'changed', callback
|
||||
cancel: => @unobserve(callback)
|
||||
|
||||
unobserve: (callback) ->
|
||||
@off 'position-changed', callback
|
||||
@off 'changed', callback
|
||||
|
||||
containsPoint: (point) ->
|
||||
@getRange().containsPoint(point)
|
||||
|
||||
notifyObservers: ({oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged}) ->
|
||||
notifyObservers: ({oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged} = {}) ->
|
||||
return if @suppressObserverNotification
|
||||
return if _.isEqual(newHeadPosition, oldHeadPosition) and _.isEqual(newTailPosition, oldTailPosition)
|
||||
|
||||
if newHeadPosition? and newTailPosition?
|
||||
return if _.isEqual(newHeadPosition, oldHeadPosition) and _.isEqual(newTailPosition, oldTailPosition)
|
||||
else if newHeadPosition?
|
||||
return if _.isEqual(newHeadPosition, oldHeadPosition)
|
||||
else if newTailPosition?
|
||||
return if _.isEqual(newTailPosition, oldTailPosition)
|
||||
|
||||
oldHeadPosition ?= @getHeadPosition()
|
||||
newHeadPosition ?= @getHeadPosition()
|
||||
oldTailPosition ?= @getTailPosition()
|
||||
newTailPosition ?= @getTailPosition()
|
||||
@trigger 'position-changed', {oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged}
|
||||
valid = @buffer.validMarkers[@id]?
|
||||
@trigger 'changed', {oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged, valid}
|
||||
|
||||
consolidateObserverNotifications: (bufferChanged, fn) ->
|
||||
@suppressObserverNotification = true
|
||||
@ -141,8 +157,14 @@ class BufferMarker
|
||||
@suppressObserverNotification = false
|
||||
@notifyObservers({oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged})
|
||||
|
||||
invalidate: (preserve) ->
|
||||
invalidate: ->
|
||||
delete @buffer.validMarkers[@id]
|
||||
@buffer.invalidMarkers[@id] = this
|
||||
@notifyObservers(bufferChanged: true)
|
||||
|
||||
revalidate: ->
|
||||
delete @buffer.invalidMarkers[@id]
|
||||
@buffer.validMarkers[@id] = this
|
||||
@notifyObservers(bufferChanged: true)
|
||||
|
||||
_.extend BufferMarker.prototype, EventEmitter
|
||||
|
@ -7,6 +7,7 @@ class DisplayBufferMarker
|
||||
bufferMarkerSubscription: null
|
||||
headScreenPosition: null
|
||||
tailScreenPosition: null
|
||||
valid: true
|
||||
|
||||
constructor: ({@id, @displayBuffer}) ->
|
||||
@buffer = @displayBuffer.buffer
|
||||
@ -57,11 +58,11 @@ class DisplayBufferMarker
|
||||
|
||||
observe: (callback) ->
|
||||
@observeBufferMarkerIfNeeded()
|
||||
@on 'position-changed', callback
|
||||
@on 'changed', callback
|
||||
cancel: => @unobserve(callback)
|
||||
|
||||
unobserve: (callback) ->
|
||||
@off 'position-changed', callback
|
||||
@off 'changed', callback
|
||||
@unobserveBufferMarkerIfNeeded()
|
||||
|
||||
observeBufferMarkerIfNeeded: ->
|
||||
@ -69,13 +70,14 @@ class DisplayBufferMarker
|
||||
@getHeadScreenPosition() # memoize current value
|
||||
@getTailScreenPosition() # memoize current value
|
||||
@bufferMarkerSubscription =
|
||||
@buffer.observeMarker @id, ({oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged}) =>
|
||||
@buffer.observeMarker @id, ({oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged, valid}) =>
|
||||
@notifyObservers
|
||||
oldHeadBufferPosition: oldHeadPosition
|
||||
newHeadBufferPosition: newHeadPosition
|
||||
oldTailBufferPosition: oldTailPosition
|
||||
newTailBufferPosition: newTailPosition
|
||||
bufferChanged: bufferChanged
|
||||
valid: valid
|
||||
@displayBuffer.markers[@id] = this
|
||||
|
||||
unobserveBufferMarkerIfNeeded: ->
|
||||
@ -83,28 +85,37 @@ class DisplayBufferMarker
|
||||
@bufferMarkerSubscription.cancel()
|
||||
delete @displayBuffer.markers[@id]
|
||||
|
||||
notifyObservers: ({oldHeadBufferPosition, oldTailBufferPosition, bufferChanged}) ->
|
||||
notifyObservers: ({oldHeadBufferPosition, oldTailBufferPosition, bufferChanged, valid} = {}) ->
|
||||
oldHeadScreenPosition = @getHeadScreenPosition()
|
||||
@headScreenPosition = null
|
||||
newHeadScreenPosition = @getHeadScreenPosition()
|
||||
|
||||
newHeadScreenPosition = oldHeadScreenPosition
|
||||
oldTailScreenPosition = @getTailScreenPosition()
|
||||
@tailScreenPosition = null
|
||||
newTailScreenPosition = @getTailScreenPosition()
|
||||
newTailScreenPosition = oldTailScreenPosition
|
||||
valid ?= true
|
||||
|
||||
return if _.isEqual(newHeadScreenPosition, oldHeadScreenPosition) and _.isEqual(newTailScreenPosition, oldTailScreenPosition)
|
||||
if valid
|
||||
@headScreenPosition = null
|
||||
newHeadScreenPosition = @getHeadScreenPosition()
|
||||
@tailScreenPosition = null
|
||||
newTailScreenPosition = @getTailScreenPosition()
|
||||
|
||||
validChanged = valid isnt @valid
|
||||
headScreenPositionChanged = not _.isEqual(newHeadScreenPosition, oldHeadScreenPosition)
|
||||
tailScreenPositionChanged = not _.isEqual(newTailScreenPosition, oldTailScreenPosition)
|
||||
return unless validChanged or headScreenPositionChanged or tailScreenPositionChanged
|
||||
|
||||
oldHeadBufferPosition ?= @getHeadBufferPosition()
|
||||
newHeadBufferPosition = @getHeadBufferPosition()
|
||||
newHeadBufferPosition = @getHeadBufferPosition() ? oldHeadBufferPosition
|
||||
oldTailBufferPosition ?= @getTailBufferPosition()
|
||||
newTailBufferPosition = @getTailBufferPosition()
|
||||
newTailBufferPosition = @getTailBufferPosition() ? oldTailBufferPosition
|
||||
@valid = valid
|
||||
|
||||
@trigger 'position-changed', {
|
||||
@trigger 'changed', {
|
||||
oldHeadScreenPosition, newHeadScreenPosition,
|
||||
oldTailScreenPosition, newTailScreenPosition,
|
||||
oldHeadBufferPosition, newHeadBufferPosition,
|
||||
oldTailBufferPosition, newTailBufferPosition,
|
||||
bufferChanged
|
||||
valid
|
||||
}
|
||||
|
||||
_.extend DisplayBufferMarker.prototype, EventEmitter
|
||||
|
@ -332,8 +332,9 @@ class DisplayBuffer
|
||||
getMarkers: ->
|
||||
_.values(@markers)
|
||||
|
||||
markScreenRange: (screenRange) ->
|
||||
@markBufferRange(@bufferRangeForScreenRange(screenRange))
|
||||
markScreenRange: (args...) ->
|
||||
bufferRange = @bufferRangeForScreenRange(args.shift())
|
||||
@markBufferRange(bufferRange, args...)
|
||||
|
||||
markBufferRange: (args...) ->
|
||||
@buffer.markRange(args...)
|
||||
|
@ -538,11 +538,11 @@ class EditSession
|
||||
_.last(@cursors)
|
||||
|
||||
addCursorAtScreenPosition: (screenPosition) ->
|
||||
marker = @markScreenPosition(screenPosition, stayValid: true)
|
||||
marker = @markScreenPosition(screenPosition, invalidationStrategy: 'never')
|
||||
@addSelection(marker).cursor
|
||||
|
||||
addCursorAtBufferPosition: (bufferPosition) ->
|
||||
marker = @markBufferPosition(bufferPosition, stayValid: true)
|
||||
marker = @markBufferPosition(bufferPosition, invalidationStrategy: 'never')
|
||||
@addSelection(marker).cursor
|
||||
|
||||
addCursor: (marker) ->
|
||||
@ -565,7 +565,7 @@ class EditSession
|
||||
selection
|
||||
|
||||
addSelectionForBufferRange: (bufferRange, options={}) ->
|
||||
options = _.defaults({stayValid: true}, options)
|
||||
options = _.defaults({invalidationStrategy: 'never'}, options)
|
||||
marker = @markBufferRange(bufferRange, options)
|
||||
@addSelection(marker)
|
||||
|
||||
|
@ -24,7 +24,7 @@ class Git
|
||||
ignore: 1 << 14
|
||||
|
||||
constructor: (path, options={}) ->
|
||||
@repo = new GitRepository(path)
|
||||
@repo = GitRepository.open(path)
|
||||
refreshIndexOnFocus = options.refreshIndexOnFocus ? true
|
||||
if refreshIndexOnFocus
|
||||
$ = require 'jquery'
|
||||
|
@ -30,13 +30,13 @@ class LanguageMode
|
||||
|
||||
buffer = @editSession.buffer
|
||||
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '($1)?')
|
||||
commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})")
|
||||
commentStartRegex = OnigRegExp.create("^(\\s*)(#{commentStartRegexString})")
|
||||
shouldUncomment = commentStartRegex.test(buffer.lineForRow(start))
|
||||
|
||||
if commentEndString = syntax.getProperty(scopes, "editor.commentEnd")
|
||||
if shouldUncomment
|
||||
commentEndRegexString = _.escapeRegExp(commentEndString).replace(/^(\s+)/, '($1)?')
|
||||
commentEndRegex = new OnigRegExp("(#{commentEndRegexString})(\\s*)$")
|
||||
commentEndRegex = OnigRegExp.create("(#{commentEndRegexString})(\\s*)$")
|
||||
startMatch = commentStartRegex.search(buffer.lineForRow(start))
|
||||
endMatch = commentEndRegex.search(buffer.lineForRow(end))
|
||||
if startMatch and endMatch
|
||||
@ -152,12 +152,12 @@ class LanguageMode
|
||||
|
||||
increaseIndentRegexForScopes: (scopes) ->
|
||||
if increaseIndentPattern = syntax.getProperty(scopes, 'editor.increaseIndentPattern')
|
||||
new OnigRegExp(increaseIndentPattern)
|
||||
OnigRegExp.create(increaseIndentPattern)
|
||||
|
||||
decreaseIndentRegexForScopes: (scopes) ->
|
||||
if decreaseIndentPattern = syntax.getProperty(scopes, 'editor.decreaseIndentPattern')
|
||||
new OnigRegExp(decreaseIndentPattern)
|
||||
OnigRegExp.create(decreaseIndentPattern)
|
||||
|
||||
foldEndRegexForScopes: (scopes) ->
|
||||
if foldEndPattern = syntax.getProperty(scopes, 'editor.foldEndPattern')
|
||||
new OnigRegExp(foldEndPattern)
|
||||
OnigRegExp.create(foldEndPattern)
|
||||
|
@ -57,7 +57,11 @@ class Range
|
||||
else
|
||||
otherRange.intersectsWith(this)
|
||||
|
||||
containsPoint: (point, { exclusive } = {}) ->
|
||||
containsRange: (otherRange, {exclusive} = {}) ->
|
||||
{ start, end } = Range.fromObject(otherRange)
|
||||
@containsPoint(start, {exclusive}) and @containsPoint(end, {exclusive})
|
||||
|
||||
containsPoint: (point, {exclusive} = {}) ->
|
||||
point = Point.fromObject(point)
|
||||
if exclusive
|
||||
point.isGreaterThan(@start) and point.isLessThan(@end)
|
||||
|
@ -28,7 +28,7 @@ class TextMateGrammar
|
||||
constructor: ({ @name, @fileTypes, @scopeName, patterns, repository, @foldingStopMarker, firstLineMatch}) ->
|
||||
@initialRule = new Rule(this, {@scopeName, patterns})
|
||||
@repository = {}
|
||||
@firstLineRegex = new OnigRegExp(firstLineMatch) if firstLineMatch
|
||||
@firstLineRegex = OnigRegExp.create(firstLineMatch) if firstLineMatch
|
||||
@fileTypes ?= []
|
||||
|
||||
for name, data of repository
|
||||
@ -111,7 +111,7 @@ class Rule
|
||||
regex = pattern.regexSource
|
||||
regexes.push regex if regex
|
||||
|
||||
regexScanner = new OnigScanner(regexes)
|
||||
regexScanner = OnigScanner.create(regexes)
|
||||
regexScanner.patterns = patterns
|
||||
@scannersByBaseGrammarName[baseGrammar.name] = regexScanner unless anchored
|
||||
regexScanner
|
||||
|
@ -7,4 +7,3 @@ module.exports =
|
||||
rootView.eachEditor (editor) =>
|
||||
if editor.attached and not editor.mini
|
||||
@autoCompleteViews.push new AutocompleteView(editor)
|
||||
|
||||
|
2
src/packages/spell-check/keymaps/spell-check.cson
Normal file
2
src/packages/spell-check/keymaps/spell-check.cson
Normal file
@ -0,0 +1,2 @@
|
||||
'.editor':
|
||||
'meta-0': 'editor:correct-misspelling'
|
71
src/packages/spell-check/lib/corrections-view.coffee
Normal file
71
src/packages/spell-check/lib/corrections-view.coffee
Normal file
@ -0,0 +1,71 @@
|
||||
{$$} = require 'space-pen'
|
||||
Range = require 'range'
|
||||
SelectList = require 'select-list'
|
||||
|
||||
module.exports =
|
||||
class CorrectionsView extends SelectList
|
||||
@viewClass: -> "corrections #{super} popover-list"
|
||||
|
||||
editor: null
|
||||
corrections: null
|
||||
misspellingRange: null
|
||||
aboveCursor: false
|
||||
|
||||
initialize: (@editor, @corrections, @misspellingRange) ->
|
||||
super
|
||||
|
||||
@attach()
|
||||
|
||||
itemForElement: (word) ->
|
||||
$$ ->
|
||||
@li word
|
||||
|
||||
selectNextItem: ->
|
||||
super
|
||||
|
||||
false
|
||||
|
||||
selectPreviousItem: ->
|
||||
super
|
||||
|
||||
false
|
||||
|
||||
confirmed: (correction) ->
|
||||
@cancel()
|
||||
return unless correction
|
||||
@editor.transact =>
|
||||
@editor.setSelectedBufferRange(@editor.bufferRangeForScreenRange(@misspellingRange))
|
||||
@editor.insertText(correction)
|
||||
|
||||
attach: ->
|
||||
@aboveCursor = false
|
||||
if @corrections.length > 0
|
||||
@setArray(@corrections)
|
||||
else
|
||||
@setError("No corrections found")
|
||||
|
||||
@editor.appendToLinesView(this)
|
||||
@setPosition()
|
||||
@miniEditor.focus()
|
||||
|
||||
detach: ->
|
||||
super
|
||||
|
||||
@editor.focus()
|
||||
|
||||
setPosition: ->
|
||||
{ left, top } = @editor.pixelPositionForScreenPosition(@misspellingRange.start)
|
||||
height = @outerHeight()
|
||||
potentialTop = top + @editor.lineHeight
|
||||
potentialBottom = potentialTop - @editor.scrollTop() + height
|
||||
|
||||
if @aboveCursor or potentialBottom > @editor.outerHeight()
|
||||
@aboveCursor = true
|
||||
@css(left: left, top: top - height, bottom: 'inherit')
|
||||
else
|
||||
@css(left: left, top: potentialTop, bottom: 'inherit')
|
||||
|
||||
populateList: ->
|
||||
super
|
||||
|
||||
@setPosition()
|
61
src/packages/spell-check/lib/misspelling-view.coffee
Normal file
61
src/packages/spell-check/lib/misspelling-view.coffee
Normal file
@ -0,0 +1,61 @@
|
||||
{View} = require 'space-pen'
|
||||
Range = require 'range'
|
||||
CorrectionsView = require './corrections-view'
|
||||
|
||||
module.exports =
|
||||
class MisspellingView extends View
|
||||
@content: ->
|
||||
@div class: 'misspelling'
|
||||
|
||||
initialize: (range, @editor) ->
|
||||
@editSession = @editor.activeEditSession
|
||||
range = @editSession.screenRangeForBufferRange(Range.fromObject(range))
|
||||
@startPosition = range.start
|
||||
@endPosition = range.end
|
||||
@misspellingValid = true
|
||||
|
||||
@marker = @editSession.markScreenRange(range, invalidationStrategy: 'between')
|
||||
@editSession.observeMarker @marker, ({newHeadScreenPosition, newTailScreenPosition, valid}) =>
|
||||
@startPosition = newTailScreenPosition
|
||||
@endPosition = newHeadScreenPosition
|
||||
@updateDisplayPosition = valid
|
||||
@misspellingValid = valid
|
||||
@hide() unless valid
|
||||
|
||||
@subscribe @editor, 'editor:display-updated', =>
|
||||
@updatePosition() if @updateDisplayPosition
|
||||
|
||||
@editor.command 'editor:correct-misspelling', =>
|
||||
return unless @misspellingValid and @containsCursor()
|
||||
|
||||
screenRange = @getScreenRange()
|
||||
misspelling = @editor.getTextInRange(@editor.bufferRangeForScreenRange(screenRange))
|
||||
corrections = $native.getCorrectionsForMisspelling(misspelling)
|
||||
@correctionsView?.remove()
|
||||
@correctionsView = new CorrectionsView(@editor, corrections, screenRange)
|
||||
|
||||
@updatePosition()
|
||||
|
||||
getScreenRange: ->
|
||||
new Range(@startPosition, @endPosition)
|
||||
|
||||
containsCursor: ->
|
||||
cursor = @editor.getCursorScreenPosition()
|
||||
@getScreenRange().containsPoint(cursor, exclusive: false)
|
||||
|
||||
updatePosition: ->
|
||||
@updateDisplayPosition = false
|
||||
startPixelPosition = @editor.pixelPositionForScreenPosition(@startPosition)
|
||||
endPixelPosition = @editor.pixelPositionForScreenPosition(@endPosition)
|
||||
@css
|
||||
top: startPixelPosition.top
|
||||
left: startPixelPosition.left
|
||||
width: endPixelPosition.left - startPixelPosition.left
|
||||
height: @editor.lineHeight
|
||||
@show()
|
||||
|
||||
destroy: ->
|
||||
@misspellingValid = false
|
||||
@editSession.destroyMarker(@marker)
|
||||
@correctionsView?.remove()
|
||||
@remove()
|
14
src/packages/spell-check/lib/spell-check-handler.coffee
Normal file
14
src/packages/spell-check/lib/spell-check-handler.coffee
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports =
|
||||
findMisspellings: (text) ->
|
||||
wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]]|$)/g
|
||||
row = 0
|
||||
misspellings = []
|
||||
for line in text.split('\n')
|
||||
while matches = wordRegex.exec(line)
|
||||
word = matches[1]
|
||||
continue unless $native.isMisspelled(word)
|
||||
startColumn = matches.index + matches[0].length - word.length
|
||||
endColumn = startColumn + word.length
|
||||
misspellings.push([[row, startColumn], [row, endColumn]])
|
||||
row++
|
||||
callTaskMethod('misspellingsFound', misspellings)
|
13
src/packages/spell-check/lib/spell-check-task.coffee
Normal file
13
src/packages/spell-check/lib/spell-check-task.coffee
Normal file
@ -0,0 +1,13 @@
|
||||
Task = require 'task'
|
||||
|
||||
module.exports =
|
||||
class SpellCheckTask extends Task
|
||||
constructor: (@text, @callback) ->
|
||||
super('spell-check/lib/spell-check-handler')
|
||||
|
||||
started: ->
|
||||
@callWorkerMethod('findMisspellings', @text)
|
||||
|
||||
misspellingsFound: (misspellings) ->
|
||||
@done()
|
||||
@callback(misspellings)
|
53
src/packages/spell-check/lib/spell-check-view.coffee
Normal file
53
src/packages/spell-check/lib/spell-check-view.coffee
Normal file
@ -0,0 +1,53 @@
|
||||
{View} = require 'space-pen'
|
||||
_ = require 'underscore'
|
||||
SpellCheckTask = require './spell-check-task'
|
||||
MisspellingView = require './misspelling-view'
|
||||
|
||||
module.exports =
|
||||
class SpellCheckView extends View
|
||||
@content: ->
|
||||
@div class: 'spell-check'
|
||||
|
||||
views: []
|
||||
|
||||
initialize: (@editor) ->
|
||||
@subscribe @editor, 'editor:path-changed', => @subscribeToBuffer()
|
||||
@subscribe @editor, 'editor:grammar-changed', => @subscribeToBuffer()
|
||||
@observeConfig 'editor.fontSize', => @subscribeToBuffer()
|
||||
@observeConfig 'spell-check.grammars', => @subscribeToBuffer()
|
||||
|
||||
@subscribeToBuffer()
|
||||
|
||||
subscribeToBuffer: ->
|
||||
@destroyViews()
|
||||
@task?.abort()
|
||||
return unless @spellCheckCurrentGrammar()
|
||||
|
||||
@buffer?.off '.spell-check'
|
||||
@buffer = @editor.getBuffer()
|
||||
@buffer.on 'contents-modified.spell-check', => @updateMisspellings()
|
||||
@updateMisspellings()
|
||||
|
||||
spellCheckCurrentGrammar: ->
|
||||
grammar = @editor.getGrammar().scopeName
|
||||
_.contains config.get('spell-check.grammars'), grammar
|
||||
|
||||
destroyViews: ->
|
||||
if @views
|
||||
view.destroy() for view in @views
|
||||
@views = []
|
||||
|
||||
addViews: (misspellings) ->
|
||||
for misspelling in misspellings
|
||||
view = new MisspellingView(misspelling, @editor)
|
||||
@views.push(view)
|
||||
@append(view)
|
||||
|
||||
updateMisspellings: ->
|
||||
@task?.abort()
|
||||
|
||||
callback = (misspellings) =>
|
||||
@destroyViews()
|
||||
@addViews(misspellings)
|
||||
@task = new SpellCheckTask(@buffer.getText(), callback)
|
||||
@task.start()
|
20
src/packages/spell-check/lib/spell-check.coffee
Normal file
20
src/packages/spell-check/lib/spell-check.coffee
Normal file
@ -0,0 +1,20 @@
|
||||
SpellCheckView = require './spell-check-view'
|
||||
|
||||
module.exports =
|
||||
configDefaults:
|
||||
grammars: [
|
||||
'text.plain'
|
||||
'source.gfm'
|
||||
'text.git-commit'
|
||||
]
|
||||
|
||||
activate: ->
|
||||
if syntax.grammars.length > 1
|
||||
@subscribeToEditors()
|
||||
else
|
||||
syntax.on 'grammars-loaded', => @subscribeToEditors()
|
||||
|
||||
subscribeToEditors: ->
|
||||
rootView.eachEditor (editor) ->
|
||||
if editor.attached and not editor.mini
|
||||
editor.underlayer.append(new SpellCheckView(editor))
|
1
src/packages/spell-check/package.cson
Normal file
1
src/packages/spell-check/package.cson
Normal file
@ -0,0 +1 @@
|
||||
'main': 'lib/spell-check.coffee'
|
98
src/packages/spell-check/spec/spell-check-spec.coffee
Normal file
98
src/packages/spell-check/spec/spell-check-spec.coffee
Normal file
@ -0,0 +1,98 @@
|
||||
RootView = require 'root-view'
|
||||
|
||||
describe "Spell check", ->
|
||||
[editor] = []
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
config.set('spell-check.grammars', [])
|
||||
window.loadPackage('spell-check')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveEditor()
|
||||
|
||||
it "decorates all misspelled words", ->
|
||||
editor.setText("This middle of thiss sentencts has issues.")
|
||||
config.set('spell-check.grammars', ['source.js'])
|
||||
|
||||
waitsFor ->
|
||||
editor.find('.misspelling').length > 0
|
||||
|
||||
runs ->
|
||||
expect(editor.find('.misspelling').length).toBe 2
|
||||
|
||||
typo1StartPosition = editor.pixelPositionForBufferPosition([0, 15])
|
||||
typo1EndPosition = editor.pixelPositionForBufferPosition([0, 20])
|
||||
expect(editor.find('.misspelling:eq(0)').position()).toEqual typo1StartPosition
|
||||
expect(editor.find('.misspelling:eq(0)').width()).toBe typo1EndPosition.left - typo1StartPosition.left
|
||||
|
||||
typo2StartPosition = editor.pixelPositionForBufferPosition([0, 21])
|
||||
typo2EndPosition = editor.pixelPositionForBufferPosition([0, 30])
|
||||
expect(editor.find('.misspelling:eq(1)').position()).toEqual typo2StartPosition
|
||||
expect(editor.find('.misspelling:eq(1)').width()).toBe typo2EndPosition.left - typo2StartPosition.left
|
||||
|
||||
it "hides decorations when a misspelled word is edited", ->
|
||||
editor.setText('notaword')
|
||||
advanceClock(editor.getBuffer().stoppedChangingDelay)
|
||||
config.set('spell-check.grammars', ['source.js'])
|
||||
|
||||
waitsFor ->
|
||||
editor.find('.misspelling').length > 0
|
||||
|
||||
runs ->
|
||||
expect(editor.find('.misspelling').length).toBe 1
|
||||
editor.moveCursorToEndOfLine()
|
||||
editor.insertText('a')
|
||||
advanceClock(editor.getBuffer().stoppedChangingDelay)
|
||||
expect(editor.find('.misspelling')).toBeHidden()
|
||||
|
||||
describe "when spell checking for a grammar is removed", ->
|
||||
it "removes all current decorations", ->
|
||||
editor.setText('notaword')
|
||||
advanceClock(editor.getBuffer().stoppedChangingDelay)
|
||||
config.set('spell-check.grammars', ['source.js'])
|
||||
|
||||
waitsFor ->
|
||||
editor.find('.misspelling').length > 0
|
||||
|
||||
runs ->
|
||||
expect(editor.find('.misspelling').length).toBe 1
|
||||
config.set('spell-check.grammars', [])
|
||||
expect(editor.find('.misspelling').length).toBe 0
|
||||
|
||||
describe "when 'editor:correct-misspelling' is triggered on the editor", ->
|
||||
describe "when the cursor touches a misspelling that has corrections", ->
|
||||
it "displays the corrections for the misspelling and replaces the misspelling when a correction is selected", ->
|
||||
editor.setText('fryday')
|
||||
advanceClock(editor.getBuffer().stoppedChangingDelay)
|
||||
config.set('spell-check.grammars', ['source.js'])
|
||||
|
||||
waitsFor ->
|
||||
editor.find('.misspelling').length > 0
|
||||
|
||||
runs ->
|
||||
editor.trigger 'editor:correct-misspelling'
|
||||
expect(editor.find('.corrections').length).toBe 1
|
||||
expect(editor.find('.corrections li').length).toBeGreaterThan 0
|
||||
expect(editor.find('.corrections li:first').text()).toBe "Friday"
|
||||
editor.find('.corrections').view().confirmSelection()
|
||||
expect(editor.getText()).toBe 'Friday'
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 6]
|
||||
advanceClock(editor.getBuffer().stoppedChangingDelay)
|
||||
expect(editor.find('.misspelling')).toBeHidden()
|
||||
expect(editor.find('.corrections').length).toBe 0
|
||||
|
||||
describe "when the cursor touches a misspelling that has no corrections", ->
|
||||
it "displays a message saying no corrections found", ->
|
||||
editor.setText('asdfasdf')
|
||||
advanceClock(editor.getBuffer().stoppedChangingDelay)
|
||||
config.set('spell-check.grammars', ['source.js'])
|
||||
|
||||
waitsFor ->
|
||||
editor.find('.misspelling').length > 0
|
||||
|
||||
runs ->
|
||||
editor.trigger 'editor:correct-misspelling'
|
||||
expect(editor.find('.corrections').length).toBe 1
|
||||
expect(editor.find('.corrections li').length).toBe 0
|
||||
expect(editor.find('.corrections .error').text()).toBe "No corrections found"
|
4
src/packages/spell-check/stylesheets/spell-check.css
Normal file
4
src/packages/spell-check/stylesheets/spell-check.css
Normal file
@ -0,0 +1,4 @@
|
||||
.misspelling {
|
||||
border-bottom: 1px dashed rgba(250, 128, 114, .5);
|
||||
position: absolute;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
module.exports =
|
||||
class GitRepository
|
||||
constructor: (path) ->
|
||||
@open: (path) ->
|
||||
unless repo = $git.getRepository(path)
|
||||
throw new Error("No Git repository found searching path: #{path}")
|
||||
repo.constructor = GitRepository
|
||||
repo.__proto__ = GitRepository.prototype
|
||||
return repo
|
||||
repo
|
||||
|
||||
getHead: $git.getHead
|
||||
getPath: $git.getPath
|
||||
|
@ -1,11 +1,11 @@
|
||||
module.exports =
|
||||
class OnigRegExp
|
||||
constructor: (source) ->
|
||||
@create: (source) ->
|
||||
regexp = $onigRegExp.buildOnigRegExp(source);
|
||||
regexp.constructor = OnigRegExp
|
||||
regexp.__proto__ = OnigRegExp.prototype
|
||||
regexp.source = source
|
||||
return regexp
|
||||
regexp
|
||||
|
||||
search: $onigRegExp.search
|
||||
test: $onigRegExp.test
|
||||
|
@ -1,10 +1,10 @@
|
||||
module.exports =
|
||||
class OnigScanner
|
||||
constructor: (sources) ->
|
||||
@create: (sources) ->
|
||||
scanner = $onigScanner.buildScanner(sources)
|
||||
scanner.constructor = OnigScanner
|
||||
scanner.__proto__ = OnigScanner.prototype
|
||||
scanner.sources = sources
|
||||
return scanner
|
||||
scanner
|
||||
|
||||
findNextMatch: $onigScanner.findNextMatch
|
||||
|
Loading…
Reference in New Issue
Block a user