diff --git a/spec/app/buffer-spec.coffee b/spec/app/buffer-spec.coffee index 04d974e14..8aa57817e 100644 --- a/spec/app/buffer-spec.coffee +++ b/spec/app/buffer-spec.coffee @@ -225,12 +225,12 @@ 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 ".scanRegexMatchesInRange(range, regex, fn)", -> + describe ".scanInRange(range, regex, 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.scanRegexMatchesInRange /cu(rr)ent/, [[4,0], [6,44]], (match, range) -> + buffer.scanInRange /cu(rr)ent/, [[4,0], [6,44]], (match, range) -> matches.push(match) ranges.push(range) @@ -245,7 +245,7 @@ describe 'Buffer', -> it "calls the iterator with each match for the given regex in the given range", -> matches = [] ranges = [] - buffer.scanRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range) -> + buffer.scanInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range) -> matches.push(match) ranges.push(range) @@ -269,7 +269,7 @@ describe 'Buffer', -> it "calls the iterator with the truncated match", -> matches = [] ranges = [] - buffer.scanRegexMatchesInRange /cu(r*)/g, [[4,0], [6,9]], (match, range) -> + buffer.scanInRange /cu(r*)/g, [[4,0], [6,9]], (match, range) -> matches.push(match) ranges.push(range) @@ -288,7 +288,7 @@ describe 'Buffer', -> it "calls the iterator with the truncated match", -> matches = [] ranges = [] - buffer.scanRegexMatchesInRange /cu(r*)e/g, [[4,0], [6,9]], (match, range) -> + buffer.scanInRange /cu(r*)e/g, [[4,0], [6,9]], (match, range) -> matches.push(match) ranges.push(range) @@ -302,7 +302,7 @@ describe 'Buffer', -> describe "when the iterator calls the 'replace' control function with a replacement string", -> it "replaces each occurrence of the regex match with the string", -> ranges = [] - buffer.scanRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { replace }) -> + buffer.scanInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { replace }) -> ranges.push(range) replace("foo") @@ -316,18 +316,18 @@ describe 'Buffer', -> describe "when the iterator calls the 'stop' control function", -> it "stops the traversal", -> ranges = [] - buffer.scanRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { stop }) -> + buffer.scanInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { stop }) -> ranges.push(range) stop() if ranges.length == 2 expect(ranges.length).toBe 2 - describe "backwardsTraverseRegexMatchesInRange(range, regex, fn)", -> + describe "backwardsScanInRange(range, regex, fn)", -> describe "when given a regex with no global flag", -> it "calls the iterator with the last match for the given regex in the given range", -> matches = [] ranges = [] - buffer.backwardsTraverseRegexMatchesInRange /cu(rr)ent/, [[4,0], [6,44]], (match, range) -> + buffer.backwardsScanInRange /cu(rr)ent/, [[4,0], [6,44]], (match, range) -> matches.push(match) ranges.push(range) @@ -342,7 +342,7 @@ describe 'Buffer', -> it "calls the iterator with each match for the given regex in the given range, starting with the last match", -> matches = [] ranges = [] - buffer.backwardsTraverseRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range) -> + buffer.backwardsScanInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range) -> matches.push(match) ranges.push(range) @@ -364,7 +364,7 @@ describe 'Buffer', -> describe "when the iterator calls the 'replace' control function with a replacement string", -> it "replaces each occurrence of the regex match with the string", -> ranges = [] - buffer.backwardsTraverseRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { replace }) -> + buffer.backwardsScanInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { replace }) -> ranges.push(range) replace("foo") unless range.start.isEqual([6,6]) @@ -378,7 +378,7 @@ describe 'Buffer', -> describe "when the iterator calls the 'stop' control function", -> it "stops the traversal", -> ranges = [] - buffer.backwardsTraverseRegexMatchesInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { stop }) -> + buffer.backwardsScanInRange /cu(rr)ent/g, [[4,0], [6,59]], (match, range, { stop }) -> ranges.push(range) stop() if ranges.length == 2 diff --git a/src/app/buffer.coffee b/src/app/buffer.coffee index b7f53ea44..8669bfb88 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -162,12 +162,17 @@ class Buffer @mode = new (require("ace/mode/#{modeName}").Mode) - scanRegexMatchesInRange: (regex, range, iterator) -> + scanInRange: (regex, range, iterator) -> range = Range.fromObject(range) global = regex.global regex = new RegExp(regex.source, 'gm') - traverseRecursively = (text, startIndex, endIndex, lengthDelta) => + text = @getText() + startIndex = @characterIndexForPosition(range.start) + endIndex = @characterIndexForPosition(range.end) + lengthDelta = 0 + + while true regex.lastIndex = startIndex return unless match = regex.exec(text) @@ -186,9 +191,9 @@ class Buffer startPosition = @positionForCharacterIndex(matchStartIndex + lengthDelta) endPosition = @positionForCharacterIndex(matchEndIndex + lengthDelta) range = new Range(startPosition, endPosition) - recurse = true + keepLooping = true replacementText = null - stop = -> recurse = false + stop = -> keepLooping = false replace = (text) -> replacementText = text iterator(match, range, { stop, replace }) @@ -200,25 +205,21 @@ class Buffer matchStartIndex++ matchEndIndex++ - if global and recurse - traverseRecursively(text, matchEndIndex, endIndex, lengthDelta) + break unless global and keepLooping + startIndex = matchEndIndex - startIndex = @characterIndexForPosition(range.start) - endIndex = @characterIndexForPosition(range.end) - traverseRecursively(@getText(), startIndex, endIndex, 0) - - backwardsTraverseRegexMatchesInRange: (regex, range, iterator) -> + backwardsScanInRange: (regex, range, iterator) -> global = regex.global regex = new RegExp(regex.source, 'gm') matches = [] - @scanRegexMatchesInRange regex, range, (match, matchRange) -> + @scanInRange regex, range, (match, matchRange) -> matches.push([match, matchRange]) matches.reverse() - recurse = true - stop = -> recurse = false + keepLooping = true + stop = -> keepLooping = false replacementText = null replace = (text) -> replacementText = text @@ -226,7 +227,7 @@ class Buffer replacementText = null iterator(match, matchRange, { stop, replace }) @change(matchRange, replacementText) if replacementText - return unless global and recurse + return unless global and keepLooping _.extend(Buffer.prototype, EventEmitter) diff --git a/src/app/command-interpreter/regex-address.coffee b/src/app/command-interpreter/regex-address.coffee index eb670a0a3..6ba6aa475 100644 --- a/src/app/command-interpreter/regex-address.coffee +++ b/src/app/command-interpreter/regex-address.coffee @@ -12,14 +12,14 @@ class RegexAddress extends Address rangeToSearch = new Range(currentRange.end, editor.getEofPosition()) rangeToReturn = null - editor.buffer.scanRegexMatchesInRange @regex, rangeToSearch, (match, range) -> + editor.buffer.scanInRange @regex, rangeToSearch, (match, range) -> rangeToReturn = range if rangeToReturn rangeToReturn else rangeToSearch = new Range([0, 0], rangeToSearch.start) - editor.buffer.scanRegexMatchesInRange @regex, rangeToSearch, (match, range) -> + editor.buffer.scanInRange @regex, rangeToSearch, (match, range) -> rangeToReturn = range rangeToReturn or currentRange diff --git a/src/app/command-interpreter/select-all-matches.coffee b/src/app/command-interpreter/select-all-matches.coffee index 6bbf49901..a0eb0babb 100644 --- a/src/app/command-interpreter/select-all-matches.coffee +++ b/src/app/command-interpreter/select-all-matches.coffee @@ -10,6 +10,6 @@ class SelectAllMatches extends Command execute: (editor, currentRange) -> rangesToSelect = [] - editor.buffer.scanRegexMatchesInRange @regex, currentRange, (match, range) -> + editor.buffer.scanInRange @regex, currentRange, (match, range) -> rangesToSelect.push(range) rangesToSelect diff --git a/src/app/command-interpreter/substitution.coffee b/src/app/command-interpreter/substitution.coffee index c1ed234eb..9851d2137 100644 --- a/src/app/command-interpreter/substitution.coffee +++ b/src/app/command-interpreter/substitution.coffee @@ -10,6 +10,6 @@ class Substitution extends Command @regex = new RegExp(pattern, options.join('')) execute: (editor, currentRange) -> - editor.buffer.scanRegexMatchesInRange @regex, currentRange, (match, matchRange, { replace }) => + editor.buffer.scanInRange @regex, currentRange, (match, matchRange, { replace }) => replace(@replacementText) [currentRange] diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index 47cbefe16..1fc71c5ba 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -86,7 +86,7 @@ class Cursor extends View range = [bufferPosition, @editor.getEofPosition()] nextPosition = null - @editor.scanRegexMatchesInRange @wordRegex, range, (match, matchRange, { stop }) => + @editor.scanInRange @wordRegex, range, (match, matchRange, { stop }) => if matchRange.start.isGreaterThan(bufferPosition) nextPosition = matchRange.start stop() @@ -104,7 +104,7 @@ class Cursor extends View currentBufferPosition = @getBufferPosition() beginningOfWordPosition = currentBufferPosition range = [[0,0], currentBufferPosition] - @editor.backwardsTraverseRegexMatchesInRange @wordRegex, range, (match, matchRange, { stop }) => + @editor.backwardsScanInRange @wordRegex, range, (match, matchRange, { stop }) => if matchRange.end.isGreaterThanOrEqual(currentBufferPosition) or allowPrevious beginningOfWordPosition = matchRange.start stop() @@ -115,7 +115,7 @@ class Cursor extends View position = null bufferPosition = @getBufferPosition() range = [bufferPosition, @editor.getEofPosition()] - @editor.scanRegexMatchesInRange @wordRegex, range, (match, matchRange, { stop }) => + @editor.scanInRange @wordRegex, range, (match, matchRange, { stop }) => position = matchRange.end if not allowNext and matchRange.start.isGreaterThan(bufferPosition) position = bufferPosition @@ -140,7 +140,7 @@ class Cursor extends View position = @getBufferPosition() range = @editor.rangeForBufferRow(position.row) newPosition = null - @editor.scanRegexMatchesInRange /^\s*/, range, (match, matchRange) => + @editor.scanInRange /^\s*/, range, (match, matchRange) => newPosition = matchRange.end newPosition = [position.row, 0] if newPosition.isEqual(position) @setBufferPosition(newPosition) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index 74b5f9640..3b5a89354 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -412,8 +412,8 @@ class Editor extends View lineForBufferRow: (row) -> @buffer.lineForRow(row) lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row) rangeForBufferRow: (row) -> @buffer.rangeForRow(row) - scanRegexMatchesInRange: (args...) -> @buffer.scanRegexMatchesInRange(args...) - backwardsTraverseRegexMatchesInRange: (args...) -> @buffer.backwardsTraverseRegexMatchesInRange(args...) + scanInRange: (args...) -> @buffer.scanInRange(args...) + backwardsScanInRange: (args...) -> @buffer.backwardsScanInRange(args...) insertText: (text) -> @compositeSelection.insertText(text)