/*******************************************************************************
* Copyright (c) 2016 Red Hat.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat - Initial Contribution
*******************************************************************************/
package org.eclipse.linuxtools.internal.docker.ui.consoles;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.custom.StyledText;
/**
* A builder for {@link StyledText}
*/
public class StyledTextBuilder {
/** The 'ESC' character that prefixes ANSI code sequences. */
public static final char ESC = (char) 27;
/**
* Parses the given {@code lineText} and returns a {@link StyledString} with
* configured foreground color on specific portions.
*
* @param lineText
* the line of text to parse
* @return the corresponding {@link StyledString}
* @see <a href="https://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape
* codes</a>
*/
public static StyledString parse(final String lineText) {
final StyledString result = new StyledString();
// looking for blocks of characters starting with 'ESC[xxm' (where 'xx'
// is
// a color code)
// and optionally ending with 'ESC[0m'
final Pattern colorSequencePattern = Pattern
.compile("\\x1b\\[(?<colorcode>\\d{1,2})m(?<content>.*)"); //$NON-NLS-1$
final Matcher colorSequenceMatcher = colorSequencePattern
.matcher(lineText);
int lastColorSequencePosition = 0;
int lastColorSequenceCode = 0; // default color (Black)
while (colorSequenceMatcher.find(lastColorSequencePosition)) {
final int currentColorSequenceStartPosition = colorSequenceMatcher
.start();
final String colorCode = colorSequenceMatcher.group("colorcode");
// catch-up with initial in-between content that has no specific
// color code boundaries or with the last color sequence position
if (lastColorSequencePosition < currentColorSequenceStartPosition) {
final String inbetweenContent = lineText.substring(
lastColorSequencePosition,
currentColorSequenceStartPosition);
if (!inbetweenContent.isEmpty()) {
result.append(inbetweenContent,
StylerBuilder.styler(lastColorSequenceCode));
}
}
lastColorSequencePosition = currentColorSequenceStartPosition
// counting the 'ESC' char too
+ (ESC + "[" + colorCode + "m").length();
lastColorSequenceCode = Integer.parseInt(colorCode);
}
// catch-up with remaining content that has no specific color code
// boundaries
if (lastColorSequencePosition < lineText.length()) {
final String lastSequence = lineText
.substring(lastColorSequencePosition);
result.append(new StyledString(lastSequence,
StylerBuilder.styler(lastColorSequenceCode)));
}
return result;
}
}