Add project outline view with all tags

Opened via meta-J and limited to a maximum
of 10 tags similar to fuzzy-finder.
This commit is contained in:
Kevin Sawicki
2012-12-17 09:00:10 -08:00
parent 0bb1442652
commit 39408ec28d
8 changed files with 148 additions and 41 deletions

View File

@@ -20,7 +20,7 @@ describe "OutlineView", ->
it "initially displays all JavaScript functions with line numbers", ->
rootView.open('sample.js')
expect(rootView.find('.outline-view')).not.toExist()
rootView.getActiveEditor().trigger "outline-view:toggle"
rootView.getActiveEditor().trigger "outline-view:toggle-file-outline"
expect(outlineView.find('.loading')).toHaveText 'Generating symbols...'
waitsFor ->
@@ -31,16 +31,16 @@ describe "OutlineView", ->
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'
expect(outlineView.list.children('li:first').find('.function-line')).toHaveText 'Line 1'
expect(outlineView.list.children('li:first').find('.function-details')).toHaveText 'Line 1'
expect(outlineView.list.children('li:last').find('.function-name')).toHaveText 'quicksort.sort'
expect(outlineView.list.children('li:last').find('.function-line')).toHaveText 'Line 2'
expect(outlineView.list.children('li:last').find('.function-details')).toHaveText 'Line 2'
expect(outlineView).not.toHaveClass "error"
expect(outlineView.error).not.toBeVisible()
it "displays error when no tags match text in mini-editor", ->
rootView.open('sample.js')
expect(rootView.find('.outline-view')).not.toExist()
rootView.getActiveEditor().trigger "outline-view:toggle"
rootView.getActiveEditor().trigger "outline-view:toggle-file-outline"
waitsFor ->
setArraySpy.callCount > 0
@@ -67,7 +67,7 @@ describe "OutlineView", ->
it "shows an error message when no matching tags are found", ->
rootView.open('sample.txt')
expect(rootView.find('.outline-view')).not.toExist()
rootView.getActiveEditor().trigger "outline-view:toggle"
rootView.getActiveEditor().trigger "outline-view:toggle-file-outline"
setErrorSpy = spyOn(outlineView, "setError").andCallThrough()
waitsFor ->
@@ -151,3 +151,24 @@ describe "OutlineView", ->
outlineView.confirmed(outlineView.array[0])
expect(rootView.getActiveEditor().getPath()).toBe rootView.project.resolve("tagged-duplicate.js")
expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [0,4]
describe "project outline", ->
it "displays all tags", ->
rootView.open("tagged.js")
expect(rootView.find('.outline-view')).not.toExist()
rootView.trigger "outline-view:toggle-project-outline"
expect(outlineView.find('.loading')).toHaveText 'Loading symbols...'
waitsFor ->
setArraySpy.callCount > 0
runs ->
expect(outlineView.find('.loading')).toBeEmpty()
expect(rootView.find('.outline-view')).toExist()
expect(outlineView.list.children('li').length).toBe 4
expect(outlineView.list.children('li:first').find('.function-name')).toHaveText 'callMeMaybe'
expect(outlineView.list.children('li:first').find('.function-details')).toHaveText 'tagged.js'
expect(outlineView.list.children('li:last').find('.function-name')).toHaveText 'thisIsCrazy'
expect(outlineView.list.children('li:last').find('.function-details')).toHaveText 'tagged.js'
expect(outlineView).not.toHaveClass "error"
expect(outlineView.error).not.toBeVisible()

View File

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

View File

@@ -14,7 +14,8 @@ class OutlineView extends SelectList
requireStylesheet 'select-list.css'
requireStylesheet 'outline-view/src/outline-view.css'
@instance = new OutlineView(rootView)
rootView.command 'outline-view:toggle', => @instance.toggle()
rootView.command 'outline-view:toggle-file-outline', => @instance.toggleFileOutline()
rootView.command 'outline-view:toggle-project-outline', => @instance.toggleProjectOutline()
rootView.command 'outline-view:jump-to-declaration', => @instance.jumpToDeclaration()
@viewClass: -> "#{super} outline-view"
@@ -24,22 +25,26 @@ class OutlineView extends SelectList
initialize: (@rootView) ->
super
itemForElement: ({position, name}) ->
itemForElement: ({position, name, file}) ->
$$ ->
@li =>
@div name, class: 'function-name'
@div class: 'right', =>
@div "Line #{position.row + 1}", class: 'function-line'
if position
text = "Line #{position.row + 1}"
else
text = fs.base(file)
@div text, class: 'function-details'
@div class: 'clear-float'
toggle: ->
toggleFileOutline: ->
if @hasParent()
@cancel()
else
@populate()
@populateFileOutline()
@attach()
populate: ->
populateFileOutline: ->
tags = []
callback = (tag) -> tags.push tag
path = @rootView.getActiveEditor().getPath()
@@ -47,6 +52,26 @@ class OutlineView extends SelectList
new TagGenerator(path, callback).generate().done =>
if tags.length > 0
@miniEditor.show()
@maxItem = Infinity
@setArray(tags)
else
@miniEditor.hide()
@setError("No symbols found")
setTimeout (=> @detach()), 2000
toggleProjectOutline: ->
if @hasParent()
@cancel()
else
@populateProjectOutline()
@attach()
populateProjectOutline: ->
@setLoading("Loading symbols...")
TagReader.getAllTags(@rootView.getActiveEditor()).done (tags) =>
if tags.length > 0
@miniEditor.show()
@maxItems = 10
@setArray(tags)
else
@miniEditor.hide()
@@ -57,9 +82,11 @@ class OutlineView extends SelectList
@cancel()
@openTag(tag)
openTag: ({position, file}) ->
@rootView.openInExistingEditor(file, true, true) if file
@moveToPosition(position)
openTag: (tag) ->
position = tag.position
position = @getTagLine(tag) unless position
@rootView.openInExistingEditor(tag.file, true, true) if tag.file
@moveToPosition(position) if position
moveToPosition: (position) ->
editor = @rootView.getActiveEditor()

View File

@@ -23,7 +23,7 @@
float: right;
}
.outline-view ol .function-line {
.outline-view ol .function-details {
display: inline-block;
margin: 4px 0;
margin-right: .5em;

View File

@@ -1,13 +1,28 @@
fs = require 'fs'
$ = require 'jquery'
module.exports =
getTagsFile: (editor) ->
project = editor.rootView().project
tagsFile = project.resolve("tags") or project.resolve("TAGS")
return tagsFile if fs.isFile(tagsFile)
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)
tagsFile = @getTagsFile(editor)
return [] unless tagsFile
$tags.find(tagsFile, word) or []
getAllTags: (editor, callback) ->
deferred = $.Deferred()
tagsFile = @getTagsFile(editor)
if tagsFile
$tags.getAllTagsAsync tagsFile, (tags) =>
deferred.resolve(tags)
else
deferred.resolve([])
deferred.promise()