package xapi.fu;
/**
* @author James X. Nelson (james@wetheinter.net)
* Created on 4/18/16.
*/
public interface Printable <Self extends Printable<Self>> extends Coercible {
String NEW_LINE = "\n";
Self append(final CharSequence s, final int start, final int end);
Self append(final char[] str, final int offset, final int len);
boolean isIndentNeeded();
Self setIndentNeeded(boolean needed);
String getIndent();
Self setIndent(String indent);
String toSource();
static SimplePrintable newPrinter() {
return toPrinter(new StringBuilder());
}
static SimplePrintable toPrinter(StringBuilder b) {
return new SimplePrintable(b);
}
class SimplePrintable implements Printable<SimplePrintable> {
private final StringBuilder target;
private String indent;
private boolean needsIndent;
public SimplePrintable() {
this(new StringBuilder());
}
public SimplePrintable(StringBuilder builder) {
this.target = builder;
indent = perIndent();
}
@Override
public SimplePrintable append(CharSequence s, int start, int end) {
onAppend();
target.append(s, start, end);
return self();
}
@Override
public SimplePrintable append(char[] str, int offset, int len) {
onAppend();
target.append(str, offset, len);
return self();
}
@Override
public boolean isIndentNeeded() {
return needsIndent;
}
@Override
public SimplePrintable setIndentNeeded(boolean needed) {
needsIndent = needed;
return self();
}
@Override
public String getIndent() {
return indent;
}
@Override
public SimplePrintable setIndent(String indent) {
this.indent = indent;
return self();
}
@Override
public String toSource() {
return target.toString();
}
}
default Self println() {
onAppend();
append(NEW_LINE);
setIndentNeeded(true);
return self();
}
default void printIndent() {
if (isIndentNeeded()) {
append(getIndent());
setIndentNeeded(false);
}
}
default void onAppend(){}
default Self append(final CharSequence s) {
append(s, 0, s.length());
return self();
}
default Self print(final String str) {
printIndent();
append(str);
return self();
}
default Self append(final boolean b) {
return append(coerce(b));
}
default Self append(final char c) {
return append(coerce(c));
}
default Self append(final int i) {
return append(coerce(i));
}
default Self append(final long lng) {
return append(coerce(lng));
}
default Self append(final float f) {
return append(coerce(f));
}
default Self append(final double d) {
return append(coerce(d));
}
default Self append(final Object s) {
append(coerce(s));
return self();
}
default Self append(final char[] str) {
append(str, 0, str.length);
return self();
}
default String perIndent() {
return " ";
}
default Self indent() {
setIndent(getIndent() + perIndent());
return self();
}
default Self indentln(final Object obj) {
printIndent();
onAppend();
append(perIndent());
append(coerce(obj));
println();
return self();
}
default Self indentln(final String str) {
printIndent();
onAppend();
append(perIndent());
append(str);
println();
return self();
}
default Self indentln(final CharSequence s) {
printIndent();
onAppend();
append(perIndent());
append(s);
println();
return self();
}
default Self indentln(final char[] str) {
printIndent();
onAppend();
append(perIndent());
append(str);
println();
return self();
}
default Self outdent() {
String indent = getIndent();
String per = perIndent();
final int end = Math.max(0, indent.length() - per.length());
if (end > 0) {
setIndent(indent.substring(0, end));
} else {
setIndent("");
}
return self();
}
default Self println(final Object obj) {
printIndent();
onAppend();
append(coerce(obj));
println();
return self();
}
default Self println(final String str) {
printIndent();
onAppend();
append(str);
println();
return self();
}
default Self printlns(String str) {
for (String line : str.split("\\r|(?:\\r?\\n)")) {
println(line.trim());
}
return self();
}
default Self println(final CharSequence s) {
printIndent();
onAppend();
append(s);
println();
return self();
}
default Self println(final char[] str) {
printIndent();
onAppend();
append(str);
println();
return self();
}
default Self clearIndent() {
setIndent("");
return self();
}
default Self add(Object ... values) {
for (Object value : values) {
append(value);
}
return self();
}
default Self ln() {
println();
return self();
}
default Self self() {
return (Self) this;
}
}