001 /*
002 * Copyright 2010-2015 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
017 package org.jetbrains.kotlin.utils;
018
019 import org.jetbrains.annotations.NotNull;
020
021 import java.io.IOException;
022 import java.util.Collection;
023 import java.util.Iterator;
024
025 public class Printer {
026 private static final String INDENTATION_UNIT = " ";
027 private static final String LINE_SEPARATOR = System.getProperty("line.separator");
028
029 protected final Appendable out;
030 private final int maxBlankLines;
031
032 private String indent = "";
033 private int blankLineCountIncludingCurrent = 0;
034 private boolean withholdIndentOnce = false;
035
036 public Printer(@NotNull Appendable out) {
037 this(out, Integer.MAX_VALUE);
038 }
039
040 public Printer(@NotNull Appendable out, int maxBlankLines) {
041 this.out = out;
042 this.maxBlankLines = maxBlankLines;
043 }
044
045 private void append(Object o) {
046 try {
047 out.append(o.toString());
048 }
049 catch (IOException e) {
050 // Do nothing
051 }
052 }
053
054 @NotNull
055 public Printer println(Object... objects) {
056 print(objects);
057 printLineSeparator();
058
059 return this;
060 }
061
062 private void printLineSeparator() {
063 if (blankLineCountIncludingCurrent <= maxBlankLines) {
064 blankLineCountIncludingCurrent++;
065 append(LINE_SEPARATOR);
066 }
067 }
068
069 @NotNull
070 public Printer print(Object... objects) {
071 if (withholdIndentOnce) {
072 withholdIndentOnce = false;
073 }
074 else if (objects.length > 0) {
075 printIndent();
076 }
077 printWithNoIndent(objects);
078
079 return this;
080 }
081
082 public void printIndent() {
083 append(indent);
084 }
085
086 @NotNull
087 public Printer printWithNoIndent(Object... objects) {
088 for (Object object : objects) {
089 blankLineCountIncludingCurrent = 0;
090 append(object);
091 }
092
093 return this;
094 }
095
096 @NotNull
097 public Printer withholdIndentOnce() {
098 withholdIndentOnce = true;
099 return this;
100 }
101
102 @NotNull
103 public Printer printlnWithNoIndent(Object... objects) {
104 printWithNoIndent(objects);
105 printLineSeparator();
106
107 return this;
108 }
109
110 @NotNull
111 public Printer pushIndent() {
112 indent += INDENTATION_UNIT;
113
114 return this;
115 }
116
117 @NotNull
118 public Printer popIndent() {
119 if (indent.length() < INDENTATION_UNIT.length()) {
120 throw new IllegalStateException("No indentation to pop");
121 }
122
123 indent = indent.substring(INDENTATION_UNIT.length());
124
125 return this;
126 }
127
128 @NotNull
129 public Printer separated(Object separator, Object... items) {
130 for (int i = 0; i < items.length; i++) {
131 if (i > 0) {
132 printlnWithNoIndent(separator);
133 }
134 printlnWithNoIndent(items[i]);
135 }
136 return this;
137 }
138
139 @NotNull
140 public Printer separated(Object separator, Collection<?> items) {
141 for (Iterator<?> iterator = items.iterator(); iterator.hasNext(); ) {
142 printlnWithNoIndent(iterator.next());
143 if (iterator.hasNext()) {
144 printlnWithNoIndent(separator);
145 }
146 }
147 return this;
148 }
149 }