Display corrections for misspelling on meta-0

A select list will now display with possible corrections
and the misspelling will be replaced when one is selected.
This commit is contained in:
Kevin Sawicki 2013-02-27 10:05:36 -08:00
parent b5c9e634fd
commit a4efc32d45
5 changed files with 150 additions and 2 deletions

View File

@ -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", "isMisspelled"
"md5ForPath", "exec", "getPlatform", "setWindowState", "getWindowState", "isMisspelled",
"getCorrectionsForMisspelling"
};
CefRefPtr<CefV8Value> nativeObject = CefV8Value::CreateObject(NULL);
@ -528,6 +529,22 @@ namespace v8_extensions {
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;
};

View File

@ -0,0 +1,2 @@
'.editor':
'meta-0': 'editor:correct-misspelling'

View 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()

View File

@ -1,5 +1,6 @@
{View} = require 'space-pen'
Range = require 'range'
CorrectionsView = require './corrections-view'
module.exports =
class MisspellingView extends View
@ -11,19 +12,37 @@ class MisspellingView extends View
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
@editor.on 'editor:display-updated', =>
@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)
@ -36,5 +55,7 @@ class MisspellingView extends View
@show()
destroy: ->
@misspellingValid = false
@editSession.destroyMarker(@marker)
@correctionsView?.remove()
@remove()

View File

@ -59,3 +59,40 @@ describe "Spell check", ->
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"