Skip to content

Commit

Permalink
Look for balanced curly brace end while searching for arguments.
Browse files Browse the repository at this point in the history
  • Loading branch information
csabakos committed Aug 23, 2019
1 parent 259a5cf commit 906e9c3
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
35 changes: 32 additions & 3 deletions src/main/java/com/jcabi/log/ConversionPattern.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class ConversionPattern {
* Regular expression for all matches.
*/
private static final Pattern METAS = Pattern.compile(
"%color(?:-([a-z]+|[0-9]{1,3};[0-9]{1,3};[0-9]{1,3}))?\\{(.*?)\\}"
"%color(?:-([a-z]+|[0-9]{1,3};[0-9]{1,3};[0-9]{1,3}))?\\{"
);

/**
Expand All @@ -67,23 +67,52 @@ class ConversionPattern {
this.colors = col;
}

/**
* Find the matching closing curly brace while keeping any nested curly brace pairs balanced.
* @param start index of first character after the opening curly brace
* @return index of the closing curly brace, or -1 if not found
*/
private static int findArgumentEnd(final String pattern, final int start) {
int openBraceCount = 1;
for (int index = start; index < pattern.length(); ++index) {
final char character = pattern.charAt(index);
if (character == '}') {
--openBraceCount;
if (openBraceCount == 0) {
return index;
}
} else if (character == '{') {
++openBraceCount;
}
}
return -1;
}

/**
* Generates the conversion pattern.
* @return Conversion pattern
*/
public String generate() {
String remainingPattern = this.pattern;
final Matcher matcher = ConversionPattern.METAS.matcher(
this.pattern
remainingPattern
);
final StringBuffer buf = new StringBuffer(0);
while (matcher.find()) {
final int argumentStart = matcher.end();
final int argumentEnd = findArgumentEnd(remainingPattern, argumentStart);
if (argumentEnd < 0) {
break;
}
matcher.appendReplacement(buf, "");
buf.append(ConversionPattern.csi())
.append(this.colors.ansi(matcher.group(1)))
.append('m')
.append(matcher.group(2))
.append(remainingPattern, argumentStart, argumentEnd)
.append(ConversionPattern.csi())
.append('m');
remainingPattern = remainingPattern.substring(argumentEnd + 1);
matcher.reset(remainingPattern);
}
matcher.appendTail(buf);
return buf.toString();
Expand Down
44 changes: 44 additions & 0 deletions src/test/java/com/jcabi/log/ConversionPatternTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.jcabi.log;

import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Test;

public class ConversionPatternTest {
private static final String CSI = "\u001b\\[";
private static final Colors COLORS = new Colors();

@Test
public void testGenerateNoReplacement() {
MatcherAssert.assertThat(convert(""), Matchers.equalTo(""));
MatcherAssert.assertThat(convert("foo"), Matchers.equalTo("foo"));
MatcherAssert.assertThat(convert("%color"), Matchers.equalTo("%color"));
MatcherAssert.assertThat(convert("%color-"), Matchers.equalTo("%color-"));
MatcherAssert.assertThat(convert("%color{%c{1}foo"), Matchers.equalTo("%color{%c{1}foo"));
}

@Test
public void testGenerateEmpty() {
MatcherAssert.assertThat(convert("%color{}"), Matchers.equalTo(CSI + "?m" + CSI + "m"));
}

@Test
public void testGenerateSimple() {
MatcherAssert.assertThat(convert("%color{Hello World}"), Matchers.equalTo(CSI + "?mHello World" + CSI + "m"));
MatcherAssert.assertThat(convert("%color{Hello World}foo"), Matchers.equalTo(CSI + "?mHello World" + CSI + "mfoo"));

MatcherAssert.assertThat(convert("%color{Hello}%color{World}"), Matchers.equalTo(CSI + "?mHello" + CSI + "m" + CSI + "?mWorld" + CSI + "m"));
}

@Test
public void testGenerateCurlyBraces() {
MatcherAssert.assertThat(convert("%color{%c{1}}"), Matchers.equalTo(CSI + "?m%c{1}" + CSI + "m"));
MatcherAssert.assertThat(convert("%color{%c{1}}foo"), Matchers.equalTo(CSI + "?m%c{1}" + CSI + "mfoo"));
MatcherAssert.assertThat(convert("%color{%c1}}foo"), Matchers.equalTo(CSI + "?m%c1" + CSI + "m}foo"));
MatcherAssert.assertThat(convert("%color{%c{{{1}{2}}}}foo"), Matchers.equalTo(CSI + "?m%c{{{1}{2}}}" + CSI + "mfoo"));
}

private static String convert(final String pat) {
return new ConversionPattern(pat, COLORS).generate();
}
}

0 comments on commit 906e9c3

Please sign in to comment.