001/*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.jetbrains.jet.utils;
018
019import org.jetbrains.annotations.NotNull;
020
021import java.io.IOException;
022import java.util.Collection;
023import java.util.Iterator;
024
025public class Printer {
026    private static final String INDENTATION_UNIT = "    ";
027    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
028
029    private final Appendable out;
030    private final int maxBlankLines;
031
032    private String indent = "";
033    private int blankLineCountIncludingCurrent = 0;
034
035    public Printer(@NotNull Appendable out) {
036        this(out, Integer.MAX_VALUE);
037    }
038
039    public Printer(@NotNull Appendable out, int maxBlankLines) {
040        this.out = out;
041        this.maxBlankLines = maxBlankLines;
042    }
043
044    private void append(Object o) {
045        try {
046            out.append(o.toString());
047        }
048        catch (IOException e) {
049            // Do nothing
050        }
051    }
052
053    @NotNull
054    public Printer println(Object... objects) {
055        print(objects);
056        printLineSeparator();
057
058        return this;
059    }
060
061    private void printLineSeparator() {
062        if (blankLineCountIncludingCurrent <= maxBlankLines) {
063            blankLineCountIncludingCurrent++;
064            append(LINE_SEPARATOR);
065        }
066    }
067
068    @NotNull
069    public Printer print(Object... objects) {
070        append(indent);
071        printWithNoIndent(objects);
072
073        return this;
074    }
075
076    @NotNull
077    public Printer printWithNoIndent(Object... objects) {
078        for (Object object : objects) {
079            blankLineCountIncludingCurrent = 0;
080            append(object);
081        }
082
083        return this;
084    }
085
086    @NotNull
087    public Printer printlnWithNoIndent(Object... objects) {
088        printWithNoIndent(objects);
089        printLineSeparator();
090
091        return this;
092    }
093
094    @NotNull
095    public Printer pushIndent() {
096        indent += INDENTATION_UNIT;
097
098        return this;
099    }
100
101    @NotNull
102    public Printer popIndent() {
103        if (indent.length() < INDENTATION_UNIT.length()) {
104            throw new IllegalStateException("No indentation to pop");
105        }
106
107        indent = indent.substring(INDENTATION_UNIT.length());
108
109        return this;
110    }
111
112    @NotNull
113    public Printer separated(Object separator, Object... items) {
114        for (int i = 0; i < items.length; i++) {
115            if (i > 0) {
116                printlnWithNoIndent(separator);
117            }
118            printlnWithNoIndent(items[i]);
119        }
120        return this;
121    }
122
123    @NotNull
124    public Printer separated(Object separator, Collection<?> items) {
125        for (Iterator<?> iterator = items.iterator(); iterator.hasNext(); ) {
126            printlnWithNoIndent(iterator.next());
127            if (iterator.hasNext()) {
128                printlnWithNoIndent(separator);
129            }
130        }
131        return this;
132    }
133}