Add Buffer.traverseRegexMatchesInRange

This commit is contained in:
Nathan Sobo
2012-03-27 17:41:53 -07:00
parent 7707ac5943
commit 847e3d16e5
2 changed files with 88 additions and 0 deletions

View File

@@ -204,6 +204,59 @@ describe 'Buffer', ->
range = [[2,10], [4,10]]
expect(buffer.getTextInRange(range)).toBe "ems.length <= 1) return items;\n var pivot = items.shift(), current, left = [], right = [];\n while("
describe ".traverseRegexMatchesInRange(range, regexSource, fn)", ->
describe "when given a regex with no global flag", ->
it "calls the iterator with the first match for the given regex in the given range", ->
matches = []
ranges = []
buffer.traverseRegexMatchesInRange /cu(rr)ent/, [[4,0], [6,44]], (match, range) ->
matches.push(match)
ranges.push(range)
expect(matches.length).toBe 1
expect(ranges.length).toBe 1
expect(matches[0][0]).toBe 'current'
expect(matches[0][1]).toBe 'rr'
expect(ranges[0]).toEqual [[5,6], [5,13]]
describe "when given a regex with a global flag", ->
it "calls the iterator with each match for the given regex in the given range", ->
matches = []
ranges = []
buffer.traverseRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range) ->
matches.push(match)
ranges.push(range)
expect(matches.length).toBe 3
expect(ranges.length).toBe 3
expect(matches[0][0]).toBe 'current'
expect(matches[0][1]).toBe 'rr'
expect(ranges[0]).toEqual [[5,6], [5,13]]
expect(matches[1][0]).toBe 'current'
expect(matches[1][1]).toBe 'rr'
expect(ranges[1]).toEqual [[6,6], [6,13]]
expect(matches[2][0]).toBe 'current'
expect(matches[2][1]).toBe 'rr'
expect(ranges[2]).toEqual [[6,34], [6,41]]
describe "when the iterator returns a replacement string", ->
it "replaces each occurrence of the regex match with the string", ->
ranges = []
buffer.traverseRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range) ->
ranges.push(range)
"foo"
expect(ranges[0]).toEqual [[5,6], [5,13]]
expect(ranges[1]).toEqual [[6,6], [6,13]]
expect(ranges[2]).toEqual [[6,30], [6,37]]
expect(buffer.lineForRow(5)).toBe ' foo = items.shift();'
expect(buffer.lineForRow(6)).toBe ' foo < pivot ? left.push(foo) : right.push(current);'
describe ".characterIndexForPosition(position)", ->
it "returns the total number of charachters that precede the given position", ->
expect(buffer.characterIndexForPosition([0, 0])).toBe 0

View File

@@ -140,4 +140,39 @@ class Buffer
@mode = new (require("ace/mode/#{modeName}").Mode)
traverseRegexMatchesInRange: (regex, range, iterator) ->
range = Range.fromObject(range)
global = regex.global
regex = new RegExp(regex.source, 'gm')
traverseRecursively = (text, startIndex, endIndex, lengthDelta) =>
regex.lastIndex = startIndex
return unless match = regex.exec(text)
matchLength = match[0].length
matchStartIndex = match.index
matchEndIndex = match.index + matchLength
return if matchEndIndex > endIndex
startPosition = @positionForCharacterIndex(matchStartIndex + lengthDelta)
endPosition = @positionForCharacterIndex(matchEndIndex + lengthDelta)
range = new Range(startPosition, endPosition)
replacementText = iterator(match, range)
if _.isString(replacementText)
@change(range, replacementText)
lengthDelta += replacementText.length - matchLength
if matchLength is 0
matchStartIndex++
matchEndIndex++
if global
traverseRecursively(text, matchEndIndex, endIndex, lengthDelta)
startIndex = @characterIndexForPosition(range.start)
endIndex = @characterIndexForPosition(range.end)
traverseRecursively(@getText(), startIndex, endIndex, 0)
_.extend(Buffer.prototype, EventEmitter)