Add OnigRegExp.captureIndices(string, index, regexes)

Allows us to know if a zero-length regex matched.
This commit is contained in:
Corey Johnson 2012-09-06 15:26:42 -07:00
parent 48fdf8a708
commit 4f2cc1f856
3 changed files with 40 additions and 20 deletions

View File

@ -57,8 +57,8 @@ public:
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];
if (captureLength == 0) continue;
array->SetValue(i++, CefV8Value::CreateInt(index));
array->SetValue(i++, CefV8Value::CreateInt(captureStart));
array->SetValue(i++, CefV8Value::CreateInt(captureStart + captureLength));
@ -93,18 +93,28 @@ bool OnigRegExp::Execute(const CefString& name,
CefRefPtr<CefV8Value> index = arguments[1];
CefRefPtr<CefV8Value> regexes = arguments[2];
int bestIndex = -1;
CefRefPtr<CefV8Value> captureIndicesForBestIndex;
CefRefPtr<CefV8Value> captureIndices;
retval = CefV8Value::CreateObject(NULL);
for (int i = 0; i < regexes->GetArrayLength(); i++) {
OnigRegExpUserData *userData = (OnigRegExpUserData *)regexes->GetValue(i)->GetUserData().get();
captureIndices = userData->GetCaptureIndices(string, index);
if (captureIndices->IsObject()) {
retval->SetValue("index", CefV8Value::CreateInt(i), V8_PROPERTY_ATTRIBUTE_NONE);
retval->SetValue("captureIndices", captureIndices, V8_PROPERTY_ATTRIBUTE_NONE);
return true;
if (captureIndices->IsNull()) continue;
if (bestIndex == -1 || captureIndices->GetValue(1)->GetIntValue() < captureIndicesForBestIndex->GetValue(1)->GetIntValue()) {
bestIndex = i;
captureIndicesForBestIndex = captureIndices;
if (captureIndices->GetValue(1)->GetIntValue() == 0) break; // If the match starts at 0, just use it!
}
}
if (bestIndex != -1) {
retval->SetValue("index", CefV8Value::CreateInt(bestIndex), V8_PROPERTY_ATTRIBUTE_NONE);
retval->SetValue("captureIndices", captureIndicesForBestIndex, V8_PROPERTY_ATTRIBUTE_NONE);
}
return true;
}

View File

@ -141,3 +141,10 @@ describe "TextMateGrammar", ->
it "returns a single token which has the global scope", ->
{tokens} = grammar.getLineTokens('')
expect(tokens[0]).toEqual value: '', scopes: ["source.coffee"]
describe "when the line matches a pattern with a 'contentName' key", ->
it "creates tokens using the content of contentName as the token name", ->
grammar = TextMateBundle.grammarForFileName("sample.txt")
{tokens} = grammar.getLineTokens('ok, cool')
expect(tokens[0]).toEqual value: 'ok, cool', scopes: ["text.plain", "meta.paragraph.text"]

View File

@ -93,23 +93,21 @@ class Rule
getAllPatterns: (included=[]) ->
return [] if _.include(included, this)
included.push(this)
regexPatternPairs = []
allPatterns = []
regexPatternPairs.push(@endPattern.getIncludedPatterns()...) if @endPattern
allPatterns.push(@endPattern.getIncludedPatterns()...) if @endPattern
for pattern in @patterns
regexPatternPairs.push(pattern.getIncludedPatterns(included)...)
regexPatternPairs
allPatterns.push(pattern.getIncludedPatterns(included)...)
allPatterns
getNextTokens: (stack, line, position) ->
captureIndices = @regex.getCaptureIndices(line, position)
patterns = @getAllPatterns()
{index, captureIndices} = OnigRegExp.captureIndices(line, position, patterns.map (p) -> p.regex )
return {} unless captureIndices?[2] > 0 # ignore zero-length matches
shiftCapture(captureIndices)
return {} unless index?
[firstCaptureIndex, firstCaptureStart, firstCaptureEnd] = captureIndices
pattern = @patternsByCaptureIndex[firstCaptureIndex]
nextTokens = pattern.handleMatch(stack, line, captureIndices)
nextTokens = patterns[index].handleMatch(stack, line, captureIndices)
{ nextTokens, tokensStartPosition: firstCaptureStart, tokensEndPosition: firstCaptureEnd }
getNextMatch: (line, position) ->
@ -167,10 +165,16 @@ class Pattern
scopes.push(@scopeName) unless @popRule
if @captures
parentCapture = captureIndices[0..2]
childCaptures = captureIndices[3..]
tokens = @getTokensForCaptureIndices(line, captureIndices, scopes)
else
[start, end] = captureIndices[1..2]
tokens = [{ value: line[start...end], scopes: scopes }]
zeroLengthMatch = end == start
if zeroLengthMatch
tokens = []
else
tokens = [{ value: line[start...end], scopes: scopes }]
if @pushRule
stack.push(@pushRule)
@ -179,12 +183,11 @@ class Pattern
tokens
getTokensForCaptureIndices: (line, captureIndices, scopes, indexOffset=captureIndices[0]) ->
getTokensForCaptureIndices: (line, captureIndices, scopes) ->
[parentCaptureIndex, parentCaptureStart, parentCaptureEnd] = shiftCapture(captureIndices)
relativeParentCaptureIndex = parentCaptureIndex - indexOffset
tokens = []
if scope = @captures[relativeParentCaptureIndex]?.name
if scope = @captures[parentCaptureIndex]?.name
scopes = scopes.concat(scope)
previousChildCaptureEnd = parentCaptureStart
@ -196,7 +199,7 @@ class Pattern
value: line[previousChildCaptureEnd...childCaptureStart]
scopes: scopes
captureTokens = @getTokensForCaptureIndices(line, captureIndices, scopes, indexOffset)
captureTokens = @getTokensForCaptureIndices(line, captureIndices, scopes)
tokens.push(captureTokens...)
previousChildCaptureEnd = childCaptureEnd