From a21082395da6139ba6dc2da2811b6ba5e0d8e328 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Mon, 9 Apr 2012 11:41:04 -0700 Subject: [PATCH 1/2] :lipstick: --- spec/app/buffer-spec.coffee | 24 +++++++++---------- src/app/buffer.coffee | 6 ++--- .../command-interpreter/regex-address.coffee | 4 ++-- .../select-all-matches.coffee | 2 +- .../command-interpreter/substitution.coffee | 2 +- src/app/cursor.coffee | 8 +++---- src/app/editor.coffee | 4 ++-- 7 files changed, 25 insertions(+), 25 deletions(-) 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..ff25816e3 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -162,7 +162,7 @@ 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') @@ -207,12 +207,12 @@ class Buffer 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() 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 01f145623..59407a3dc 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 position = null bufferPosition = @getBufferPosition() range = [[0,0], bufferPosition] - @editor.backwardsTraverseRegexMatchesInRange @wordRegex, range, (match, matchRange, { stop }) => + @editor.backwardsScanInRange @wordRegex, range, (match, matchRange, { stop }) => position = matchRange.start if not allowPrevious and matchRange.end.isLessThan(bufferPosition) position = bufferPosition @@ -116,7 +116,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 @@ -141,7 +141,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) From 6db9360c5f0bfca3235da1ccb078e284e4d31a27 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Mon, 9 Apr 2012 12:03:55 -0700 Subject: [PATCH 2/2] Make scanInRange iterative instead of recursive --- src/app/buffer.coffee | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/app/buffer.coffee b/src/app/buffer.coffee index ff25816e3..8669bfb88 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -167,7 +167,12 @@ class Buffer 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,12 +205,8 @@ class Buffer matchStartIndex++ matchEndIndex++ - if global and recurse - traverseRecursively(text, matchEndIndex, endIndex, lengthDelta) - - startIndex = @characterIndexForPosition(range.start) - endIndex = @characterIndexForPosition(range.end) - traverseRecursively(@getText(), startIndex, endIndex, 0) + break unless global and keepLooping + startIndex = matchEndIndex backwardsScanInRange: (regex, range, iterator) -> global = regex.global @@ -217,8 +218,8 @@ class Buffer 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)