Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Issue #77 Allow end-user configuration of tags path relative to project root #137

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

Display the list of functions/methods in the editor via `cmd-r` in Atom.

If your project has a `tags`/`.tags`/`TAGS`/`.TAGS` file at the root then
following are supported:
If your project has a `tags`/`.tags`/`TAGS`/`.TAGS` file at the root or at a
custom directory defined in `tagsDirectory` then the following are supported:

|Command|Description|Keybinding (Linux)|Keybinding (OS X)|Keybinding (Windows)|
|-------|-----------|------------------|-----------------|--------------------|
Expand Down
12 changes: 7 additions & 5 deletions lib/load-tags-handler.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ async = require 'async'
ctags = require 'ctags'
getTagsFile = require './get-tags-file'

module.exports = (directoryPaths) ->
module.exports = (tagDirectoryObjects) ->
async.each(
directoryPaths,
(directoryPath, done) ->
tagsFilePath = getTagsFile(directoryPath)
tagDirectoryObjects,
({tagsPath, projectPath}, done) ->
tagsFilePath = getTagsFile(tagsPath)
return done() unless tagsFilePath

stream = ctags.createReadStream(tagsFilePath)
stream.on 'data', (tags) ->
tag.directory = directoryPath for tag in tags
for tag in tags
tag.projectPath = projectPath
tag.directory = tagsPath
emit('tags', tags)
stream.on('end', done)
stream.on('error', done)
Expand Down
5 changes: 4 additions & 1 deletion lib/main.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ module.exports =
default: true
type: 'boolean'
description: 'Force ctags to use the name of the current file\'s language in Atom when generating tags. By default, ctags automatically selects the language of a source file, ignoring those files whose language cannot be determined. This option forces the specified language to be used instead of automatically selecting the language based upon its extension.'

tagsDirectory:
default: './'
type: 'string'
description: 'A directory relative to your project path where symbols-view will look for your tags file. By default this is set to project root.'
activate: ->
@stack = []

Expand Down
22 changes: 14 additions & 8 deletions lib/project-view.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ class ProjectView extends SymbolsView
@reloadTags = true
@setMaxItems(10)

@relativeTagsDirectoryWatcher = atom.config.onDidChange 'symbols-view.tagsDirectory', (newValue) =>
@triggerReloadTags()

destroy: ->
@stopTask()
@unwatchTagsFiles()
@relativeTagsDirectoryWatcher.dispose()
super

toggle: ->
Expand Down Expand Up @@ -59,20 +63,22 @@ class ProjectView extends SymbolsView

@watchTagsFiles()

triggerReloadTags: ->
@reloadTags = true
@watchTagsFiles()

watchTagsFiles: ->
@unwatchTagsFiles()

@tagsFileSubscriptions = new CompositeDisposable()
reloadTags = =>
@reloadTags = true
@watchTagsFiles()

for projectPath in atom.project.getPaths()
if tagsFilePath = getTagsFile(projectPath)
relativeTagsDirectory = atom.config.get('symbols-view.tagsDirectory')
for {tagsPath} in TagReader.getTagsPaths(relativeTagsDirectory)
if tagsFilePath = getTagsFile(tagsPath)
tagsFile = new File(tagsFilePath)
@tagsFileSubscriptions.add(tagsFile.onDidChange(reloadTags))
@tagsFileSubscriptions.add(tagsFile.onDidDelete(reloadTags))
@tagsFileSubscriptions.add(tagsFile.onDidRename(reloadTags))
@tagsFileSubscriptions.add(tagsFile.onDidChange(=> @triggerReloadTags()))
@tagsFileSubscriptions.add(tagsFile.onDidDelete(=> @triggerReloadTags()))
@tagsFileSubscriptions.add(tagsFile.onDidRename(=> @triggerReloadTags()))

return

Expand Down
8 changes: 5 additions & 3 deletions lib/symbols-view.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ class SymbolsView extends SelectListView

getFilterKey: -> 'name'

viewForItem: ({position, name, file, directory}) ->
viewForItem: ({position, name, file, directory, projectPath}) ->
# Style matched characters in search results
matches = match(name, @getFilterQuery())

file = path.relative(projectPath, path.join(directory, file))
if atom.project.getPaths().length > 1
file = path.join(path.basename(directory), file)
file = path.join(path.basename(projectPath), file)

$$ ->
@li class: 'two-lines', =>
Expand All @@ -63,7 +64,8 @@ class SymbolsView extends SelectListView

confirmed: (tag) ->
if tag.file and not fs.isFileSync(path.join(tag.directory, tag.file))
@setError('Selected file does not exist')
@setError("Selected file does not exist. Try running ctags with the " +
"--tag-relative option inside your project directory.")
setTimeout((=> @setError()), 2000)
else
@cancel()
Expand Down
23 changes: 18 additions & 5 deletions lib/tag-reader.coffee
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
path = require 'path'
{Task} = require 'atom'
ctags = require 'ctags'
async = require 'async'
Expand All @@ -21,19 +22,31 @@ module.exports =
allTags = []

async.each(
atom.project.getPaths(),
(projectPath, done) ->
tagsFile = getTagsFile(projectPath)
@getTagsPaths(atom.config.get('symbols-view.tagsDirectory'))
({tagsPath, projectPath}, done) ->
tagsFile = getTagsFile(tagsPath)
return done() unless tagsFile?
ctags.findTags tagsFile, symbol, (err, tags=[]) ->
tag.directory = projectPath for tag in tags
for tag in tags
tag.projectPath = projectPath
tag.directory = tagsPath
allTags = allTags.concat(tags)
done(err)
(err) -> callback(err, allTags)
)

getAllTags: (callback) ->
projectTags = []
task = Task.once handlerPath, atom.project.getPaths(), -> callback(projectTags)
relativeTagsDirectory = atom.config.get('symbols-view.tagsDirectory')
task = Task.once handlerPath, @getTagsPaths(relativeTagsDirectory), -> callback(projectTags)
task.on 'tags', (tags) -> projectTags.push(tags...)
task

getTagsPaths: (relativeTagsDirectory) ->
paths = []
for projectPath in atom.project.getPaths()
paths.push(
projectPath: projectPath
tagsPath: path.join(projectPath, relativeTagsDirectory)
)
paths
10 changes: 10 additions & 0 deletions spec/fixtures/js/tagsDir/tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /[email protected]/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.8 //
callMeMaybe ../tagged.js /^function callMeMaybe() {$/;" f
duplicate ../tagged-duplicate.js /^function duplicate() {$/;" f
duplicate ../tagged.js /^function duplicate() {$/;" f
thisIsCrazy ../tagged.js /^var thisIsCrazy = true;$/;" v
48 changes: 48 additions & 0 deletions spec/symbols-view-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,54 @@ describe "SymbolsView", ->

runs ->
expect(symbolsView.list.children('li').length).toBe 0
it "displays all tags when the tagsDirectory is set to \"tagsDir\"", ->

jasmine.unspy(window, 'setTimeout')
atom.config.set('symbols-view.tagsDirectory', 'tagsDir')

waitsForPromise ->
atom.workspace.open(directory.resolve("tagged.js"))

runs ->
atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols")

waitsForPromise ->
activationPromise

runs ->
symbolsView = $(getWorkspaceView()).find('.symbols-view').view()

waitsFor "loading", ->
symbolsView.setLoading.callCount > 1

waitsFor ->
symbolsView.list.children('li').length > 0

runs ->
directoryBasename = path.basename(directory.getPath())
expect(symbolsView.loading).toBeEmpty()
expect($(getWorkspaceView()).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 path.join(directoryBasename, 'tagged.js')
expect(symbolsView.list.children('li:last').find('.primary-line')).toHaveText 'thisIsCrazy'
expect(symbolsView.list.children('li:last').find('.secondary-line')).toHaveText path.join(directoryBasename, 'tagged.js')
expect(symbolsView.error).not.toBeVisible()
atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols")

fs.removeSync(directory.resolve('tagsDir/tags'))

waitsFor ->
symbolsView.reloadTags

runs ->
atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols")

waitsFor ->
symbolsView.error.text().length > 0

runs ->
expect(symbolsView.list.children('li').length).toBe 0

describe "when there is only one project", ->
beforeEach ->
Expand Down