Skip to content

Commit

Permalink
issue #24: ability to specify default fg/bg colors
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Oster committed Jan 25, 2015
1 parent d111c11 commit 780b24f
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,8 @@
0.4.2 (Next)
============

* [#24](https://github.com/dblock/jenkins-ansicolor-plugin/issues/24): Configurable default fg/bg colors - [@ejelly](https://github.com/ejelly).

* Your contribution here.

0.4.1 (12/11/2014)
Expand Down
Expand Up @@ -14,7 +14,7 @@

class AnsiAttributeElement {
public static enum AnsiAttrType {
BOLD, UNDERLINE, FG, BG
DEFAULT, BOLD, UNDERLINE, FG, BG
}

AnsiAttrType ansiAttrType;
Expand Down
Expand Up @@ -51,6 +51,7 @@
*
* @author Daniel Doubrovkine
*/
@SuppressWarnings("unused")
public final class AnsiColorBuildWrapper extends BuildWrapper {

private final String colorMapName;
Expand All @@ -61,7 +62,7 @@ public final class AnsiColorBuildWrapper extends BuildWrapper {
* Create a new {@link AnsiColorBuildWrapper}.
*/
@DataBoundConstructor
public AnsiColorBuildWrapper(String colorMapName) {
public AnsiColorBuildWrapper(String colorMapName, Integer defaultFg, Integer defaultBg) {
this.colorMapName = colorMapName;
}

Expand All @@ -86,6 +87,10 @@ public Environment setUp(AbstractBuild build, Launcher launcher,
public OutputStream decorateLogger(AbstractBuild build, final OutputStream logger) {
final AnsiColorMap colorMap = getDescriptor().getColorMap(getColorMapName());

if (logger == null) {
return null;
}

return new LineTransformationOutputStream() {
AnsiHtmlOutputStream ansi = new AnsiHtmlOutputStream(logger, colorMap, new AnsiAttributeElement.Emitter() {
public void emitHtml(String html) {
Expand Down Expand Up @@ -153,6 +158,7 @@ public boolean configure(final StaplerRequest req, final JSONObject formData) th
}
}

@SuppressWarnings("unused")
public FormValidation doCheckName(@QueryParameter final String value) {
return (value.trim().length() == 0) ? FormValidation.error("Name cannot be empty.") : FormValidation.ok();
}
Expand All @@ -175,6 +181,7 @@ public AnsiColorMap getColorMap(final String name) {
return AnsiColorMap.Default;
}

@SuppressWarnings("unused")
public ListBoxModel doFillColorMapNameItems() {
ListBoxModel m = new ListBoxModel();
for(AnsiColorMap colorMap : getColorMaps()) {
Expand All @@ -185,6 +192,28 @@ public ListBoxModel doFillColorMapNameItems() {
return m;
}

@SuppressWarnings("unused")
public ListBoxModel doFillDefaultForegroundItems() {
ListBoxModel m = new ListBoxModel();

m.add("Jenkins Default", "");
m.add("black", "0");
m.add("red", "1");
m.add("green", "2");
m.add("yellow", "3");
m.add("blue", "4");
m.add("magenta", "5");
m.add("cyan", "6");
m.add("white", "7");

return m;
}

@SuppressWarnings("unused")
public ListBoxModel doFillDefaultBackgroundItems() {
return doFillDefaultForegroundItems();
}

/**
* {@inheritDoc}
*/
Expand Down
25 changes: 18 additions & 7 deletions src/main/java/hudson/plugins/ansicolor/AnsiColorMap.java
Expand Up @@ -23,10 +23,10 @@ public final class AnsiColorMap implements Serializable
private static final String[] GnomeTerminalFg = { "#2E3436", "#CC0000", "#4E9A06", "#C4A000", "#3465A4", "#75507B", "#06989A", "#D3D7CF" };
private static final String[] GnomeTerminalBg = GnomeTerminalFg;

public static final AnsiColorMap XTerm = new AnsiColorMap(XTermName, XTermFg, XTermBg);
public static final AnsiColorMap VGA = new AnsiColorMap(VGAName, VGAFg, VGABg);
public static final AnsiColorMap CSS = new AnsiColorMap(CSSName, CSSFg, CSSBg);
public static final AnsiColorMap GnomeTerminal = new AnsiColorMap(GnomeTerminalName, GnomeTerminalFg, GnomeTerminalBg);
public static final AnsiColorMap XTerm = new AnsiColorMap(XTermName, XTermFg, XTermBg, null, null);
public static final AnsiColorMap VGA = new AnsiColorMap(VGAName, VGAFg, VGABg, 7, 0);
public static final AnsiColorMap CSS = new AnsiColorMap(CSSName, CSSFg, CSSBg, null, null);
public static final AnsiColorMap GnomeTerminal = new AnsiColorMap(GnomeTerminalName, GnomeTerminalFg, GnomeTerminalBg, 7, 0);

public static final AnsiColorMap Default = XTerm;
public static final String DefaultName = Default.getName();
Expand All @@ -40,27 +40,35 @@ public static AnsiColorMap[] defaultColorMaps() {
private final String[] fgMap;
private final String[] bgMap;

// Those are nullable to not impose any default color on the output.
private final Integer defaultForeground;
private final Integer defaultBackground;

@DataBoundConstructor
public AnsiColorMap(
String name,
String black, String red, String green, String blue, String yellow, String magenta, String cyan, String white,
String blackB, String redB, String greenB, String blueB, String yellowB, String magentaB, String cyanB, String whiteB) {
String blackB, String redB, String greenB, String blueB, String yellowB, String magentaB, String cyanB, String whiteB,
Integer defaultForeground, Integer defaultBackground) {

this(
name,
colorArray(black,red,green,blue,yellow,magenta,cyan,white),
colorArray(blackB,redB,greenB,blueB,yellowB,magentaB,cyanB,whiteB));
colorArray(blackB,redB,greenB,blueB,yellowB,magentaB,cyanB,whiteB),
defaultForeground, defaultBackground);
}

private static String[] colorArray(String a, String b, String c, String d, String e, String f, String g, String h) {
String[] arr = {a,b,c,d,e,f,g,h};
return arr;
}

public AnsiColorMap(String name, String[] fgMap, String[] bgMap) {
public AnsiColorMap(String name, String[] fgMap, String[] bgMap, Integer defaultForeground, Integer defaultBackground) {
this.name = name;
this.fgMap = (String[])fgMap.clone();
this.bgMap = (String[])bgMap.clone();
this.defaultForeground = defaultForeground;
this.defaultBackground = defaultBackground;
}

public String getName() { return name; }
Expand Down Expand Up @@ -88,4 +96,7 @@ public AnsiColorMap(String name, String[] fgMap, String[] bgMap) {

public String getForeground(int index) { return fgMap[index]; }
public String getBackground(int index) { return bgMap[index]; }

public Integer getDefaultForeground() { return defaultForeground; }
public Integer getDefaultBackground() { return defaultBackground; }
}
31 changes: 25 additions & 6 deletions src/main/java/hudson/plugins/ansicolor/AnsiHtmlOutputStream.java
Expand Up @@ -50,9 +50,9 @@ public class AnsiHtmlOutputStream extends AnsiOutputStream {
private final AnsiAttributeElement.Emitter emitter;

private static enum State {
DATA, PREAMBLE, NOTE, POSTAMBLE
INIT, DATA, PREAMBLE, NOTE, POSTAMBLE
}
private State state = State.DATA;
private State state = State.INIT;
private int amblePos = 0;

// A Deque might be a better choice, but we are constrained by the Java 5 API.
Expand Down Expand Up @@ -86,9 +86,13 @@ private void openTag(AnsiAttributeElement tag) throws IOException {
tag.emitOpen(emitter);
}

private void closeOpenTags() throws IOException {
private void closeOpenTags(AnsiAttrType until) throws IOException {
while (!openTags.isEmpty()) {
openTags.remove(openTags.size() - 1).emitClose(emitter);
int index = openTags.size() - 1;
if (until != null && openTags.get(index).ansiAttrType == until)
break;

openTags.remove(index).emitClose(emitter);
}
}

Expand Down Expand Up @@ -138,6 +142,20 @@ private void closeTagOfType(AnsiAttrType ansiAttrType) throws IOException {
public void write(int data) throws IOException {
// This little state machine only exists to handle embedded notes from other sources, whereas
// the preamble is an ANSI escape sequence itself.

if (state == State.INIT) {
Integer defaultFg = colorMap.getDefaultForeground();
Integer defaultBg = colorMap.getDefaultBackground();

if (defaultFg != null || defaultBg != null) {
openTag(new AnsiAttributeElement(AnsiAttrType.DEFAULT, "div", "style=\"" +
(defaultBg != null ? "background-color: " + colorMap.getBackground(defaultBg) + ";" : "") +
(defaultFg != null ? "color: " + colorMap.getForeground(defaultFg) + ";" : "") + "\""));
}

state = State.DATA;
}

switch (state) {
case DATA:
if (data == ConsoleNote.PREAMBLE[0]) {
Expand Down Expand Up @@ -193,7 +211,8 @@ private void collectAmbleCharacter(int data, byte[] amble) throws IOException {

@Override
public void close() throws IOException {
processAttributeRest();
stopConcealing();
closeOpenTags(null);
super.close();
}

Expand Down Expand Up @@ -230,7 +249,7 @@ protected void processSetAttribute(int attribute) throws IOException {
@Override
protected void processAttributeRest() throws IOException {
stopConcealing();
closeOpenTags();
closeOpenTags(AnsiAttrType.DEFAULT);
}

@Override
Expand Down
Expand Up @@ -7,6 +7,12 @@
<f:entry title="Name" field="name">
<f:textbox value="${colorMap.name}"/>
</f:entry>
<f:entry title="Default Background" field="defaultBackground">
<f:select default="${colorMap.defaultBackground}"/>
</f:entry>
<f:entry title="Default Foreground" field="defaultForeground">
<f:select default="${colorMap.defaultForeground}"/>
</f:entry>
<f:entry title="Black">
<f:textbox title="fg" field="black" value="${colorMap.black}"/>
<f:textbox title="bg" field="blackB" value="${colorMap.blackB}"/>
Expand Down
Expand Up @@ -156,6 +156,16 @@ public void testResetBackgroundColor() throws IOException {
"<span style=\"background-color: #00FF00;\">tic<b>tac</b></span><b>toe</b>");
}

@Test
public void testDefaultColors() throws IOException {
assertThat(
annotate("\033[32mtic\033[1mtac\033[39mtoe", AnsiColorMap.VGA),
is("<div style=\"background-color: #555555;color: #AAAAAA;\">" +
"<span style=\"color: #00AA00;\">tic<b>tac</b></span><b>toe</b>" +
"</div>"));
}


@Test
public void testConsoleNote() throws IOException {
assertThat(
Expand Down

0 comments on commit 780b24f

Please sign in to comment.