org.crsh.text.Style Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2012 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.crsh.text;
import org.crsh.util.Utils;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Arrays;
/**
* A control for the text stylistric attributes:
*
* background color
* foreground color
* underline
* bold
* blink
*
*
* A style is either a composite style or the {@link #reset} style. Styles can be composed together to form a new
* style style.merge(other)
.
*/
public abstract class Style implements Serializable {
public static final Style reset = new Style() {
@Override
public Style merge(Style s) throws NullPointerException {
if (s == null) {
throw new NullPointerException();
}
return s;
}
@Override
public String toString() {
return "Style.Reset[]";
}
@Override
public void writeAnsiTo(Appendable appendable) throws IOException {
appendable.append("\033[0m");
}
};
public static final class Composite extends Style {
/** . */
protected final Boolean bold;
/** . */
protected final Boolean underline;
/** . */
protected final Boolean blink;
/** . */
protected final Color foreground;
/** . */
protected final Color background;
private Composite(Boolean bold, Boolean underline, Boolean blink, Color foreground, Color background) {
this.bold = bold;
this.underline = underline;
this.blink = blink;
this.foreground = foreground;
this.background = background;
}
public Composite fg(Color color) {
return foreground(color);
}
public Composite foreground(Color color) {
return style(bold, underline, blink, color, background);
}
public Composite bg(Color value) {
return background(value);
}
public Composite background(Color value) {
return style(bold, underline, blink, foreground, value);
}
public Composite bold() {
return bold(true);
}
public Composite underline() {
return underline(true);
}
public Composite blink() {
return blink(true);
}
public Composite bold(Boolean value) {
return style(value, underline, blink, foreground, background);
}
public Composite underline(Boolean value) {
return style(bold, value, blink, foreground, background);
}
public Composite blink(Boolean value) {
return style(bold, underline, value, foreground, background);
}
public Composite decoration(Decoration decoration) {
if (decoration != null) {
switch (decoration) {
case bold:
return bold(true);
case bold_off:
return bold(false);
case underline:
return underline(true);
case underline_off:
return underline(false);
case blink:
return blink(true);
case blink_off:
return blink(false);
}
}
return this;
}
public Boolean getBold() {
return bold;
}
public Boolean getUnderline() {
return underline;
}
public Boolean getBlink() {
return blink;
}
public Color getForeground() {
return foreground;
}
public Color getBackground() {
return background;
}
public Style merge(Style s) throws NullPointerException {
if (s == null) {
throw new NullPointerException();
}
if (s == reset) {
return reset;
} else {
Style.Composite that = (Composite)s;
Boolean bold = Utils.notNull(that.getBold(), getBold());
Boolean underline = Utils.notNull(that.getUnderline(), getUnderline());
Boolean blink = Utils.notNull(that.getBlink(), getBlink());
Color foreground = Utils.notNull(that.getForeground(), getForeground());
Color background = Utils.notNull(that.getBackground(), getBackground());
return style(bold, underline, blink, foreground, background);
}
}
@Override
public String toString() {
return "Style.Composite[bold=" + bold + ",underline=" + underline + ",blink=" + blink +
",background=" + background + ",foreground=" + foreground + "]";
}
private static boolean decoration(
Appendable appendable,
String on,
String off,
Boolean value,
boolean append) throws IOException {
if (value != null) {
if (append) {
appendable.append(';');
} else {
appendable.append("\033[");
}
if (value) {
appendable.append(on);
} else {
appendable.append(off);
}
return true;
}
return false;
}
private static boolean color(
Appendable appendable,
Color color,
char base,
boolean append) throws IOException {
if (color != null) {
if (append) {
appendable.append(';');
} else {
appendable.append("\033[");
}
appendable.append(base);
appendable.append(color.c);
return true;
}
return false;
}
@Override
public void writeAnsiTo(Appendable appendable) throws IOException {
boolean appended = decoration(appendable, Decoration.bold.code, Decoration.bold_off.code, bold, false);
appended |= decoration(appendable, Decoration.underline.code, Decoration.underline_off.code, underline, appended);
appended |= decoration(appendable, Decoration.blink.code, Decoration.blink_off.code, blink, appended);
appended |= color(appendable, foreground, '3', appended);
appended |= color(appendable, background, '4', appended);
if (appended) {
appendable.append("m");
}
}
}
/** . */
private static final Boolean[] BOOLEANS = {true,false,null};
/** . */
private static final Color[] COLORS = Arrays.copyOf(Color.values(), Color.values().length + 1);
/** [bold][underline][blink][foreground][background]. */
private static final Composite[][][][][] ALL;
static {
ALL = new Composite[BOOLEANS.length][][][][];
for (int bold = 0;bold < BOOLEANS.length;bold++) {
ALL[bold] = new Composite[BOOLEANS.length][][][];
for (int underline = 0;underline < BOOLEANS.length;underline++) {
ALL[bold][underline] = new Composite[BOOLEANS.length][][];
for (int blink = 0;blink < BOOLEANS.length;blink++) {
ALL[bold][underline][blink] = new Composite[COLORS.length][];
for (int foreground = 0;foreground < COLORS.length;foreground++) {
ALL[bold][underline][blink][foreground] = new Composite[COLORS.length];
for (int background = 0;background < COLORS.length;background++) {
ALL[bold][underline][blink][foreground][background] = new Composite(
BOOLEANS[bold],
BOOLEANS[underline],
BOOLEANS[blink],
COLORS[foreground],
COLORS[background]);
}
}
}
}
}
}
public static Composite style(Color foreground) {
return style(null, foreground, null);
}
public static Composite style(Color foreground, Color background) {
return style(null, foreground, background);
}
public static Composite style(Decoration decoration, Color foreground, Color background) {
Boolean bold = null;
Boolean underline = null;
Boolean blink = null;
if (decoration != null) {
switch (decoration) {
case bold:
bold = true;
break;
case bold_off:
bold = false;
break;
case underline:
underline = true;
break;
case underline_off:
underline = false;
break;
case blink:
blink = true;
break;
case blink_off:
blink = false;
break;
}
}
return style(bold, underline, blink, foreground, background);
}
public static Composite style(Boolean bold, Boolean underline, Boolean blink, Color foreground, Color background) {
int bo = bold != null ? bold ? 0 : 1: 2;
int un = underline != null ? underline ? 0 : 1: 2;
int bl = blink != null ? blink ? 0 : 1: 2;
int fg = foreground != null ? foreground.ordinal() : COLORS.length - 1;
int bg = background != null ? background.ordinal() : COLORS.length - 1;
return ALL[bo][un][bl][fg][bg];
}
/**
* Create a new blank style.
*
* @return the style
*/
public static Composite style() {
return style(null, null, null);
}
public static Composite style(Decoration decoration) {
return style(decoration, null, null);
}
public static Composite style(Decoration decoration, Color foreground) {
return style(decoration, foreground, null);
}
public abstract Style merge(Style s) throws NullPointerException;
public CharSequence toAnsiSequence() {
StringBuilder sb = new StringBuilder();
try {
writeAnsiTo(sb);
}
catch (IOException e) {
// Should not happen
throw new UndeclaredThrowableException(e);
}
return sb.toString();
}
public abstract void writeAnsiTo(Appendable appendable) throws IOException;
@Override
public abstract String toString();
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy