diff --git a/Atom/src/OnigRegexpExtension.mm b/Atom/src/OnigRegexpExtension.mm index 0d95259be..e76dd4860 100644 --- a/Atom/src/OnigRegexpExtension.mm +++ b/Atom/src/OnigRegexpExtension.mm @@ -37,37 +37,27 @@ public: return resultArray; } - CefRefPtr GetCaptureTree(CefRefPtr string, CefRefPtr index) { + CefRefPtr GetCaptureIndices(CefRefPtr string, CefRefPtr index) { OnigResult *result = [m_regex search:stringFromCefV8Value(string) start:index->GetIntValue()]; if ([result count] == 0) return CefV8Value::CreateNull(); - return BuildCaptureTree(result); + return BuildCaptureIndices(result); } - CefRefPtr BuildCaptureTree(OnigResult *result) { - int index = 0; - return BuildCaptureTree(result, index); - } + CefRefPtr BuildCaptureIndices(OnigResult *result) { + CefRefPtr array = CefV8Value::CreateArray(); + int i = 0; - CefRefPtr BuildCaptureTree(OnigResult *result, int &index) { - int currentIndex = index++; - int startPosition = [result locationAt:currentIndex]; - int endPosition = startPosition + [result lengthAt:currentIndex]; - - CefRefPtr tree = CefV8Value::CreateArray(); - int i = 0; - tree->SetValue(i++, CefV8Value::CreateInt(currentIndex)); - tree->SetValue(i++, CefV8Value::CreateInt(startPosition)); - tree->SetValue(i++, CefV8Value::CreateInt(endPosition)); - - while (index < [result count] && [result locationAt:index] < endPosition) { - if ([result lengthAt:index] == 0) { - index++; - } else { - tree->SetValue(i++, BuildCaptureTree(result, index)); - } + int resultCount = [result count]; + for (int index = 0; index < resultCount; index++) { + int captureLength = [result lengthAt:index]; + if (captureLength == 0) continue; + int captureStart = [result locationAt:index]; + array->SetValue(i++, CefV8Value::CreateInt(index)); + array->SetValue(i++, CefV8Value::CreateInt(captureStart)); + array->SetValue(i++, CefV8Value::CreateInt(captureStart + captureLength)); } - return tree; + return array; } CefRefPtr CaptureCount() { @@ -91,11 +81,11 @@ bool OnigRegexpExtension::Execute(const CefString& name, CefRefPtr& retval, CefString& exception) { - if (name == "getCaptureTree") { + if (name == "getCaptureIndices") { CefRefPtr string = arguments[0]; CefRefPtr index = arguments.size() > 1 ? arguments[1] : CefV8Value::CreateInt(0); OnigRegexpUserData *userData = (OnigRegexpUserData *)object->GetUserData().get(); - retval = userData->GetCaptureTree(string, index); + retval = userData->GetCaptureIndices(string, index); return true; } else if (name == "buildOnigRegExp") { diff --git a/src/app/text-mate-grammar.coffee b/src/app/text-mate-grammar.coffee index b85a04f45..35056b152 100644 --- a/src/app/text-mate-grammar.coffee +++ b/src/app/text-mate-grammar.coffee @@ -92,22 +92,17 @@ class Rule regexPatternPairs getNextTokens: (stack, line, position) -> - captureTree = @regex.getCaptureTree(line, position) - return {} unless captureTree?[2] > 0 # ignore zero-length matches + captureIndices = @regex.getCaptureIndices(line, position) - firstCapture = captureTree[3] - [firstCaptureIndex, firstCaptureStart, firstCaptureEnd] = firstCapture + return {} unless captureIndices?[2] > 0 # ignore zero-length matches + + shiftCapture(captureIndices) + + [firstCaptureIndex, firstCaptureStart, firstCaptureEnd] = captureIndices pattern = @patternsByCaptureIndex[firstCaptureIndex] - - @adjustCaptureTreeIndices(firstCapture, firstCaptureIndex) - nextTokens = pattern.handleMatch(stack, line, firstCapture) + nextTokens = pattern.handleMatch(stack, line, captureIndices) { nextTokens, tokensStartPosition: firstCaptureStart, tokensEndPosition: firstCaptureEnd } - adjustCaptureTreeIndices: (tree, startIndex) -> - tree[0] -= startIndex - for capture in tree[3..] - @adjustCaptureTreeIndices(capture, startIndex) - getNextMatch: (line, position) -> nextMatch = null matchedPattern = null @@ -156,16 +151,16 @@ class Pattern rule = @grammar.ruleForInclude(@include) rule.getNextMatch(line, position) else - { match: @regex.getCaptureTree(line, position), pattern: this } + { match: @regex.getCaptureIndices(line, position), pattern: this } - handleMatch: (stack, line, captureTree) -> + handleMatch: (stack, line, captureIndices) -> scopes = _.pluck(stack, "scopeName") scopes.push(@scopeName) unless @popRule if @captures - tokens = @getTokensForCaptureTree(line, captureTree, scopes) + tokens = @getTokensForCaptureIndices(line, captureIndices, scopes) else - [start, end] = captureTree[1..2] + [start, end] = captureIndices[1..2] tokens = [{ value: line[start...end], scopes: scopes }] if @pushRule @@ -175,22 +170,24 @@ class Pattern tokens - getTokensForCaptureTree: (line, parentCapture, scopes) -> - [parentCaptureIndex, parentCaptureStart, parentCaptureEnd, childCaptures...] = parentCapture + getTokensForCaptureIndices: (line, captureIndices, scopes, indexOffset=captureIndices[0]) -> + [parentCaptureIndex, parentCaptureStart, parentCaptureEnd] = shiftCapture(captureIndices) + relativeParentCaptureIndex = parentCaptureIndex - indexOffset tokens = [] - if scope = @captures[parentCaptureIndex]?.name + if scope = @captures[relativeParentCaptureIndex]?.name scopes = scopes.concat(scope) previousChildCaptureEnd = parentCaptureStart - for childCapture in childCaptures - [childCaptureIndex, childCaptureStart, childCaptureEnd] = childCapture + while captureIndices.length and captureIndices[1] < parentCaptureEnd + [childCaptureIndex, childCaptureStart, childCaptureEnd] = captureIndices + if childCaptureStart > previousChildCaptureEnd tokens.push value: line[previousChildCaptureEnd...childCaptureStart] scopes: scopes - captureTokens = @getTokensForCaptureTree(line, childCapture, scopes) + captureTokens = @getTokensForCaptureIndices(line, captureIndices, scopes, indexOffset) tokens.push(captureTokens...) previousChildCaptureEnd = childCaptureEnd @@ -200,3 +197,7 @@ class Pattern scopes: scopes tokens + +shiftCapture = (captureIndices) -> + [captureIndices.shift(), captureIndices.shift(), captureIndices.shift()] + diff --git a/src/stdlib/onig-reg-exp-extension.js b/src/stdlib/onig-reg-exp-extension.js index c1802b465..9e4c66be1 100644 --- a/src/stdlib/onig-reg-exp-extension.js +++ b/src/stdlib/onig-reg-exp-extension.js @@ -1,7 +1,7 @@ (function() { native function buildOnigRegExp(source); native function search(string, index); - native function getCaptureTree(source, index); + native function getCaptureIndices(source, index); native function getCaptureCount(); function OnigRegExp(source) { @@ -13,7 +13,7 @@ } OnigRegExp.prototype.search = search; - OnigRegExp.prototype.getCaptureTree = getCaptureTree; + OnigRegExp.prototype.getCaptureIndices = getCaptureIndices; OnigRegExp.prototype.getCaptureCount = getCaptureCount; this.OnigRegExp = OnigRegExp;