mirror of
https://github.com/atom/atom.git
synced 2026-01-24 06:18:03 -05:00
merge dev, fix conflicts from package rewrite
This commit is contained in:
Binary file not shown.
67
spec/app/atom-package-spec.coffee
Normal file
67
spec/app/atom-package-spec.coffee
Normal file
@@ -0,0 +1,67 @@
|
||||
RootView = require 'root-view'
|
||||
AtomPackage = require 'atom-package'
|
||||
fs = require 'fs'
|
||||
|
||||
describe "AtomPackage", ->
|
||||
describe ".load()", ->
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
|
||||
describe "when the package metadata includes activation events", ->
|
||||
[packageMainModule, pack] = []
|
||||
|
||||
beforeEach ->
|
||||
new RootView(fixturesProject.getPath())
|
||||
pack = new AtomPackage(fs.resolve(config.packageDirPaths..., 'package-with-activation-events'))
|
||||
packageMainModule = require 'fixtures/packages/package-with-activation-events/main'
|
||||
spyOn(packageMainModule, 'activate').andCallThrough()
|
||||
pack.load()
|
||||
|
||||
it "defers activating the package until an activation event bubbles to the root view", ->
|
||||
expect(packageMainModule.activate).not.toHaveBeenCalled()
|
||||
rootView.trigger 'activation-event'
|
||||
expect(packageMainModule.activate).toHaveBeenCalled()
|
||||
|
||||
it "triggers the activation event on all handlers registered during activation", ->
|
||||
rootView.open('sample.js')
|
||||
editor = rootView.getActiveEditor()
|
||||
eventHandler = jasmine.createSpy("activation-event")
|
||||
editor.command 'activation-event', eventHandler
|
||||
editor.trigger 'activation-event'
|
||||
expect(packageMainModule.activate.callCount).toBe 1
|
||||
expect(packageMainModule.activationEventCallCount).toBe 1
|
||||
expect(eventHandler.callCount).toBe 1
|
||||
editor.trigger 'activation-event'
|
||||
expect(packageMainModule.activationEventCallCount).toBe 2
|
||||
expect(eventHandler.callCount).toBe 2
|
||||
expect(packageMainModule.activate.callCount).toBe 1
|
||||
|
||||
describe "when the package does not specify a main module", ->
|
||||
describe "when the package has an index.coffee", ->
|
||||
it "uses index.coffee as the main module", ->
|
||||
new RootView(fixturesProject.getPath())
|
||||
pack = new AtomPackage(fs.resolve(config.packageDirPaths..., 'package-with-module'))
|
||||
packageMainModule = require 'fixtures/packages/package-with-module'
|
||||
spyOn(packageMainModule, 'activate').andCallThrough()
|
||||
|
||||
expect(packageMainModule.activate).not.toHaveBeenCalled()
|
||||
pack.load()
|
||||
expect(packageMainModule.activate).toHaveBeenCalled()
|
||||
|
||||
describe "when the package doesn't have an index.coffee", ->
|
||||
it "does not throw an exception or log an error", ->
|
||||
spyOn(console, "error")
|
||||
spyOn(console, "warn")
|
||||
new RootView(fixturesProject.getPath())
|
||||
pack = new AtomPackage(fs.resolve(config.packageDirPaths..., 'package-with-keymaps-manifest'))
|
||||
|
||||
expect(-> pack.load()).not.toThrow()
|
||||
expect(console.error).not.toHaveBeenCalled()
|
||||
expect(console.warn).not.toHaveBeenCalled()
|
||||
|
||||
describe "when a package is activated", ->
|
||||
it "loads config defaults based on the `configDefaults` key", ->
|
||||
expect(config.get('package-with-module.numbers.one')).toBeUndefined()
|
||||
atom.loadPackage("package-with-module")
|
||||
expect(config.get('package-with-module.numbers.one')).toBe 1
|
||||
expect(config.get('package-with-module.numbers.two')).toBe 2
|
||||
@@ -2,11 +2,16 @@ RootView = require 'root-view'
|
||||
{$$} = require 'space-pen'
|
||||
|
||||
describe "the `atom` global", ->
|
||||
beforeEach ->
|
||||
new RootView
|
||||
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
|
||||
describe ".loadPackage(name)", ->
|
||||
[extension, stylesheetPath] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView
|
||||
extension = require "package-with-module"
|
||||
stylesheetPath = require.resolve("fixtures/packages/package-with-module/stylesheets/styles.css")
|
||||
|
||||
@@ -14,9 +19,9 @@ describe "the `atom` global", ->
|
||||
removeStylesheet(stylesheetPath)
|
||||
|
||||
it "requires and activates the package's main module if it exists", ->
|
||||
spyOn(rootView, 'activatePackage').andCallThrough()
|
||||
spyOn(atom, 'activateAtomPackage').andCallThrough()
|
||||
atom.loadPackage("package-with-module")
|
||||
expect(rootView.activatePackage).toHaveBeenCalled()
|
||||
expect(atom.activateAtomPackage).toHaveBeenCalled()
|
||||
|
||||
it "logs warning instead of throwing an exception if a package fails to load", ->
|
||||
config.set("core.disabledPackages", [])
|
||||
@@ -70,6 +75,7 @@ describe "the `atom` global", ->
|
||||
syntax.on 'grammars-loaded', eventHandler
|
||||
disabledPackages = config.get("core.disabledPackages")
|
||||
disabledPackages.push('textmate-package.tmbundle')
|
||||
disabledPackages.push('package-with-snippets')
|
||||
config.set "core.disabledPackages", disabledPackages
|
||||
atom.loadPackages()
|
||||
|
||||
@@ -78,3 +84,61 @@ describe "the `atom` global", ->
|
||||
runs ->
|
||||
expect(Worker.prototype.terminate).toHaveBeenCalled()
|
||||
expect(Worker.prototype.terminate.calls.length).toBe 1
|
||||
|
||||
describe "package lifecycle", ->
|
||||
[pack, packageModule] = []
|
||||
|
||||
beforeEach ->
|
||||
pack =
|
||||
name: "package"
|
||||
packageMain:
|
||||
activate: jasmine.createSpy("activate")
|
||||
deactivate: ->
|
||||
serialize: -> "it worked"
|
||||
|
||||
packageModule = pack.packageMain
|
||||
|
||||
describe ".activateAtomPackage(package)", ->
|
||||
it "calls activate on the package", ->
|
||||
atom.activateAtomPackage(pack)
|
||||
expect(packageModule.activate).toHaveBeenCalledWith(undefined)
|
||||
|
||||
it "calls activate on the package module with its previous state", ->
|
||||
atom.activateAtomPackage(pack)
|
||||
packageModule.activate.reset()
|
||||
|
||||
serializedState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
RootView.deserialize(serializedState)
|
||||
|
||||
atom.activateAtomPackage(pack)
|
||||
expect(packageModule.activate).toHaveBeenCalledWith("it worked")
|
||||
|
||||
describe ".deactivateAtomPackages()", ->
|
||||
it "deactivates and removes the package module from the package module map", ->
|
||||
atom.activateAtomPackage(pack)
|
||||
spyOn(packageModule, "deactivate").andCallThrough()
|
||||
atom.deactivateAtomPackages()
|
||||
expect(packageModule.deactivate).toHaveBeenCalled()
|
||||
expect(rootView.packages.length).toBe 0
|
||||
|
||||
describe ".serializeAtomPackages()", ->
|
||||
it "absorbs exceptions that are thrown by the package module's serialize methods", ->
|
||||
spyOn(console, 'error')
|
||||
|
||||
atom.activateAtomPackage
|
||||
name: "bad-egg"
|
||||
packageMain:
|
||||
activate: ->
|
||||
serialize: -> throw new Error("I'm broken")
|
||||
|
||||
atom.activateAtomPackage
|
||||
name: "good-egg"
|
||||
packageMain:
|
||||
activate: ->
|
||||
serialize: -> "I still get called"
|
||||
|
||||
packageStates = atom.serializeAtomPackages()
|
||||
expect(packageStates['good-egg']).toBe "I still get called"
|
||||
expect(packageStates['bad-egg']).toBeUndefined()
|
||||
expect(console.error).toHaveBeenCalled()
|
||||
|
||||
@@ -19,192 +19,6 @@ describe "LanguageMode", ->
|
||||
expect(jsEditSession.languageMode.grammar.name).toBe "JavaScript"
|
||||
jsEditSession.destroy()
|
||||
|
||||
describe "bracket insertion", ->
|
||||
beforeEach ->
|
||||
editSession.buffer.setText("")
|
||||
|
||||
describe "when more than one character is inserted", ->
|
||||
it "does not insert a matching bracket", ->
|
||||
editSession.insertText("woah(")
|
||||
expect(editSession.buffer.getText()).toBe "woah("
|
||||
|
||||
describe "when there is a word character after the cursor", ->
|
||||
it "does not insert a matching bracket", ->
|
||||
editSession.buffer.setText("ab")
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText("(")
|
||||
|
||||
expect(editSession.buffer.getText()).toBe "a(b"
|
||||
|
||||
describe "when there are multiple cursors", ->
|
||||
it "inserts ) at each cursor", ->
|
||||
editSession.buffer.setText("()\nab\n[]\n12")
|
||||
editSession.setCursorBufferPosition([3, 1])
|
||||
editSession.addCursorAtBufferPosition([2, 1])
|
||||
editSession.addCursorAtBufferPosition([1, 1])
|
||||
editSession.addCursorAtBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
|
||||
expect(editSession.buffer.getText()).toBe "())\na)b\n[)]\n1)2"
|
||||
|
||||
describe "when there is a non-word character after the cursor", ->
|
||||
it "inserts a closing bracket after an opening bracket is inserted", ->
|
||||
editSession.buffer.setText("}")
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.insertText '{'
|
||||
expect(buffer.lineForRow(0)).toBe "{}}"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
describe "when the cursor is at the end of the line", ->
|
||||
it "inserts a closing bracket after an opening bracket is inserted", ->
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '{'
|
||||
expect(buffer.lineForRow(0)).toBe "{}"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '('
|
||||
expect(buffer.lineForRow(0)).toBe "()"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '['
|
||||
expect(buffer.lineForRow(0)).toBe "[]"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe '""'
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText "'"
|
||||
expect(buffer.lineForRow(0)).toBe "''"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
describe "when the cursor is on a closing bracket and a closing bracket is inserted", ->
|
||||
describe "when the closing bracket was there previously", ->
|
||||
it "inserts a closing bracket", ->
|
||||
editSession.insertText '()x'
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "())x"
|
||||
expect(editSession.getCursorBufferPosition().column).toBe 2
|
||||
|
||||
describe "when the closing bracket was automatically inserted from inserting an opening bracket", ->
|
||||
it "only moves cursor over the closing bracket one time", ->
|
||||
editSession.insertText '('
|
||||
expect(buffer.lineForRow(0)).toBe "()"
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "()"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 2]
|
||||
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "())"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 2]
|
||||
|
||||
it "moves cursor over the closing bracket after other text is inserted", ->
|
||||
editSession.insertText '('
|
||||
editSession.insertText 'ok cool'
|
||||
expect(buffer.lineForRow(0)).toBe "(ok cool)"
|
||||
editSession.setCursorBufferPosition([0, 8])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(ok cool)"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 9]
|
||||
|
||||
it "works with nested brackets", ->
|
||||
editSession.insertText '('
|
||||
editSession.insertText '1'
|
||||
editSession.insertText '('
|
||||
editSession.insertText '2'
|
||||
expect(buffer.lineForRow(0)).toBe "(1(2))"
|
||||
editSession.setCursorBufferPosition([0, 4])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(1(2))"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 5]
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(1(2))"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 6]
|
||||
|
||||
it "works with mixed brackets", ->
|
||||
editSession.insertText '('
|
||||
editSession.insertText '}'
|
||||
expect(buffer.lineForRow(0)).toBe "(})"
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(})"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 3]
|
||||
|
||||
it "closes brackets with the same begin/end character correctly", ->
|
||||
editSession.insertText '"'
|
||||
editSession.insertText 'ok'
|
||||
expect(buffer.lineForRow(0)).toBe '"ok"'
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 3]
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe '"ok"'
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 4]
|
||||
|
||||
describe "when there is text selected on a single line", ->
|
||||
it "wraps the selection with brackets", ->
|
||||
editSession.insertText 'text'
|
||||
editSession.moveCursorToBottom()
|
||||
editSession.selectToTop()
|
||||
editSession.selectAll()
|
||||
editSession.insertText '('
|
||||
expect('(text)').toBe buffer.getText()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [0, 5]]
|
||||
expect(editSession.getSelection().isReversed()).toBeTruthy()
|
||||
|
||||
describe "when there is text selected on multiple lines", ->
|
||||
it "wraps the selection with brackets", ->
|
||||
editSession.insertText 'text\nabcd'
|
||||
editSession.moveCursorToBottom()
|
||||
editSession.selectToTop()
|
||||
editSession.selectAll()
|
||||
editSession.insertText '('
|
||||
expect('(text\nabcd)').toBe buffer.getText()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [1, 4]]
|
||||
expect(editSession.getSelection().isReversed()).toBeTruthy()
|
||||
|
||||
describe "when inserting a quote", ->
|
||||
describe "when a word character is before the cursor", ->
|
||||
it "does not automatically insert closing quote", ->
|
||||
editSession.buffer.setText("abc")
|
||||
editSession.setCursorBufferPosition([0, 3])
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe "abc\""
|
||||
|
||||
editSession.buffer.setText("abc")
|
||||
editSession.setCursorBufferPosition([0, 3])
|
||||
editSession.insertText '\''
|
||||
expect(buffer.lineForRow(0)).toBe "abc\'"
|
||||
|
||||
describe "when a non word character is before the cursor", ->
|
||||
it "automatically insert closing quote", ->
|
||||
editSession.buffer.setText("ab@")
|
||||
editSession.setCursorBufferPosition([0, 3])
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe "ab@\"\""
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 4]
|
||||
|
||||
describe "when the cursor is on an empty line", ->
|
||||
it "automatically insert closing quote", ->
|
||||
editSession.buffer.setText("")
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe "\"\""
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 1]
|
||||
|
||||
describe "bracket deletion", ->
|
||||
it "deletes the end bracket when it directly proceeds a begin bracket that is being backspaced", ->
|
||||
buffer.setText("")
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.insertText '{'
|
||||
expect(buffer.lineForRow(0)).toBe "{}"
|
||||
editSession.backspace()
|
||||
expect(buffer.lineForRow(0)).toBe ""
|
||||
|
||||
describe "javascript", ->
|
||||
beforeEach ->
|
||||
editSession = fixturesProject.buildEditSessionForPath('sample.js', autoIndent: false)
|
||||
|
||||
@@ -50,6 +50,14 @@ describe "RootView", ->
|
||||
expect(rootView.getEditors()[0].getText()).toEqual ""
|
||||
expect(rootView.getTitle()).toBe 'untitled'
|
||||
|
||||
describe ".deactivate()", ->
|
||||
it "deactivates all packages", ->
|
||||
pack = atom.loadPackage("package-with-module")
|
||||
atom.activateAtomPackage(pack)
|
||||
spyOn(pack.packageMain, "deactivate").andCallThrough()
|
||||
rootView.deactivate()
|
||||
expect(pack.packageMain.deactivate).toHaveBeenCalled()
|
||||
|
||||
describe "@deserialize()", ->
|
||||
viewState = null
|
||||
|
||||
@@ -151,25 +159,6 @@ describe "RootView", ->
|
||||
expect(rootView.find('.pane').length).toBe 1
|
||||
expect(rootView.find('.pane').children().length).toBe 0
|
||||
|
||||
describe ".serialize()", ->
|
||||
it "absorbs exceptions that are thrown by the package module's serialize methods", ->
|
||||
spyOn(console, 'error')
|
||||
|
||||
rootView.activatePackage("bad-egg",
|
||||
activate: ->
|
||||
serialize: -> throw new Error("I'm broken")
|
||||
)
|
||||
|
||||
rootView.activatePackage("good-egg"
|
||||
activate: ->
|
||||
serialize: -> "I still get called"
|
||||
)
|
||||
|
||||
data = rootView.serialize()
|
||||
expect(data.packageStates['good-egg']).toBe "I still get called"
|
||||
expect(data.packageStates['bad-egg']).toBeUndefined()
|
||||
expect(console.error).toHaveBeenCalled()
|
||||
|
||||
describe "focus", ->
|
||||
describe "when there is an active editor", ->
|
||||
it "hands off focus to the active editor", ->
|
||||
@@ -418,54 +407,6 @@ describe "RootView", ->
|
||||
rootView.focusNextPane()
|
||||
expect(view1.focus).toHaveBeenCalled()
|
||||
|
||||
describe "packages", ->
|
||||
packageModule = null
|
||||
|
||||
beforeEach ->
|
||||
packageModule =
|
||||
configDefaults: foo: { bar: 2, baz: 3 }
|
||||
activate: jasmine.createSpy("activate")
|
||||
deactivate: ->
|
||||
serialize: -> "it worked"
|
||||
|
||||
describe ".activatePackage(name, packageModule)", ->
|
||||
it "calls activate on the package module", ->
|
||||
rootView.activatePackage('package', packageModule)
|
||||
expect(packageModule.activate).toHaveBeenCalledWith(rootView, undefined)
|
||||
|
||||
it "calls activate on the package module with its previous state", ->
|
||||
rootView.activatePackage('package', packageModule)
|
||||
packageModule.activate.reset()
|
||||
|
||||
newRootView = RootView.deserialize(rootView.serialize())
|
||||
newRootView.activatePackage('package', packageModule)
|
||||
expect(packageModule.activate).toHaveBeenCalledWith(newRootView, "it worked")
|
||||
newRootView.remove()
|
||||
|
||||
it "loads config defaults based on the `configDefaults` key", ->
|
||||
expect(config.get('foo.bar')).toBeUndefined()
|
||||
rootView.activatePackage('package', packageModule)
|
||||
config.set("package.foo.bar", 1)
|
||||
expect(config.get('package.foo.bar')).toBe 1
|
||||
expect(config.get('package.foo.baz')).toBe 3
|
||||
|
||||
describe ".deactivatePackage(packageName)", ->
|
||||
it "deactivates and removes the package module from the package module map", ->
|
||||
rootView.activatePackage('package', packageModule)
|
||||
expect(rootView.packageModules['package']).toBeTruthy()
|
||||
spyOn(packageModule, "deactivate").andCallThrough()
|
||||
rootView.deactivatePackage('package')
|
||||
expect(packageModule.deactivate).toHaveBeenCalled()
|
||||
expect(rootView.packageModules['package']).toBeFalsy()
|
||||
|
||||
it "is called when the rootView is deactivated to deactivate all packages", ->
|
||||
rootView.activatePackage('package', packageModule)
|
||||
spyOn(rootView, "deactivatePackage").andCallThrough()
|
||||
spyOn(packageModule, "deactivate").andCallThrough()
|
||||
rootView.deactivate()
|
||||
expect(rootView.deactivatePackage).toHaveBeenCalled()
|
||||
expect(packageModule.deactivate).toHaveBeenCalled()
|
||||
|
||||
describe "keymap wiring", ->
|
||||
commandHandler = null
|
||||
beforeEach ->
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
TextMateGrammar = require 'text-mate-grammar'
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
plist = require 'plist'
|
||||
fs = require 'fs'
|
||||
_ = require 'underscore'
|
||||
@@ -257,3 +258,14 @@ describe "TextMateGrammar", ->
|
||||
{tokens, ruleStack} = grammar.tokenizeLine("if(1){if(1){m()}}")
|
||||
expect(tokens[5]).toEqual value: "if", scopes: ["source.c", "meta.block.c", "keyword.control.c"]
|
||||
expect(tokens[10]).toEqual value: "m", scopes: ["source.c", "meta.block.c", "meta.block.c", "meta.function-call.c", "support.function.any-method.c"]
|
||||
|
||||
describe "when the grammar is CSON", ->
|
||||
it "loads the grammar and correctly parses a keyword", ->
|
||||
spyOn(syntax, 'addGrammar')
|
||||
pack = new TextMatePackage(fixturesProject.resolve("packages/package-with-a-cson-grammar.tmbundle"))
|
||||
pack.load()
|
||||
grammar = pack.grammars[0]
|
||||
expect(grammar).toBeTruthy()
|
||||
expect(grammar.scopeName).toBe "source.alot"
|
||||
{tokens} = grammar.tokenizeLine("this is alot of code")
|
||||
expect(tokens[1]).toEqual value: "alot", scopes: ["source.alot", "keyword.alot"]
|
||||
|
||||
11
spec/fixtures/packages/package-with-a-cson-grammar.tmbundle/Syntaxes/alot.cson
vendored
Normal file
11
spec/fixtures/packages/package-with-a-cson-grammar.tmbundle/Syntaxes/alot.cson
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'fileTypes': ['alot']
|
||||
'name': 'Alot'
|
||||
'scopeName': 'source.alot'
|
||||
'patterns': [
|
||||
{
|
||||
'captures':
|
||||
'0':
|
||||
'name': 'keyword.alot'
|
||||
'match': 'alot'
|
||||
}
|
||||
]
|
||||
6
spec/fixtures/packages/package-with-activation-events/main.coffee
vendored
Normal file
6
spec/fixtures/packages/package-with-activation-events/main.coffee
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports =
|
||||
activationEventCallCount: 0
|
||||
|
||||
activate: ->
|
||||
rootView.getActiveEditor()?.command 'activation-event', =>
|
||||
@activationEventCallCount++
|
||||
2
spec/fixtures/packages/package-with-activation-events/package.cson
vendored
Normal file
2
spec/fixtures/packages/package-with-activation-events/package.cson
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
'activationEvents': ['activation-event']
|
||||
'main': 'main'
|
||||
@@ -1,6 +1,8 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
|
||||
module.exports =
|
||||
class MyPackage extends AtomPackage
|
||||
configDefaults:
|
||||
numbers: { one: 1, two: 2 }
|
||||
|
||||
activate: ->
|
||||
@activateCalled = true
|
||||
|
||||
deactivate: ->
|
||||
@@ -17,12 +17,20 @@ fixturePackagesPath = require.resolve('fixtures/packages')
|
||||
require.paths.unshift(fixturePackagesPath)
|
||||
[bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = []
|
||||
|
||||
# Load TextMate bundles, which specs rely on (but not other packages)
|
||||
atom.loadTextMatePackages()
|
||||
# Specs rely on TextMate bundles (but not atom packages)
|
||||
window.loadTextMatePackages = ->
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
config.packageDirPaths.unshift(fixturePackagesPath)
|
||||
window.textMatePackages = []
|
||||
for path in atom.getPackagePaths() when TextMatePackage.testName(path)
|
||||
window.textMatePackages.push atom.loadPackage(fs.base(path))
|
||||
|
||||
window.loadTextMatePackages()
|
||||
|
||||
beforeEach ->
|
||||
window.fixturesProject = new Project(require.resolve('fixtures'))
|
||||
window.resetTimeouts()
|
||||
atom.atomPackageStates = {}
|
||||
|
||||
# used to reset keymap after each spec
|
||||
bindingSetsToRestore = _.clone(keymap.bindingSets)
|
||||
@@ -30,7 +38,6 @@ beforeEach ->
|
||||
|
||||
# reset config before each spec; don't load or save from/to `config.json`
|
||||
window.config = new Config()
|
||||
config.packageDirPaths.unshift(fixturePackagesPath)
|
||||
spyOn(config, 'load')
|
||||
spyOn(config, 'save')
|
||||
config.set "editor.fontSize", 16
|
||||
|
||||
@@ -1,42 +1,88 @@
|
||||
Package = require 'package'
|
||||
fs = require 'fs'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class AtomPackage extends Package
|
||||
metadata: null
|
||||
keymapsDirPath: null
|
||||
autoloadStylesheets: true
|
||||
packageMain: null
|
||||
|
||||
constructor: (@name) ->
|
||||
super
|
||||
@keymapsDirPath = fs.join(@path, 'keymaps')
|
||||
|
||||
load: ->
|
||||
load: ({activateImmediately}={}) ->
|
||||
try
|
||||
@loadMetadata()
|
||||
@loadKeymaps()
|
||||
@loadStylesheets() if @autoloadStylesheets
|
||||
rootView?.activatePackage(@name, this) unless @isDirectory
|
||||
@loadStylesheets()
|
||||
if @metadata.activationEvents and not activateImmediately
|
||||
@subscribeToActivationEvents()
|
||||
else
|
||||
@activatePackageMain()
|
||||
catch e
|
||||
console.warn "Failed to load package named '#{@name}'", e.stack
|
||||
this
|
||||
|
||||
disableEventHandlersOnBubblePath: (event) ->
|
||||
bubblePathEventHandlers = []
|
||||
disabledHandler = ->
|
||||
element = $(event.target)
|
||||
while element.length
|
||||
if eventHandlers = element.data('events')?[event.type]
|
||||
for eventHandler in eventHandlers
|
||||
eventHandler.disabledHandler = eventHandler.handler
|
||||
eventHandler.handler = disabledHandler
|
||||
bubblePathEventHandlers.push(eventHandler)
|
||||
element = element.parent()
|
||||
bubblePathEventHandlers
|
||||
|
||||
restoreEventHandlersOnBubblePath: (eventHandlers) ->
|
||||
for eventHandler in eventHandlers
|
||||
eventHandler.handler = eventHandler.disabledHandler
|
||||
delete eventHandler.disabledHandler
|
||||
|
||||
unsubscribeFromActivationEvents: (activateHandler) ->
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.off(event, activateHandler) for event in @metadata.activationEvents
|
||||
else
|
||||
rootView.off(event, selector, activateHandler) for event, selector of @metadata.activationEvents
|
||||
|
||||
subscribeToActivationEvents: () ->
|
||||
activateHandler = (event) =>
|
||||
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
|
||||
@activatePackageMain()
|
||||
$(event.target).trigger(event)
|
||||
@restoreEventHandlersOnBubblePath(bubblePathEventHandlers)
|
||||
@unsubscribeFromActivationEvents(activateHandler)
|
||||
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.command(event, activateHandler) for event in @metadata.activationEvents
|
||||
else
|
||||
rootView.command(event, selector, activateHandler) for event, selector of @metadata.activationEvents
|
||||
|
||||
activatePackageMain: ->
|
||||
mainPath = @path
|
||||
mainPath = fs.join(mainPath, @metadata.main) if @metadata.main
|
||||
mainPath = require.resolve(mainPath)
|
||||
if fs.isFile(mainPath)
|
||||
@packageMain = require(mainPath)
|
||||
config.setDefaults(@name, @packageMain.configDefaults)
|
||||
atom.activateAtomPackage(this)
|
||||
|
||||
loadMetadata: ->
|
||||
if metadataPath = fs.resolveExtension(fs.join(@path, "package"), ['cson', 'json'])
|
||||
if metadataPath = fs.resolveExtension(fs.join(@path, 'package'), ['cson', 'json'])
|
||||
@metadata = fs.readObject(metadataPath)
|
||||
@metadata ?= {}
|
||||
|
||||
loadKeymaps: ->
|
||||
if keymaps = @metadata?.keymaps
|
||||
keymaps = keymaps.map (relativePath) =>
|
||||
fs.resolve(@keymapsDirPath, relativePath, ['cson', 'json', ''])
|
||||
keymap.load(keymapPath) for keymapPath in keymaps
|
||||
keymapsDirPath = fs.join(@path, 'keymaps')
|
||||
|
||||
if @metadata.keymaps
|
||||
for path in @metadata.keymaps
|
||||
keymapPath = fs.resolve(keymapsDirPath, path, ['cson', 'json', ''])
|
||||
keymap.load(keymapPath)
|
||||
else
|
||||
keymap.loadDirectory(@keymapsDirPath)
|
||||
keymap.loadDirectory(keymapsDirPath)
|
||||
|
||||
loadStylesheets: ->
|
||||
for stylesheetPath in @getStylesheetPaths()
|
||||
requireStylesheet(stylesheetPath)
|
||||
|
||||
getStylesheetPaths: ->
|
||||
stylesheetDirPath = fs.join(@path, 'stylesheets')
|
||||
fs.list(stylesheetDirPath)
|
||||
for stylesheetPath in fs.list(stylesheetDirPath)
|
||||
requireStylesheet(stylesheetPath)
|
||||
@@ -12,42 +12,58 @@ _.extend atom,
|
||||
exitWhenDone: window.location.params.exitWhenDone
|
||||
loadedThemes: []
|
||||
pendingBrowserProcessCallbacks: {}
|
||||
loadedPackages: []
|
||||
activatedAtomPackages: []
|
||||
atomPackageStates: {}
|
||||
|
||||
activateAtomPackage: (pack) ->
|
||||
@activatedAtomPackages.push(pack)
|
||||
pack.packageMain.activate(@atomPackageStates[pack.name])
|
||||
|
||||
deactivateAtomPackages: ->
|
||||
pack.packageMain.deactivate?() for pack in @activatedAtomPackages
|
||||
@activatedAtomPackages = []
|
||||
|
||||
serializeAtomPackages: ->
|
||||
packageStates = {}
|
||||
for pack in @activatedAtomPackages
|
||||
try
|
||||
packageStates[pack.name] = pack.packageMain.serialize?()
|
||||
catch e
|
||||
console?.error("Exception serializing '#{pack.name}' package's module\n", e.stack)
|
||||
packageStates
|
||||
|
||||
loadPackage: (name, options) ->
|
||||
packagePath = _.find @getPackagePaths(), (packagePath) -> fs.base(packagePath) == name
|
||||
pack = Package.build(packagePath)
|
||||
pack?.load(options)
|
||||
|
||||
loadPackages: ->
|
||||
{packages, asyncTextMatePackages} = _.groupBy @getPackages(), (pack) ->
|
||||
if pack instanceof TextMatePackage and pack.name isnt 'text.tmbundle'
|
||||
'asyncTextMatePackages'
|
||||
textMatePackages = []
|
||||
for path in @getPackagePaths()
|
||||
pack = Package.build(path)
|
||||
@loadedPackages.push(pack)
|
||||
if pack instanceof TextMatePackage and fs.base(pack.path) isnt 'text.tmbundle'
|
||||
textMatePackages.push(pack)
|
||||
else
|
||||
'packages'
|
||||
pack.load()
|
||||
|
||||
pack.load() for pack in packages
|
||||
if asyncTextMatePackages.length
|
||||
new LoadTextMatePackagesTask(asyncTextMatePackages).start()
|
||||
new LoadTextMatePackagesTask(textMatePackages).start() if textMatePackages.length > 0
|
||||
|
||||
getPackages: ->
|
||||
@packages ?= @getPackageNames().map((name) -> Package.build(name))
|
||||
.filter((pack) -> pack?)
|
||||
new Array(@packages...)
|
||||
getLoadedPackages: ->
|
||||
_.clone(@loadedPackages)
|
||||
|
||||
loadTextMatePackages: ->
|
||||
pack.load() for pack in @getTextMatePackages()
|
||||
|
||||
getTextMatePackages: ->
|
||||
@getPackages().filter (pack) -> pack instanceof TextMatePackage
|
||||
|
||||
loadPackage: (name) ->
|
||||
Package.build(name)?.load()
|
||||
|
||||
getPackageNames: ->
|
||||
getPackagePaths: ->
|
||||
disabledPackages = config.get("core.disabledPackages") ? []
|
||||
allPackageNames = []
|
||||
packagePaths = []
|
||||
for packageDirPath in config.packageDirPaths
|
||||
packageNames = fs.list(packageDirPath)
|
||||
.filter((packagePath) -> fs.isDirectory(packagePath))
|
||||
.map((packagePath) -> fs.base(packagePath))
|
||||
allPackageNames.push(packageNames...)
|
||||
_.unique(allPackageNames)
|
||||
.filter (name) -> not _.contains(disabledPackages, name)
|
||||
for packagePath in fs.list(packageDirPath)
|
||||
continue if not fs.isDirectory(packagePath)
|
||||
continue if fs.base(packagePath) in disabledPackages
|
||||
continue if packagePath in packagePaths
|
||||
packagePaths.push(packagePath)
|
||||
|
||||
packagePaths
|
||||
|
||||
loadThemes: ->
|
||||
themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class DeferredAtomPackage extends AtomPackage
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@autoloadStylesheets = false
|
||||
|
||||
activate: (@rootView, @state) ->
|
||||
@instance = null
|
||||
onLoadEvent = (e) => @onLoadEvent(e, @getInstance())
|
||||
if _.isArray(@loadEvents)
|
||||
for event in @loadEvents
|
||||
@rootView.command(event, onLoadEvent)
|
||||
else
|
||||
for event, selector of @loadEvents
|
||||
@rootView.command(event, selector, onLoadEvent)
|
||||
this
|
||||
|
||||
deactivate: -> @instance?.deactivate?()
|
||||
|
||||
serialize: ->
|
||||
if @instance
|
||||
@instance.serialize?()
|
||||
else
|
||||
@state
|
||||
|
||||
getInstance: ->
|
||||
unless @instance
|
||||
@loadStylesheets()
|
||||
InstanceClass = require @instanceClass
|
||||
@instance = InstanceClass.activate(@rootView, @state)
|
||||
@instance
|
||||
@@ -8,78 +8,10 @@ class LanguageMode
|
||||
buffer = null
|
||||
grammar = null
|
||||
editSession = null
|
||||
pairedCharacters:
|
||||
'(': ')'
|
||||
'[': ']'
|
||||
'{': '}'
|
||||
'"': '"'
|
||||
"'": "'"
|
||||
|
||||
constructor: (@editSession) ->
|
||||
@buffer = @editSession.buffer
|
||||
@reloadGrammar()
|
||||
@bracketMarkers = []
|
||||
|
||||
_.adviseBefore @editSession, 'insertText', (text) =>
|
||||
return true if @editSession.hasMultipleCursors()
|
||||
|
||||
cursorBufferPosition = @editSession.getCursorBufferPosition()
|
||||
previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
|
||||
nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
|
||||
|
||||
if @isOpeningBracket(text) and not @editSession.getSelection().isEmpty()
|
||||
@wrapSelectionInBrackets(text)
|
||||
return false
|
||||
|
||||
hasWordAfterCursor = /\w/.test(nextCharacter)
|
||||
hasWordBeforeCursor = /\w/.test(previousCharacter)
|
||||
|
||||
autoCompleteOpeningBracket = @isOpeningBracket(text) and not hasWordAfterCursor and not (@isQuote(text) and hasWordBeforeCursor)
|
||||
skipOverExistingClosingBracket = false
|
||||
if @isClosingBracket(text) and nextCharacter == text
|
||||
if bracketMarker = _.find(@bracketMarkers, (marker) => @editSession.getMarkerBufferRange(marker)?.end.isEqual(cursorBufferPosition))
|
||||
skipOverExistingClosingBracket = true
|
||||
|
||||
if skipOverExistingClosingBracket
|
||||
@editSession.destroyMarker(bracketMarker)
|
||||
_.remove(@bracketMarkers, bracketMarker)
|
||||
@editSession.moveCursorRight()
|
||||
false
|
||||
else if autoCompleteOpeningBracket
|
||||
@editSession.insertText(text + @pairedCharacters[text])
|
||||
@editSession.moveCursorLeft()
|
||||
range = [cursorBufferPosition, cursorBufferPosition.add([0, text.length])]
|
||||
@bracketMarkers.push @editSession.markBufferRange(range)
|
||||
false
|
||||
|
||||
_.adviseBefore @editSession, 'backspace', =>
|
||||
return if @editSession.hasMultipleCursors()
|
||||
return unless @editSession.getSelection().isEmpty()
|
||||
|
||||
cursorBufferPosition = @editSession.getCursorBufferPosition()
|
||||
previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
|
||||
nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
|
||||
if @pairedCharacters[previousCharacter] is nextCharacter
|
||||
@editSession.transact =>
|
||||
@editSession.moveCursorLeft()
|
||||
@editSession.delete()
|
||||
@editSession.delete()
|
||||
false
|
||||
|
||||
wrapSelectionInBrackets: (bracket) ->
|
||||
pair = @pairedCharacters[bracket]
|
||||
@editSession.mutateSelectedText (selection) =>
|
||||
return if selection.isEmpty()
|
||||
|
||||
range = selection.getBufferRange()
|
||||
options = reverse: selection.isReversed()
|
||||
selection.insertText("#{bracket}#{selection.getText()}#{pair}")
|
||||
selectionStart = range.start.add([0, 1])
|
||||
if range.start.row is range.end.row
|
||||
selectionEnd = range.end.add([0, 1])
|
||||
else
|
||||
selectionEnd = range.end
|
||||
selection.setBufferRange([selectionStart, selectionEnd], options)
|
||||
|
||||
reloadGrammar: ->
|
||||
path = @buffer.getPath()
|
||||
@@ -92,23 +24,6 @@ class LanguageMode
|
||||
throw new Error("No grammar found for path: #{path}") unless @grammar
|
||||
previousGrammar isnt @grammar
|
||||
|
||||
isQuote: (string) ->
|
||||
/'|"/.test(string)
|
||||
|
||||
isOpeningBracket: (string) ->
|
||||
@pairedCharacters[string]?
|
||||
|
||||
isClosingBracket: (string) ->
|
||||
@getInvertedPairedCharacters()[string]?
|
||||
|
||||
getInvertedPairedCharacters: ->
|
||||
return @invertedPairedCharacters if @invertedPairedCharacters
|
||||
|
||||
@invertedPairedCharacters = {}
|
||||
for open, close of @pairedCharacters
|
||||
@invertedPairedCharacters[close] = open
|
||||
@invertedPairedCharacters
|
||||
|
||||
toggleLineCommentsForBufferRows: (start, end) ->
|
||||
scopes = @editSession.scopesForBufferPosition([start, 0])
|
||||
return unless commentStartString = syntax.getProperty(scopes, "editor.commentStart")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
|
||||
module.exports =
|
||||
loadPackage: (name) ->
|
||||
callTaskMethod('packageLoaded', new TextMatePackage(name).readGrammars())
|
||||
loadPackage: (path) ->
|
||||
callTaskMethod('packageLoaded', new TextMatePackage(path).readGrammars())
|
||||
|
||||
@@ -16,10 +16,10 @@ class LoadTextMatePackagesTask extends Task
|
||||
return
|
||||
|
||||
@package = @packages.shift()
|
||||
@loadPackage(@package.name)
|
||||
@loadPackage(@package.path)
|
||||
|
||||
loadPackage: (name) ->
|
||||
@callWorkerMethod('loadPackage', name)
|
||||
loadPackage: (path) ->
|
||||
@callWorkerMethod('loadPackage', path)
|
||||
|
||||
packageLoaded: (grammars) ->
|
||||
@package.loadGrammars(grammars)
|
||||
|
||||
@@ -2,34 +2,17 @@ fs = require 'fs'
|
||||
|
||||
module.exports =
|
||||
class Package
|
||||
@resolve: (name) ->
|
||||
path = require.resolve(name, verifyExistence: false)
|
||||
return path if path
|
||||
throw new Error("No package found named '#{name}'")
|
||||
|
||||
@build: (name) ->
|
||||
@build: (path) ->
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
AtomPackage = require 'atom-package'
|
||||
if TextMatePackage.testName(name)
|
||||
new TextMatePackage(name)
|
||||
|
||||
if TextMatePackage.testName(path)
|
||||
new TextMatePackage(path)
|
||||
else
|
||||
if fs.isDirectory(@resolve(name))
|
||||
new AtomPackage(name)
|
||||
else
|
||||
try
|
||||
PackageClass = require name
|
||||
new PackageClass(name) if typeof PackageClass is 'function'
|
||||
catch e
|
||||
console.warn "Failed to load package named '#{name}'", e.stack
|
||||
new AtomPackage(path)
|
||||
|
||||
name: null
|
||||
path: null
|
||||
isDirectory: false
|
||||
module: null
|
||||
|
||||
constructor: (@name) ->
|
||||
@path = Package.resolve(@name)
|
||||
@isDirectory = fs.isDirectory(@path)
|
||||
@path = fs.directory(@path) unless @isDirectory
|
||||
|
||||
activate: (rootView) ->
|
||||
constructor: (@path) ->
|
||||
@name = fs.base(@path)
|
||||
|
||||
@@ -118,6 +118,10 @@ class Project
|
||||
getEditSessions: ->
|
||||
new Array(@editSessions...)
|
||||
|
||||
eachEditSession: (callback) ->
|
||||
callback(editSession) for editSession in @getEditSessions()
|
||||
@on 'edit-session-created', (editSession) -> callback(editSession)
|
||||
|
||||
removeEditSession: (editSession) ->
|
||||
_.remove(@editSessions, editSession)
|
||||
|
||||
@@ -125,9 +129,12 @@ class Project
|
||||
buffers = []
|
||||
for editSession in @editSessions when not _.include(buffers, editSession.buffer)
|
||||
buffers.push editSession.buffer
|
||||
|
||||
buffers
|
||||
|
||||
eachBuffer: (callback) ->
|
||||
callback(buffer) for buffer in @getBuffers()
|
||||
@on 'buffer-created', (buffer) -> callback(buffer)
|
||||
|
||||
bufferForPath: (filePath) ->
|
||||
if filePath?
|
||||
filePath = @resolve(filePath)
|
||||
|
||||
@@ -29,19 +29,19 @@ class RootView extends View
|
||||
else
|
||||
projectOrPathToOpen = projectPath # This will migrate people over to the new project serialization scheme. It should be removed eventually.
|
||||
|
||||
rootView = new RootView(projectOrPathToOpen , packageStates: packageStates, suppressOpen: true)
|
||||
atom.atomPackageStates = packageStates ? {}
|
||||
|
||||
rootView = new RootView(projectOrPathToOpen , suppressOpen: true)
|
||||
rootView.setRootPane(rootView.deserializeView(panesViewState)) if panesViewState
|
||||
rootView
|
||||
|
||||
packageModules: null
|
||||
packageStates: null
|
||||
packages: null
|
||||
title: null
|
||||
pathToOpenIsFile: false
|
||||
|
||||
initialize: (projectOrPathToOpen, { @packageStates, suppressOpen } = {}) ->
|
||||
initialize: (projectOrPathToOpen, { suppressOpen } = {}) ->
|
||||
window.rootView = this
|
||||
@packageStates ?= {}
|
||||
@packageModules = {}
|
||||
@packages = []
|
||||
@viewClasses = {
|
||||
"Pane": Pane,
|
||||
"PaneRow": PaneRow,
|
||||
@@ -68,7 +68,7 @@ class RootView extends View
|
||||
serialize: ->
|
||||
projectState: @project?.serialize()
|
||||
panesViewState: @panes.children().view()?.serialize()
|
||||
packageStates: @serializePackages()
|
||||
packageStates: atom.serializeAtomPackages()
|
||||
|
||||
handleFocus: (e) ->
|
||||
if @getActiveEditor()
|
||||
@@ -118,33 +118,15 @@ class RootView extends View
|
||||
afterAttach: (onDom) ->
|
||||
@focus() if onDom
|
||||
|
||||
serializePackages: ->
|
||||
packageStates = {}
|
||||
for name, packageModule of @packageModules
|
||||
try
|
||||
packageStates[name] = packageModule.serialize?()
|
||||
catch e
|
||||
console?.error("Exception serializing '#{name}' package's module\n", e.stack)
|
||||
packageStates
|
||||
|
||||
registerViewClass: (viewClass) ->
|
||||
@viewClasses[viewClass.name] = viewClass
|
||||
|
||||
deserializeView: (viewState) ->
|
||||
@viewClasses[viewState.viewClass]?.deserialize(viewState, this)
|
||||
|
||||
activatePackage: (name, packageModule) ->
|
||||
config.setDefaults(name, packageModule.configDefaults) if packageModule.configDefaults?
|
||||
@packageModules[name] = packageModule
|
||||
packageModule.activate(this, @packageStates[name])
|
||||
|
||||
deactivatePackage: (name) ->
|
||||
@packageModules[name].deactivate?()
|
||||
delete @packageModules[name]
|
||||
|
||||
deactivate: ->
|
||||
atom.setRootViewStateForPath(@project.getPath(), @serialize())
|
||||
@deactivatePackage(name) for name of @packageModules
|
||||
atom.deactivateAtomPackages()
|
||||
@remove()
|
||||
|
||||
open: (path, options = {}) ->
|
||||
@@ -274,9 +256,11 @@ class RootView extends View
|
||||
callback(editor) for editor in @getEditors()
|
||||
@on 'editor:attached', (e, editor) -> callback(editor)
|
||||
|
||||
eachEditSession: (callback) ->
|
||||
@project.eachEditSession(callback)
|
||||
|
||||
eachBuffer: (callback) ->
|
||||
callback(buffer) for buffer in @project.getBuffers()
|
||||
@project.on 'buffer-created', (buffer) -> callback(buffer)
|
||||
@project.eachBuffer(callback)
|
||||
|
||||
indexOfPane: (pane) ->
|
||||
index = -1
|
||||
|
||||
@@ -9,9 +9,12 @@ module.exports =
|
||||
class TextMateGrammar
|
||||
@readFromPath: (path) ->
|
||||
grammarContent = null
|
||||
plist.parseString fs.read(path), (e, data) ->
|
||||
throw new Error(e) if e
|
||||
grammarContent = data[0]
|
||||
if fs.extension(path) is '.cson'
|
||||
grammarContent = fs.readObject(path)
|
||||
else
|
||||
plist.parseString fs.read(path), (e, data) ->
|
||||
throw new Error(e) if e
|
||||
grammarContent = data[0]
|
||||
throw new Error("Failed to load grammar at path `#{path}`") unless grammarContent
|
||||
grammarContent
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class TextMatePackage extends Package
|
||||
try
|
||||
@loadGrammars()
|
||||
catch e
|
||||
console.warn "Failed to load package named '#{@name}'", e.stack
|
||||
console.warn "Failed to load package at '#{@path}'", e.stack
|
||||
this
|
||||
|
||||
getGrammars: -> @grammars
|
||||
|
||||
@@ -37,8 +37,8 @@ windowAdditions =
|
||||
# Note: RootView assigns itself on window on initialization so that
|
||||
# window.rootView is available when loading user configuration
|
||||
attachRootView: (pathToOpen) ->
|
||||
if rootViewState = atom.getRootViewStateForPath(pathToOpen)
|
||||
RootView.deserialize(rootViewState)
|
||||
if pathState = atom.getRootViewStateForPath(pathToOpen)
|
||||
RootView.deserialize(pathState)
|
||||
else
|
||||
new RootView(pathToOpen)
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
AutocompleteView = require './src/autocomplete-view'
|
||||
|
||||
module.exports =
|
||||
class Autocomplete extends AtomPackage
|
||||
activate: (rootView) -> AutocompleteView.activate(rootView)
|
||||
@@ -4,10 +4,6 @@ SelectList = require 'select-list'
|
||||
|
||||
module.exports =
|
||||
class AutocompleteView extends SelectList
|
||||
@activate: (rootView) ->
|
||||
rootView.eachEditor (editor) ->
|
||||
new AutocompleteView(editor) if editor.attached and not editor.mini
|
||||
|
||||
@viewClass: -> "autocomplete #{super} popover-list"
|
||||
|
||||
editor: null
|
||||
@@ -21,7 +17,6 @@ class AutocompleteView extends SelectList
|
||||
|
||||
initialize: (@editor) ->
|
||||
super
|
||||
|
||||
@handleEvents()
|
||||
@setCurrentBuffer(@editor.getBuffer())
|
||||
|
||||
10
src/packages/autocomplete/lib/autocomplete.coffee
Normal file
10
src/packages/autocomplete/lib/autocomplete.coffee
Normal file
@@ -0,0 +1,10 @@
|
||||
AutocompleteView = require './autocomplete-view'
|
||||
|
||||
module.exports =
|
||||
autoCompleteViews: []
|
||||
|
||||
activate: ->
|
||||
rootView.eachEditor (editor) =>
|
||||
if editor.attached and not editor.mini
|
||||
@autoCompleteViews.push new AutocompleteView(editor)
|
||||
|
||||
3
src/packages/autocomplete/package.cson
Normal file
3
src/packages/autocomplete/package.cson
Normal file
@@ -0,0 +1,3 @@
|
||||
'main': 'lib/autocomplete'
|
||||
'activationEvents':
|
||||
'autocomplete:attach': '.editor'
|
||||
@@ -1,37 +1,33 @@
|
||||
$ = require 'jquery'
|
||||
Autocomplete = require 'autocomplete/src/autocomplete-view'
|
||||
AutocompleteView = require 'autocomplete/lib/autocomplete-view'
|
||||
Autocomplete = require 'autocomplete/lib/autocomplete'
|
||||
Buffer = require 'buffer'
|
||||
Editor = require 'editor'
|
||||
RootView = require 'root-view'
|
||||
|
||||
describe "Autocomplete", ->
|
||||
autocomplete = null
|
||||
editor = null
|
||||
miniEditor = null
|
||||
|
||||
beforeEach ->
|
||||
editor = new Editor(editSession: fixturesProject.buildEditSessionForPath('sample.js'))
|
||||
atom.loadPackage('autocomplete')
|
||||
autocomplete = new Autocomplete(editor)
|
||||
miniEditor = autocomplete.miniEditor
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
rootView.simulateDomAttachment()
|
||||
|
||||
afterEach ->
|
||||
editor?.remove()
|
||||
rootView.deactivate()
|
||||
|
||||
describe "@activate(rootView)", ->
|
||||
describe "@activate()", ->
|
||||
it "activates autocomplete on all existing and future editors (but not on autocomplete's own mini editor)", ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
rootView.simulateDomAttachment()
|
||||
Autocomplete.activate(rootView)
|
||||
spyOn(AutocompleteView.prototype, 'initialize').andCallThrough()
|
||||
autocompletePackage = atom.loadPackage("autocomplete")
|
||||
expect(AutocompleteView.prototype.initialize).not.toHaveBeenCalled()
|
||||
|
||||
leftEditor = rootView.getActiveEditor()
|
||||
rightEditor = rootView.getActiveEditor().splitRight()
|
||||
|
||||
spyOn(Autocomplete.prototype, 'initialize')
|
||||
|
||||
leftEditor.trigger 'autocomplete:attach'
|
||||
expect(leftEditor.find('.autocomplete')).toExist()
|
||||
expect(rightEditor.find('.autocomplete')).not.toExist()
|
||||
|
||||
expect(AutocompleteView.prototype.initialize).toHaveBeenCalled()
|
||||
|
||||
autoCompleteView = leftEditor.find('.autocomplete').view()
|
||||
autoCompleteView.trigger 'core:cancel'
|
||||
expect(leftEditor.find('.autocomplete')).not.toExist()
|
||||
@@ -39,9 +35,20 @@ describe "Autocomplete", ->
|
||||
rightEditor.trigger 'autocomplete:attach'
|
||||
expect(rightEditor.find('.autocomplete')).toExist()
|
||||
|
||||
expect(Autocomplete.prototype.initialize).not.toHaveBeenCalled()
|
||||
describe "AutocompleteView", ->
|
||||
autocomplete = null
|
||||
editor = null
|
||||
miniEditor = null
|
||||
|
||||
rootView.deactivate()
|
||||
beforeEach ->
|
||||
new RootView
|
||||
editor = new Editor(editSession: fixturesProject.buildEditSessionForPath('sample.js'))
|
||||
atom.loadPackage('autocomplete')
|
||||
autocomplete = new AutocompleteView(editor)
|
||||
miniEditor = autocomplete.miniEditor
|
||||
|
||||
afterEach ->
|
||||
editor?.remove()
|
||||
|
||||
describe 'autocomplete:attach event', ->
|
||||
it "shows autocomplete view and focuses its mini-editor", ->
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
|
||||
module.exports =
|
||||
class Autoflow extends AtomPackage
|
||||
activate: (rootView) ->
|
||||
activate: ->
|
||||
rootView.command 'autoflow:reflow-paragraph', '.editor', (e) =>
|
||||
@reflowParagraph(e.currentTargetView())
|
||||
|
||||
1
src/packages/autoflow/package.cson
Normal file
1
src/packages/autoflow/package.cson
Normal file
@@ -0,0 +1 @@
|
||||
'main': 'autoflow'
|
||||
@@ -1,10 +1,15 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
_ = require 'underscore'
|
||||
{$$} = require 'space-pen'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
class BracketMatcher extends AtomPackage
|
||||
pairedCharacters:
|
||||
'(': ')'
|
||||
'[': ']'
|
||||
'{': '}'
|
||||
'"': '"'
|
||||
"'": "'"
|
||||
|
||||
startPairMatches:
|
||||
'(': ')'
|
||||
'[': ']'
|
||||
@@ -17,8 +22,9 @@ class BracketMatcher extends AtomPackage
|
||||
|
||||
pairHighlighted: false
|
||||
|
||||
activate: (rootView) ->
|
||||
activate: ->
|
||||
rootView.eachEditor (editor) => @subscribeToEditor(editor) if editor.attached
|
||||
rootView.eachEditSession (editSession) => @subscribeToEditSession(editSession)
|
||||
|
||||
subscribeToEditor: (editor) ->
|
||||
editor.on 'cursor:moved.bracket-matcher', => @updateMatch(editor)
|
||||
@@ -118,3 +124,84 @@ class BracketMatcher extends AtomPackage
|
||||
underlayer.append(@createView(editor, matchPosition))
|
||||
underlayer.append(@createView(editor, position))
|
||||
@pairHighlighted = true
|
||||
|
||||
subscribeToEditSession: (editSession) ->
|
||||
@bracketMarkers = []
|
||||
|
||||
_.adviseBefore editSession, 'insertText', (text) =>
|
||||
return true if editSession.hasMultipleCursors()
|
||||
|
||||
cursorBufferPosition = editSession.getCursorBufferPosition()
|
||||
previousCharacter = editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
|
||||
nextCharacter = editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
|
||||
|
||||
if @isOpeningBracket(text) and not editSession.getSelection().isEmpty()
|
||||
@wrapSelectionInBrackets(editSession, text)
|
||||
return false
|
||||
|
||||
hasWordAfterCursor = /\w/.test(nextCharacter)
|
||||
hasWordBeforeCursor = /\w/.test(previousCharacter)
|
||||
|
||||
autoCompleteOpeningBracket = @isOpeningBracket(text) and not hasWordAfterCursor and not (@isQuote(text) and hasWordBeforeCursor)
|
||||
skipOverExistingClosingBracket = false
|
||||
if @isClosingBracket(text) and nextCharacter == text
|
||||
if bracketMarker = _.find(@bracketMarkers, (marker) => editSession.getMarkerBufferRange(marker)?.end.isEqual(cursorBufferPosition))
|
||||
skipOverExistingClosingBracket = true
|
||||
|
||||
if skipOverExistingClosingBracket
|
||||
editSession.destroyMarker(bracketMarker)
|
||||
_.remove(@bracketMarkers, bracketMarker)
|
||||
editSession.moveCursorRight()
|
||||
false
|
||||
else if autoCompleteOpeningBracket
|
||||
editSession.insertText(text + @pairedCharacters[text])
|
||||
editSession.moveCursorLeft()
|
||||
range = [cursorBufferPosition, cursorBufferPosition.add([0, text.length])]
|
||||
@bracketMarkers.push editSession.markBufferRange(range)
|
||||
false
|
||||
|
||||
_.adviseBefore editSession, 'backspace', =>
|
||||
return if editSession.hasMultipleCursors()
|
||||
return unless editSession.getSelection().isEmpty()
|
||||
|
||||
cursorBufferPosition = editSession.getCursorBufferPosition()
|
||||
previousCharacter = editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
|
||||
nextCharacter = editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
|
||||
if @pairedCharacters[previousCharacter] is nextCharacter
|
||||
editSession.transact =>
|
||||
editSession.moveCursorLeft()
|
||||
editSession.delete()
|
||||
editSession.delete()
|
||||
false
|
||||
|
||||
wrapSelectionInBrackets: (editSession, bracket) ->
|
||||
pair = @pairedCharacters[bracket]
|
||||
editSession.mutateSelectedText (selection) =>
|
||||
return if selection.isEmpty()
|
||||
|
||||
range = selection.getBufferRange()
|
||||
options = reverse: selection.isReversed()
|
||||
selection.insertText("#{bracket}#{selection.getText()}#{pair}")
|
||||
selectionStart = range.start.add([0, 1])
|
||||
if range.start.row is range.end.row
|
||||
selectionEnd = range.end.add([0, 1])
|
||||
else
|
||||
selectionEnd = range.end
|
||||
selection.setBufferRange([selectionStart, selectionEnd], options)
|
||||
|
||||
isQuote: (string) ->
|
||||
/'|"/.test(string)
|
||||
|
||||
getInvertedPairedCharacters: ->
|
||||
return @invertedPairedCharacters if @invertedPairedCharacters
|
||||
|
||||
@invertedPairedCharacters = {}
|
||||
for open, close of @pairedCharacters
|
||||
@invertedPairedCharacters[close] = open
|
||||
@invertedPairedCharacters
|
||||
|
||||
isOpeningBracket: (string) ->
|
||||
@pairedCharacters[string]?
|
||||
|
||||
isClosingBracket: (string) ->
|
||||
@getInvertedPairedCharacters()[string]?
|
||||
1
src/packages/bracket-matcher/package.cson
Normal file
1
src/packages/bracket-matcher/package.cson
Normal file
@@ -0,0 +1 @@
|
||||
'main': 'lib/bracket-matcher'
|
||||
@@ -1,63 +1,66 @@
|
||||
RootView = require 'root-view'
|
||||
|
||||
describe "bracket matching", ->
|
||||
[rootView, editor] = []
|
||||
[editor, editSession, buffer] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
atom.loadPackage('bracket-matcher')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveEditor()
|
||||
editSession = editor.activeEditSession
|
||||
buffer = editSession.buffer
|
||||
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
|
||||
describe "when the cursor is before a starting pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
|
||||
describe "when the cursor is after a starting pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
|
||||
describe "when the cursor is before an ending pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.moveCursorLeft()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
|
||||
describe "when the cursor is after an ending pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
|
||||
describe "when the cursor is moved off a pair", ->
|
||||
it "removes the starting pair and ending pair highlights", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
editor.moveCursorToBeginningOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 0
|
||||
|
||||
describe "pair balancing", ->
|
||||
describe "when a second starting pair preceeds the first ending pair", ->
|
||||
it "advances to the second ending pair", ->
|
||||
editor.setCursorBufferPosition([8,42])
|
||||
describe "matching bracket highlighting", ->
|
||||
describe "when the cursor is before a starting pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([8,42])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([8,54])
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
|
||||
describe "when the cursor is after a starting pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
|
||||
describe "when the cursor is before an ending pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.moveCursorLeft()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
|
||||
describe "when the cursor is after an ending pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
|
||||
describe "when the cursor is moved off a pair", ->
|
||||
it "removes the starting pair and ending pair highlights", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
editor.moveCursorToBeginningOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 0
|
||||
|
||||
describe "pair balancing", ->
|
||||
describe "when a second starting pair preceeds the first ending pair", ->
|
||||
it "advances to the second ending pair", ->
|
||||
editor.setCursorBufferPosition([8,42])
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([8,42])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([8,54])
|
||||
|
||||
describe "when editor:go-to-matching-bracket is triggered", ->
|
||||
describe "when the cursor is before the starting pair", ->
|
||||
@@ -84,3 +87,189 @@ describe "bracket matching", ->
|
||||
editor.setCursorBufferPosition([12, 1])
|
||||
editor.trigger "editor:go-to-matching-bracket"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 28]
|
||||
|
||||
describe "matching bracket insertion", ->
|
||||
beforeEach ->
|
||||
editSession.buffer.setText("")
|
||||
|
||||
describe "when more than one character is inserted", ->
|
||||
it "does not insert a matching bracket", ->
|
||||
editSession.insertText("woah(")
|
||||
expect(editSession.buffer.getText()).toBe "woah("
|
||||
|
||||
describe "when there is a word character after the cursor", ->
|
||||
it "does not insert a matching bracket", ->
|
||||
editSession.buffer.setText("ab")
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText("(")
|
||||
|
||||
expect(editSession.buffer.getText()).toBe "a(b"
|
||||
|
||||
describe "when there are multiple cursors", ->
|
||||
it "inserts ) at each cursor", ->
|
||||
editSession.buffer.setText("()\nab\n[]\n12")
|
||||
editSession.setCursorBufferPosition([3, 1])
|
||||
editSession.addCursorAtBufferPosition([2, 1])
|
||||
editSession.addCursorAtBufferPosition([1, 1])
|
||||
editSession.addCursorAtBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
|
||||
expect(editSession.buffer.getText()).toBe "())\na)b\n[)]\n1)2"
|
||||
|
||||
describe "when there is a non-word character after the cursor", ->
|
||||
it "inserts a closing bracket after an opening bracket is inserted", ->
|
||||
editSession.buffer.setText("}")
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.insertText '{'
|
||||
expect(buffer.lineForRow(0)).toBe "{}}"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
describe "when the cursor is at the end of the line", ->
|
||||
it "inserts a closing bracket after an opening bracket is inserted", ->
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '{'
|
||||
expect(buffer.lineForRow(0)).toBe "{}"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '('
|
||||
expect(buffer.lineForRow(0)).toBe "()"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '['
|
||||
expect(buffer.lineForRow(0)).toBe "[]"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe '""'
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
editSession.buffer.setText("")
|
||||
editSession.insertText "'"
|
||||
expect(buffer.lineForRow(0)).toBe "''"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([0,1])
|
||||
|
||||
describe "when the cursor is on a closing bracket and a closing bracket is inserted", ->
|
||||
describe "when the closing bracket was there previously", ->
|
||||
it "inserts a closing bracket", ->
|
||||
editSession.insertText '()x'
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "())x"
|
||||
expect(editSession.getCursorBufferPosition().column).toBe 2
|
||||
|
||||
describe "when the closing bracket was automatically inserted from inserting an opening bracket", ->
|
||||
it "only moves cursor over the closing bracket one time", ->
|
||||
editSession.insertText '('
|
||||
expect(buffer.lineForRow(0)).toBe "()"
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "()"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 2]
|
||||
|
||||
editSession.setCursorBufferPosition([0, 1])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "())"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 2]
|
||||
|
||||
it "moves cursor over the closing bracket after other text is inserted", ->
|
||||
editSession.insertText '('
|
||||
editSession.insertText 'ok cool'
|
||||
expect(buffer.lineForRow(0)).toBe "(ok cool)"
|
||||
editSession.setCursorBufferPosition([0, 8])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(ok cool)"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 9]
|
||||
|
||||
it "works with nested brackets", ->
|
||||
editSession.insertText '('
|
||||
editSession.insertText '1'
|
||||
editSession.insertText '('
|
||||
editSession.insertText '2'
|
||||
expect(buffer.lineForRow(0)).toBe "(1(2))"
|
||||
editSession.setCursorBufferPosition([0, 4])
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(1(2))"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 5]
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(1(2))"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 6]
|
||||
|
||||
it "works with mixed brackets", ->
|
||||
editSession.insertText '('
|
||||
editSession.insertText '}'
|
||||
expect(buffer.lineForRow(0)).toBe "(})"
|
||||
editSession.insertText ')'
|
||||
expect(buffer.lineForRow(0)).toBe "(})"
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 3]
|
||||
|
||||
it "closes brackets with the same begin/end character correctly", ->
|
||||
editSession.insertText '"'
|
||||
editSession.insertText 'ok'
|
||||
expect(buffer.lineForRow(0)).toBe '"ok"'
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 3]
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe '"ok"'
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 4]
|
||||
|
||||
describe "when there is text selected on a single line", ->
|
||||
it "wraps the selection with brackets", ->
|
||||
editSession.insertText 'text'
|
||||
editSession.moveCursorToBottom()
|
||||
editSession.selectToTop()
|
||||
editSession.selectAll()
|
||||
editSession.insertText '('
|
||||
expect('(text)').toBe buffer.getText()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [0, 5]]
|
||||
expect(editSession.getSelection().isReversed()).toBeTruthy()
|
||||
|
||||
describe "when there is text selected on multiple lines", ->
|
||||
it "wraps the selection with brackets", ->
|
||||
editSession.insertText 'text\nabcd'
|
||||
editSession.moveCursorToBottom()
|
||||
editSession.selectToTop()
|
||||
editSession.selectAll()
|
||||
editSession.insertText '('
|
||||
expect('(text\nabcd)').toBe buffer.getText()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [1, 4]]
|
||||
expect(editSession.getSelection().isReversed()).toBeTruthy()
|
||||
|
||||
describe "when inserting a quote", ->
|
||||
describe "when a word character is before the cursor", ->
|
||||
it "does not automatically insert closing quote", ->
|
||||
editSession.buffer.setText("abc")
|
||||
editSession.setCursorBufferPosition([0, 3])
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe "abc\""
|
||||
|
||||
editSession.buffer.setText("abc")
|
||||
editSession.setCursorBufferPosition([0, 3])
|
||||
editSession.insertText '\''
|
||||
expect(buffer.lineForRow(0)).toBe "abc\'"
|
||||
|
||||
describe "when a non word character is before the cursor", ->
|
||||
it "automatically insert closing quote", ->
|
||||
editSession.buffer.setText("ab@")
|
||||
editSession.setCursorBufferPosition([0, 3])
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe "ab@\"\""
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 4]
|
||||
|
||||
describe "when the cursor is on an empty line", ->
|
||||
it "automatically insert closing quote", ->
|
||||
editSession.buffer.setText("")
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.insertText '"'
|
||||
expect(buffer.lineForRow(0)).toBe "\"\""
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [0, 1]
|
||||
|
||||
describe "matching bracket deletion", ->
|
||||
it "deletes the end bracket when it directly proceeds a begin bracket that is being backspaced", ->
|
||||
buffer.setText("")
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.insertText '{'
|
||||
expect(buffer.lineForRow(0)).toBe "{}"
|
||||
editSession.backspace()
|
||||
expect(buffer.lineForRow(0)).toBe ""
|
||||
|
||||
@@ -4,18 +4,12 @@ _ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class CommandLoggerView extends ScrollView
|
||||
@activate: (rootView, state) ->
|
||||
@instance = new CommandLoggerView(rootView)
|
||||
|
||||
@content: (rootView) ->
|
||||
@div class: 'command-logger', tabindex: -1, =>
|
||||
@h1 class: 'category-header', outlet: 'categoryHeader'
|
||||
@h1 class: 'category-summary', outlet: 'categorySummary'
|
||||
@div class: 'tree-map', outlet: 'treeMap'
|
||||
|
||||
@serialize: ->
|
||||
@instance.serialize()
|
||||
|
||||
eventLog: null
|
||||
ignoredEvents: [
|
||||
'core:backspace'
|
||||
@@ -30,7 +24,7 @@ class CommandLoggerView extends ScrollView
|
||||
'tree-view:directory-modified'
|
||||
]
|
||||
|
||||
initialize: (@rootView) ->
|
||||
initialize: ->
|
||||
super
|
||||
|
||||
@command 'core:cancel', => @detach()
|
||||
@@ -176,7 +170,7 @@ class CommandLoggerView extends ScrollView
|
||||
d3.select('.command-logger').on('click', -> zoom(root))
|
||||
|
||||
attach: ->
|
||||
@rootView.append(this)
|
||||
rootView.append(this)
|
||||
@addTreeMap()
|
||||
@focus()
|
||||
|
||||
@@ -184,8 +178,5 @@ class CommandLoggerView extends ScrollView
|
||||
return if @detaching
|
||||
@detaching = true
|
||||
super
|
||||
@rootView.focus()
|
||||
rootView.focus()
|
||||
@detaching = false
|
||||
|
||||
serialize: ->
|
||||
eventLog: @eventLog
|
||||
@@ -1,18 +1,14 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class CommandLogger extends DeferredAtomPackage
|
||||
|
||||
loadEvents: ['command-logger:toggle']
|
||||
|
||||
instanceClass: 'command-logger/src/command-logger-view'
|
||||
|
||||
activate: (rootView, state={})->
|
||||
super
|
||||
eventLog: {}
|
||||
commandLoggerView: null
|
||||
originalTrigger: null
|
||||
|
||||
activate: (state={})->
|
||||
@eventLog = state.eventLog ? {}
|
||||
rootView.command 'command-logger:clear-data', => @eventLog = {}
|
||||
rootView.command 'command-logger:toggle', => @createView().toggle(@eventLog)
|
||||
|
||||
registerTriggeredEvent = (eventName) =>
|
||||
eventNameLog = @eventLog[eventName]
|
||||
@@ -23,10 +19,22 @@ class CommandLogger extends DeferredAtomPackage
|
||||
@eventLog[eventName] = eventNameLog
|
||||
eventNameLog.count++
|
||||
eventNameLog.lastRun = new Date().getTime()
|
||||
originalTrigger = $.fn.trigger
|
||||
trigger = $.fn.trigger
|
||||
@originalTrigger = trigger
|
||||
$.fn.trigger = (eventName) ->
|
||||
eventName = eventName.type if eventName.type
|
||||
registerTriggeredEvent(eventName) if $(this).events()[eventName]
|
||||
originalTrigger.apply(this, arguments)
|
||||
trigger.apply(this, arguments)
|
||||
|
||||
onLoadEvent: (event, instance) -> instance.toggle(@eventLog)
|
||||
deactivate: ->
|
||||
$.fn.trigger = @originalTrigger if @originalTrigger?
|
||||
@commandLoggerView = null
|
||||
@eventLog = {}
|
||||
|
||||
serialize: ->
|
||||
{@eventLog}
|
||||
|
||||
createView: ->
|
||||
unless @commandLoggerView
|
||||
CommandLoggerView = require 'command-logger/lib/command-logger-view'
|
||||
@commandLoggerView = new CommandLoggerView
|
||||
1
src/packages/command-logger/package.cson
Normal file
1
src/packages/command-logger/package.cson
Normal file
@@ -0,0 +1 @@
|
||||
'main': 'lib/command-logger'
|
||||
@@ -1,12 +1,13 @@
|
||||
RootView = require 'root-view'
|
||||
CommandLogger = require 'command-logger/src/command-logger-view'
|
||||
CommandLogger = require 'command-logger/lib/command-logger-view'
|
||||
|
||||
describe "CommandLogger", ->
|
||||
[rootView, commandLogger, editor] = []
|
||||
[commandLogger, editor] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
commandLogger = atom.loadPackage('command-logger')
|
||||
new RootView(require.resolve('fixtures/sample.js'))
|
||||
commandLogger = atom.loadPackage('command-logger').packageMain
|
||||
commandLogger.eventLog = {}
|
||||
editor = rootView.getActiveEditor()
|
||||
|
||||
afterEach ->
|
||||
@@ -43,7 +44,7 @@ describe "CommandLogger", ->
|
||||
|
||||
describe "when an event is ignored", ->
|
||||
it "does not create a node for that event", ->
|
||||
commandLoggerView = commandLogger.getInstance()
|
||||
commandLoggerView = commandLogger.createView()
|
||||
commandLoggerView.ignoredEvents.push 'editor:delete-line'
|
||||
editor.trigger 'editor:delete-line'
|
||||
commandLoggerView.eventLog = commandLogger.eventLog
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
|
||||
module.exports =
|
||||
class CommandPalette extends DeferredAtomPackage
|
||||
|
||||
loadEvents: ['command-palette:toggle']
|
||||
|
||||
instanceClass: 'command-palette/src/command-palette-view'
|
||||
|
||||
onLoadEvent: (event, instance) -> instance.attach()
|
||||
@@ -5,8 +5,8 @@ _ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class CommandPaletteView extends SelectList
|
||||
@activate: (rootView) ->
|
||||
@instance = new CommandPaletteView(rootView)
|
||||
@activate: ->
|
||||
new CommandPaletteView
|
||||
|
||||
@viewClass: ->
|
||||
"#{super} command-palette overlay from-top"
|
||||
@@ -16,12 +16,17 @@ class CommandPaletteView extends SelectList
|
||||
previouslyFocusedElement: null
|
||||
keyBindings: null
|
||||
|
||||
initialize: (@rootView) ->
|
||||
@command 'command-palette:toggle', =>
|
||||
@cancel()
|
||||
false
|
||||
initialize: ->
|
||||
super
|
||||
|
||||
rootView.command 'command-palette:toggle', => @toggle()
|
||||
|
||||
toggle: ->
|
||||
if @hasParent()
|
||||
@cancel()
|
||||
else
|
||||
@attach()
|
||||
|
||||
attach: ->
|
||||
super
|
||||
|
||||
@@ -34,7 +39,7 @@ class CommandPaletteView extends SelectList
|
||||
events = _.sortBy events, (e) -> e.eventDescription
|
||||
|
||||
@setArray(events)
|
||||
@appendTo(@rootView)
|
||||
@appendTo(rootView)
|
||||
@miniEditor.focus()
|
||||
|
||||
itemForElement: ({eventName, eventDescription}) ->
|
||||
2
src/packages/command-palette/package.cson
Normal file
2
src/packages/command-palette/package.cson
Normal file
@@ -0,0 +1,2 @@
|
||||
'main': 'lib/command-palette-view'
|
||||
'activationEvents': ['command-palette:toggle']
|
||||
@@ -1,17 +1,17 @@
|
||||
RootView = require 'root-view'
|
||||
CommandPalette = require 'command-palette/src/command-palette-view'
|
||||
CommandPalette = require 'command-palette/lib/command-palette-view'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "CommandPalette", ->
|
||||
[rootView, palette] = []
|
||||
[palette] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
atom.loadPackage("command-palette").getInstance()
|
||||
palette = CommandPalette.instance
|
||||
atom.loadPackage("command-palette")
|
||||
rootView.attachToDom().focus()
|
||||
rootView.trigger 'command-palette:toggle'
|
||||
palette = rootView.find('.command-palette').view()
|
||||
|
||||
afterEach ->
|
||||
rootView.remove()
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
|
||||
module.exports =
|
||||
class CommandPanel extends DeferredAtomPackage
|
||||
|
||||
loadEvents: [
|
||||
'command-panel:toggle'
|
||||
'command-panel:toggle-preview'
|
||||
'command-panel:find-in-file'
|
||||
'command-panel:find-in-project'
|
||||
'command-panel:repeat-relative-address'
|
||||
'command-panel:repeat-relative-address-in-reverse'
|
||||
'command-panel:set-selection-as-regex-address'
|
||||
]
|
||||
|
||||
instanceClass: 'command-panel/src/command-panel-view'
|
||||
|
||||
onLoadEvent: (event, instance) ->
|
||||
switch event.type
|
||||
when 'command-panel:toggle'
|
||||
instance.toggle()
|
||||
when 'command-panel:toggle-preview'
|
||||
instance.togglePreview()
|
||||
when 'command-panel:find-in-file'
|
||||
instance.attach("/")
|
||||
when 'command-panel:find-in-project'
|
||||
instance.attach("Xx/")
|
||||
when 'command-panel:repeat-relative-address'
|
||||
instance.repeatRelativeAddress()
|
||||
when 'command-panel:repeat-relative-address-in-reverse'
|
||||
instance.repeatRelativeAddressInReverse()
|
||||
when 'command-panel:set-selection-as-regex-address'
|
||||
instance.setSelectionAsLastRelativeAddress()
|
||||
@@ -6,7 +6,7 @@ class CommandInterpreter
|
||||
constructor: (@project) ->
|
||||
|
||||
eval: (string, activeEditSession) ->
|
||||
@parser ?= PEG.buildParser(fs.read(require.resolve 'command-panel/commands.pegjs'))
|
||||
@parser ?= PEG.buildParser(fs.read(require.resolve 'command-panel/lib/commands.pegjs'))
|
||||
compositeCommand = @parser.parse(string)
|
||||
@lastRelativeAddress = compositeCommand if compositeCommand.isRelativeAddress()
|
||||
compositeCommand.execute(@project, activeEditSession)
|
||||
@@ -1,28 +1,15 @@
|
||||
{View, $$, $$$} = require 'space-pen'
|
||||
CommandInterpreter = require 'command-panel/src/command-interpreter'
|
||||
RegexAddress = require 'command-panel/src/commands/regex-address'
|
||||
CompositeCommand = require 'command-panel/src/commands/composite-command'
|
||||
PreviewList = require 'command-panel/src/preview-list'
|
||||
CommandInterpreter = require './command-interpreter'
|
||||
RegexAddress = require './commands/regex-address'
|
||||
CompositeCommand = require './commands/composite-command'
|
||||
PreviewList = require './preview-list'
|
||||
Editor = require 'editor'
|
||||
{SyntaxError} = require('pegjs').parser
|
||||
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class CommandPanelView extends View
|
||||
@activate: (rootView, state) ->
|
||||
if state?
|
||||
@instance = @deserialize(state, rootView)
|
||||
else
|
||||
@instance = new CommandPanelView(rootView)
|
||||
|
||||
@deserialize: (state, rootView) ->
|
||||
commandPanel = new CommandPanelView(rootView, state.history)
|
||||
commandPanel.attach(state.text, focus: false) if state.visible
|
||||
commandPanel.miniEditor.focus() if state.miniEditorFocused
|
||||
commandPanel
|
||||
|
||||
@content: (rootView) ->
|
||||
@content: ->
|
||||
@div class: 'command-panel tool-panel', =>
|
||||
@div outlet: 'previewCount', class: 'preview-count'
|
||||
@subview 'previewList', new PreviewList(rootView)
|
||||
@@ -36,38 +23,42 @@ class CommandPanelView extends View
|
||||
historyIndex: 0
|
||||
maxSerializedHistorySize: 100
|
||||
|
||||
initialize: (@rootView, @history) ->
|
||||
@commandInterpreter = new CommandInterpreter(@rootView.project)
|
||||
initialize: (state={}) ->
|
||||
@commandInterpreter = new CommandInterpreter(rootView.project)
|
||||
|
||||
@history ?= []
|
||||
@historyIndex = @history.length
|
||||
|
||||
@command 'tool-panel:unfocus', => @rootView.focus()
|
||||
@command 'tool-panel:unfocus', => rootView.focus()
|
||||
@command 'core:close', => @detach(); false
|
||||
@command 'core:confirm', => @execute()
|
||||
@command 'core:move-up', => @navigateBackwardInHistory()
|
||||
@command 'core:move-down', => @navigateForwardInHistory()
|
||||
|
||||
rootView.command 'command-panel:toggle', => @toggle()
|
||||
rootView.command 'command-panel:toggle-preview', => @togglePreview()
|
||||
rootView.command 'command-panel:find-in-file', => @attach('/')
|
||||
rootView.command 'command-panel:find-in-project', => @attach('Xx/')
|
||||
rootView.command 'command-panel:repeat-relative-address', => @repeatRelativeAddress()
|
||||
rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse()
|
||||
rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
|
||||
@previewList.hide()
|
||||
@previewCount.hide()
|
||||
@errorMessages.hide()
|
||||
@prompt.iconSize(@miniEditor.getFontSize())
|
||||
|
||||
@history = state.history ? []
|
||||
@historyIndex = @history.length
|
||||
|
||||
serialize: ->
|
||||
text: @miniEditor.getText()
|
||||
visible: @hasParent()
|
||||
miniEditorFocused: @miniEditor.isFocused
|
||||
history: @history[-@maxSerializedHistorySize..]
|
||||
|
||||
deactivate: -> @destroy()
|
||||
|
||||
destroy: ->
|
||||
@previewList.destroy()
|
||||
|
||||
toggle: ->
|
||||
if @miniEditor.isFocused
|
||||
@detach()
|
||||
@rootView.focus()
|
||||
rootView.focus()
|
||||
else
|
||||
@attach() unless @hasParent()
|
||||
@miniEditor.focus()
|
||||
@@ -77,7 +68,7 @@ class CommandPanelView extends View
|
||||
@previewList.hide()
|
||||
@previewCount.hide()
|
||||
@detach()
|
||||
@rootView.focus()
|
||||
rootView.focus()
|
||||
else
|
||||
@attach() unless @hasParent()
|
||||
if @previewList.hasOperations()
|
||||
@@ -90,13 +81,13 @@ class CommandPanelView extends View
|
||||
@errorMessages.hide()
|
||||
|
||||
focus = options.focus ? true
|
||||
@rootView.vertical.append(this)
|
||||
rootView.vertical.append(this)
|
||||
@miniEditor.focus() if focus
|
||||
@miniEditor.setText(text)
|
||||
@miniEditor.setCursorBufferPosition([0, Infinity])
|
||||
|
||||
detach: ->
|
||||
@rootView.focus()
|
||||
rootView.focus()
|
||||
@previewList.hide()
|
||||
@previewCount.hide()
|
||||
super
|
||||
@@ -108,7 +99,7 @@ class CommandPanelView extends View
|
||||
@errorMessages.empty()
|
||||
|
||||
try
|
||||
@commandInterpreter.eval(command, @rootView.getActiveEditSession()).done ({operationsToPreview, errorMessages}) =>
|
||||
@commandInterpreter.eval(command, rootView.getActiveEditSession()).done ({operationsToPreview, errorMessages}) =>
|
||||
@history.push(command)
|
||||
@historyIndex = @history.length
|
||||
|
||||
@@ -141,12 +132,12 @@ class CommandPanelView extends View
|
||||
@miniEditor.setText(@history[@historyIndex] or '')
|
||||
|
||||
repeatRelativeAddress: ->
|
||||
@commandInterpreter.repeatRelativeAddress(@rootView.getActiveEditSession())
|
||||
@commandInterpreter.repeatRelativeAddress(rootView.getActiveEditSession())
|
||||
|
||||
repeatRelativeAddressInReverse: ->
|
||||
@commandInterpreter.repeatRelativeAddressInReverse(@rootView.getActiveEditSession())
|
||||
@commandInterpreter.repeatRelativeAddressInReverse(rootView.getActiveEditSession())
|
||||
|
||||
setSelectionAsLastRelativeAddress: ->
|
||||
selection = @rootView.getActiveEditor().getSelectedText()
|
||||
selection = rootView.getActiveEditor().getSelectedText()
|
||||
regex = _.escapeRegExp(selection)
|
||||
@commandInterpreter.lastRelativeAddress = new CompositeCommand([new RegexAddress(regex)])
|
||||
17
src/packages/command-panel/lib/command-panel.coffee
Normal file
17
src/packages/command-panel/lib/command-panel.coffee
Normal file
@@ -0,0 +1,17 @@
|
||||
CommandPanelView = require './command-panel-view'
|
||||
|
||||
module.exports =
|
||||
commandPanelView: null
|
||||
|
||||
activate: (@state) ->
|
||||
@commandPanelView = new CommandPanelView(@state)
|
||||
|
||||
deactivate: ->
|
||||
@commandPanelView?.destroy()
|
||||
@commandPanelView = null
|
||||
|
||||
serialize: ->
|
||||
if @commandPanelView?
|
||||
@commandPanelView.serialize()
|
||||
else
|
||||
@state
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
var CompositeCommand = require('command-panel/src/commands/composite-command')
|
||||
var Substitution = require('command-panel/src/commands/substitution');
|
||||
var ZeroAddress = require('command-panel/src/commands/zero-address');
|
||||
var EofAddress = require('command-panel/src/commands/eof-address');
|
||||
var LineAddress = require('command-panel/src/commands/line-address');
|
||||
var AddressRange = require('command-panel/src/commands/address-range');
|
||||
var DefaultAddressRange = require('command-panel/src/commands/default-address-range');
|
||||
var CurrentSelectionAddress = require('command-panel/src/commands/current-selection-address')
|
||||
var RegexAddress = require('command-panel/src/commands/regex-address')
|
||||
var SelectAllMatches = require('command-panel/src/commands/select-all-matches')
|
||||
var SelectAllMatchesInProject = require('command-panel/src/commands/select-all-matches-in-project')
|
||||
var CompositeCommand = require('command-panel/lib/commands/composite-command')
|
||||
var Substitution = require('command-panel/lib/commands/substitution');
|
||||
var ZeroAddress = require('command-panel/lib/commands/zero-address');
|
||||
var EofAddress = require('command-panel/lib/commands/eof-address');
|
||||
var LineAddress = require('command-panel/lib/commands/line-address');
|
||||
var AddressRange = require('command-panel/lib/commands/address-range');
|
||||
var DefaultAddressRange = require('command-panel/lib/commands/default-address-range');
|
||||
var CurrentSelectionAddress = require('command-panel/lib/commands/current-selection-address')
|
||||
var RegexAddress = require('command-panel/lib/commands/regex-address')
|
||||
var SelectAllMatches = require('command-panel/lib/commands/select-all-matches')
|
||||
var SelectAllMatchesInProject = require('command-panel/lib/commands/select-all-matches-in-project')
|
||||
}
|
||||
|
||||
start = _ commands:( selectAllMatchesInProject / textCommand ) {
|
||||
@@ -1,4 +1,4 @@
|
||||
Address = require 'command-panel/src/commands/address'
|
||||
Address = require 'command-panel/lib/commands/address'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
@@ -1,5 +1,5 @@
|
||||
Command = require 'command-panel/src/commands/command'
|
||||
Operation = require 'command-panel/src/operation'
|
||||
Command = require './command'
|
||||
Operation = require 'command-panel/lib/operation'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
@@ -1,5 +1,3 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class Command
|
||||
isAddress: -> false
|
||||
@@ -1,5 +1,4 @@
|
||||
Address = require 'command-panel/src/commands/address'
|
||||
Range = require 'range'
|
||||
Address = require './address'
|
||||
|
||||
module.exports =
|
||||
class CurrentSelectionAddress extends Address
|
||||
@@ -1,5 +1,4 @@
|
||||
Address = require 'command-panel/src/commands/address'
|
||||
Range = require 'range'
|
||||
Address = require './address'
|
||||
|
||||
module.exports =
|
||||
class DefaultAddressRange extends Address
|
||||
@@ -1,4 +1,4 @@
|
||||
Address = require 'command-panel/src/commands/address'
|
||||
Address = require './address'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
@@ -1,4 +1,4 @@
|
||||
Address = require 'command-panel/src/commands/address'
|
||||
Address = require './address'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
@@ -1,4 +1,4 @@
|
||||
Address = require 'command-panel/src/commands/address'
|
||||
Address = require './address'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
@@ -1,5 +1,5 @@
|
||||
Command = require 'command-panel/src/commands/command'
|
||||
Operation = require 'command-panel/src/operation'
|
||||
Command = require './command'
|
||||
Operation = require 'command-panel/lib/operation'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
@@ -1,5 +1,5 @@
|
||||
Command = require 'command-panel/src/commands/command'
|
||||
Operation = require 'command-panel/src/operation'
|
||||
Command = require './command'
|
||||
Operation = require 'command-panel/lib/operation'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
@@ -1,5 +1,5 @@
|
||||
Command = require 'command-panel/src/commands/command'
|
||||
Operation = require 'command-panel/src/operation'
|
||||
Command = require './command'
|
||||
Operation = require 'command-panel/lib/operation'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
@@ -1,4 +1,4 @@
|
||||
Address = require 'command-panel/src/commands/address'
|
||||
Address = require './address'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
@@ -1,5 +1,3 @@
|
||||
{$$$} = require 'space-pen'
|
||||
|
||||
module.exports =
|
||||
class Operation
|
||||
constructor: ({@project, @buffer, bufferRange, @newText, @preserveSelection, @errorMessage}) ->
|
||||
10
src/packages/command-panel/package.cson
Normal file
10
src/packages/command-panel/package.cson
Normal file
@@ -0,0 +1,10 @@
|
||||
'main': 'lib/command-panel'
|
||||
'activationEvents': [
|
||||
'command-panel:toggle'
|
||||
'command-panel:toggle-preview'
|
||||
'command-panel:find-in-file'
|
||||
'command-panel:find-in-project'
|
||||
'command-panel:repeat-relative-address'
|
||||
'command-panel:repeat-relative-address-in-reverse'
|
||||
'command-panel:set-selection-as-regex-address'
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
CommandInterpreter = require 'command-panel/src/command-interpreter'
|
||||
CommandInterpreter = require 'command-panel/lib/command-interpreter'
|
||||
Project = require 'project'
|
||||
Buffer = require 'buffer'
|
||||
EditSession = require 'edit-session'
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
RootView = require 'root-view'
|
||||
CommandPanelView = require 'command-panel/src/command-panel-view'
|
||||
CommandPanelView = require 'command-panel/lib/command-panel-view'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "CommandPanel", ->
|
||||
[rootView, editor, buffer, commandPanel, project, CommandPanel] = []
|
||||
[editor, buffer, commandPanel, project, CommandPanel] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView
|
||||
new RootView
|
||||
rootView.open(require.resolve 'fixtures/sample.js')
|
||||
rootView.enableKeymap()
|
||||
project = rootView.project
|
||||
editor = rootView.getActiveEditor()
|
||||
buffer = editor.activeEditSession.buffer
|
||||
CommandPanel = atom.loadPackage('command-panel')
|
||||
commandPanel = CommandPanel.getInstance()
|
||||
commandPanelMain = atom.loadPackage('command-panel', activateImmediately: true).packageMain
|
||||
commandPanel = commandPanelMain.commandPanelView
|
||||
commandPanel.history = []
|
||||
commandPanel.historyIndex = 0
|
||||
|
||||
@@ -21,7 +21,7 @@ describe "CommandPanel", ->
|
||||
rootView.deactivate()
|
||||
|
||||
describe "serialization", ->
|
||||
it "preserves the command panel's mini-editor text, visibility, focus, and history across reloads", ->
|
||||
it "preserves the command panel's history across reloads", ->
|
||||
rootView.attachToDom()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
@@ -31,29 +31,20 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.historyIndex).toBe(1)
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
commandPanel.miniEditor.insertText 'abc'
|
||||
rootView2 = RootView.deserialize(rootView.serialize())
|
||||
rootView.deactivate()
|
||||
rootView2.attachToDom()
|
||||
|
||||
commandPanel = rootView2.activatePackage('command-panel', CommandPanel).getInstance()
|
||||
expect(rootView2.find('.command-panel')).toExist()
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'abc'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
RootView.deserialize(rootViewState).attachToDom()
|
||||
atom.loadPackage('command-panel')
|
||||
|
||||
expect(rootView.find('.command-panel')).not.toExist()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(rootView.find('.command-panel')).toExist()
|
||||
commandPanel = rootView.find('.command-panel').view()
|
||||
expect(commandPanel.history.length).toBe(1)
|
||||
expect(commandPanel.history[0]).toBe('/.')
|
||||
expect(commandPanel.historyIndex).toBe(1)
|
||||
|
||||
rootView2.focus()
|
||||
expect(commandPanel.miniEditor.isFocused).toBeFalsy()
|
||||
rootView3 = RootView.deserialize(rootView2.serialize())
|
||||
rootView2.deactivate()
|
||||
rootView3.attachToDom()
|
||||
commandPanel = rootView3.activatePackage('command-panel', CommandPanel).getInstance()
|
||||
|
||||
expect(commandPanel.miniEditor.isFocused).toBeFalsy()
|
||||
rootView3.deactivate()
|
||||
|
||||
it "only retains the configured max serialized history size", ->
|
||||
rootView.attachToDom()
|
||||
|
||||
@@ -67,18 +58,18 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.history[2]).toBe('/test3')
|
||||
expect(commandPanel.historyIndex).toBe(3)
|
||||
|
||||
rootView2 = RootView.deserialize(rootView.serialize())
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
rootView2.attachToDom()
|
||||
RootView.deserialize(rootViewState).attachToDom()
|
||||
atom.loadPackage('command-panel')
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
|
||||
commandPanel = rootView2.activatePackage('command-panel', CommandPanel).getInstance()
|
||||
commandPanel = rootView.find('.command-panel').view()
|
||||
expect(commandPanel.history.length).toBe(2)
|
||||
expect(commandPanel.history[0]).toBe('/test2')
|
||||
expect(commandPanel.history[1]).toBe('/test3')
|
||||
expect(commandPanel.historyIndex).toBe(2)
|
||||
|
||||
rootView2.deactivate()
|
||||
|
||||
describe "when core:close is triggered on the command panel", ->
|
||||
it "detaches the command panel, focuses the RootView and does not bubble the core:close event", ->
|
||||
commandPanel.attach()
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
Stats = require './src/stats'
|
||||
|
||||
module.exports =
|
||||
class EditorStats extends DeferredAtomPackage
|
||||
loadEvents: ['editor-stats:toggle']
|
||||
instanceClass: 'editor-stats/src/editor-stats-view'
|
||||
stats: new Stats
|
||||
|
||||
activate: (rootView) ->
|
||||
super
|
||||
|
||||
rootView.on 'keydown', => @stats.track()
|
||||
rootView.on 'mouseup', => @stats.track()
|
||||
|
||||
onLoadEvent: (event, instance) -> instance.toggle(@stats)
|
||||
@@ -5,10 +5,10 @@ $ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class EditorStatsView extends ScrollView
|
||||
@activate: (rootView, state) ->
|
||||
@instance = new EditorStatsView(rootView)
|
||||
@activate: ->
|
||||
new EditorStatsView
|
||||
|
||||
@content: (rootView) ->
|
||||
@content: ->
|
||||
@div class: 'editor-stats-wrapper', tabindex: -1, =>
|
||||
@div class: 'editor-stats', outlet: 'editorStats'
|
||||
|
||||
@@ -17,7 +17,7 @@ class EditorStatsView extends ScrollView
|
||||
pb: 3
|
||||
pr: 25
|
||||
|
||||
initialize: (@rootView) ->
|
||||
initialize: ->
|
||||
super
|
||||
|
||||
resizer = =>
|
||||
@@ -30,7 +30,7 @@ class EditorStatsView extends ScrollView
|
||||
@editorStats.empty()
|
||||
@x ?= d3.scale.ordinal().domain d3.range(@stats.hours * 60)
|
||||
@y ?= d3.scale.linear()
|
||||
w = @rootView.vertical.width()
|
||||
w = rootView.vertical.width()
|
||||
h = @height()
|
||||
data = d3.entries @stats.eventLog
|
||||
max = d3.max data, (d) -> d.value
|
||||
@@ -94,10 +94,10 @@ class EditorStatsView extends ScrollView
|
||||
@attach()
|
||||
|
||||
attach: ->
|
||||
@rootView.vertical.append(@)
|
||||
rootView.vertical.append(this)
|
||||
@draw()
|
||||
|
||||
detach: ->
|
||||
super()
|
||||
super
|
||||
clearInterval(@updateInterval)
|
||||
@rootView.focus()
|
||||
rootView.focus()
|
||||
19
src/packages/editor-stats/lib/editor-stats.coffee
Normal file
19
src/packages/editor-stats/lib/editor-stats.coffee
Normal file
@@ -0,0 +1,19 @@
|
||||
StatsTracker = require './stats-tracker'
|
||||
|
||||
module.exports =
|
||||
stats: null
|
||||
editorStatsView: null
|
||||
|
||||
activate: ->
|
||||
@stats = new StatsTracker()
|
||||
rootView.command 'editor-stats:toggle', => @createView().toggle(@stats)
|
||||
|
||||
deactivate: ->
|
||||
@editorStatsView = null
|
||||
@stats = null
|
||||
|
||||
createView: ->
|
||||
unless @editorStatsView
|
||||
EditorStatsView = require 'editor-stats/lib/editor-stats-view'
|
||||
@editorStatsView = new EditorStatsView()
|
||||
@editorStatsView
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports =
|
||||
class Stats
|
||||
class StatsTracker
|
||||
startDate: new Date
|
||||
hours: 6
|
||||
eventLog: []
|
||||
@@ -12,6 +12,9 @@ class Stats
|
||||
while date < future
|
||||
@eventLog[@time(date)] = 0
|
||||
|
||||
rootView.on 'keydown', => @track()
|
||||
rootView.on 'mouseup', => @track()
|
||||
|
||||
clear: ->
|
||||
@eventLog = []
|
||||
|
||||
1
src/packages/editor-stats/package.cson
Normal file
1
src/packages/editor-stats/package.cson
Normal file
@@ -0,0 +1 @@
|
||||
'main': 'lib/editor-stats'
|
||||
@@ -1,9 +1,9 @@
|
||||
$ = require 'jquery'
|
||||
RootView = require 'root-view'
|
||||
EditorStats = require 'editor-stats/src/editor-stats-view'
|
||||
EditorStats = require 'editor-stats/lib/editor-stats-view'
|
||||
|
||||
describe "EditorStats", ->
|
||||
[rootView, editorStats, time] = []
|
||||
[editorStats, time] = []
|
||||
|
||||
simulateKeyUp = (key) ->
|
||||
e = $.Event "keydown", keyCode: key.charCodeAt(0)
|
||||
@@ -23,10 +23,7 @@ describe "EditorStats", ->
|
||||
mins = if mins == 60 then '01' else mins + 1
|
||||
time = "#{hours}:#{mins}"
|
||||
|
||||
editorStatsPackage = atom.loadPackage('editor-stats')
|
||||
editorStatsPackage.getInstance()
|
||||
editorStats = editorStatsPackage.stats
|
||||
editorStats.clear()
|
||||
editorStats = atom.loadPackage('editor-stats').packageMain.stats
|
||||
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
|
||||
32
src/packages/editor-stats/src/stats-tracker.coffee
Normal file
32
src/packages/editor-stats/src/stats-tracker.coffee
Normal file
@@ -0,0 +1,32 @@
|
||||
module.exports =
|
||||
class StatsTracker
|
||||
startDate: new Date
|
||||
hours: 6
|
||||
eventLog: []
|
||||
|
||||
constructor: ->
|
||||
date = new Date(@startDate)
|
||||
future = new Date(date.getTime() + (36e5 * @hours))
|
||||
@eventLog[@time(date)] = 0
|
||||
|
||||
while date < future
|
||||
@eventLog[@time(date)] = 0
|
||||
|
||||
rootView.on 'keydown', => @track()
|
||||
rootView.on 'mouseup', => @track()
|
||||
|
||||
clear: ->
|
||||
@eventLog = []
|
||||
|
||||
track: ->
|
||||
date = new Date
|
||||
times = @time date
|
||||
@eventLog[times] ?= 0
|
||||
@eventLog[times] += 1
|
||||
@eventLog.shift() if @eventLog.length > (@hours * 60)
|
||||
|
||||
time: (date) ->
|
||||
date.setTime(date.getTime() + 6e4)
|
||||
hour = date.getHours()
|
||||
minute = date.getMinutes()
|
||||
"#{hour}:#{minute}"
|
||||
@@ -1,32 +0,0 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
|
||||
module.exports =
|
||||
class FuzzyFinder extends DeferredAtomPackage
|
||||
loadEvents: [
|
||||
'fuzzy-finder:toggle-file-finder'
|
||||
'fuzzy-finder:toggle-buffer-finder'
|
||||
'fuzzy-finder:find-under-cursor'
|
||||
]
|
||||
|
||||
instanceClass: 'fuzzy-finder/src/fuzzy-finder-view'
|
||||
|
||||
activate: (rootView) ->
|
||||
super
|
||||
|
||||
if rootView.project.getPath()?
|
||||
callback = (paths) => @projectPaths = paths
|
||||
LoadPathsTask = require 'fuzzy-finder/src/load-paths-task'
|
||||
new LoadPathsTask(rootView, callback).start()
|
||||
|
||||
onLoadEvent: (event, instance) ->
|
||||
if @projectPaths? and not instance.projectPaths?
|
||||
instance.projectPaths = @projectPaths
|
||||
instance.reloadProjectPaths = false
|
||||
|
||||
switch event.type
|
||||
when 'fuzzy-finder:toggle-file-finder'
|
||||
instance.toggleFileFinder()
|
||||
when 'fuzzy-finder:toggle-buffer-finder'
|
||||
instance.toggleBufferFinder()
|
||||
when 'fuzzy-finder:find-under-cursor'
|
||||
instance.findUnderCursor()
|
||||
@@ -3,15 +3,12 @@ SelectList = require 'select-list'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
fs = require 'fs'
|
||||
LoadPathsTask = require 'fuzzy-finder/src/load-paths-task'
|
||||
LoadPathsTask = require './load-paths-task'
|
||||
|
||||
module.exports =
|
||||
class FuzzyFinderView extends SelectList
|
||||
filenameRegex: /[\w\.\-\/\\]+/
|
||||
|
||||
@activate: (rootView) ->
|
||||
@instance = new FuzzyFinderView(rootView)
|
||||
|
||||
@viewClass: ->
|
||||
[super, 'fuzzy-finder', 'overlay', 'from-top'].join(' ')
|
||||
|
||||
@@ -20,7 +17,7 @@ class FuzzyFinderView extends SelectList
|
||||
projectPaths: null
|
||||
reloadProjectPaths: true
|
||||
|
||||
initialize: (@rootView) ->
|
||||
initialize: ->
|
||||
super
|
||||
|
||||
@subscribe $(window), 'focus', => @reloadProjectPaths = true
|
||||
@@ -54,15 +51,15 @@ class FuzzyFinderView extends SelectList
|
||||
@span " - #{folder}/", class: 'directory'
|
||||
|
||||
openPath: (path) ->
|
||||
@rootView.open(path, {@allowActiveEditorChange}) if path
|
||||
rootView.open(path, {@allowActiveEditorChange}) if path
|
||||
|
||||
splitOpenPath: (fn) ->
|
||||
path = @getSelectedElement()
|
||||
return unless path
|
||||
|
||||
editor = @rootView.getActiveEditor()
|
||||
editor = rootView.getActiveEditor()
|
||||
if editor
|
||||
fn(editor, @rootView.project.buildEditSessionForPath(path))
|
||||
fn(editor, rootView.project.buildEditSessionForPath(path))
|
||||
else
|
||||
@openPath(path)
|
||||
|
||||
@@ -79,7 +76,7 @@ class FuzzyFinderView extends SelectList
|
||||
if @hasParent()
|
||||
@cancel()
|
||||
else
|
||||
return unless @rootView.project.getPath()?
|
||||
return unless rootView.project.getPath()?
|
||||
@allowActiveEditorChange = false
|
||||
@populateProjectPaths()
|
||||
@attach()
|
||||
@@ -96,9 +93,9 @@ class FuzzyFinderView extends SelectList
|
||||
if @hasParent()
|
||||
@cancel()
|
||||
else
|
||||
return unless @rootView.project.getPath()?
|
||||
return unless rootView.project.getPath()?
|
||||
@allowActiveEditorChange = false
|
||||
editor = @rootView.getActiveEditor()
|
||||
editor = rootView.getActiveEditor()
|
||||
currentWord = editor.getWordUnderCursor(wordRegex: @filenameRegex)
|
||||
|
||||
if currentWord.length == 0
|
||||
@@ -110,7 +107,7 @@ class FuzzyFinderView extends SelectList
|
||||
@attach()
|
||||
@setError("No files match '#{currentWord}'")
|
||||
else if paths.length == 1
|
||||
@rootView.open(paths[0])
|
||||
rootView.open(paths[0])
|
||||
else
|
||||
@attach()
|
||||
@miniEditor.setText(currentWord)
|
||||
@@ -142,16 +139,21 @@ class FuzzyFinderView extends SelectList
|
||||
|
||||
@setArray(listedItems)
|
||||
options.done(listedItems) if options.done?
|
||||
@loadPathsTask = new LoadPathsTask(@rootView, callback)
|
||||
@loadPathsTask = new LoadPathsTask(callback)
|
||||
@loadPathsTask.start()
|
||||
|
||||
populateOpenBufferPaths: ->
|
||||
@paths = @rootView.getOpenBufferPaths().map (path) =>
|
||||
@rootView.project.relativize(path)
|
||||
@paths = rootView.getOpenBufferPaths().map (path) =>
|
||||
rootView.project.relativize(path)
|
||||
@setArray(@paths)
|
||||
|
||||
detach: ->
|
||||
super
|
||||
|
||||
@loadPathsTask?.terminate()
|
||||
|
||||
attach: ->
|
||||
super
|
||||
|
||||
@rootView.append(this)
|
||||
rootView.append(this)
|
||||
@miniEditor.focus()
|
||||
32
src/packages/fuzzy-finder/lib/fuzzy-finder.coffee
Normal file
32
src/packages/fuzzy-finder/lib/fuzzy-finder.coffee
Normal file
@@ -0,0 +1,32 @@
|
||||
module.exports =
|
||||
projectPaths: null
|
||||
fuzzyFinderView: null
|
||||
|
||||
activate: ->
|
||||
rootView.command 'fuzzy-finder:toggle-file-finder', =>
|
||||
@createView().toggleFileFinder()
|
||||
rootView.command 'fuzzy-finder:toggle-buffer-finder', =>
|
||||
@createView().toggleBufferFinder()
|
||||
rootView.command 'fuzzy-finder:find-under-cursor', =>
|
||||
@createView().findUnderCursor()
|
||||
|
||||
if rootView.project.getPath()?
|
||||
LoadPathsTask = require 'fuzzy-finder/lib/load-paths-task'
|
||||
@loadPathsTask = new LoadPathsTask((paths) => @projectPaths = paths)
|
||||
@loadPathsTask.start()
|
||||
|
||||
deactivate: ->
|
||||
@loadPathsTask?.terminate()
|
||||
@fuzzyFinderView?.cancel()
|
||||
@fuzzyFinderView = null
|
||||
@projectPaths = null
|
||||
@fuzzyFinderView = null
|
||||
|
||||
createView: ->
|
||||
unless @fuzzyFinderView
|
||||
FuzzyFinderView = require 'fuzzy-finder/lib/fuzzy-finder-view'
|
||||
@fuzzyFinderView = new FuzzyFinderView()
|
||||
if @projectPaths? and not @fuzzyFinderView.projectPaths?
|
||||
@fuzzyFinderView.projectPaths = @projectPaths
|
||||
@fuzzyFinderView.reloadProjectPaths = false
|
||||
@fuzzyFinderView
|
||||
@@ -1,11 +1,13 @@
|
||||
fs = require 'fs'
|
||||
_ = require 'underscore'
|
||||
Git = require 'git'
|
||||
|
||||
module.exports =
|
||||
loadPaths: (rootPath, ignoredNames, excludeGitIgnoredPaths) ->
|
||||
if excludeGitIgnoredPaths
|
||||
Git = require 'git'
|
||||
repo = Git.open(rootPath, refreshIndexOnFocus: false)
|
||||
|
||||
paths = []
|
||||
repo = Git.open(rootPath, refreshIndexOnFocus: false) if excludeGitIgnoredPaths
|
||||
isIgnored = (path) ->
|
||||
for segment in path.split('/')
|
||||
return true if _.contains(ignoredNames, segment)
|
||||
@@ -15,5 +17,7 @@ module.exports =
|
||||
onDirectory = (path) ->
|
||||
not isIgnored(path)
|
||||
fs.traverseTree(rootPath, onFile, onDirectory)
|
||||
|
||||
repo?.destroy()
|
||||
|
||||
callTaskMethod('pathsLoaded', paths)
|
||||
@@ -2,14 +2,14 @@ Task = require 'task'
|
||||
|
||||
module.exports =
|
||||
class LoadPathsTask extends Task
|
||||
constructor: (@rootView, @callback)->
|
||||
super('fuzzy-finder/src/load-paths-handler')
|
||||
constructor: (@callback) ->
|
||||
super('fuzzy-finder/lib/load-paths-handler')
|
||||
|
||||
started: ->
|
||||
ignoredNames = config.get('fuzzyFinder.ignoredNames') ? []
|
||||
ignoredNames = ignoredNames.concat(config.get('core.ignoredNames') ? [])
|
||||
excludeGitIgnoredPaths = config.get('core.hideGitIgnoredFiles')
|
||||
rootPath = @rootView.project.getPath()
|
||||
rootPath = rootView.project.getPath()
|
||||
@callWorkerMethod('loadPaths', rootPath, ignoredNames, excludeGitIgnoredPaths)
|
||||
|
||||
pathsLoaded: (paths) ->
|
||||
1
src/packages/fuzzy-finder/package.cson
Normal file
1
src/packages/fuzzy-finder/package.cson
Normal file
@@ -0,0 +1 @@
|
||||
'main': 'lib/fuzzy-finder'
|
||||
@@ -1,21 +1,20 @@
|
||||
RootView = require 'root-view'
|
||||
FuzzyFinder = require 'fuzzy-finder/src/fuzzy-finder-view'
|
||||
LoadPathsTask = require 'fuzzy-finder/src/load-paths-task'
|
||||
FuzzyFinder = require 'fuzzy-finder/lib/fuzzy-finder-view'
|
||||
LoadPathsTask = require 'fuzzy-finder/lib/load-paths-task'
|
||||
$ = require 'jquery'
|
||||
{$$} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
|
||||
describe 'FuzzyFinder', ->
|
||||
[rootView, finder] = []
|
||||
[finderView] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
rootView.enableKeymap()
|
||||
atom.loadPackage("fuzzy-finder").getInstance()
|
||||
finder = FuzzyFinder.instance
|
||||
finderView = atom.loadPackage("fuzzy-finder").packageMain.createView()
|
||||
|
||||
afterEach ->
|
||||
rootView.remove()
|
||||
rootView.deactivate()
|
||||
|
||||
describe "file-finder behavior", ->
|
||||
describe "toggling", ->
|
||||
@@ -26,12 +25,13 @@ describe 'FuzzyFinder', ->
|
||||
rootView.find('.editor').trigger 'editor:split-right'
|
||||
[editor1, editor2] = rootView.find('.editor').map -> $(this).view()
|
||||
|
||||
expect(rootView.find('.fuzzy-finder')).not.toExist()
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
expect(rootView.find('.fuzzy-finder')).toExist()
|
||||
expect(finder.miniEditor.isFocused).toBeTruthy()
|
||||
expect(finderView.miniEditor.isFocused).toBeTruthy()
|
||||
expect(editor1.isFocused).toBeFalsy()
|
||||
expect(editor2.isFocused).toBeFalsy()
|
||||
finder.miniEditor.insertText('this should not show up next time we toggle')
|
||||
finderView.miniEditor.insertText('this should not show up next time we toggle')
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
expect(editor1.isFocused).toBeFalsy()
|
||||
@@ -39,27 +39,27 @@ describe 'FuzzyFinder', ->
|
||||
expect(rootView.find('.fuzzy-finder')).not.toExist()
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
expect(finder.miniEditor.getText()).toBe ''
|
||||
expect(finderView.miniEditor.getText()).toBe ''
|
||||
|
||||
it "shows all relative file paths for the current project and selects the first", ->
|
||||
rootView.attachToDom()
|
||||
finder.maxItems = Infinity
|
||||
finderView.maxItems = Infinity
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
paths = null
|
||||
expect(finder.find(".loading")).toBeVisible()
|
||||
expect(finder.find(".loading")).toHaveText "Indexing..."
|
||||
expect(finderView.find(".loading")).toBeVisible()
|
||||
expect(finderView.find(".loading")).toHaveText "Indexing..."
|
||||
|
||||
waitsFor "all project paths to load", 5000, ->
|
||||
if finder.projectPaths?.length > 0
|
||||
paths = finder.projectPaths
|
||||
if finderView.projectPaths?.length > 0
|
||||
paths = finderView.projectPaths
|
||||
true
|
||||
|
||||
runs ->
|
||||
expect(finder.list.children('li').length).toBe paths.length
|
||||
expect(finderView.list.children('li').length).toBe paths.length
|
||||
for path in paths
|
||||
expect(finder.list.find("li:contains(#{fs.base(path)})")).toExist()
|
||||
expect(finder.list.children().first()).toHaveClass 'selected'
|
||||
expect(finder.find(".loading")).not.toBeVisible()
|
||||
expect(finderView.list.find("li:contains(#{fs.base(path)})")).toExist()
|
||||
expect(finderView.list.children().first()).toHaveClass 'selected'
|
||||
expect(finderView.find(".loading")).not.toBeVisible()
|
||||
|
||||
describe "when root view's project has no path", ->
|
||||
beforeEach ->
|
||||
@@ -78,10 +78,10 @@ describe 'FuzzyFinder', ->
|
||||
expect(rootView.getActiveEditor()).toBe editor2
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
|
||||
finder.confirmed('dir/a')
|
||||
finderView.confirmed('dir/a')
|
||||
expectedPath = fixturesProject.resolve('dir/a')
|
||||
|
||||
expect(finder.hasParent()).toBeFalsy()
|
||||
expect(finderView.hasParent()).toBeFalsy()
|
||||
expect(editor1.getPath()).not.toBe expectedPath
|
||||
expect(editor2.getPath()).toBe expectedPath
|
||||
expect(editor2.isFocused).toBeTruthy()
|
||||
@@ -91,12 +91,12 @@ describe 'FuzzyFinder', ->
|
||||
rootView.attachToDom()
|
||||
path = rootView.getActiveEditor().getPath()
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
finder.confirmed('dir/this/is/not/a/file.txt')
|
||||
expect(finder.hasParent()).toBeTruthy()
|
||||
finderView.confirmed('dir/this/is/not/a/file.txt')
|
||||
expect(finderView.hasParent()).toBeTruthy()
|
||||
expect(rootView.getActiveEditor().getPath()).toBe path
|
||||
expect(finder.find('.error').text().length).toBeGreaterThan 0
|
||||
expect(finderView.find('.error').text().length).toBeGreaterThan 0
|
||||
advanceClock(2000)
|
||||
expect(finder.find('.error').text().length).toBe 0
|
||||
expect(finderView.find('.error').text().length).toBe 0
|
||||
|
||||
describe "buffer-finder behavior", ->
|
||||
describe "toggling", ->
|
||||
@@ -113,7 +113,7 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(rootView.find('.fuzzy-finder')).toExist()
|
||||
expect(rootView.find('.fuzzy-finder input:focus')).toExist()
|
||||
finder.miniEditor.insertText('this should not show up next time we toggle')
|
||||
finderView.miniEditor.insertText('this should not show up next time we toggle')
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(editor1.isFocused).toBeFalsy()
|
||||
@@ -121,14 +121,14 @@ describe 'FuzzyFinder', ->
|
||||
expect(rootView.find('.fuzzy-finder')).not.toExist()
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(finder.miniEditor.getText()).toBe ''
|
||||
expect(finderView.miniEditor.getText()).toBe ''
|
||||
|
||||
it "lists the paths of the current open buffers", ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(finder.list.children('li').length).toBe 2
|
||||
expect(finder.list.find("li:contains(sample.js)")).toExist()
|
||||
expect(finder.list.find("li:contains(sample.txt)")).toExist()
|
||||
expect(finder.list.children().first()).toHaveClass 'selected'
|
||||
expect(finderView.list.children('li').length).toBe 2
|
||||
expect(finderView.list.find("li:contains(sample.js)")).toExist()
|
||||
expect(finderView.list.find("li:contains(sample.txt)")).toExist()
|
||||
expect(finderView.list.children().first()).toHaveClass 'selected'
|
||||
|
||||
describe "when the active editor only contains edit sessions for anonymous buffers", ->
|
||||
it "does not open", ->
|
||||
@@ -162,9 +162,9 @@ describe 'FuzzyFinder', ->
|
||||
describe "when there is an edit session for the confirmed path in the active editor", ->
|
||||
it "switches the active editor to the edit session for the selected path", ->
|
||||
expectedPath = fixturesProject.resolve('sample.txt')
|
||||
finder.confirmed('sample.txt')
|
||||
finderView.confirmed('sample.txt')
|
||||
|
||||
expect(finder.hasParent()).toBeFalsy()
|
||||
expect(finderView.hasParent()).toBeFalsy()
|
||||
expect(editor1.getPath()).not.toBe expectedPath
|
||||
expect(editor2.getPath()).toBe expectedPath
|
||||
expect(editor2.isFocused).toBeTruthy()
|
||||
@@ -178,9 +178,9 @@ describe 'FuzzyFinder', ->
|
||||
expect(rootView.getActiveEditor()).toBe editor1
|
||||
|
||||
expectedPath = fixturesProject.resolve('sample.txt')
|
||||
finder.confirmed('sample.txt')
|
||||
finderView.confirmed('sample.txt')
|
||||
|
||||
expect(finder.hasParent()).toBeFalsy()
|
||||
expect(finderView.hasParent()).toBeFalsy()
|
||||
expect(editor1.getPath()).not.toBe expectedPath
|
||||
expect(editor2.getPath()).toBe expectedPath
|
||||
expect(editor2.isFocused).toBeTruthy()
|
||||
@@ -194,31 +194,31 @@ describe 'FuzzyFinder', ->
|
||||
activeEditor.focus()
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
expect(finder.hasParent()).toBeTruthy()
|
||||
expect(finderView.hasParent()).toBeTruthy()
|
||||
expect(activeEditor.isFocused).toBeFalsy()
|
||||
expect(finder.miniEditor.isFocused).toBeTruthy()
|
||||
expect(finderView.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
finder.cancel()
|
||||
finderView.cancel()
|
||||
|
||||
expect(finder.hasParent()).toBeFalsy()
|
||||
expect(finderView.hasParent()).toBeFalsy()
|
||||
expect(activeEditor.isFocused).toBeTruthy()
|
||||
expect(finder.miniEditor.isFocused).toBeFalsy()
|
||||
expect(finderView.miniEditor.isFocused).toBeFalsy()
|
||||
|
||||
describe "when no editors are open", ->
|
||||
it "detaches the finder and surrenders focus to the body", ->
|
||||
it "detaches the finder and focuses the previously focused element", ->
|
||||
rootView.attachToDom()
|
||||
rootView.getActiveEditor().destroyActiveEditSession()
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
expect(finder.hasParent()).toBeTruthy()
|
||||
expect(finderView.hasParent()).toBeTruthy()
|
||||
expect(rootView.isFocused).toBeFalsy()
|
||||
expect(finder.miniEditor.isFocused).toBeTruthy()
|
||||
expect(finderView.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
finder.cancel()
|
||||
finderView.cancel()
|
||||
|
||||
expect(finder.hasParent()).toBeFalsy()
|
||||
expect(document.activeElement).toBe $('body')[0]
|
||||
expect(finder.miniEditor.isFocused).toBeFalsy()
|
||||
expect(finderView.hasParent()).toBeFalsy()
|
||||
expect($(document.activeElement).view()).toBe rootView
|
||||
expect(finderView.miniEditor.isFocused).toBeFalsy()
|
||||
|
||||
describe "cached file paths", ->
|
||||
it "caches file paths after first time", ->
|
||||
@@ -226,26 +226,26 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
|
||||
waitsFor ->
|
||||
finder.list.children('li').length > 0
|
||||
finderView.list.children('li').length > 0
|
||||
|
||||
runs ->
|
||||
expect(finder.loadPathsTask.start).toHaveBeenCalled()
|
||||
finder.loadPathsTask.start.reset()
|
||||
expect(finderView.loadPathsTask.start).toHaveBeenCalled()
|
||||
finderView.loadPathsTask.start.reset()
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
|
||||
waitsFor ->
|
||||
finder.list.children('li').length > 0
|
||||
finderView.list.children('li').length > 0
|
||||
|
||||
runs ->
|
||||
expect(finder.loadPathsTask.start).not.toHaveBeenCalled()
|
||||
expect(finderView.loadPathsTask.start).not.toHaveBeenCalled()
|
||||
|
||||
it "doesn't cache buffer paths", ->
|
||||
spyOn(rootView, "getOpenBufferPaths").andCallThrough()
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
|
||||
waitsFor ->
|
||||
finder.list.children('li').length > 0
|
||||
finderView.list.children('li').length > 0
|
||||
|
||||
runs ->
|
||||
expect(rootView.getOpenBufferPaths).toHaveBeenCalled()
|
||||
@@ -254,7 +254,7 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
|
||||
waitsFor ->
|
||||
finder.list.children('li').length > 0
|
||||
finderView.list.children('li').length > 0
|
||||
|
||||
runs ->
|
||||
expect(rootView.getOpenBufferPaths).toHaveBeenCalled()
|
||||
@@ -264,27 +264,27 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
|
||||
waitsFor ->
|
||||
finder.list.children('li').length > 0
|
||||
finderView.list.children('li').length > 0
|
||||
|
||||
runs ->
|
||||
expect(finder.loadPathsTask.start).toHaveBeenCalled()
|
||||
finder.loadPathsTask.start.reset()
|
||||
expect(finderView.loadPathsTask.start).toHaveBeenCalled()
|
||||
finderView.loadPathsTask.start.reset()
|
||||
$(window).trigger 'focus'
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
expect(finder.loadPathsTask.start).toHaveBeenCalled()
|
||||
expect(finderView.loadPathsTask.start).toHaveBeenCalled()
|
||||
|
||||
describe "path ignoring", ->
|
||||
it "ignores paths that match entries in config.fuzzyFinder.ignoredNames", ->
|
||||
config.set("fuzzyFinder.ignoredNames", ["tree-view.js"])
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
finder.maxItems = Infinity
|
||||
finderView.maxItems = Infinity
|
||||
|
||||
waitsFor ->
|
||||
finder.list.children('li').length > 0
|
||||
finderView.list.children('li').length > 0
|
||||
|
||||
runs ->
|
||||
expect(finder.list.find("li:contains(tree-view.js)")).not.toExist()
|
||||
expect(finderView.list.find("li:contains(tree-view.js)")).not.toExist()
|
||||
|
||||
describe "fuzzy find by content under cursor", ->
|
||||
editor = null
|
||||
@@ -298,10 +298,10 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:find-under-cursor'
|
||||
|
||||
waitsFor ->
|
||||
finder.list.children('li').length > 0
|
||||
finderView.list.children('li').length > 0
|
||||
|
||||
runs ->
|
||||
expect(finder).toBeVisible()
|
||||
expect(finderView).toBeVisible()
|
||||
expect(rootView.find('.fuzzy-finder input:focus')).toExist()
|
||||
|
||||
it "opens a file directly when there is a single match", ->
|
||||
@@ -316,7 +316,7 @@ describe 'FuzzyFinder', ->
|
||||
openedPath != null
|
||||
|
||||
runs ->
|
||||
expect(finder).not.toBeVisible()
|
||||
expect(finderView).not.toBeVisible()
|
||||
expect(openedPath).toBe "sample.txt"
|
||||
|
||||
it "displays error when the word under the cursor doesn't match any files", ->
|
||||
@@ -326,10 +326,10 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:find-under-cursor'
|
||||
|
||||
waitsFor ->
|
||||
finder.is(':visible')
|
||||
finderView.is(':visible')
|
||||
|
||||
runs ->
|
||||
expect(finder.find('.error').text().length).toBeGreaterThan 0
|
||||
expect(finderView.find('.error').text().length).toBeGreaterThan 0
|
||||
|
||||
it "displays error when there is no word under the cursor", ->
|
||||
editor.setText("&&&&&&&&&&&&&&& sample")
|
||||
@@ -338,10 +338,10 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:find-under-cursor'
|
||||
|
||||
waitsFor ->
|
||||
finder.is(':visible')
|
||||
finderView.is(':visible')
|
||||
|
||||
runs ->
|
||||
expect(finder.find('.error').text().length).toBeGreaterThan 0
|
||||
expect(finderView.find('.error').text().length).toBeGreaterThan 0
|
||||
|
||||
|
||||
describe "opening a path into a split", ->
|
||||
@@ -354,7 +354,7 @@ describe 'FuzzyFinder', ->
|
||||
spyOn(editor, "splitLeft").andCallThrough()
|
||||
expect(rootView.find('.editor').length).toBe 1
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
finder.miniEditor.trigger 'editor:split-left'
|
||||
finderView.miniEditor.trigger 'editor:split-left'
|
||||
expect(rootView.find('.editor').length).toBe 2
|
||||
expect(editor.splitLeft).toHaveBeenCalled()
|
||||
expect(rootView.getActiveEditor()).not.toBe editor
|
||||
@@ -365,7 +365,7 @@ describe 'FuzzyFinder', ->
|
||||
spyOn(editor, "splitRight").andCallThrough()
|
||||
expect(rootView.find('.editor').length).toBe 1
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
finder.miniEditor.trigger 'editor:split-right'
|
||||
finderView.miniEditor.trigger 'editor:split-right'
|
||||
expect(rootView.find('.editor').length).toBe 2
|
||||
expect(editor.splitRight).toHaveBeenCalled()
|
||||
expect(rootView.getActiveEditor()).not.toBe editor
|
||||
@@ -376,7 +376,7 @@ describe 'FuzzyFinder', ->
|
||||
spyOn(editor, "splitDown").andCallThrough()
|
||||
expect(rootView.find('.editor').length).toBe 1
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
finder.miniEditor.trigger 'editor:split-down'
|
||||
finderView.miniEditor.trigger 'editor:split-down'
|
||||
expect(rootView.find('.editor').length).toBe 2
|
||||
expect(editor.splitDown).toHaveBeenCalled()
|
||||
expect(rootView.getActiveEditor()).not.toBe editor
|
||||
@@ -387,8 +387,8 @@ describe 'FuzzyFinder', ->
|
||||
spyOn(editor, "splitUp").andCallThrough()
|
||||
expect(rootView.find('.editor').length).toBe 1
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
finder.miniEditor.trigger 'editor:split-up'
|
||||
finderView.miniEditor.trigger 'editor:split-up'
|
||||
expect(rootView.find('.editor').length).toBe 2
|
||||
expect(editor.splitUp).toHaveBeenCalled()
|
||||
expect(rootView.getActiveEditor()).not.toBe editor
|
||||
expect(rootView.getActiveEditor().getPath()).toBe editor.getPath()
|
||||
expect(rootView.getActiveEditor().getPath()).toBe editor.getPath()
|
||||
62
src/packages/gfm.tmbundle/Syntaxes/gfm.cson
Normal file
62
src/packages/gfm.tmbundle/Syntaxes/gfm.cson
Normal file
@@ -0,0 +1,62 @@
|
||||
'name': 'GitHub Markdown'
|
||||
'scopeName': 'source.gfm'
|
||||
'fileTypes': [
|
||||
'markdown'
|
||||
'md'
|
||||
'mkd'
|
||||
'mkdown'
|
||||
'ron'
|
||||
]
|
||||
'patterns': [
|
||||
{
|
||||
'match': '\\*\\*[^\\*]+\\*\\*'
|
||||
'name': 'markup.bold.gfm'
|
||||
}
|
||||
{
|
||||
'match': '__[^_]+__'
|
||||
'name': 'markup.bold.gfm'
|
||||
}
|
||||
{
|
||||
'match': '\\*[^\\*]+\\*'
|
||||
'name': 'markup.italic.gfm'
|
||||
}
|
||||
{
|
||||
'match': '_[^_]+_'
|
||||
'name': 'markup.italic.gfm'
|
||||
}
|
||||
{
|
||||
'match': '^#{1,6}\\s+.+$'
|
||||
'name': 'markup.heading.gfm'
|
||||
}
|
||||
{
|
||||
'match': '\\:[^\\:]+\\:'
|
||||
'name': 'variable.emoji.gfm'
|
||||
}
|
||||
{
|
||||
'begin': '^```.*$'
|
||||
'beginCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'end': '^```$'
|
||||
'endCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'patterns': [
|
||||
'match': '.*'
|
||||
'name': 'markup.raw.gfm'
|
||||
]
|
||||
}
|
||||
{
|
||||
'match': '`[^`]+`'
|
||||
'name': 'markup.raw.gfm'
|
||||
}
|
||||
{
|
||||
'match': '\\!?\\[([^\\]]*)\\]\\(([^\\)]+)\\)'
|
||||
'captures':
|
||||
'1': 'name': 'entity.gfm'
|
||||
'2': 'name': 'markup.underline.gfm'
|
||||
}
|
||||
{
|
||||
'match': '^\\s*([\\*\\+-])[ \\t]+'
|
||||
'captures':
|
||||
'1': 'name': 'constant.gfm'
|
||||
}
|
||||
]
|
||||
106
src/packages/gfm.tmbundle/spec/gfm-spec.coffee
Normal file
106
src/packages/gfm.tmbundle/spec/gfm-spec.coffee
Normal file
@@ -0,0 +1,106 @@
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
|
||||
describe "GitHub Flavored Markdown grammar", ->
|
||||
grammar = null
|
||||
|
||||
beforeEach ->
|
||||
spyOn(syntax, "addGrammar")
|
||||
pack = new TextMatePackage(require.resolve("gfm.tmbundle"))
|
||||
pack.load()
|
||||
grammar = pack.grammars[0]
|
||||
|
||||
it "parses the grammar", ->
|
||||
expect(grammar).toBeTruthy()
|
||||
expect(grammar.scopeName).toBe "source.gfm"
|
||||
|
||||
it "tokenizes **bold** text", ->
|
||||
{tokens} = grammar.tokenizeLine("****")
|
||||
expect(tokens[0]).toEqual value: "****", scopes: ["source.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine("this is **bold** text")
|
||||
expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "**bold**", scopes: ["source.gfm", "markup.bold.gfm"]
|
||||
expect(tokens[2]).toEqual value: " text", scopes: ["source.gfm"]
|
||||
|
||||
it "tokenizes __bold__ text", ->
|
||||
{tokens} = grammar.tokenizeLine("____")
|
||||
expect(tokens[0]).toEqual value: "____", scopes: ["source.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine("this is __bold__ text")
|
||||
expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "__bold__", scopes: ["source.gfm", "markup.bold.gfm"]
|
||||
expect(tokens[2]).toEqual value: " text", scopes: ["source.gfm"]
|
||||
|
||||
it "tokenizes *italic* text", ->
|
||||
{tokens} = grammar.tokenizeLine("**")
|
||||
expect(tokens[0]).toEqual value: "**", scopes: ["source.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine("this is *italic* text")
|
||||
expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "*italic*", scopes: ["source.gfm", "markup.italic.gfm"]
|
||||
expect(tokens[2]).toEqual value: " text", scopes: ["source.gfm"]
|
||||
|
||||
it "tokenizes _italic_ text", ->
|
||||
{tokens} = grammar.tokenizeLine("__")
|
||||
expect(tokens[0]).toEqual value: "__", scopes: ["source.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine("this is _italic_ text")
|
||||
expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "_italic_", scopes: ["source.gfm", "markup.italic.gfm"]
|
||||
expect(tokens[2]).toEqual value: " text", scopes: ["source.gfm"]
|
||||
|
||||
it "tokenizes a ## Heading", ->
|
||||
{tokens} = grammar.tokenizeLine("# Heading 1")
|
||||
expect(tokens[0]).toEqual value: "# Heading 1", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
{tokens} = grammar.tokenizeLine("### Heading 3")
|
||||
expect(tokens[0]).toEqual value: "### Heading 3", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
|
||||
it "tokenizies an :emoji:", ->
|
||||
{tokens} = grammar.tokenizeLine("this is :no_good:")
|
||||
expect(tokens[0]).toEqual value: "this is ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: ":no_good:", scopes: ["source.gfm", "variable.emoji.gfm"]
|
||||
|
||||
it "tokenizes a ``` code block```", ->
|
||||
{tokens, ruleStack} = grammar.tokenizeLine("```coffeescript")
|
||||
expect(tokens[0]).toEqual value: "```coffeescript", scopes: ["source.gfm", "support.gfm"]
|
||||
{tokens, ruleStack} = grammar.tokenizeLine("-> 'hello'", ruleStack)
|
||||
expect(tokens[0]).toEqual value: "-> 'hello'", scopes: ["source.gfm", "markup.raw.gfm"]
|
||||
{tokens} = grammar.tokenizeLine("```", ruleStack)
|
||||
expect(tokens[0]).toEqual value: "```", scopes: ["source.gfm", "support.gfm"]
|
||||
|
||||
it "tokenizes inline `code` blocks", ->
|
||||
{tokens} = grammar.tokenizeLine("`this` is `code`")
|
||||
expect(tokens[0]).toEqual value: "`this`", scopes: ["source.gfm", "markup.raw.gfm"]
|
||||
expect(tokens[1]).toEqual value: " is ", scopes: ["source.gfm"]
|
||||
expect(tokens[2]).toEqual value: "`code`", scopes: ["source.gfm", "markup.raw.gfm"]
|
||||
|
||||
it "tokenizes [links](links)", ->
|
||||
{tokens} = grammar.tokenizeLine("please click [this link](website)")
|
||||
expect(tokens[0]).toEqual value: "please click ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "[", scopes: ["source.gfm"]
|
||||
expect(tokens[2]).toEqual value: "this link", scopes: ["source.gfm", "entity.gfm"]
|
||||
expect(tokens[3]).toEqual value: "](", scopes: ["source.gfm"]
|
||||
expect(tokens[4]).toEqual value: "website", scopes: ["source.gfm", "markup.underline.gfm"]
|
||||
expect(tokens[5]).toEqual value: ")", scopes: ["source.gfm"]
|
||||
|
||||
it "tokenizes lists", ->
|
||||
{tokens} = grammar.tokenizeLine("*Item 1")
|
||||
expect(tokens[0]).toEqual value: "*Item 1", scopes: ["source.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine(" * Item 1")
|
||||
expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "*", scopes: ["source.gfm", "constant.gfm"]
|
||||
expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"]
|
||||
expect(tokens[3]).toEqual value: "Item 1", scopes: ["source.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine(" + Item 2")
|
||||
expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "+", scopes: ["source.gfm", "constant.gfm"]
|
||||
expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"]
|
||||
expect(tokens[3]).toEqual value: "Item 2", scopes: ["source.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine(" - Item 3")
|
||||
expect(tokens[0]).toEqual value: " ", scopes: ["source.gfm"]
|
||||
expect(tokens[1]).toEqual value: "-", scopes: ["source.gfm", "constant.gfm"]
|
||||
expect(tokens[2]).toEqual value: " ", scopes: ["source.gfm"]
|
||||
expect(tokens[3]).toEqual value: "Item 3", scopes: ["source.gfm"]
|
||||
@@ -1,12 +0,0 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
|
||||
module.exports =
|
||||
class GistsPackage extends DeferredAtomPackage
|
||||
|
||||
loadEvents:
|
||||
'gist:create': '.editor'
|
||||
|
||||
instanceClass: 'gists/lib/gists'
|
||||
|
||||
onLoadEvent: (event, instance) ->
|
||||
instance.createGist(event.currentTargetView())
|
||||
@@ -3,12 +3,15 @@ $ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class Gists
|
||||
@activate: -> new Gists
|
||||
|
||||
@activate: (rootView) -> new Gists(rootView)
|
||||
|
||||
constructor: (@rootView) ->
|
||||
constructor: ->
|
||||
rootView.command 'gist:create', '.editor', => @createGist()
|
||||
|
||||
createGist: (editor) ->
|
||||
editor = rootView.getActiveEditor()
|
||||
return unless editor?
|
||||
|
||||
gist = { public: false, files: {} }
|
||||
gist.files[editor.getBuffer().getBaseName()] =
|
||||
content: editor.getSelectedText() or editor.getText()
|
||||
@@ -27,5 +30,5 @@ class Gists
|
||||
@div class: 'content', =>
|
||||
@h3 "Gist #{response.id} created", class: 'title'
|
||||
@p "The url is on your clipboard", class: 'message'
|
||||
@rootView.append(notification.hide())
|
||||
rootView.append(notification.hide())
|
||||
notification.fadeIn().delay(2000).fadeOut(complete: -> $(this).remove())
|
||||
|
||||
3
src/packages/gists/package.cson
Normal file
3
src/packages/gists/package.cson
Normal file
@@ -0,0 +1,3 @@
|
||||
'main': 'lib/gists'
|
||||
'activationEvents':
|
||||
'gist:create': '.editor'
|
||||
@@ -2,12 +2,11 @@ RootView = require 'root-view'
|
||||
$ = require 'jquery'
|
||||
|
||||
describe "Gists package", ->
|
||||
|
||||
[rootView, editor] = []
|
||||
[editor] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(fixturesProject.resolve('sample.js'))
|
||||
atom.loadPackage('gists').getInstance()
|
||||
atom.loadPackage('gists')
|
||||
editor = rootView.getActiveEditor()
|
||||
spyOn($, 'ajax')
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
|
||||
module.exports =
|
||||
class GoToLinePackage extends DeferredAtomPackage
|
||||
|
||||
loadEvents:
|
||||
'editor:go-to-line': '.editor'
|
||||
|
||||
instanceClass: 'go-to-line/lib/go-to-line-view'
|
||||
|
||||
onLoadEvent: (event, instance) ->
|
||||
instance.toggle(event.currentTargetView())
|
||||
@@ -6,14 +6,15 @@ Point = require 'point'
|
||||
module.exports =
|
||||
class GoToLineView extends View
|
||||
|
||||
@activate: (rootView) -> new GoToLineView(rootView)
|
||||
@activate: -> new GoToLineView
|
||||
|
||||
@content: ->
|
||||
@div class: 'go-to-line overlay from-top mini', =>
|
||||
@subview 'miniEditor', new Editor(mini: true)
|
||||
@div class: 'message', outlet: 'message'
|
||||
|
||||
initialize: (@rootView) ->
|
||||
initialize: ->
|
||||
rootView.command 'editor:go-to-line', '.editor', => @toggle()
|
||||
@miniEditor.on 'focusout', => @detach()
|
||||
@on 'core:confirm', => @confirm()
|
||||
@on 'core:cancel', => @detach()
|
||||
@@ -42,13 +43,13 @@ class GoToLineView extends View
|
||||
@detach()
|
||||
|
||||
return unless editor and lineNumber.length
|
||||
position = new Point(parseInt(lineNumber - 1, 0))
|
||||
position = new Point(parseInt(lineNumber - 1))
|
||||
editor.scrollToBufferPosition(position, center: true)
|
||||
editor.setCursorBufferPosition(position)
|
||||
editor.moveCursorToFirstCharacterOfLine()
|
||||
|
||||
attach: ->
|
||||
@previouslyFocusedElement = $(':focus')
|
||||
@rootView.append(this)
|
||||
@message.text("Enter a line number 1-#{@rootView.getActiveEditor().getLineCount()}")
|
||||
rootView.append(this)
|
||||
@message.text("Enter a line number 1-#{rootView.getActiveEditor().getLineCount()}")
|
||||
@miniEditor.focus()
|
||||
|
||||
3
src/packages/go-to-line/package.cson
Normal file
3
src/packages/go-to-line/package.cson
Normal file
@@ -0,0 +1,3 @@
|
||||
'activationEvents':
|
||||
'editor:go-to-line': '.editor'
|
||||
'main': './lib/go-to-line-view'
|
||||
@@ -1,13 +1,14 @@
|
||||
RootView = require 'root-view'
|
||||
GoToLineView = require 'go-to-line/lib/go-to-line-view'
|
||||
|
||||
describe 'GoToLine', ->
|
||||
[rootView, goToLine, editor] = []
|
||||
[goToLine, editor] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
new RootView(require.resolve('fixtures/sample.js'))
|
||||
rootView.enableKeymap()
|
||||
goToLine = atom.loadPackage("go-to-line").getInstance()
|
||||
editor = rootView.getActiveEditor()
|
||||
goToLine = GoToLineView.activate()
|
||||
editor.setCursorBufferPosition([1,0])
|
||||
|
||||
afterEach ->
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
|
||||
module.exports =
|
||||
class MarkdownPreview extends DeferredAtomPackage
|
||||
loadEvents: ['markdown-preview:toggle']
|
||||
|
||||
instanceClass: 'markdown-preview/src/markdown-preview-view'
|
||||
|
||||
onLoadEvent: (event, instance) -> instance.toggle()
|
||||
@@ -5,19 +5,19 @@ $ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class MarkdownPreviewView extends ScrollView
|
||||
@activate: (rootView, state) ->
|
||||
@instance = new this(rootView)
|
||||
@activate: ->
|
||||
@instance = new MarkdownPreviewView
|
||||
|
||||
@content: (rootView) ->
|
||||
@content: ->
|
||||
@div class: 'markdown-preview', tabindex: -1, =>
|
||||
@div class: 'markdown-body', outlet: 'markdownBody'
|
||||
|
||||
initialize: (@rootView) ->
|
||||
initialize: ->
|
||||
super
|
||||
|
||||
@editor = @rootView.getActiveEditor()
|
||||
@subscribe @editor, 'focus', => @detach() unless @detaching
|
||||
@command 'core:cancel', => @detach() unless @detaching
|
||||
rootView.command 'markdown-preview:toggle', => @toggle()
|
||||
@on 'blur', => @detach() unless document.activeElement is this[0]
|
||||
@command 'core:cancel', => @detach()
|
||||
|
||||
toggle: ->
|
||||
if @hasParent()
|
||||
@@ -27,22 +27,23 @@ class MarkdownPreviewView extends ScrollView
|
||||
|
||||
attach: ->
|
||||
return unless @isMarkdownFile(@getActivePath())
|
||||
@rootView.append(this)
|
||||
rootView.append(this)
|
||||
@markdownBody.html(@getLoadingHtml())
|
||||
@loadHtml()
|
||||
@focus()
|
||||
|
||||
detach: ->
|
||||
return if @detaching
|
||||
@detaching = true
|
||||
super
|
||||
@rootView.focus()
|
||||
rootView.focus()
|
||||
@detaching = false
|
||||
|
||||
getActivePath: ->
|
||||
@editor.getPath()
|
||||
rootView.getActiveEditor()?.getPath()
|
||||
|
||||
getActiveText: ->
|
||||
@editor.getText()
|
||||
rootView.getActiveEditor()?.getText()
|
||||
|
||||
getErrorHtml: (error) ->
|
||||
$$$ ->
|
||||
@@ -76,4 +77,4 @@ class MarkdownPreviewView extends ScrollView
|
||||
@markdownBody.html(html) if @hasParent()
|
||||
|
||||
isMarkdownFile: (path) ->
|
||||
fs.isMarkdownExtension(fs.extension(path))
|
||||
path and fs.isMarkdownExtension(fs.extension(path))
|
||||
3
src/packages/markdown-preview/package.cson
Normal file
3
src/packages/markdown-preview/package.cson
Normal file
@@ -0,0 +1,3 @@
|
||||
'main': 'lib/markdown-preview-view'
|
||||
'activationEvents':
|
||||
'markdown-preview:toggle': '.editor'
|
||||
@@ -1,12 +1,12 @@
|
||||
$ = require 'jquery'
|
||||
RootView = require 'root-view'
|
||||
MarkdownPreview = require 'markdown-preview/src/markdown-preview-view'
|
||||
MarkdownPreview = require 'markdown-preview/lib/markdown-preview-view'
|
||||
|
||||
describe "MarkdownPreview", ->
|
||||
[rootView, markdownPreview] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/markdown'))
|
||||
atom.loadPackage("markdown-preview")
|
||||
spyOn(MarkdownPreview.prototype, 'loadHtml')
|
||||
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
@@ -15,44 +15,37 @@ describe "MarkdownPreview", ->
|
||||
it "toggles on/off a preview for a .md file", ->
|
||||
rootView.open('file.md')
|
||||
editor = rootView.getActiveEditor()
|
||||
markdownPreview = atom.loadPackage("markdown-preview").getInstance()
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
spyOn(markdownPreview, 'loadHtml')
|
||||
editor.trigger('markdown-preview:toggle')
|
||||
|
||||
markdownPreviewView = rootView.find('.markdown-preview')?.view()
|
||||
expect(rootView.find('.markdown-preview')).toExist()
|
||||
expect(markdownPreview.loadHtml).toHaveBeenCalled();
|
||||
expect(markdownPreviewView.loadHtml).toHaveBeenCalled()
|
||||
markdownPreviewView.trigger('markdown-preview:toggle')
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
|
||||
it "displays a preview for a .markdown file", ->
|
||||
rootView.open('file.markdown')
|
||||
editor = rootView.getActiveEditor()
|
||||
markdownPreview = atom.loadPackage("markdown-preview").getInstance()
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
spyOn(markdownPreview, 'loadHtml')
|
||||
editor.trigger('markdown-preview:toggle')
|
||||
expect(rootView.find('.markdown-preview')).toExist()
|
||||
expect(markdownPreview.loadHtml).toHaveBeenCalled();
|
||||
markdownPreviewView = rootView.find('.markdown-preview')?.view()
|
||||
expect(markdownPreviewView.loadHtml).toHaveBeenCalled()
|
||||
|
||||
it "does not display a preview for non-markdown file", ->
|
||||
rootView.open('file.js')
|
||||
editor = rootView.getActiveEditor()
|
||||
markdownPreview = atom.loadPackage("markdown-preview").getInstance()
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
spyOn(markdownPreview, 'loadHtml')
|
||||
editor.trigger('markdown-preview:toggle')
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
expect(markdownPreview.loadHtml).not.toHaveBeenCalled();
|
||||
expect(MarkdownPreview.prototype.loadHtml).not.toHaveBeenCalled()
|
||||
|
||||
describe "core:cancel event", ->
|
||||
it "removes markdown preview", ->
|
||||
rootView.open('file.md')
|
||||
editor = rootView.getActiveEditor()
|
||||
markdownPreview = atom.loadPackage("markdown-preview").getInstance()
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
spyOn(markdownPreview, 'loadHtml')
|
||||
editor.trigger('markdown-preview:toggle')
|
||||
|
||||
markdownPreviewView = rootView.find('.markdown-preview')?.view()
|
||||
@@ -62,14 +55,19 @@ describe "MarkdownPreview", ->
|
||||
|
||||
describe "when the editor receives focus", ->
|
||||
it "removes the markdown preview view", ->
|
||||
rootView.attachToDom()
|
||||
rootView.open('file.md')
|
||||
editor = rootView.getActiveEditor()
|
||||
markdownPreview = atom.loadPackage("markdown-preview").getInstance()
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
spyOn(markdownPreview, 'loadHtml')
|
||||
editor.trigger('markdown-preview:toggle')
|
||||
|
||||
markdownPreviewView = rootView.find('.markdown-preview')
|
||||
expect(markdownPreviewView).toExist()
|
||||
editor.focus()
|
||||
expect(markdownPreviewView).toExist()
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
|
||||
describe "when no editor is open", ->
|
||||
it "does not attach", ->
|
||||
expect(rootView.getActiveEditor()).toBeFalsy()
|
||||
rootView.trigger('markdown-preview:toggle')
|
||||
expect(rootView.find('.markdown-preview')).not.toExist()
|
||||
|
||||
@@ -4,8 +4,8 @@ TextMatePackage = require 'text-mate-package'
|
||||
module.exports =
|
||||
class LoadSnippetsTask extends Task
|
||||
constructor: (@snippets) ->
|
||||
super('snippets/src/load-snippets-handler')
|
||||
@packages = atom.getPackages()
|
||||
super('snippets/lib/load-snippets-handler')
|
||||
@packages = atom.getLoadedPackages()
|
||||
@packages.push(path: config.configDirPath)
|
||||
|
||||
started: ->
|
||||
@@ -1,22 +1,25 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
fs = require 'fs'
|
||||
_ = require 'underscore'
|
||||
SnippetExpansion = require './src/snippet-expansion'
|
||||
Snippet = require './src/snippet'
|
||||
LoadSnippetsTask = require './src/load-snippets-task'
|
||||
SnippetExpansion = require './snippet-expansion'
|
||||
Snippet = require './snippet'
|
||||
LoadSnippetsTask = require './load-snippets-task'
|
||||
|
||||
module.exports =
|
||||
class Snippets extends AtomPackage
|
||||
snippetsByExtension: {}
|
||||
loaded: false
|
||||
|
||||
activate: (@rootView) ->
|
||||
activate: ->
|
||||
window.snippets = this
|
||||
@loadAll()
|
||||
@rootView.on 'editor:attached', (e, editor) => @enableSnippetsInEditor(editor)
|
||||
rootView.on 'editor:attached', (e, editor) => @enableSnippetsInEditor(editor)
|
||||
|
||||
deactivate: ->
|
||||
@loadSnippetsTask?.terminate()
|
||||
|
||||
loadAll: ->
|
||||
new LoadSnippetsTask(this).start()
|
||||
@loadSnippetsTask = new LoadSnippetsTask(this)
|
||||
@loadSnippetsTask.start()
|
||||
|
||||
loadDirectory: (snippetsDirPath) ->
|
||||
for snippetsPath in fs.list(snippetsDirPath) when fs.base(snippetsPath).indexOf('.') isnt 0
|
||||
@@ -41,7 +44,7 @@ class Snippets extends AtomPackage
|
||||
syntax.addProperties(selector, snippets: snippetsByPrefix)
|
||||
|
||||
getBodyParser: ->
|
||||
require 'snippets/src/snippet-body-parser'
|
||||
require 'snippets/lib/snippet-body-parser'
|
||||
|
||||
enableSnippetsInEditor: (editor) ->
|
||||
editor.command 'snippets:expand', (e) =>
|
||||
1
src/packages/snippets/package.cson
Normal file
1
src/packages/snippets/package.cson
Normal file
@@ -0,0 +1 @@
|
||||
'main': 'lib/snippets'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user