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

Commit 404804b

Browse files
author
Max Brunsfeld
committed
Merge pull request #102 from atom/mb-use-bulk-spell-checking-method
Speed up spell checking
2 parents 4d87c10 + 577ff80 commit 404804b

8 files changed

+144
-103
lines changed

lib/corrections-view.coffee

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class CorrectionsView extends SelectListView
2424
@cancel()
2525
return unless correction
2626
@editor.transact =>
27-
@editor.selectMarker(@marker)
27+
@editor.setSelectedBufferRange(@marker.getRange())
2828
@editor.insertText(correction)
2929

3030
cancelled: ->

lib/main.coffee

+7-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ module.exports =
1414
description: 'List of scopes for languages which will be checked for misspellings. See [the README](https://github.com/atom/spell-check#spell-check-package-) for more information on finding the correct scope for a specific language.'
1515

1616
activate: ->
17-
@disposable = atom.workspace.observeTextEditors(addViewToEditor)
17+
@viewsByEditor = new WeakMap
18+
@disposable = atom.workspace.observeTextEditors (editor) =>
19+
SpellCheckView ?= require './spell-check-view'
20+
@viewsByEditor.set(editor, new SpellCheckView(editor))
21+
22+
misspellingMarkersForEditor: (editor) ->
23+
@viewsByEditor.get(editor).markerLayer.getMarkers()
1824

1925
deactivate: ->
2026
@disposable.dispose()
21-
22-
addViewToEditor = (editor) ->
23-
SpellCheckView ?= require './spell-check-view'
24-
new SpellCheckView(editor)

lib/misspelling-view.coffee

-44
This file was deleted.

lib/spell-check-handler.coffee

+24-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
11
SpellChecker = require 'spellchecker'
22

3-
wordRegex = /(?:^|[\s\[\]"'])([a-zA-Z]+([a-zA-Z']+[a-zA-Z])?)(?=[\s\.\[\]:,"']|$)/g
4-
53
module.exports = ({id, text}) ->
4+
SpellChecker.add("GitHub")
5+
SpellChecker.add("github")
6+
7+
misspelledCharacterRanges = SpellChecker.checkSpelling(text)
8+
69
row = 0
10+
rangeIndex = 0
11+
characterIndex = 0
712
misspellings = []
8-
for line in text.split('\n')
9-
while matches = wordRegex.exec(line)
10-
word = matches[1]
11-
continue if word in ['GitHub', 'github']
12-
continue unless SpellChecker.isMisspelled(word)
13+
while characterIndex < text.length and rangeIndex < misspelledCharacterRanges.length
14+
lineBreakIndex = text.indexOf('\n', characterIndex)
15+
if lineBreakIndex is -1
16+
lineBreakIndex = Infinity
1317

14-
startColumn = matches.index + matches[0].length - word.length
15-
endColumn = startColumn + word.length
16-
misspellings.push([[row, startColumn], [row, endColumn]])
18+
loop
19+
range = misspelledCharacterRanges[rangeIndex]
20+
if range and range.start < lineBreakIndex
21+
misspellings.push([
22+
[row, range.start - characterIndex],
23+
[row, range.end - characterIndex]
24+
])
25+
rangeIndex++
26+
else
27+
break
28+
29+
characterIndex = lineBreakIndex + 1
1730
row++
31+
1832
{id, misspellings}

lib/spell-check-view.coffee

+41-11
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
_ = require 'underscore-plus'
22
{CompositeDisposable} = require 'atom'
3-
MisspellingView = require './misspelling-view'
43
SpellCheckTask = require './spell-check-task'
54

5+
CorrectionsView = null
6+
SpellChecker = null
7+
68
module.exports =
79
class SpellCheckView
810
@content: ->
911
@div class: 'spell-check'
1012

1113
constructor: (@editor) ->
1214
@disposables = new CompositeDisposable
13-
@views = []
1415
@task = new SpellCheckTask()
16+
@initializeMarkerLayer()
17+
18+
@correctMisspellingCommand = atom.commands.add atom.views.getView(@editor), 'spell-check:correct-misspelling', =>
19+
if marker = @markerLayer.findMarkers({containsPoint: @editor.getCursorBufferPosition()})[0]
20+
CorrectionsView ?= require './corrections-view'
21+
@correctionsView?.destroy()
22+
@correctionsView = new CorrectionsView(@editor, @getCorrections(marker), marker)
1523

1624
@task.onDidSpellCheck (misspellings) =>
17-
@destroyViews()
18-
@addViews(misspellings) if @buffer?
25+
@detroyMarkers()
26+
@addMarkers(misspellings) if @buffer?
1927

2028
@disposables.add @editor.onDidChangePath =>
2129
@subscribeToBuffer()
@@ -33,13 +41,25 @@ class SpellCheckView
3341

3442
@disposables.add @editor.onDidDestroy(@destroy.bind(this))
3543

44+
initializeMarkerLayer: ->
45+
@markerLayer = @editor.getBuffer().addMarkerLayer()
46+
@markerLayerDecoration = @editor.decorateMarkerLayer(@markerLayer, {
47+
type: 'highlight',
48+
class: 'spell-check-misspelling',
49+
deprecatedRegionClass: 'misspelling'
50+
})
51+
3652
destroy: ->
3753
@unsubscribeFromBuffer()
3854
@disposables.dispose()
3955
@task.terminate()
56+
@markerLayer.destroy()
57+
@markerLayerDecoration.destroy()
58+
@correctMisspellingCommand.dispose()
59+
@correctionsView?.remove()
4060

4161
unsubscribeFromBuffer: ->
42-
@destroyViews()
62+
@detroyMarkers()
4363

4464
if @buffer?
4565
@bufferDisposable.dispose()
@@ -57,18 +77,28 @@ class SpellCheckView
5777
grammar = @editor.getGrammar().scopeName
5878
_.contains(atom.config.get('spell-check.grammars'), grammar)
5979

60-
destroyViews: ->
61-
while view = @views.shift()
62-
view.destroy()
80+
detroyMarkers: ->
81+
@markerLayer.destroy()
82+
@markerLayerDecoration.destroy()
83+
@initializeMarkerLayer()
6384

64-
addViews: (misspellings) ->
85+
addMarkers: (misspellings) ->
6586
for misspelling in misspellings
66-
view = new MisspellingView(misspelling, @editor)
67-
@views.push(view)
87+
@markerLayer.markRange(misspelling,
88+
invalidate: 'touch',
89+
replicate: 'false',
90+
persistent: false,
91+
maintainHistory: false,
92+
)
6893

6994
updateMisspellings: ->
7095
# Task::start can throw errors atom/atom#3326
7196
try
7297
@task.start(@buffer.getText())
7398
catch error
7499
console.warn('Error starting spell check task', error.stack ? error)
100+
101+
getCorrections: (marker) ->
102+
SpellChecker ?= require 'spellchecker'
103+
misspelling = @editor.getTextInBufferRange(marker.getRange())
104+
corrections = SpellChecker.getCorrectionsForMisspelling(misspelling)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"description": "Highlights misspelled words and shows possible corrections.",
66
"dependencies": {
77
"atom-space-pen-views": "^2.0.0",
8-
"spellchecker": "^3.1.2",
8+
"spellchecker": "3.2.0",
99
"underscore-plus": "^1"
1010
},
1111
"repository": "https://github.com/atom/spell-check",

script/benchmark.coffee

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env coffee
2+
3+
handler = require '../lib/spell-check-handler'
4+
fs = require 'fs'
5+
6+
pathToCheck = process.argv[2]
7+
console.log("Spellchecking %s...", pathToCheck)
8+
9+
text = fs.readFileSync(pathToCheck, 'utf8')
10+
11+
t0 = Date.now()
12+
result = handler({id: 1, text})
13+
t1 = Date.now()
14+
15+
console.log("Found %d misspellings in %d milliseconds", result.misspellings.length, t1 - t0)

0 commit comments

Comments
 (0)