Pull out symbols-view package into a separate repo

This commit is contained in:
Kevin Sawicki
2013-08-13 10:03:24 -07:00
parent 7bc135d82e
commit c1c50a0b4c
9 changed files with 1 additions and 434 deletions

View File

@@ -8,7 +8,6 @@
},
"dependencies": {
"coffee-script": "1.6.2",
"ctags": "0.5.0",
"oniguruma": "0.16.0",
"mkdirp": "0.3.5",
"git-utils": "0.19.0",
@@ -77,6 +76,7 @@
"grammar-selector": "0.1.0",
"image-view": "0.1.0",
"spell-check": "0.1.0",
"symbols-view": "0.1.0",
"terminal": "0.3.0",
"toml": "0.1.0",
"wrap-guide": "0.1.0"

View File

@@ -1,6 +0,0 @@
'.editor':
'meta-j': 'symbols-view:toggle-file-symbols'
'meta-.': 'symbols-view:go-to-declaration'
'body':
'meta-J': 'symbols-view:toggle-project-symbols'

View File

@@ -1,17 +0,0 @@
ctags = require 'ctags'
fsUtils = require 'fs-utils'
path = require 'path'
getTagsFile = (directoryPath) ->
tagsFile = path.join(directoryPath, "tags")
return tagsFile if fsUtils.isFileSync(tagsFile)
tagsFile = path.join(directoryPath, "TAGS")
return tagsFile if fsUtils.isFileSync(tagsFile)
module.exports = (directoryPath) ->
tagsFilePath = getTagsFile(directoryPath)
if tagsFilePath
ctags.getTags(tagsFilePath)
else
[]

View File

@@ -1,124 +0,0 @@
{$$} = require 'space-pen'
SelectList = require 'select-list'
TagGenerator = require './tag-generator'
TagReader = require './tag-reader'
Point = require 'point'
fsUtils = require 'fs-utils'
path = require 'path'
$ = require 'jquery'
module.exports =
class SymbolsView extends SelectList
@activate: ->
new SymbolsView
@viewClass: -> "#{super} symbols-view overlay from-top"
filterKey: 'name'
initialize: ->
super
rootView.command 'symbols-view:toggle-file-symbols', => @toggleFileSymbols()
rootView.command 'symbols-view:toggle-project-symbols', => @toggleProjectSymbols()
rootView.command 'symbols-view:go-to-declaration', => @goToDeclaration()
itemForElement: ({position, name, file}) ->
$$ ->
@li class: 'two-lines', =>
@div name, class: 'primary-line'
if position
text = "Line #{position.row + 1}"
else
text = path.basename(file)
@div text, class: 'secondary-line'
getEmptyMessage: (itemCount) ->
if itemCount is 0
'No symbols found'
else
super
toggleFileSymbols: ->
if @hasParent()
@cancel()
else
@populateFileSymbols()
@attach()
populateFileSymbols: ->
filePath = rootView.getActiveView().getPath()
@list.empty()
@setLoading("Generating symbols...")
new TagGenerator(filePath).generate().done (tags) =>
@maxItem = Infinity
@setArray(tags)
toggleProjectSymbols: ->
if @hasParent()
@cancel()
else
@populateProjectSymbols()
@attach()
populateProjectSymbols: ->
@list.empty()
@setLoading("Loading symbols...")
TagReader.getAllTags(project).done (tags) =>
@maxItems = 10
@setArray(tags)
confirmed : (tag) ->
if tag.file and not fsUtils.isFileSync(project.resolve(tag.file))
@setError('Selected file does not exist')
setTimeout((=> @setError()), 2000)
else
@cancel()
@openTag(tag)
openTag: (tag) ->
position = tag.position
position = @getTagLine(tag) unless position
rootView.open(tag.file, {changeFocus: true, allowActiveEditorChange:true}) if tag.file
@moveToPosition(position) if position
moveToPosition: (position) ->
editor = rootView.getActiveView()
editor.scrollToBufferPosition(position, center: true)
editor.setCursorBufferPosition(position)
editor.moveCursorToFirstCharacterOfLine()
attach: ->
super
rootView.append(this)
@miniEditor.focus()
getTagLine: (tag) ->
pattern = $.trim(tag.pattern?.replace(/(^^\/\^)|(\$\/$)/g, '')) # Remove leading /^ and trailing $/
return unless pattern
file = project.resolve(tag.file)
return unless fsUtils.isFileSync(file)
for line, index in fsUtils.read(file).split('\n')
return new Point(index, 0) if pattern is $.trim(line)
goToDeclaration: ->
editor = rootView.getActiveView()
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: path.basename(match.file)
position: position
@miniEditor.show()
@setArray(tags)
@attach()

View File

@@ -1,30 +0,0 @@
Point = require 'point'
$ = require 'jquery'
BufferedProcess = require 'buffered-process'
fsUtils = require 'fs-utils'
module.exports =
class TagGenerator
constructor: (@path) ->
parseTagLine: (line) ->
sections = line.split('\t')
if sections.length > 3
position: new Point(parseInt(sections[2]) - 1)
name: sections[0]
else
null
generate: ->
deferred = $.Deferred()
tags = []
command = fsUtils.resolveOnLoadPath('ctags')
args = ['--fields=+KS', '-nf', '-', @path]
stdout = (lines) =>
for line in lines.split('\n')
tag = @parseTagLine(line)
tags.push(tag) if tag
exit = ->
deferred.resolve(tags)
new BufferedProcess({command, args, stdout, exit})
deferred

View File

@@ -1,30 +0,0 @@
fsUtils = require 'fs-utils'
$ = require 'jquery'
Task = require 'task'
ctags = require 'ctags'
handlerPath = require.resolve('./load-tags-handler')
module.exports =
getTagsFile: (project) ->
tagsFile = project.resolve("tags") or project.resolve("TAGS")
return tagsFile if fsUtils.isFileSync(tagsFile)
find: (editor) ->
word = editor.getTextInRange(editor.getCursor().getCurrentWordBufferRange())
return [] unless word.length > 0
tagsFile = @getTagsFile(project)
return [] unless tagsFile
ctags.findTags(tagsFile, word)
getAllTags: (project, callback) ->
deferred = $.Deferred()
task = new Task(handlerPath)
task.start project.getPath(), (tags) ->
deferred.resolve(tags)
task.terminate()
deferred.promise()

View File

@@ -1,6 +0,0 @@
'main': './lib/symbols-view'
'description': 'Jump to a function or method in the current editor with `meta-j`.'
'activationEvents':
'symbols-view:toggle-file-symbols': '.editor'
'symbols-view:toggle-project-symbols': null
'symbols-view:go-to-declaration': '.editor'

View File

@@ -1,220 +0,0 @@
RootView = require 'root-view'
SymbolsView = require 'symbols-view/lib/symbols-view'
TagGenerator = require 'symbols-view/lib/tag-generator'
fsUtils = require 'fs-utils'
describe "SymbolsView", ->
[symbolsView, setArraySpy] = []
beforeEach ->
window.rootView = new RootView
atom.activatePackage("symbols-view")
rootView.attachToDom()
setArraySpy = spyOn(SymbolsView.prototype, 'setArray').andCallThrough()
afterEach ->
setArraySpy.reset()
describe "when tags can be generated for a file", ->
it "initially displays all JavaScript functions with line numbers", ->
rootView.open('sample.js')
rootView.getActiveView().trigger "symbols-view:toggle-file-symbols"
symbolsView = rootView.find('.symbols-view').view()
expect(symbolsView.loading).toHaveText 'Generating symbols...'
waitsFor ->
setArraySpy.callCount > 0
runs ->
expect(symbolsView.loading).toBeEmpty()
expect(rootView.find('.symbols-view')).toExist()
expect(symbolsView.list.children('li').length).toBe 2
expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText 'quicksort'
expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText 'Line 1'
expect(symbolsView.list.children('li:last').find('.primary-line')).toHaveText 'quicksort.sort'
expect(symbolsView.list.children('li:last').find('.secondary-line')).toHaveText 'Line 2'
expect(symbolsView.error).not.toBeVisible()
it "displays error when no tags match text in mini-editor", ->
rootView.open('sample.js')
rootView.getActiveView().trigger "symbols-view:toggle-file-symbols"
symbolsView = rootView.find('.symbols-view').view()
waitsFor ->
setArraySpy.callCount > 0
runs ->
symbolsView.miniEditor.setText("nothing will match this")
window.advanceClock(symbolsView.inputThrottle)
expect(rootView.find('.symbols-view')).toExist()
expect(symbolsView.list.children('li').length).toBe 0
expect(symbolsView.error).toBeVisible()
expect(symbolsView.error.text().length).toBeGreaterThan 0
# Should remove error
symbolsView.miniEditor.setText("")
window.advanceClock(symbolsView.inputThrottle)
expect(symbolsView.list.children('li').length).toBe 2
expect(symbolsView.error).not.toBeVisible()
describe "when tags can't be generated for a file", ->
it "shows an error message when no matching tags are found", ->
rootView.open('sample.txt')
rootView.getActiveView().trigger "symbols-view:toggle-file-symbols"
symbolsView = rootView.find('.symbols-view').view()
setErrorSpy = spyOn(symbolsView, "setError").andCallThrough()
waitsFor ->
setErrorSpy.callCount > 0
runs ->
expect(symbolsView).toExist()
expect(symbolsView.list.children('li').length).toBe 0
expect(symbolsView.error).toBeVisible()
expect(symbolsView.error.text().length).toBeGreaterThan 0
expect(symbolsView.loadingArea).not.toBeVisible()
it "moves the cursor to the selected function", ->
tags = []
waitsForPromise ->
path = require.resolve('fixtures/sample.js')
generator = new TagGenerator(path)
generator.generate().done (generatedTags) ->
tags = generatedTags
runs ->
rootView.open('sample.js')
expect(rootView.getActiveView().getCursorBufferPosition()).toEqual [0,0]
expect(rootView.find('.symbols-view')).not.toExist()
symbolsView = SymbolsView.activate()
symbolsView.setArray(tags)
symbolsView.attach()
expect(rootView.find('.symbols-view')).toExist()
symbolsView.confirmed(tags[1])
expect(rootView.getActiveView().getCursorBufferPosition()).toEqual [1,2]
describe "TagGenerator", ->
it "generates tags for all JavaScript functions", ->
tags = []
waitsForPromise ->
path = require.resolve('fixtures/sample.js')
generator = new TagGenerator(path)
generator.generate().done (generatedTags) ->
tags = generatedTags
runs ->
expect(tags.length).toBe 2
expect(tags[0].name).toBe "quicksort"
expect(tags[0].position.row).toBe 0
expect(tags[1].name).toBe "quicksort.sort"
expect(tags[1].position.row).toBe 1
it "generates no tags for text file", ->
tags = []
waitsForPromise ->
path = require.resolve('fixtures/sample.txt')
generator = new TagGenerator(path)
generator.generate().done (generatedTags) ->
tags = generatedTags
runs ->
expect(tags.length).toBe 0
describe "go to declaration", ->
it "doesn't move the cursor when no declaration is found", ->
rootView.open("tagged.js")
editor = rootView.getActiveView()
editor.setCursorBufferPosition([0,2])
editor.trigger 'symbols-view:go-to-declaration'
expect(editor.getCursorBufferPosition()).toEqual [0,2]
it "moves the cursor to the declaration", ->
rootView.open("tagged.js")
editor = rootView.getActiveView()
editor.setCursorBufferPosition([6,24])
editor.trigger 'symbols-view:go-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.getActiveView()
editor.setCursorBufferPosition([8,14])
editor.trigger 'symbols-view:go-to-declaration'
symbolsView = rootView.find('.symbols-view').view()
expect(symbolsView.list.children('li').length).toBe 2
expect(symbolsView).toBeVisible()
symbolsView.confirmed(symbolsView.array[0])
expect(rootView.getActiveView().getPath()).toBe project.resolve("tagged-duplicate.js")
expect(rootView.getActiveView().getCursorBufferPosition()).toEqual [0,4]
describe "when the tag is in a file that doesn't exist", ->
renamedPath = null
beforeEach ->
renamedPath = project.resolve("tagged-duplicate-renamed.js")
fsUtils.remove(renamedPath) if fsUtils.exists(renamedPath)
fsUtils.move(project.resolve("tagged-duplicate.js"), renamedPath)
afterEach ->
fsUtils.move(renamedPath, project.resolve("tagged-duplicate.js"))
it "doesn't display the tag", ->
rootView.open("tagged.js")
editor = rootView.getActiveView()
editor.setCursorBufferPosition([8,14])
editor.trigger 'symbols-view:go-to-declaration'
symbolsView = rootView.find('.symbols-view').view()
expect(symbolsView.list.children('li').length).toBe 1
expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText 'tagged.js'
describe "project symbols", ->
it "displays all tags", ->
rootView.open("tagged.js")
expect(rootView.find('.symbols-view')).not.toExist()
rootView.trigger "symbols-view:toggle-project-symbols"
symbolsView = rootView.find('.symbols-view').view()
expect(symbolsView.loading).toHaveText 'Loading symbols...'
waitsFor ->
setArraySpy.callCount > 0
runs ->
expect(symbolsView.loading).toBeEmpty()
expect(rootView.find('.symbols-view')).toExist()
expect(symbolsView.list.children('li').length).toBe 4
expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText 'callMeMaybe'
expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText 'tagged.js'
expect(symbolsView.list.children('li:last').find('.primary-line')).toHaveText 'thisIsCrazy'
expect(symbolsView.list.children('li:last').find('.secondary-line')).toHaveText 'tagged.js'
expect(symbolsView.error).not.toBeVisible()
describe "when selecting a tag", ->
describe "when the file doesn't exist", ->
renamedPath = null
beforeEach ->
renamedPath = project.resolve("tagged-renamed.js")
fsUtils.remove(renamedPath) if fsUtils.exists(renamedPath)
fsUtils.move(project.resolve("tagged.js"), renamedPath)
afterEach ->
fsUtils.move(renamedPath, project.resolve("tagged.js"))
it "doesn't open the editor", ->
rootView.trigger "symbols-view:toggle-project-symbols"
symbolsView = rootView.find('.symbols-view').view()
waitsFor ->
setArraySpy.callCount > 0
runs ->
spyOn(rootView, 'open').andCallThrough()
symbolsView.list.children('li:first').mousedown().mouseup()
expect(rootView.open).not.toHaveBeenCalled()
expect(symbolsView.error.text().length).toBeGreaterThan 0

BIN
vendor/ctags vendored

Binary file not shown.