Load snippets in a web worker

A single web worker is now used to load
snippets one bundle at a time.
This commit is contained in:
Kevin Sawicki
2013-01-24 08:36:53 -08:00
parent cab281c6db
commit 9ab730b3d0
8 changed files with 159 additions and 55 deletions

View File

@@ -4,14 +4,14 @@ PEG = require 'pegjs'
_ = require 'underscore'
SnippetExpansion = require './src/snippet-expansion'
Snippet = require './src/snippet'
require './src/package-extensions'
SnippetsTask = require './src/snippets-task'
module.exports =
class Snippets extends AtomPackage
snippetsByExtension: {}
parser: PEG.buildParser(fs.read(require.resolve 'snippets/snippets.pegjs'), trackLineAndColumn: true)
userSnippetsDir: fs.join(config.configDirPath, 'snippets')
loaded: false
activate: (@rootView) ->
window.snippets = this
@@ -19,10 +19,7 @@ class Snippets extends AtomPackage
@rootView.on 'editor:attached', (e, editor) => @enableSnippetsInEditor(editor)
loadAll: ->
for pack in atom.getPackages()
pack.loadSnippets()
@loadDirectory(@userSnippetsDir) if fs.exists(@userSnippetsDir)
new SnippetsTask(this).start()
loadDirectory: (snippetsDirPath) ->
for snippetsPath in fs.list(snippetsDirPath) when fs.base(snippetsPath).indexOf('.') isnt 0

View File

@@ -1,5 +1,6 @@
Snippets = require 'snippets'
Snippet = require 'snippets/src/snippet'
SnippetsTask = require 'snippets/src/snippets-task'
RootView = require 'root-view'
Buffer = require 'buffer'
Editor = require 'editor'
@@ -12,8 +13,7 @@ describe "Snippets extension", ->
[buffer, editor] = []
beforeEach ->
rootView = new RootView(require.resolve('fixtures/sample.js'))
spyOn(AtomPackage.prototype, 'loadSnippets')
spyOn(TextMatePackage.prototype, 'loadSnippets')
spyOn(SnippetsTask.prototype, 'start')
atom.loadPackage("snippets")
editor = rootView.getActiveEditor()
buffer = editor.getBuffer()
@@ -216,28 +216,36 @@ describe "Snippets extension", ->
describe "snippet loading", ->
it "loads non-hidden snippet files from all atom packages with snippets directories, logging a warning if a file can't be parsed", ->
spyOn(console, 'warn').andCallThrough()
jasmine.unspy(AtomPackage.prototype, 'loadSnippets')
jasmine.unspy(SnippetsTask.prototype, 'start')
snippets.loaded = false
snippets.loadAll()
expect(syntax.getProperty(['.test'], 'snippets.test')?.constructor).toBe Snippet
waitsFor((-> snippets.loaded), "Waiting for all snippets to load", 5000)
# warn about junk-file, but don't even try to parse a hidden file
expect(console.warn).toHaveBeenCalled()
expect(console.warn.calls.length).toBeGreaterThan 0
runs ->
expect(syntax.getProperty(['.test'], 'snippets.test')?.constructor).toBe Snippet
# warn about junk-file, but don't even try to parse a hidden file
expect(console.warn).toHaveBeenCalled()
expect(console.warn.calls.length).toBeGreaterThan 0
it "loads snippets from all TextMate packages with snippets", ->
jasmine.unspy(TextMatePackage.prototype, 'loadSnippets')
jasmine.unspy(SnippetsTask.prototype, 'start')
snippets.loaded = false
snippets.loadAll()
snippet = syntax.getProperty(['.source.js'], 'snippets.fun')
expect(snippet.constructor).toBe Snippet
expect(snippet.prefix).toBe 'fun'
expect(snippet.name).toBe 'Function'
expect(snippet.body).toBe """
function function_name (argument) {
\t// body...
}
"""
waitsFor((-> snippets.loaded), "Waiting for all snippets to load", 5000)
runs ->
snippet = syntax.getProperty(['.source.js'], 'snippets.fun')
expect(snippet.constructor).toBe Snippet
expect(snippet.prefix).toBe 'fun'
expect(snippet.name).toBe 'Function'
expect(snippet.body).toBe """
function function_name (argument) {
\t// body...
}
"""
describe "Snippets parser", ->
it "breaks a snippet body into lines, with each line containing tab stops at the appropriate position", ->

View File

@@ -1,25 +0,0 @@
AtomPackage = require 'atom-package'
TextMatePackage = require 'text-mate-package'
fs = require 'fs'
AtomPackage.prototype.loadSnippets = ->
snippetsDirPath = fs.join(@path, 'snippets')
snippets.loadDirectory(snippetsDirPath) if fs.exists(snippetsDirPath)
TextMatePackage.prototype.loadSnippets = ->
snippetsDirPath = fs.join(@path, 'Snippets')
if fs.exists(snippetsDirPath)
tmSnippets = fs.list(snippetsDirPath).map (snippetPath) -> fs.readPlist(snippetPath)
snippets.add(@translateSnippets(tmSnippets))
TextMatePackage.prototype.translateSnippets = (tmSnippets) ->
atomSnippets = {}
for { scope, name, content, tabTrigger } in tmSnippets
if scope
scope = TextMatePackage.cssSelectorFromScopeSelector(scope)
else
scope = '*'
snippetsForScope = (atomSnippets[scope] ?= {})
snippetsForScope[name] = { prefix: tabTrigger, body: content }
atomSnippets

View File

@@ -0,0 +1,43 @@
eval("window = {};")
eval("console = {};")
console.warn = ->
self.postMessage
type: 'warn'
details: arguments
console.log = ->
self.postMessage
type: 'warn'
details: arguments
eval("attachEvent = function(){};")
self.addEventListener 'message', (event) ->
switch event.data.type
when 'start'
window.resourcePath = event.data.resourcePath
importScripts(event.data.requirePath)
self.postMessage(type:'started')
else
self[event.data.type](event.data)
self.loadTextmateSnippets = ({path}) ->
fs = require 'fs'
snippetsDirPath = fs.join(path, 'Snippets')
snippets = fs.list(snippetsDirPath).map (snippetPath) ->
fs.readPlist(snippetPath)
self.postMessage
type: 'loadSnippets'
snippets: snippets
self.loadAtomSnippets = ({path}) ->
fs = require 'fs'
snippetsDirPath = fs.join(path, 'snippets')
snippets = []
for snippetsPath in fs.list(snippetsDirPath)
continue if fs.base(snippetsPath).indexOf('.') is 0
try
snippets.push(fs.readObject(snippetsPath))
catch e
console.warn "Error reading snippets file '#{snippetsPath}'"
self.postMessage
type: 'loadSnippets'
snippets: snippets

View File

@@ -0,0 +1,42 @@
Task = require 'Task'
TextMatePackage = require 'text-mate-package'
module.exports =
class SnippetsTask extends Task
constructor: (@snippets) ->
super('snippets/src/snippets-reader')
@packages = atom.getPackages()
@packages.push(path: config.configDirPath)
onProgress: (event) =>
if event.data.type is 'loadSnippets'
rawSnippets = event.data.snippets
if @package instanceof TextMatePackage
@snippets.add(@translateTextmateSnippets(rawSnippets))
else
@snippets.add(snippet) for snippet in rawSnippets
@package = @packages.shift()
if not @package?
@snippets.loaded = true
return
if @package instanceof TextMatePackage
eventType = 'loadTextmateSnippets'
else
eventType = 'loadAtomSnippets'
{ type: eventType, path: @package.path }
translateTextmateSnippets: (tmSnippets) ->
atomSnippets = {}
for { scope, name, content, tabTrigger } in tmSnippets
if scope
scope = TextMatePackage.cssSelectorFromScopeSelector(scope)
else
scope = '*'
snippetsForScope = (atomSnippets[scope] ?= {})
snippetsForScope[name] = { prefix: tabTrigger, body: content }
atomSnippets