diff --git a/src/packages/symbols-view/lib/tag-generator.coffee b/src/packages/symbols-view/lib/tag-generator.coffee index a5543bc3b..8367e74d6 100644 --- a/src/packages/symbols-view/lib/tag-generator.coffee +++ b/src/packages/symbols-view/lib/tag-generator.coffee @@ -1,6 +1,7 @@ Point = require 'point' ChildProcess = nodeRequire 'child_process' $ = require 'jquery' +BufferedProcess = require 'buffered-process' module.exports = class TagGenerator @@ -15,18 +16,15 @@ class TagGenerator null generate: -> + deferred = $.Deferred() + tags = [] command = "#{require.resolve('ctags')}" args = ['--fields=+KS', '-nf', '-', @path] - ctags = ChildProcess.spawn(command, args) - deferred = $.Deferred() - output = '' - ctags.stdout.setEncoding('utf8') - ctags.stdout.on 'data', (data) -> - output += data - ctags.stdout.on 'close', => - tags = [] - for line in output.split('\n') + 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 diff --git a/src/stdlib/buffered-process.coffee b/src/stdlib/buffered-process.coffee new file mode 100644 index 000000000..2c325192c --- /dev/null +++ b/src/stdlib/buffered-process.coffee @@ -0,0 +1,46 @@ +ChildProcess = nodeRequire 'child_process' + +module.exports = +class BufferedProcess + constructor: (options={}) -> + process = ChildProcess.spawn(options.command, options.args) + + stdoutClosed = true + stderrClosed = true + processExited = true + triggerExitCallback = -> + if stdoutClosed and stderrClosed and processExited + options.exit?() + + if options.stdout + stdoutClosed = false + @bufferStream process.stdout, options.stdout, -> + stdoutClosed = true + triggerExitCallback() + + if options.stderr + stderrClosed = false + @bufferStream process.stderr, options.stderr, -> + stderrClosed = true + triggerExitCallback() + + if options.exit + processExited = false + process.on 'exit', -> + processExited = true + triggerExitCallback() + + bufferStream: (stream, onLines, onDone) -> + stream.setEncoding('utf8') + buffered = '' + + stream.on 'data', (data) -> + buffered += data + lastNewlineIndex = buffered.lastIndexOf('\n') + if lastNewlineIndex isnt -1 + onLines(buffered.substring(0, lastNewlineIndex + 1)) + buffered = buffered.substring(lastNewlineIndex + 1) + + stream.on 'close', => + onLines(buffered) if buffered.length > 0 + onDone()