Merge branch 'master' into config

Conflicts:
	spec/app/project-spec.coffee
	src/extensions/wrap-guide/src/wrap-guide.coffee
This commit is contained in:
Corey Johnson & Nathan Sobo
2012-12-14 14:14:50 -08:00
31 changed files with 1546 additions and 51 deletions

View File

@@ -2,4 +2,3 @@ window.keymap.bindKeys ".select-list .mini.editor input",
'enter': 'core:confirm',
'escape': 'core:cancel'
'meta-w': 'core:cancel'

View File

@@ -52,20 +52,14 @@ class Project
getFilePaths: ->
deferred = $.Deferred()
fs.getAllPathsAsync @getPath(), (paths) =>
fs.getAllFilePathsAsync @getPath(), (paths) =>
paths = paths.filter (path) => not @isPathIgnored(path)
deferred.resolve(paths)
deferred.promise()
isPathIgnored: (path) ->
lastSlash = path.lastIndexOf('/')
if lastSlash isnt -1
name = path.substring(lastSlash + 1)
else
name = path
for ignored in @ignoredNames
return true if name is ignored
for segment in path.split("/")
return true if _.contains(@ignoredNames, segment)
@ignoreRepositoryPath(path)

View File

@@ -15,13 +15,15 @@ class SelectList extends View
@viewClass: -> 'select-list'
maxItems: Infinity
scheduleTimeout: null
inputThrottle: 200
filteredArray: null
cancelling: false
initialize: ->
requireStylesheet 'select-list.css'
@miniEditor.getBuffer().on 'change', => @populateList()
@miniEditor.getBuffer().on 'change', => @schedulePopulateList()
@miniEditor.on 'focusout', => @cancel() unless @cancelling
@on 'core:move-up', => @selectPreviousItem()
@on 'core:move-down', => @selectNextItem()
@@ -36,6 +38,10 @@ class SelectList extends View
@confirmSelection() if $(e.target).closest('li').hasClass('selected')
e.preventDefault()
schedulePopulateList: ->
clearTimeout(@scheduleTimeout)
@scheduleTimeout = setTimeout((=> @populateList()), @inputThrottle)
setArray: (@array) ->
@populateList()
@selectItem(@list.find('li:first'))
@@ -43,12 +49,11 @@ class SelectList extends View
setError: (message) ->
if not message or message.length == ""
@error.text("")
@error.hide()
@error.text("").hide()
@removeClass("error")
else
@error.text(message)
@error.show()
@setLoading()
@error.text(message).show()
@addClass("error")
setLoading: (message) ->
@@ -113,8 +118,9 @@ class SelectList extends View
@confirmed(element) if element?
cancel: ->
@list.empty()
@cancelling = true
@cancelled()
@detach()
@cancelling = false
clearTimeout(@scheduleTimeout)

View File

@@ -20,7 +20,9 @@ class EventPalette extends SelectList
keyBindings: null
initialize: (@rootView) ->
@command 'event-palette:toggle', => @cancel()
@command 'event-palette:toggle', =>
@cancel()
false
super
attach: ->

View File

@@ -189,3 +189,23 @@ describe 'FuzzyFinder', ->
expect(finder.hasParent()).toBeFalsy()
expect(activeEditor.isFocused).toBeTruthy()
expect(finder.miniEditor.isFocused).toBeFalsy()
describe "cached file paths", ->
it "caches file paths after first time", ->
spyOn(rootView.project, "getFilePaths").andCallThrough()
rootView.trigger 'fuzzy-finder:toggle-file-finder'
waitsFor ->
finder.list.children('li').length > 0
runs ->
expect(rootView.project.getFilePaths).toHaveBeenCalled()
rootView.project.getFilePaths.reset()
rootView.trigger 'fuzzy-finder:toggle-file-finder'
rootView.trigger 'fuzzy-finder:toggle-file-finder'
waitsFor ->
finder.list.children('li').length > 0
runs ->
expect(rootView.project.getFilePaths).not.toHaveBeenCalled()

View File

@@ -1,6 +1,7 @@
{View, $$} = require 'space-pen'
SelectList = require 'select-list'
_ = require 'underscore'
$ = require 'jquery'
Editor = require 'editor'
module.exports =
@@ -20,6 +21,7 @@ class FuzzyFinder extends SelectList
initialize: (@rootView) ->
super
$(window).on 'focus', => @array = null
itemForElement: (path) ->
$$ -> @li path
@@ -51,9 +53,12 @@ class FuzzyFinder extends SelectList
@attach() if @paths?.length
populateProjectPaths: ->
@setLoading("Indexing...")
@rootView.project.getFilePaths().done (paths) =>
@setArray(paths)
if @array?.length > 0
@setArray(@array)
else
@setLoading("Indexing...")
@rootView.project.getFilePaths().done (paths) =>
@setArray(paths)
populateOpenBufferPaths: ->
@paths = @rootView.getOpenBufferPaths().map (path) =>

View File

@@ -3,28 +3,31 @@ OutlineView = require 'outline-view'
TagGenerator = require 'outline-view/src/tag-generator'
describe "OutlineView", ->
[rootView, outlineView] = []
[rootView, outlineView, setArraySpy] = []
beforeEach ->
rootView = new RootView(require.resolve('fixtures'))
rootView.activateExtension(OutlineView)
outlineView = OutlineView.instance
rootView.attachToDom()
setArraySpy = spyOn(outlineView, 'setArray').andCallThrough()
afterEach ->
rootView.deactivate()
setArraySpy.reset()
describe "when tags can be generated for a file", ->
it "initially displays all JavaScript functions with line numbers", ->
rootView.open('sample.js')
expect(rootView.find('.outline-view')).not.toExist()
attachSpy = spyOn(outlineView, 'attach').andCallThrough()
rootView.getActiveEditor().trigger "outline-view:toggle"
expect(outlineView.find('.loading')).toHaveText 'Generating symbols...'
waitsFor ->
attachSpy.callCount > 0
setArraySpy.callCount > 0
runs ->
expect(outlineView.find('.loading')).toBeEmpty()
expect(rootView.find('.outline-view')).toExist()
expect(outlineView.list.children('li').length).toBe 2
expect(outlineView.list.children('li:first').find('.function-name')).toHaveText 'quicksort'
@@ -37,14 +40,15 @@ describe "OutlineView", ->
it "displays error when no tags match text in mini-editor", ->
rootView.open('sample.js')
expect(rootView.find('.outline-view')).not.toExist()
attachSpy = spyOn(outlineView, 'attach').andCallThrough()
rootView.getActiveEditor().trigger "outline-view:toggle"
waitsFor ->
attachSpy.callCount > 0
setArraySpy.callCount > 0
runs ->
outlineView.miniEditor.setText("nothing will match this")
window.advanceClock(outlineView.inputThrottle)
expect(rootView.find('.outline-view')).toExist()
expect(outlineView.list.children('li').length).toBe 0
expect(outlineView.error).toBeVisible()
@@ -53,6 +57,8 @@ describe "OutlineView", ->
# Should remove error
outlineView.miniEditor.setText("")
window.advanceClock(outlineView.inputThrottle)
expect(outlineView.list.children('li').length).toBe 2
expect(outlineView).not.toHaveClass "error"
expect(outlineView.error).not.toBeVisible()
@@ -61,11 +67,11 @@ describe "OutlineView", ->
it "shows an error message when no matching tags are found", ->
rootView.open('sample.txt')
expect(rootView.find('.outline-view')).not.toExist()
attachSpy = spyOn(outlineView, 'attach').andCallThrough()
rootView.getActiveEditor().trigger "outline-view:toggle"
setErrorSpy = spyOn(outlineView, "setError").andCallThrough()
waitsFor ->
attachSpy.callCount > 0
setErrorSpy.callCount > 0
runs ->
expect(rootView.find('.outline-view')).toExist()
@@ -73,6 +79,7 @@ describe "OutlineView", ->
expect(outlineView.error).toBeVisible()
expect(outlineView.error.text().length).toBeGreaterThan 0
expect(outlineView).toHaveClass "error"
expect(outlineView.find('.loading')).not.toBeVisible()
it "moves the cursor to the selected function", ->
tags = []
@@ -92,7 +99,7 @@ describe "OutlineView", ->
outlineView.attach()
expect(rootView.find('.outline-view')).toExist()
outlineView.confirmed(tags[1])
expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [1,0]
expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [1,2]
describe "TagGenerator", ->
it "generates tags for all JavaScript functions", ->
@@ -118,3 +125,29 @@ describe "OutlineView", ->
generator = new TagGenerator(path, callback)
generator.generate().done ->
expect(tags.length).toBe 0
describe "jump to declaration", ->
it "doesn't move the cursor when no declaration is found", ->
rootView.open("tagged.js")
editor = rootView.getActiveEditor()
editor.setCursorBufferPosition([0,2])
editor.trigger 'outline-view:jump-to-declaration'
expect(editor.getCursorBufferPosition()).toEqual [0,2]
it "moves the cursor to the declaration", ->
rootView.open("tagged.js")
editor = rootView.getActiveEditor()
editor.setCursorBufferPosition([6,24])
editor.trigger 'outline-view:jump-to-declaration'
expect(editor.getCursorBufferPosition()).toEqual [2,0]
it "displays matches when more than one exists and opens the selected match", ->
rootView.open("tagged.js")
editor = rootView.getActiveEditor()
editor.setCursorBufferPosition([8,14])
editor.trigger 'outline-view:jump-to-declaration'
expect(outlineView.list.children('li').length).toBe 2
expect(outlineView).toBeVisible()
outlineView.confirmed(outlineView.array[0])
expect(rootView.getActiveEditor().getPath()).toBe rootView.project.resolve("tagged-duplicate.js")
expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [0,4]

View File

@@ -1,2 +1,3 @@
window.keymap.bindKeys '.editor'
'meta-j': 'outline-view:toggle'
'meta-.': 'outline-view:jump-to-declaration'

View File

@@ -2,6 +2,10 @@
SelectList = require 'select-list'
Editor = require 'editor'
TagGenerator = require 'outline-view/src/tag-generator'
TagReader = require 'outline-view/src/tag-reader'
Point = require 'point'
fs = require 'fs'
$ = require 'jquery'
module.exports =
class OutlineView extends SelectList
@@ -11,6 +15,7 @@ class OutlineView extends SelectList
requireStylesheet 'outline-view/src/outline-view.css'
@instance = new OutlineView(rootView)
rootView.command 'outline-view:toggle', => @instance.toggle()
rootView.command 'outline-view:jump-to-declaration', => @instance.jumpToDeclaration()
@viewClass: -> "#{super} outline-view"
@@ -32,11 +37,13 @@ class OutlineView extends SelectList
@cancel()
else
@populate()
@attach()
populate: ->
tags = []
callback = (tag) -> tags.push tag
path = @rootView.getActiveEditor().getPath()
@setLoading("Generating symbols...")
new TagGenerator(path, callback).generate().done =>
if tags.length > 0
@miniEditor.show()
@@ -46,13 +53,19 @@ class OutlineView extends SelectList
@setError("No symbols found")
setTimeout (=> @detach()), 2000
@attach()
confirmed : ({position, name}) ->
confirmed : (tag) ->
@cancel()
@openTag(tag)
openTag: ({position, file}) ->
@rootView.openInExistingEditor(file, true, true) if file
@moveToPosition(position)
moveToPosition: (position) ->
editor = @rootView.getActiveEditor()
editor.scrollToBufferPosition(position, center: true)
editor.setCursorBufferPosition(position)
editor.moveCursorToFirstCharacterOfLine()
cancelled: ->
@miniEditor.setText('')
@@ -61,3 +74,30 @@ class OutlineView extends SelectList
attach: ->
@rootView.append(this)
@miniEditor.focus()
getTagLine: (tag) ->
pattern = $.trim(tag.pattern?.replace(/(^^\/\^)|(\$\/$)/g, '')) # Remove leading /^ and trailing $/
return unless pattern
for line, index in fs.read(@rootView.project.resolve(tag.file)).split('\n')
return new Point(index, 0) if pattern is $.trim(line)
jumpToDeclaration: ->
editor = @rootView.getActiveEditor()
matches = TagReader.find(editor)
return unless matches.length
if matches.length is 1
position = @getTagLine(matches[0])
@openTag(file: matches[0].file, position: position) if position
else
tags = []
for match in matches
position = @getTagLine(match)
continue unless position
tags.push
file: match.file
name: fs.base(match.file)
position: position
@miniEditor.show()
@setArray(tags)
@attach()

View File

@@ -31,8 +31,5 @@
color: #ddd;
-webkit-border-radius: 3px;
padding: 0 4px;
}
.outline-view ol .function-line {
background: rgba(0, 0, 0, .2);
}

View File

@@ -0,0 +1,13 @@
fs = require 'fs'
module.exports =
find: (editor) ->
word = editor.getTextInRange(editor.getCursor().getCurrentWordBufferRange())
return [] unless word.length > 0
project = editor.rootView().project
tagsFile = project.resolve("tags") or project.resolve("TAGS")
return [] unless fs.isFile(tagsFile)
$tags.find(tagsFile, word) or []

View File

@@ -31,6 +31,7 @@ class WrapGuide extends View
@updateGuide(@editor)
@editor.on 'editor-path-change', => @updateGuide(@editor)
config.on 'update', => @setFontSize(config.editor.fontSize)
@editor.on 'before-remove', => @rootView.off('.wrap-guide')
setFontSize: (fontSize) ->
return if fontSize == @fontSize

View File

@@ -112,8 +112,8 @@ module.exports =
@makeTree(@directory(path))
@makeDirectory(path)
getAllPathsAsync: (rootPath, callback) ->
$native.getAllPathsAsync(rootPath, callback)
getAllFilePathsAsync: (rootPath, callback) ->
$native.getAllFilePathsAsync(rootPath, callback)
traverseTree: (rootPath, onFile, onDirectory) ->
$native.traverseTree(rootPath, onFile, onDirectory)