diff --git a/spec/app/project-spec.coffee b/spec/app/project-spec.coffee index ae0232e1c..a8a50a0cc 100644 --- a/spec/app/project-spec.coffee +++ b/spec/app/project-spec.coffee @@ -128,12 +128,12 @@ describe "Project", -> runs -> expect(matches[0]).toEqual path: project.resolve('a') - match: ['aaa', 'a'] + match: 'aaa' range: [[0, 0], [0, 3]] expect(matches[1]).toEqual path: project.resolve('a') - match: ['aa', 'a'] + match: 'aa' range: [[1, 3], [1, 5]] it "works on evil filenames", -> @@ -147,11 +147,9 @@ describe "Project", -> runs -> expect(paths.length).toBe 5 - matches.forEach (match) -> expect(match).toEqual ['evil'] + matches.forEach (match) -> expect(match).toEqual 'evil' expect(paths[0]).toMatch /a_file_with_utf8.txt$/ expect(paths[1]).toMatch /file with spaces.txt$/ expect(paths[2]).toMatch /goddam\nnewlines$/m expect(paths[3]).toMatch /quote".txt$/m expect(fs.base(paths[4])).toBe "utfa\u0306.md" - - diff --git a/src/app/project.coffee b/src/app/project.coffee index 918de78e6..72745f1e9 100644 --- a/src/app/project.coffee +++ b/src/app/project.coffee @@ -138,32 +138,58 @@ class Project scan: (regex, iterator) -> regex = new RegExp(regex.source, 'g') - command = "#{require.resolve('ack')} --all --match \"#{regex.source}\" \"#{@getPath()}\"" + command = "#{require.resolve('ag')} --ackmate \"#{regex.source}\" \"#{@getPath()}\"" bufferedData = "" - console.log command - promise = ChildProcess.exec command , bufferLines: true, stdout: (data) -> - bufferedData += data - currentIndex = 0 - while currentIndex < bufferedData.length - pathEndIndex = bufferedData.indexOf('\0', currentIndex) - break unless pathEndIndex >= 0 - lineNumberEndIndex = bufferedData.indexOf('\0', pathEndIndex + 1) - lineEndIndex = bufferedData.indexOf('\n', lineNumberEndIndex + 1) + state = 'readingPath' + path = null + + readPath = (line) -> + if /^[0-9,; ]+:/.test(line) + state = 'readingLines' + else if /^:/.test line + path = line.substr(1) + else + path += ('\n' + line) + + readLine = (line) -> + if line.length == 0 + state = 'readingPath' + path = null + else + colonIndex = line.indexOf(':') + matchInfo = line.substring(0, colonIndex) + lineText = line.substring(colonIndex + 1) + readMatches(matchInfo, lineText) + + readMatches = (matchInfo, lineText) -> + [lineNumber, matchPositionsText] = matchInfo.match(/(\d+);(.+)/)[1..] + row = parseInt(lineNumber) - 1 + + + + matchPositions = matchPositionsText.split(',').map (positionText) -> positionText.split(' ').map (pos) -> parseInt(pos) + + for [column, length] in matchPositions + range = new Range([row, column], [row, column + length]) + match = lineText.substr(column, length) + iterator({path, range, match}) + + ChildProcess.exec command , bufferLines: true, stdout: (data) -> + lines = data.split('\n') + try + for line in lines + readPath(line) if state is 'readingPath' + readLine(line) if state is 'readingLines' + catch e + console.log e.stack + + - path = bufferedData.substring(currentIndex, pathEndIndex) - row = parseInt(bufferedData.substring(pathEndIndex + 1, lineNumberEndIndex)) - 1 - line = bufferedData.substring(lineNumberEndIndex + 1, lineEndIndex) - while match = regex.exec(line) - range = new Range([row, match.index], [row, match.index + match[0].length]) - iterator({path, match, range}) - currentIndex = lineEndIndex + 1 - bufferedData = bufferedData.substring(currentIndex) - promise.done -> console.log "DONE" _.extend Project.prototype, EventEmitter diff --git a/vendor/ag b/vendor/ag new file mode 100755 index 000000000..9fe011bbd Binary files /dev/null and b/vendor/ag differ