/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform 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 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform 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 the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.operations;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import org.whole.lang.util.StringUtils;
/**
* @author Riccardo Solmi
*/
public class PrettyPrintWriter implements IPrettyPrintWriter {
private final PrintWriter printWriter;
protected boolean isStartOfLine = true;
public PrettyPrintWriter(PrintWriter printWriter) {
this.printWriter = printWriter;
}
protected boolean inlined = false;
public boolean isInlined() {
return inlined;
}
public boolean setInlined(boolean inlined) {
boolean result = this.inlined;
this.inlined = inlined;
return result;
}
protected String prefixString = "";
protected String indentationString = " ";
protected int indentation = 0;
protected int indentSize = 4;
public void addLinePrefix(String prefix) {
prefixString = indentationString()+prefix;
indentation = 0;
}
public void removeLinePrefix(String prefix) {
prefixString = prefixString.substring(0, prefixString.lastIndexOf(prefix));
indentation = 0;
}
public int getIndentSize() {
return indentSize;
}
public int setIndentSize(int indentSize) {
int result = this.indentSize;
this.indentSize = indentSize;
return result;
}
public void setRelativeIndentation(int delta) {
indentation += delta;
}
protected String indentationString() {
if (indentation > 0) {
if (indentation * indentSize < indentationString.length())
return prefixString + indentationString.substring(0, indentation * indentSize);
else
return prefixString + indentationString;
} else
//FIXME workaround
return prefixString.substring(0, Math.max(0, prefixString.length() - -indentation * indentSize));
}
protected void ensureLinePrefix() {
if (isStartOfLine) {
isStartOfLine = false;
printWriter.print(StringUtils.stripTrailing(prefixString));
}
}
protected void ensureIndentation() {
if (isStartOfLine) {
isStartOfLine = false;
printWriter.print(indentationString());
}
}
public void print(boolean b) {
ensureIndentation();
printWriter.print(b);
}
public void print(byte b) {
ensureIndentation();
printWriter.print(b);
}
public void print(char c) {
if (StringUtils.isNewLineChar(c))
println();
else {
ensureIndentation();
printWriter.print(c);
}
}
public void print(double d) {
ensureIndentation();
printWriter.print(d);
}
public void print(float f) {
ensureIndentation();
printWriter.print(f);
}
public void print(int i) {
ensureIndentation();
printWriter.print(i);
}
public void print(long l) {
ensureIndentation();
printWriter.print(l);
}
public void print(short s) {
ensureIndentation();
printWriter.print(s);
}
public void print(String s) {
if (isMultiline(s)) {
String[] split = StringUtils.EOL_PATTERN.split(s, -1);
int lastIndex = split.length-1;
if (split[lastIndex].length() == 0)
for (int i=0; i<lastIndex; i++)
printlnRaw(split[i]);
else
for (int i=0; i<=lastIndex; i++) {
printRaw(split[i]);
if (i<lastIndex)
println();
}
} else
printRaw(s);
}
public void print(Object o) {
print(String.valueOf(o));
}
public void ensureNewLine() {
if (!isStartOfLine)
println();
}
public void println() {
ensureLinePrefix();
if (!isInlined()) {
printWriter.println();
isStartOfLine = true;
}
}
public void println(String s) {
print(s);
println();
}
public void printRaw(String s) {
ensureIndentation();
printWriter.print(s);
}
public void printlnRaw(String s) {
printRaw(s);
println();
}
public boolean isMultiline(CharSequence s) {
return StringUtils.EOL_PATTERN.matcher(s).find();
}
public Appendable append(CharSequence csq) throws IOException {
if (isMultiline(csq)) {
String[] split = StringUtils.EOL_PATTERN.split(csq, -1);
int lastIndex = split.length-1;
if (split[lastIndex].length() == 0)
for (int i=0; i<lastIndex; i++) {
ensureIndentation();
printWriter.append(split[i]);
println();
}
else
for (int i=0; i<=lastIndex; i++) {
ensureIndentation();
printWriter.append(split[i]);
if (i<lastIndex)
println();
}
} else {
ensureIndentation();
printWriter.append(csq);
}
return this;
}
public Appendable append(char c) throws IOException {
if (StringUtils.isNewLineChar(c))
println();
else {
ensureIndentation();
printWriter.append(c);
}
return this;
}
public Appendable append(CharSequence csq, int start, int end) throws IOException {
return append(csq.subSequence(start, end));
}
public Writer asWriter() { //TODO ? add boolean raw
return new WriterAdapter(); // raw ? printWriter : new WriterAdapter();
}
public class WriterAdapter extends Writer {
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
PrettyPrintWriter.this.append(String.valueOf(cbuf), off, off+len);
}
@Override
public void write(int c) throws IOException {
PrettyPrintWriter.this.append((char) c);
}
@Override
public void write(String str) throws IOException {
PrettyPrintWriter.this.append(str);
}
public void write(String str, int off, int len) throws IOException {
PrettyPrintWriter.this.append(str, off, off+len);
}
@Override
public Writer append(char c) throws IOException {
PrettyPrintWriter.this.append(c);
return this;
}
@Override
public Writer append(CharSequence csq) throws IOException {
PrettyPrintWriter.this.append(csq);
return this;
}
@Override
public Writer append(CharSequence csq, int start, int end) throws IOException {
PrettyPrintWriter.this.append(csq, start, end);
return this;
}
@Override
public void flush() throws IOException {
PrettyPrintWriter.this.printWriter.flush();
}
@Override
public void close() throws IOException {
PrettyPrintWriter.this.printWriter.close();
}
}
}