org.gradle.internal.logging.console.AnsiConsole Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-tooling-api Show documentation
Show all versions of gradle-tooling-api Show documentation
Gradle Tooling API - the programmatic API to invoke Gradle
The newest version!
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.internal.logging.console;
import org.gradle.api.Action;
import org.gradle.api.UncheckedIOException;
import org.gradle.internal.nativeintegration.console.ConsoleMetaData;
import java.io.Flushable;
import java.io.IOException;
public class AnsiConsole implements Console {
private final Action redrawAction = new Action() {
@Override
public void execute(AnsiContext ansiContext) {
buildStatusArea.redraw(ansiContext);
// When build output area is not visible, position the cursor at the end of the output area
if (!buildStatusArea.isVisible()) {
ansiContext.cursorAt(buildOutputArea.getWritePosition());
}
}
};
private final Flushable flushable;
private final MultiLineBuildProgressArea buildStatusArea = new MultiLineBuildProgressArea();
private final DefaultTextArea buildOutputArea;
private final AnsiExecutor ansiExecutor;
public AnsiConsole(Appendable target, Flushable flushable, ColorMap colorMap, ConsoleMetaData consoleMetaData, boolean forceAnsi) {
this(target, flushable, colorMap, consoleMetaData, new DefaultAnsiFactory(forceAnsi));
}
private AnsiConsole(Appendable target, Flushable flushable, ColorMap colorMap, ConsoleMetaData consoleMetaData, AnsiFactory factory) {
this.flushable = flushable;
this.ansiExecutor = new DefaultAnsiExecutor(target, colorMap, factory, consoleMetaData, Cursor.newBottomLeft(), new Listener());
buildOutputArea = new DefaultTextArea(ansiExecutor);
}
@Override
public void flush() {
redraw();
try {
flushable.flush();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private void redraw() {
// Calculate how many rows of the status area overlap with the text area
int numberOfOverlappedRows = buildStatusArea.getWritePosition().row - buildOutputArea.getWritePosition().row;
// If textArea is on a status line but nothing was written, this means a new line was just written. While
// we wait for additional text, we assume this row doesn't count as overlapping and use it as a status
// line. In the opposite case, we want to scroll the progress area one more line. This avoid having an one
// line gap between the text area and the status area.
if (buildOutputArea.getWritePosition().col > 0) {
numberOfOverlappedRows++;
}
if (numberOfOverlappedRows > 0) {
buildStatusArea.scrollDownBy(numberOfOverlappedRows);
}
ansiExecutor.write(redrawAction);
}
@Override
public StyledLabel getStatusBar() {
return buildStatusArea.getProgressBar();
}
@Override
public BuildProgressArea getBuildProgressArea() {
return buildStatusArea;
}
@Override
public TextArea getBuildOutputArea() {
return buildOutputArea;
}
private class Listener implements DefaultAnsiExecutor.NewLineListener {
@Override
public void beforeNewLineWritten(AnsiContext ansi, Cursor writeCursor) {
if (buildStatusArea.isOverlappingWith(writeCursor)) {
ansi.eraseForward();
}
if (writeCursor.row == 0) {
buildOutputArea.newLineAdjustment();
buildStatusArea.newLineAdjustment();
}
}
@Override
public void beforeLineWrap(AnsiContext ansi, Cursor writeCursor) {
if (writeCursor.row == 0) {
buildStatusArea.newLineAdjustment();
}
}
@Override
public void afterLineWrap(AnsiContext ansi, Cursor writeCursor) {
if (buildStatusArea.isOverlappingWith(writeCursor)) {
ansi.eraseForward();
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy