mirror of https://github.com/apache/maven.git
[MNG-7995] Switch to JLine to provide line editing (#1279)
This commit is contained in:
parent
47fc18faf9
commit
782e8679bf
|
@ -98,8 +98,8 @@ under the License.
|
|||
<artifactId>maven-slf4j-provider</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
<artifactId>jansi</artifactId>
|
||||
<groupId>org.jline</groupId>
|
||||
<artifactId>jline</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DI Runtime -->
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
Copyright (c) 2002-2023, the original author or authors.
|
||||
All rights reserved.
|
||||
|
||||
https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
Neither the name of JLine nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -26,7 +26,7 @@ import org.apache.maven.api.annotations.Nonnull;
|
|||
* @since 4.0.0
|
||||
* @see MessageBuilderFactory
|
||||
*/
|
||||
public interface MessageBuilder {
|
||||
public interface MessageBuilder extends Appendable {
|
||||
|
||||
/**
|
||||
* Append message content in trace style.
|
||||
|
@ -36,7 +36,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder trace(Object message);
|
||||
default MessageBuilder trace(Object message) {
|
||||
return style(".trace:-bold,f:magenta", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in debug style.
|
||||
|
@ -46,7 +48,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder debug(Object message);
|
||||
default MessageBuilder debug(Object message) {
|
||||
return style(".debug:-bold,f:cyan", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in info style.
|
||||
|
@ -56,7 +60,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder info(Object message);
|
||||
default MessageBuilder info(Object message) {
|
||||
return style(".info:-bold,f:blue", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in warning style.
|
||||
|
@ -66,7 +72,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder warning(Object message);
|
||||
default MessageBuilder warning(Object message) {
|
||||
return style(".warning:-bold,f:yellow", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in error style.
|
||||
|
@ -76,7 +84,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder error(Object message);
|
||||
default MessageBuilder error(Object message) {
|
||||
return style(".error:-bold,f:red", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in success style.
|
||||
|
@ -86,7 +96,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder success(Object message);
|
||||
default MessageBuilder success(Object message) {
|
||||
return style(".success:-bold,f:green", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in failure style.
|
||||
|
@ -96,7 +108,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder failure(Object message);
|
||||
default MessageBuilder failure(Object message) {
|
||||
return style(".failure:-bold,f:red", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in strong style.
|
||||
|
@ -106,7 +120,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder strong(Object message);
|
||||
default MessageBuilder strong(Object message) {
|
||||
return style(".strong:-bold", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in mojo style.
|
||||
|
@ -116,7 +132,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder mojo(Object message);
|
||||
default MessageBuilder mojo(Object message) {
|
||||
return style(".mojo:-f:green", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append message content in project style.
|
||||
|
@ -126,11 +144,35 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder project(Object message);
|
||||
default MessageBuilder project(Object message) {
|
||||
return style(".project:-f:cyan", message);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
default MessageBuilder style(String style, Object message) {
|
||||
return style(style).a(message).resetStyle();
|
||||
}
|
||||
|
||||
MessageBuilder style(String style);
|
||||
|
||||
MessageBuilder resetStyle();
|
||||
|
||||
//
|
||||
// message building methods modelled after Ansi methods
|
||||
//
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
MessageBuilder append(CharSequence cs);
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
MessageBuilder append(CharSequence cs, int start, int end);
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
MessageBuilder append(char c);
|
||||
|
||||
/**
|
||||
* Append content to the message buffer.
|
||||
*
|
||||
|
@ -140,7 +182,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder a(char[] value, int offset, int len);
|
||||
default MessageBuilder a(char[] value, int offset, int len) {
|
||||
return append(String.valueOf(value, offset, len));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append content to the message buffer.
|
||||
|
@ -149,7 +193,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder a(char[] value);
|
||||
default MessageBuilder a(char[] value) {
|
||||
return append(String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append content to the message buffer.
|
||||
|
@ -160,7 +206,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder a(CharSequence value, int start, int end);
|
||||
default MessageBuilder a(CharSequence value, int start, int end) {
|
||||
return append(value, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append content to the message buffer.
|
||||
|
@ -169,7 +217,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder a(CharSequence value);
|
||||
default MessageBuilder a(CharSequence value) {
|
||||
return append(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append content to the message buffer.
|
||||
|
@ -178,7 +228,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder a(Object value);
|
||||
default MessageBuilder a(Object value) {
|
||||
return append(String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append newline to the message buffer.
|
||||
|
@ -186,7 +238,9 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder newline();
|
||||
default MessageBuilder newline() {
|
||||
return append(System.lineSeparator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Append formatted content to the buffer.
|
||||
|
@ -197,7 +251,17 @@ public interface MessageBuilder {
|
|||
* @return the current builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder format(String pattern, Object... args);
|
||||
default MessageBuilder format(String pattern, Object... args) {
|
||||
return append(String.format(pattern, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the buffer length.
|
||||
*
|
||||
* @param length the new length
|
||||
* @return the current builder
|
||||
*/
|
||||
MessageBuilder setLength(int length);
|
||||
|
||||
/**
|
||||
* Return the built message.
|
||||
|
@ -206,11 +270,4 @@ public interface MessageBuilder {
|
|||
*/
|
||||
@Nonnull
|
||||
String build();
|
||||
|
||||
/**
|
||||
* Set the buffer length.
|
||||
*
|
||||
* @param length the new length
|
||||
*/
|
||||
void setLength(int length);
|
||||
}
|
||||
|
|
|
@ -48,21 +48,11 @@ public interface MessageBuilderFactory extends Service {
|
|||
@Nonnull
|
||||
MessageBuilder builder();
|
||||
|
||||
/**
|
||||
* Creates a new message builder backed by the given string builder.
|
||||
* @param stringBuilder a string builder
|
||||
* @return a new message builder
|
||||
*/
|
||||
@Nonnull
|
||||
MessageBuilder builder(@Nonnull StringBuilder stringBuilder);
|
||||
|
||||
/**
|
||||
* Creates a new message builder of the specified size.
|
||||
* @param size the initial size of the message builder buffer
|
||||
* @return a new message builder
|
||||
*/
|
||||
@Nonnull
|
||||
default MessageBuilder builder(int size) {
|
||||
return builder(new StringBuilder(size));
|
||||
}
|
||||
MessageBuilder builder(int size);
|
||||
}
|
||||
|
|
|
@ -36,111 +36,36 @@ public class DefaultMessageBuilder implements MessageBuilder {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder trace(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder debug(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder info(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder warning(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder error(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder success(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder failure(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder strong(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder mojo(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder project(Object o) {
|
||||
return a(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(char[] chars, int i, int i1) {
|
||||
buffer.append(chars, i, i1);
|
||||
public MessageBuilder style(String style) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(char[] chars) {
|
||||
buffer.append(chars);
|
||||
public MessageBuilder resetStyle() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(CharSequence charSequence, int i, int i1) {
|
||||
buffer.append(charSequence, i, i1);
|
||||
public MessageBuilder append(CharSequence cs) {
|
||||
buffer.append(cs);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(CharSequence charSequence) {
|
||||
buffer.append(charSequence);
|
||||
public MessageBuilder append(CharSequence cs, int start, int end) {
|
||||
buffer.append(cs, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(Object o) {
|
||||
buffer.append(o);
|
||||
public MessageBuilder append(char c) {
|
||||
buffer.append(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder newline() {
|
||||
buffer.append(System.getProperty("line.separator"));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder format(String s, Object... objects) {
|
||||
buffer.append(String.format(s, objects));
|
||||
public MessageBuilder setLength(int length) {
|
||||
buffer.setLength(length);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -154,9 +79,4 @@ public class DefaultMessageBuilder implements MessageBuilder {
|
|||
public String toString() {
|
||||
return build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLength(int length) {
|
||||
buffer.setLength(length);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ import javax.inject.Inject;
|
|||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
|
@ -57,7 +55,7 @@ public class DefaultMessageBuilderFactory implements MessageBuilderFactory {
|
|||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder builder(@Nonnull StringBuilder stringBuilder) {
|
||||
return new DefaultMessageBuilder(Objects.requireNonNull(stringBuilder));
|
||||
public MessageBuilder builder(int size) {
|
||||
return new DefaultMessageBuilder(new StringBuilder(size));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,6 +99,10 @@ under the License.
|
|||
<exportedPackage>org.codehaus.plexus.logging</exportedPackage>
|
||||
<exportedPackage>org.codehaus.plexus.personality</exportedPackage>
|
||||
|
||||
<!-- plexus-interactivity-api -->
|
||||
<exportedPackage>org.codehaus.plexus.components.interactivity</exportedPackage>
|
||||
<exportedPackage>org.fusesource.jansi.Ansi</exportedPackage>
|
||||
|
||||
<!-- javax.inject (JSR-330) -->
|
||||
<exportedPackage>javax.inject.*</exportedPackage>
|
||||
<!-- javax.enterprise.inject (JSR-299): Must never be exported if needed at plugin level, plugin adds it
|
||||
|
|
|
@ -88,6 +88,16 @@ under the License.
|
|||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-interpolation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-interactivity-api</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
|
@ -97,11 +107,6 @@ under the License.
|
|||
<artifactId>commons-cli</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
<artifactId>jansi</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
|
@ -112,6 +117,10 @@ under the License.
|
|||
<artifactId>slf4j-simple</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jline</groupId>
|
||||
<artifactId>jline</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.apache.commons.cli.HelpFormatter;
|
|||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.maven.cli.jansi.MessageUtils;
|
||||
import org.apache.maven.cli.jline.MessageUtils;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.Date;
|
|||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.maven.cli.jansi.MessageUtils;
|
||||
import org.apache.maven.cli.jline.MessageUtils;
|
||||
import org.apache.maven.utils.Os;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ import org.apache.maven.cli.event.ExecutionEventLogger;
|
|||
import org.apache.maven.cli.internal.BootstrapCoreExtensionManager;
|
||||
import org.apache.maven.cli.internal.extension.io.CoreExtensionsStaxReader;
|
||||
import org.apache.maven.cli.internal.extension.model.CoreExtension;
|
||||
import org.apache.maven.cli.jansi.JansiMessageBuilderFactory;
|
||||
import org.apache.maven.cli.jansi.MessageUtils;
|
||||
import org.apache.maven.cli.jline.JLineMessageBuilderFactory;
|
||||
import org.apache.maven.cli.jline.MessageUtils;
|
||||
import org.apache.maven.cli.logging.Slf4jConfiguration;
|
||||
import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
|
||||
import org.apache.maven.cli.logging.Slf4jLoggerManager;
|
||||
|
@ -188,7 +188,7 @@ public class MavenCli {
|
|||
// This supports painless invocation by the Verifier during embedded execution of the core ITs
|
||||
public MavenCli(ClassWorld classWorld) {
|
||||
this.classWorld = classWorld;
|
||||
this.messageBuilderFactory = new JansiMessageBuilderFactory();
|
||||
this.messageBuilderFactory = new JLineMessageBuilderFactory();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -1676,7 +1676,7 @@ public class MavenCli {
|
|||
//
|
||||
|
||||
protected TransferListener getConsoleTransferListener(boolean printResourceNames) {
|
||||
return new ConsoleMavenTransferListener(System.out, printResourceNames);
|
||||
return new ConsoleMavenTransferListener(messageBuilderFactory, System.out, printResourceNames);
|
||||
}
|
||||
|
||||
protected TransferListener getBatchTransferListener() {
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cli.jansi;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.fusesource.jansi.Ansi;
|
||||
|
||||
@Experimental
|
||||
public class JansiMessageBuilder implements MessageBuilder {
|
||||
private final Ansi ansi;
|
||||
private StringBuilder sb;
|
||||
|
||||
@SuppressWarnings("magicnumber")
|
||||
public JansiMessageBuilder() {
|
||||
this.sb = new StringBuilder(80);
|
||||
this.ansi = Ansi.ansi();
|
||||
}
|
||||
|
||||
public JansiMessageBuilder(StringBuilder sb) {
|
||||
this.sb = sb;
|
||||
this.ansi = Ansi.ansi(sb);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder trace(Object o) {
|
||||
return style(Style.TRACE, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder debug(Object o) {
|
||||
return style(Style.DEBUG, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder info(Object o) {
|
||||
return style(Style.INFO, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder warning(Object o) {
|
||||
return style(Style.WARNING, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder error(Object o) {
|
||||
return style(Style.ERROR, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder success(Object o) {
|
||||
return style(Style.SUCCESS, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder failure(Object o) {
|
||||
return style(Style.FAILURE, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder strong(Object o) {
|
||||
return style(Style.STRONG, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder mojo(Object o) {
|
||||
return style(Style.MOJO, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder project(Object o) {
|
||||
return style(Style.PROJECT, o);
|
||||
}
|
||||
|
||||
private MessageBuilder style(Style style, Object o) {
|
||||
style.apply(ansi).a(o).reset();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(char[] chars, int i, int i1) {
|
||||
ansi.a(chars, i, i1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(char[] chars) {
|
||||
ansi.a(chars);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(CharSequence charSequence, int i, int i1) {
|
||||
ansi.a(charSequence, i, i1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(CharSequence charSequence) {
|
||||
ansi.a(charSequence);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder a(Object o) {
|
||||
ansi.a(o);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder newline() {
|
||||
ansi.newline();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder format(String s, Object... objects) {
|
||||
ansi.format(s, objects);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String build() {
|
||||
return ansi.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLength(int length) {
|
||||
sb.setLength(length);
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cli.jansi;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.annotations.Nonnull;
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
|
||||
@Experimental
|
||||
@Named
|
||||
@Singleton
|
||||
public class JansiMessageBuilderFactory implements MessageBuilderFactory {
|
||||
|
||||
@Override
|
||||
public boolean isColorEnabled() {
|
||||
return MessageUtils.isColorEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTerminalWidth() {
|
||||
return MessageUtils.getTerminalWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder builder() {
|
||||
return builder(new StringBuilder());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public MessageBuilder builder(@Nonnull StringBuilder stringBuilder) {
|
||||
return MessageUtils.builder(stringBuilder);
|
||||
}
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cli.jansi;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.internal.impl.DefaultMessageBuilder;
|
||||
import org.fusesource.jansi.Ansi;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
import org.fusesource.jansi.AnsiMode;
|
||||
|
||||
/**
|
||||
* Colored message utils, to manage colors. This is the core implementation of the
|
||||
* {@link JansiMessageBuilderFactory} and {@link JansiMessageBuilder} classes.
|
||||
* This class should not be used outside of maven-embedder and the public
|
||||
* {@link org.apache.maven.api.services.MessageBuilderFactory} should be used instead.
|
||||
* <p>
|
||||
* Internally, <a href="http://fusesource.github.io/jansi/">Jansi</a> is used to render
|
||||
* <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#Colors">ANSI colors</a> on any platform.
|
||||
* <p>
|
||||
*
|
||||
* @see MessageBuilder
|
||||
* @see org.apache.maven.api.services.MessageBuilderFactory
|
||||
* @see JansiMessageBuilderFactory
|
||||
* @see JansiMessageBuilder
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class MessageUtils {
|
||||
private static final boolean JANSI;
|
||||
|
||||
/** Reference to the JVM shutdown hook, if registered */
|
||||
private static Thread shutdownHook;
|
||||
|
||||
/** Synchronization monitor for the "uninstall" */
|
||||
private static final Object STARTUP_SHUTDOWN_MONITOR = new Object();
|
||||
|
||||
static {
|
||||
boolean jansi = true;
|
||||
try {
|
||||
// Jansi is provided by Maven core since 3.5.0
|
||||
Class.forName("org.fusesource.jansi.Ansi");
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
jansi = false;
|
||||
}
|
||||
JANSI = jansi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install color support.
|
||||
* This method is called by Maven core, and calling it is not necessary in plugins.
|
||||
*/
|
||||
public static void systemInstall() {
|
||||
if (JANSI) {
|
||||
AnsiConsole.systemInstall();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo a previous {@link #systemInstall()}. If {@link #systemInstall()} was called
|
||||
* multiple times, {@link #systemUninstall()} must be called call the same number of times before
|
||||
* it is actually uninstalled.
|
||||
*/
|
||||
public static void systemUninstall() {
|
||||
synchronized (STARTUP_SHUTDOWN_MONITOR) {
|
||||
doSystemUninstall();
|
||||
|
||||
// hook can only set when Jansi is true
|
||||
if (shutdownHook != null) {
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||
} catch (IllegalStateException ex) {
|
||||
// ignore - VM is already shutting down
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void doSystemUninstall() {
|
||||
if (JANSI) {
|
||||
AnsiConsole.systemUninstall();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables message color (if Jansi is available).
|
||||
* @param flag to enable Jansi
|
||||
*/
|
||||
public static void setColorEnabled(boolean flag) {
|
||||
if (JANSI) {
|
||||
AnsiConsole.out().setMode(flag ? AnsiMode.Force : AnsiMode.Strip);
|
||||
Ansi.setEnabled(flag);
|
||||
System.setProperty(
|
||||
AnsiConsole.JANSI_MODE, flag ? AnsiConsole.JANSI_MODE_FORCE : AnsiConsole.JANSI_MODE_STRIP);
|
||||
boolean installed = AnsiConsole.isInstalled();
|
||||
while (AnsiConsole.isInstalled()) {
|
||||
AnsiConsole.systemUninstall();
|
||||
}
|
||||
if (installed) {
|
||||
AnsiConsole.systemInstall();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is message color enabled: requires Jansi available (through Maven) and the color has not been disabled.
|
||||
* @return whether colored messages are enabled
|
||||
*/
|
||||
public static boolean isColorEnabled() {
|
||||
return JANSI ? Ansi.isEnabled() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default message buffer.
|
||||
* @return a new buffer
|
||||
*/
|
||||
public static MessageBuilder builder() {
|
||||
return builder(new StringBuilder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a message buffer with an internal buffer of defined size.
|
||||
* @param size size of the buffer
|
||||
* @return a new buffer
|
||||
*/
|
||||
public static MessageBuilder builder(int size) {
|
||||
return builder(new StringBuilder(size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a message buffer with defined String builder.
|
||||
* @param builder initial content of the message buffer
|
||||
* @return a new buffer
|
||||
*/
|
||||
public static MessageBuilder builder(StringBuilder builder) {
|
||||
return JANSI && isColorEnabled() ? new JansiMessageBuilder(builder) : new DefaultMessageBuilder(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any ANSI code from a message (colors or other escape sequences).
|
||||
* @param msg message eventually containing ANSI codes
|
||||
* @return the message with ANSI codes removed
|
||||
*/
|
||||
public static String stripAnsiCodes(String msg) {
|
||||
return msg.replaceAll("\u001B\\[[;\\d]*[ -/]*[@-~]", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shutdown hook with the JVM runtime, uninstalling Ansi support on
|
||||
* JVM shutdown unless is has already been uninstalled at that time.
|
||||
* <p>Delegates to {@link #doSystemUninstall()} for the actual uninstall procedure
|
||||
*
|
||||
* @see Runtime#addShutdownHook(Thread)
|
||||
* @see MessageUtils#systemUninstall()
|
||||
* @see #doSystemUninstall()
|
||||
*/
|
||||
public static void registerShutdownHook() {
|
||||
if (JANSI && shutdownHook == null) {
|
||||
// No shutdown hook registered yet.
|
||||
shutdownHook = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (STARTUP_SHUTDOWN_MONITOR) {
|
||||
while (AnsiConsole.isInstalled()) {
|
||||
doSystemUninstall();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the terminal width or -1 if the width cannot be determined.
|
||||
*
|
||||
* @return the terminal width
|
||||
*/
|
||||
public static int getTerminalWidth() {
|
||||
if (JANSI) {
|
||||
int width = AnsiConsole.getTerminalWidth();
|
||||
return width > 0 ? width : -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cli.jansi;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.fusesource.jansi.Ansi;
|
||||
import org.fusesource.jansi.Ansi.Color;
|
||||
|
||||
/**
|
||||
* Configurable message styles.
|
||||
* @since 4.0.0
|
||||
*/
|
||||
enum Style {
|
||||
TRACE("bold,magenta"),
|
||||
DEBUG("bold,cyan"),
|
||||
INFO("bold,blue"),
|
||||
WARNING("bold,yellow"),
|
||||
ERROR("bold,red"),
|
||||
SUCCESS("bold,green"),
|
||||
FAILURE("bold,red"),
|
||||
STRONG("bold"),
|
||||
MOJO("green"),
|
||||
PROJECT("cyan");
|
||||
|
||||
private final boolean bold;
|
||||
|
||||
private final boolean bright;
|
||||
|
||||
private final Color color;
|
||||
|
||||
private final boolean bgBright;
|
||||
|
||||
private final Color bgColor;
|
||||
|
||||
Style(String defaultValue) {
|
||||
boolean currentBold = false;
|
||||
boolean currentBright = false;
|
||||
Color currentColor = null;
|
||||
boolean currentBgBright = false;
|
||||
Color currentBgColor = null;
|
||||
|
||||
String value = System.getProperty("style." + name().toLowerCase(Locale.ENGLISH), defaultValue)
|
||||
.toLowerCase(Locale.ENGLISH);
|
||||
|
||||
for (String token : value.split(",")) {
|
||||
if ("bold".equals(token)) {
|
||||
currentBold = true;
|
||||
} else if (token.startsWith("bg")) {
|
||||
token = token.substring(2);
|
||||
if (token.startsWith("bright")) {
|
||||
currentBgBright = true;
|
||||
token = token.substring(6);
|
||||
}
|
||||
currentBgColor = toColor(token);
|
||||
} else {
|
||||
if (token.startsWith("bright")) {
|
||||
currentBright = true;
|
||||
token = token.substring(6);
|
||||
}
|
||||
currentColor = toColor(token);
|
||||
}
|
||||
}
|
||||
|
||||
this.bold = currentBold;
|
||||
this.bright = currentBright;
|
||||
this.color = currentColor;
|
||||
this.bgBright = currentBgBright;
|
||||
this.bgColor = currentBgColor;
|
||||
}
|
||||
|
||||
private static Color toColor(String token) {
|
||||
for (Color color : Color.values()) {
|
||||
if (color.toString().equalsIgnoreCase(token)) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Ansi apply(Ansi ansi) {
|
||||
if (bold) {
|
||||
ansi.bold();
|
||||
}
|
||||
if (color != null) {
|
||||
if (bright) {
|
||||
ansi.fgBright(color);
|
||||
} else {
|
||||
ansi.fg(color);
|
||||
}
|
||||
}
|
||||
if (bgColor != null) {
|
||||
if (bgBright) {
|
||||
ansi.bgBright(bgColor);
|
||||
} else {
|
||||
ansi.bg(bgColor);
|
||||
}
|
||||
}
|
||||
return ansi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (!bold && color == null && bgColor == null) {
|
||||
return name();
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(name() + '=');
|
||||
if (bold) {
|
||||
sb.append("bold");
|
||||
}
|
||||
if (color != null) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
if (bright) {
|
||||
sb.append("bright");
|
||||
}
|
||||
sb.append(color.name());
|
||||
}
|
||||
if (bgColor != null) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append("bg");
|
||||
if (bgBright) {
|
||||
sb.append("bright");
|
||||
}
|
||||
sb.append(bgColor.name());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cli.jline;
|
||||
|
||||
import javax.annotation.Priority;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.maven.api.annotations.Experimental;
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.codehaus.plexus.components.interactivity.InputHandler;
|
||||
import org.codehaus.plexus.components.interactivity.OutputHandler;
|
||||
import org.codehaus.plexus.components.interactivity.Prompter;
|
||||
import org.codehaus.plexus.components.interactivity.PrompterException;
|
||||
import org.jline.utils.AttributedStringBuilder;
|
||||
import org.jline.utils.AttributedStyle;
|
||||
import org.jline.utils.StyleResolver;
|
||||
|
||||
import static org.jline.utils.AttributedStyle.DEFAULT;
|
||||
|
||||
@Experimental
|
||||
@Named
|
||||
@Singleton
|
||||
@Priority(10)
|
||||
public class JLineMessageBuilderFactory implements MessageBuilderFactory, Prompter, InputHandler, OutputHandler {
|
||||
|
||||
private final StyleResolver resolver;
|
||||
|
||||
public JLineMessageBuilderFactory() {
|
||||
this.resolver = new MavenStyleResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isColorEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTerminalWidth() {
|
||||
return MessageUtils.getTerminalWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder builder() {
|
||||
return new JlineMessageBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder builder(int size) {
|
||||
return new JlineMessageBuilder(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readLine() throws IOException {
|
||||
return doPrompt(null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readPassword() throws IOException {
|
||||
return doPrompt(null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> readMultipleLines() throws IOException {
|
||||
List<String> lines = new ArrayList<>();
|
||||
for (String line = this.readLine(); line != null && !line.isEmpty(); line = readLine()) {
|
||||
lines.add(line);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String line) throws IOException {
|
||||
doDisplay(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLine(String line) throws IOException {
|
||||
doDisplay(line + System.lineSeparator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prompt(String message) throws PrompterException {
|
||||
return prompt(message, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prompt(String message, String defaultReply) throws PrompterException {
|
||||
return prompt(message, null, defaultReply);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prompt(String message, List possibleValues) throws PrompterException {
|
||||
return prompt(message, possibleValues, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prompt(String message, List possibleValues, String defaultReply) throws PrompterException {
|
||||
return doPrompt(message, possibleValues, defaultReply, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String promptForPassword(String message) throws PrompterException {
|
||||
return doPrompt(message, null, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(String message) throws PrompterException {
|
||||
try {
|
||||
doDisplay(message);
|
||||
} catch (IOException e) {
|
||||
throw new PrompterException("Failed to present prompt", e);
|
||||
}
|
||||
}
|
||||
|
||||
String doPrompt(String message, List<Object> possibleValues, String defaultReply, boolean password)
|
||||
throws PrompterException {
|
||||
String formattedMessage = formatMessage(message, possibleValues, defaultReply);
|
||||
String line;
|
||||
do {
|
||||
try {
|
||||
line = doPrompt(formattedMessage, password);
|
||||
if (line == null && defaultReply == null) {
|
||||
throw new IOException("EOF");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new PrompterException("Failed to prompt user", e);
|
||||
}
|
||||
if (line == null || line.isEmpty()) {
|
||||
line = defaultReply;
|
||||
}
|
||||
if (line != null && (possibleValues != null && !possibleValues.contains(line))) {
|
||||
try {
|
||||
doDisplay("Invalid selection.\n");
|
||||
} catch (IOException e) {
|
||||
throw new PrompterException("Failed to present feedback", e);
|
||||
}
|
||||
}
|
||||
} while (line == null || (possibleValues != null && !possibleValues.contains(line)));
|
||||
return line;
|
||||
}
|
||||
|
||||
private String formatMessage(String message, List<Object> possibleValues, String defaultReply) {
|
||||
StringBuilder formatted = new StringBuilder(message.length() * 2);
|
||||
formatted.append(message);
|
||||
if (possibleValues != null && !possibleValues.isEmpty()) {
|
||||
formatted.append(" (");
|
||||
for (Iterator<?> it = possibleValues.iterator(); it.hasNext(); ) {
|
||||
String possibleValue = String.valueOf(it.next());
|
||||
formatted.append(possibleValue);
|
||||
if (it.hasNext()) {
|
||||
formatted.append('/');
|
||||
}
|
||||
}
|
||||
formatted.append(')');
|
||||
}
|
||||
if (defaultReply != null) {
|
||||
formatted.append(' ').append(defaultReply).append(": ");
|
||||
}
|
||||
return formatted.toString();
|
||||
}
|
||||
|
||||
private void doDisplay(String message) throws IOException {
|
||||
try {
|
||||
MessageUtils.terminal.writer().print(message);
|
||||
MessageUtils.terminal.flush();
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Unable to display message", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String doPrompt(String message, boolean password) throws IOException {
|
||||
try {
|
||||
return MessageUtils.reader.readLine(message != null ? message + ": " : null, password ? '*' : null);
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Unable to prompt user", e);
|
||||
}
|
||||
}
|
||||
|
||||
class JlineMessageBuilder implements MessageBuilder {
|
||||
|
||||
final AttributedStringBuilder builder;
|
||||
|
||||
JlineMessageBuilder() {
|
||||
builder = new AttributedStringBuilder();
|
||||
}
|
||||
|
||||
JlineMessageBuilder(int size) {
|
||||
builder = new AttributedStringBuilder(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder style(String style) {
|
||||
if (MessageUtils.isColorEnabled()) {
|
||||
builder.style(resolver.resolve(style));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder resetStyle() {
|
||||
builder.style(DEFAULT);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder append(CharSequence cs) {
|
||||
builder.append(cs);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder append(CharSequence cs, int start, int end) {
|
||||
builder.append(cs, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder append(char c) {
|
||||
builder.append(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder setLength(int length) {
|
||||
builder.setLength(length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String build() {
|
||||
return builder.toAnsi(MessageUtils.terminal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return build();
|
||||
}
|
||||
}
|
||||
|
||||
static class MavenStyleResolver extends StyleResolver {
|
||||
|
||||
private final Map<String, AttributedStyle> styles = new ConcurrentHashMap<>();
|
||||
|
||||
MavenStyleResolver() {
|
||||
super(s -> System.getProperty("style." + s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributedStyle resolve(String spec) {
|
||||
return styles.computeIfAbsent(spec, this::doResolve);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributedStyle resolve(String spec, String defaultSpec) {
|
||||
return resolve(defaultSpec != null ? spec + ":-" + defaultSpec : spec);
|
||||
}
|
||||
|
||||
private AttributedStyle doResolve(String spec) {
|
||||
String def = null;
|
||||
int i = spec.indexOf(":-");
|
||||
if (i != -1) {
|
||||
String[] parts = spec.split(":-");
|
||||
spec = parts[0].trim();
|
||||
def = parts[1].trim();
|
||||
}
|
||||
return super.resolve(spec, def);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.maven.cli.jline;
|
||||
|
||||
import java.io.IOError;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.jline.jansi.AnsiConsole;
|
||||
import org.jline.reader.LineReader;
|
||||
import org.jline.reader.LineReaderBuilder;
|
||||
import org.jline.terminal.Terminal;
|
||||
import org.jline.terminal.TerminalBuilder;
|
||||
|
||||
public class MessageUtils {
|
||||
|
||||
static Terminal terminal;
|
||||
static LineReader reader;
|
||||
static MessageBuilderFactory messageBuilderFactory = new JLineMessageBuilderFactory();
|
||||
static boolean colorEnabled = true;
|
||||
static Thread shutdownHook;
|
||||
static final Object STARTUP_SHUTDOWN_MONITOR = new Object();
|
||||
|
||||
static PrintStream prevOut;
|
||||
static PrintStream prevErr;
|
||||
|
||||
public static void systemInstall() {
|
||||
try {
|
||||
terminal = TerminalBuilder.builder().name("Maven").dumb(true).build();
|
||||
reader = LineReaderBuilder.builder().terminal(terminal).build();
|
||||
AnsiConsole.setTerminal(terminal);
|
||||
AnsiConsole.systemInstall();
|
||||
} catch (IOException e) {
|
||||
throw new IOError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerShutdownHook() {
|
||||
if (shutdownHook == null) {
|
||||
shutdownHook = new Thread(() -> {
|
||||
synchronized (MessageUtils.STARTUP_SHUTDOWN_MONITOR) {
|
||||
MessageUtils.doSystemUninstall();
|
||||
}
|
||||
});
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
}
|
||||
}
|
||||
|
||||
public static void systemUninstall() {
|
||||
doSystemUninstall();
|
||||
if (shutdownHook != null) {
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||
} catch (IllegalStateException var3) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void doSystemUninstall() {
|
||||
try {
|
||||
AnsiConsole.systemUninstall();
|
||||
} finally {
|
||||
terminal = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setColorEnabled(boolean enabled) {
|
||||
colorEnabled = enabled;
|
||||
}
|
||||
|
||||
public static boolean isColorEnabled() {
|
||||
return colorEnabled && terminal != null;
|
||||
}
|
||||
|
||||
public static int getTerminalWidth() {
|
||||
return terminal != null ? terminal.getWidth() : -1;
|
||||
}
|
||||
|
||||
public static MessageBuilder builder() {
|
||||
return messageBuilderFactory.builder();
|
||||
}
|
||||
}
|
|
@ -21,7 +21,8 @@ package org.apache.maven.cli.transfer;
|
|||
import java.io.PrintStream;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.maven.cli.jansi.MessageUtils;
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.eclipse.aether.transfer.AbstractTransferListener;
|
||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
||||
import org.eclipse.aether.transfer.TransferEvent;
|
||||
|
@ -31,31 +32,27 @@ import org.eclipse.aether.transfer.TransferResource;
|
|||
* AbstractMavenTransferListener
|
||||
*/
|
||||
public abstract class AbstractMavenTransferListener extends AbstractTransferListener {
|
||||
public static final String STYLE = ".transfer:-faint";
|
||||
|
||||
private static final String ESC = "\u001B";
|
||||
private static final String ANSI_DARK_SET = ESC + "[90m";
|
||||
private static final String ANSI_DARK_RESET = ESC + "[0m";
|
||||
protected final MessageBuilderFactory messageBuilderFactory;
|
||||
protected final PrintStream out;
|
||||
|
||||
protected PrintStream out;
|
||||
|
||||
protected AbstractMavenTransferListener(PrintStream out) {
|
||||
protected AbstractMavenTransferListener(MessageBuilderFactory messageBuilderFactory, PrintStream out) {
|
||||
this.messageBuilderFactory = messageBuilderFactory;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferInitiated(TransferEvent event) {
|
||||
String darkOn = MessageUtils.isColorEnabled() ? ANSI_DARK_SET : "";
|
||||
String darkOff = MessageUtils.isColorEnabled() ? ANSI_DARK_RESET : "";
|
||||
|
||||
String action = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading";
|
||||
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
|
||||
|
||||
TransferResource resource = event.getResource();
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(darkOn).append(action).append(' ').append(direction).append(' ');
|
||||
message.append(darkOff).append(resource.getRepositoryId());
|
||||
message.append(darkOn).append(": ").append(resource.getRepositoryUrl());
|
||||
message.append(darkOff).append(resource.getResourceName());
|
||||
MessageBuilder message = messageBuilderFactory.builder();
|
||||
message.style(STYLE).append(action).append(' ').append(direction).append(' ');
|
||||
message.resetStyle().append(resource.getRepositoryId());
|
||||
message.style(STYLE).append(": ").append(resource.getRepositoryUrl());
|
||||
message.resetStyle().append(resource.getResourceName());
|
||||
|
||||
out.println(message.toString());
|
||||
}
|
||||
|
@ -70,9 +67,6 @@ public abstract class AbstractMavenTransferListener extends AbstractTransferList
|
|||
|
||||
@Override
|
||||
public void transferSucceeded(TransferEvent event) {
|
||||
String darkOn = MessageUtils.isColorEnabled() ? ANSI_DARK_SET : "";
|
||||
String darkOff = MessageUtils.isColorEnabled() ? ANSI_DARK_RESET : "";
|
||||
|
||||
String action = (event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded");
|
||||
String direction = event.getRequestType() == TransferEvent.RequestType.PUT ? "to" : "from";
|
||||
|
||||
|
@ -80,13 +74,12 @@ public abstract class AbstractMavenTransferListener extends AbstractTransferList
|
|||
long contentLength = event.getTransferredBytes();
|
||||
FileSizeFormat format = new FileSizeFormat(Locale.ENGLISH);
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(action).append(darkOn).append(' ').append(direction).append(' ');
|
||||
message.append(darkOff).append(resource.getRepositoryId());
|
||||
message.append(darkOn).append(": ").append(resource.getRepositoryUrl());
|
||||
message.append(darkOff).append(resource.getResourceName());
|
||||
message.append(darkOn).append(" (");
|
||||
format.format(message, contentLength);
|
||||
MessageBuilder message = messageBuilderFactory.builder();
|
||||
message.append(action).style(STYLE).append(' ').append(direction).append(' ');
|
||||
message.resetStyle().append(resource.getRepositoryId());
|
||||
message.style(STYLE).append(": ").append(resource.getRepositoryUrl());
|
||||
message.resetStyle().append(resource.getResourceName());
|
||||
message.style(STYLE).append(" (").append(format.format(contentLength));
|
||||
|
||||
long duration = System.currentTimeMillis() - resource.getTransferStartTime();
|
||||
if (duration > 0L) {
|
||||
|
@ -96,7 +89,7 @@ public abstract class AbstractMavenTransferListener extends AbstractTransferList
|
|||
message.append("/s");
|
||||
}
|
||||
|
||||
message.append(')').append(darkOff);
|
||||
message.append(')').resetStyle();
|
||||
out.println(message.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.LinkedHashMap;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilderFactory;
|
||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
||||
import org.eclipse.aether.transfer.TransferEvent;
|
||||
import org.eclipse.aether.transfer.TransferResource;
|
||||
|
@ -41,8 +42,9 @@ public class ConsoleMavenTransferListener extends AbstractMavenTransferListener
|
|||
private boolean printResourceNames;
|
||||
private int lastLength;
|
||||
|
||||
public ConsoleMavenTransferListener(PrintStream out, boolean printResourceNames) {
|
||||
super(out);
|
||||
public ConsoleMavenTransferListener(
|
||||
MessageBuilderFactory messageBuilderFactory, PrintStream out, boolean printResourceNames) {
|
||||
super(messageBuilderFactory, out);
|
||||
this.printResourceNames = printResourceNames;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.apache.maven.cli.transfer;
|
|||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
|
||||
/**
|
||||
* Formats file size with the associated <a href="https://en.wikipedia.org/wiki/Metric_prefix">SI</a> prefix
|
||||
* (GB, MB, kB) and using the patterns <code>#0.0</code> for numbers between 1 and 10
|
||||
|
@ -147,6 +149,38 @@ public class FileSizeFormat {
|
|||
}
|
||||
}
|
||||
|
||||
public void format(MessageBuilder builder, long size) {
|
||||
format(builder, size, null, false);
|
||||
}
|
||||
|
||||
public void format(MessageBuilder builder, long size, ScaleUnit unit) {
|
||||
format(builder, size, unit, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("checkstyle:magicnumber")
|
||||
private void format(MessageBuilder builder, long size, ScaleUnit unit, boolean omitSymbol) {
|
||||
if (size < 0L) {
|
||||
throw new IllegalArgumentException("file size cannot be negative: " + size);
|
||||
}
|
||||
if (unit == null) {
|
||||
unit = ScaleUnit.getScaleUnit(size);
|
||||
}
|
||||
|
||||
double scaledSize = (double) size / unit.bytes();
|
||||
|
||||
if (unit == ScaleUnit.BYTE) {
|
||||
builder.append(Long.toString(size));
|
||||
} else if (scaledSize < 0.05d || scaledSize >= 10.0d) {
|
||||
builder.append(Long.toString(Math.round(scaledSize)));
|
||||
} else {
|
||||
builder.append(Double.toString(Math.round(scaledSize * 10d) / 10d));
|
||||
}
|
||||
|
||||
if (!omitSymbol) {
|
||||
builder.append(" ").append(unit.symbol());
|
||||
}
|
||||
}
|
||||
|
||||
public String formatProgress(long progressedSize, long size) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
formatProgress(sb, progressedSize, size);
|
||||
|
|
|
@ -0,0 +1,952 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.fusesource.jansi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Provides a fluent API for generating
|
||||
* <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences">ANSI escape sequences</a>.
|
||||
*
|
||||
* This class comes from Jansi and is provided for backward compatibility
|
||||
* with maven-shared-utils, while Maven has migrated to JLine (into which Jansi has been merged
|
||||
* since JLine 3.25.0).
|
||||
*/
|
||||
@SuppressWarnings({"checkstyle:MagicNumber", "unused"})
|
||||
public class Ansi implements Appendable {
|
||||
|
||||
private static final char FIRST_ESC_CHAR = 27;
|
||||
private static final char SECOND_ESC_CHAR = '[';
|
||||
|
||||
/**
|
||||
* <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#Colors">ANSI 8 colors</a> for fluent API
|
||||
*/
|
||||
public enum Color {
|
||||
BLACK(0, "BLACK"),
|
||||
RED(1, "RED"),
|
||||
GREEN(2, "GREEN"),
|
||||
YELLOW(3, "YELLOW"),
|
||||
BLUE(4, "BLUE"),
|
||||
MAGENTA(5, "MAGENTA"),
|
||||
CYAN(6, "CYAN"),
|
||||
WHITE(7, "WHITE"),
|
||||
DEFAULT(9, "DEFAULT");
|
||||
|
||||
private final int value;
|
||||
private final String name;
|
||||
|
||||
Color(int index, String name) {
|
||||
this.value = index;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public int fg() {
|
||||
return value + 30;
|
||||
}
|
||||
|
||||
public int bg() {
|
||||
return value + 40;
|
||||
}
|
||||
|
||||
public int fgBright() {
|
||||
return value + 90;
|
||||
}
|
||||
|
||||
public int bgBright() {
|
||||
return value + 100;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display attributes, also know as
|
||||
* <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters">SGR
|
||||
* (Select Graphic Rendition) parameters</a>.
|
||||
*/
|
||||
public enum Attribute {
|
||||
RESET(0, "RESET"),
|
||||
INTENSITY_BOLD(1, "INTENSITY_BOLD"),
|
||||
INTENSITY_FAINT(2, "INTENSITY_FAINT"),
|
||||
ITALIC(3, "ITALIC_ON"),
|
||||
UNDERLINE(4, "UNDERLINE_ON"),
|
||||
BLINK_SLOW(5, "BLINK_SLOW"),
|
||||
BLINK_FAST(6, "BLINK_FAST"),
|
||||
NEGATIVE_ON(7, "NEGATIVE_ON"),
|
||||
CONCEAL_ON(8, "CONCEAL_ON"),
|
||||
STRIKETHROUGH_ON(9, "STRIKETHROUGH_ON"),
|
||||
UNDERLINE_DOUBLE(21, "UNDERLINE_DOUBLE"),
|
||||
INTENSITY_BOLD_OFF(22, "INTENSITY_BOLD_OFF"),
|
||||
ITALIC_OFF(23, "ITALIC_OFF"),
|
||||
UNDERLINE_OFF(24, "UNDERLINE_OFF"),
|
||||
BLINK_OFF(25, "BLINK_OFF"),
|
||||
NEGATIVE_OFF(27, "NEGATIVE_OFF"),
|
||||
CONCEAL_OFF(28, "CONCEAL_OFF"),
|
||||
STRIKETHROUGH_OFF(29, "STRIKETHROUGH_OFF");
|
||||
|
||||
private final int value;
|
||||
private final String name;
|
||||
|
||||
Attribute(int index, String name) {
|
||||
this.value = index;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ED (Erase in Display) / EL (Erase in Line) parameter (see
|
||||
* <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences">CSI sequence J and K</a>)
|
||||
* @see Ansi#eraseScreen(Erase)
|
||||
* @see Ansi#eraseLine(Erase)
|
||||
*/
|
||||
public enum Erase {
|
||||
FORWARD(0, "FORWARD"),
|
||||
BACKWARD(1, "BACKWARD"),
|
||||
ALL(2, "ALL");
|
||||
|
||||
private final int value;
|
||||
private final String name;
|
||||
|
||||
Erase(int index, String name) {
|
||||
this.value = index;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Consumer {
|
||||
void apply(Ansi ansi);
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return org.apache.maven.cli.jline.MessageUtils.isColorEnabled() && org.jline.jansi.Ansi.isEnabled();
|
||||
}
|
||||
|
||||
public static Ansi ansi() {
|
||||
if (isEnabled()) {
|
||||
return new Ansi();
|
||||
} else {
|
||||
return new NoAnsi();
|
||||
}
|
||||
}
|
||||
|
||||
public static Ansi ansi(StringBuilder builder) {
|
||||
if (isEnabled()) {
|
||||
return new Ansi(builder);
|
||||
} else {
|
||||
return new NoAnsi(builder);
|
||||
}
|
||||
}
|
||||
|
||||
public static Ansi ansi(int size) {
|
||||
if (isEnabled()) {
|
||||
return new Ansi(size);
|
||||
} else {
|
||||
return new NoAnsi(size);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoAnsi extends Ansi {
|
||||
NoAnsi() {
|
||||
super();
|
||||
}
|
||||
|
||||
NoAnsi(int size) {
|
||||
super(size);
|
||||
}
|
||||
|
||||
NoAnsi(StringBuilder builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi fg(Color color) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi bg(Color color) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi fgBright(Color color) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi bgBright(Color color) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi fg(int color) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi fgRgb(int r, int g, int b) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi bg(int color) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi bgRgb(int r, int g, int b) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi a(Attribute attribute) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursor(int row, int column) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorToColumn(int x) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorUp(int y) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorRight(int x) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorDown(int y) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorLeft(int x) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorDownLine() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorDownLine(final int n) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorUpLine() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi cursorUpLine(final int n) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi eraseScreen() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi eraseScreen(Erase kind) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi eraseLine() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi eraseLine(Erase kind) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi scrollUp(int rows) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi scrollDown(int rows) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi saveCursorPosition() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Ansi restorCursorPosition() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi restoreCursorPosition() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi reset() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private final StringBuilder builder;
|
||||
private final ArrayList<Integer> attributeOptions = new ArrayList<>(5);
|
||||
|
||||
public Ansi() {
|
||||
this(new StringBuilder(80));
|
||||
}
|
||||
|
||||
public Ansi(Ansi parent) {
|
||||
this(new StringBuilder(parent.builder));
|
||||
attributeOptions.addAll(parent.attributeOptions);
|
||||
}
|
||||
|
||||
public Ansi(int size) {
|
||||
this(new StringBuilder(size));
|
||||
}
|
||||
|
||||
public Ansi(StringBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public Ansi fg(Color color) {
|
||||
attributeOptions.add(color.fg());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi fg(int color) {
|
||||
attributeOptions.add(38);
|
||||
attributeOptions.add(5);
|
||||
attributeOptions.add(color & 0xff);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi fgRgb(int color) {
|
||||
return fgRgb(color >> 16, color >> 8, color);
|
||||
}
|
||||
|
||||
public Ansi fgRgb(int r, int g, int b) {
|
||||
attributeOptions.add(38);
|
||||
attributeOptions.add(2);
|
||||
attributeOptions.add(r & 0xff);
|
||||
attributeOptions.add(g & 0xff);
|
||||
attributeOptions.add(b & 0xff);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi fgBlack() {
|
||||
return this.fg(Color.BLACK);
|
||||
}
|
||||
|
||||
public Ansi fgBlue() {
|
||||
return this.fg(Color.BLUE);
|
||||
}
|
||||
|
||||
public Ansi fgCyan() {
|
||||
return this.fg(Color.CYAN);
|
||||
}
|
||||
|
||||
public Ansi fgDefault() {
|
||||
return this.fg(Color.DEFAULT);
|
||||
}
|
||||
|
||||
public Ansi fgGreen() {
|
||||
return this.fg(Color.GREEN);
|
||||
}
|
||||
|
||||
public Ansi fgMagenta() {
|
||||
return this.fg(Color.MAGENTA);
|
||||
}
|
||||
|
||||
public Ansi fgRed() {
|
||||
return this.fg(Color.RED);
|
||||
}
|
||||
|
||||
public Ansi fgYellow() {
|
||||
return this.fg(Color.YELLOW);
|
||||
}
|
||||
|
||||
public Ansi bg(Color color) {
|
||||
attributeOptions.add(color.bg());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi bg(int color) {
|
||||
attributeOptions.add(48);
|
||||
attributeOptions.add(5);
|
||||
attributeOptions.add(color & 0xff);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi bgRgb(int color) {
|
||||
return bgRgb(color >> 16, color >> 8, color);
|
||||
}
|
||||
|
||||
public Ansi bgRgb(int r, int g, int b) {
|
||||
attributeOptions.add(48);
|
||||
attributeOptions.add(2);
|
||||
attributeOptions.add(r & 0xff);
|
||||
attributeOptions.add(g & 0xff);
|
||||
attributeOptions.add(b & 0xff);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi bgCyan() {
|
||||
return this.bg(Color.CYAN);
|
||||
}
|
||||
|
||||
public Ansi bgDefault() {
|
||||
return this.bg(Color.DEFAULT);
|
||||
}
|
||||
|
||||
public Ansi bgGreen() {
|
||||
return this.bg(Color.GREEN);
|
||||
}
|
||||
|
||||
public Ansi bgMagenta() {
|
||||
return this.bg(Color.MAGENTA);
|
||||
}
|
||||
|
||||
public Ansi bgRed() {
|
||||
return this.bg(Color.RED);
|
||||
}
|
||||
|
||||
public Ansi bgYellow() {
|
||||
return this.bg(Color.YELLOW);
|
||||
}
|
||||
|
||||
public Ansi fgBright(Color color) {
|
||||
attributeOptions.add(color.fgBright());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi fgBrightBlack() {
|
||||
return this.fgBright(Color.BLACK);
|
||||
}
|
||||
|
||||
public Ansi fgBrightBlue() {
|
||||
return this.fgBright(Color.BLUE);
|
||||
}
|
||||
|
||||
public Ansi fgBrightCyan() {
|
||||
return this.fgBright(Color.CYAN);
|
||||
}
|
||||
|
||||
public Ansi fgBrightDefault() {
|
||||
return this.fgBright(Color.DEFAULT);
|
||||
}
|
||||
|
||||
public Ansi fgBrightGreen() {
|
||||
return this.fgBright(Color.GREEN);
|
||||
}
|
||||
|
||||
public Ansi fgBrightMagenta() {
|
||||
return this.fgBright(Color.MAGENTA);
|
||||
}
|
||||
|
||||
public Ansi fgBrightRed() {
|
||||
return this.fgBright(Color.RED);
|
||||
}
|
||||
|
||||
public Ansi fgBrightYellow() {
|
||||
return this.fgBright(Color.YELLOW);
|
||||
}
|
||||
|
||||
public Ansi bgBright(Color color) {
|
||||
attributeOptions.add(color.bgBright());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi bgBrightCyan() {
|
||||
return this.bgBright(Color.CYAN);
|
||||
}
|
||||
|
||||
public Ansi bgBrightDefault() {
|
||||
return this.bgBright(Color.DEFAULT);
|
||||
}
|
||||
|
||||
public Ansi bgBrightGreen() {
|
||||
return this.bgBright(Color.GREEN);
|
||||
}
|
||||
|
||||
public Ansi bgBrightMagenta() {
|
||||
return this.bgBright(Color.MAGENTA);
|
||||
}
|
||||
|
||||
public Ansi bgBrightRed() {
|
||||
return this.bgBright(Color.RED);
|
||||
}
|
||||
|
||||
public Ansi bgBrightYellow() {
|
||||
return this.bgBright(Color.YELLOW);
|
||||
}
|
||||
|
||||
public Ansi a(Attribute attribute) {
|
||||
attributeOptions.add(attribute.value());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor to row n, column m. The values are 1-based.
|
||||
* Any values less than 1 are mapped to 1.
|
||||
*
|
||||
* @param row row (1-based) from top
|
||||
* @param column column (1 based) from left
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursor(final int row, final int column) {
|
||||
return appendEscapeSequence('H', Math.max(1, row), Math.max(1, column));
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor to column n. The parameter n is 1-based.
|
||||
* If n is less than 1 it is moved to the first column.
|
||||
*
|
||||
* @param x the index (1-based) of the column to move to
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorToColumn(final int x) {
|
||||
return appendEscapeSequence('G', Math.max(1, x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor up. If the parameter y is negative it moves the cursor down.
|
||||
*
|
||||
* @param y the number of lines to move up
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorUp(final int y) {
|
||||
return y > 0 ? appendEscapeSequence('A', y) : y < 0 ? cursorDown(-y) : this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor down. If the parameter y is negative it moves the cursor up.
|
||||
*
|
||||
* @param y the number of lines to move down
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorDown(final int y) {
|
||||
return y > 0 ? appendEscapeSequence('B', y) : y < 0 ? cursorUp(-y) : this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor right. If the parameter x is negative it moves the cursor left.
|
||||
*
|
||||
* @param x the number of characters to move right
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorRight(final int x) {
|
||||
return x > 0 ? appendEscapeSequence('C', x) : x < 0 ? cursorLeft(-x) : this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor left. If the parameter x is negative it moves the cursor right.
|
||||
*
|
||||
* @param x the number of characters to move left
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorLeft(final int x) {
|
||||
return x > 0 ? appendEscapeSequence('D', x) : x < 0 ? cursorRight(-x) : this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor relative to the current position. The cursor is moved right if x is
|
||||
* positive, left if negative and down if y is positive and up if negative.
|
||||
*
|
||||
* @param x the number of characters to move horizontally
|
||||
* @param y the number of lines to move vertically
|
||||
* @return this Ansi instance
|
||||
* @since 2.2
|
||||
*/
|
||||
public Ansi cursorMove(final int x, final int y) {
|
||||
return cursorRight(x).cursorDown(y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor to the beginning of the line below.
|
||||
*
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorDownLine() {
|
||||
return appendEscapeSequence('E');
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor to the beginning of the n-th line below. If the parameter n is negative it
|
||||
* moves the cursor to the beginning of the n-th line above.
|
||||
*
|
||||
* @param n the number of lines to move the cursor
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorDownLine(final int n) {
|
||||
return n < 0 ? cursorUpLine(-n) : appendEscapeSequence('E', n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor to the beginning of the line above.
|
||||
*
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorUpLine() {
|
||||
return appendEscapeSequence('F');
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor to the beginning of the n-th line above. If the parameter n is negative it
|
||||
* moves the cursor to the beginning of the n-th line below.
|
||||
*
|
||||
* @param n the number of lines to move the cursor
|
||||
* @return this Ansi instance
|
||||
*/
|
||||
public Ansi cursorUpLine(final int n) {
|
||||
return n < 0 ? cursorDownLine(-n) : appendEscapeSequence('F', n);
|
||||
}
|
||||
|
||||
public Ansi eraseScreen() {
|
||||
return appendEscapeSequence('J', Erase.ALL.value());
|
||||
}
|
||||
|
||||
public Ansi eraseScreen(final Erase kind) {
|
||||
return appendEscapeSequence('J', kind.value());
|
||||
}
|
||||
|
||||
public Ansi eraseLine() {
|
||||
return appendEscapeSequence('K');
|
||||
}
|
||||
|
||||
public Ansi eraseLine(final Erase kind) {
|
||||
return appendEscapeSequence('K', kind.value());
|
||||
}
|
||||
|
||||
public Ansi scrollUp(final int rows) {
|
||||
if (rows == Integer.MIN_VALUE) {
|
||||
return scrollDown(Integer.MAX_VALUE);
|
||||
}
|
||||
return rows > 0 ? appendEscapeSequence('S', rows) : rows < 0 ? scrollDown(-rows) : this;
|
||||
}
|
||||
|
||||
public Ansi scrollDown(final int rows) {
|
||||
if (rows == Integer.MIN_VALUE) {
|
||||
return scrollUp(Integer.MAX_VALUE);
|
||||
}
|
||||
return rows > 0 ? appendEscapeSequence('T', rows) : rows < 0 ? scrollUp(-rows) : this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Ansi restorCursorPosition() {
|
||||
return restoreCursorPosition();
|
||||
}
|
||||
|
||||
public Ansi saveCursorPosition() {
|
||||
saveCursorPositionSCO();
|
||||
return saveCursorPositionDEC();
|
||||
}
|
||||
|
||||
// SCO command
|
||||
public Ansi saveCursorPositionSCO() {
|
||||
return appendEscapeSequence('s');
|
||||
}
|
||||
|
||||
// DEC command
|
||||
public Ansi saveCursorPositionDEC() {
|
||||
builder.append(FIRST_ESC_CHAR);
|
||||
builder.append('7');
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi restoreCursorPosition() {
|
||||
restoreCursorPositionSCO();
|
||||
return restoreCursorPositionDEC();
|
||||
}
|
||||
|
||||
// SCO command
|
||||
public Ansi restoreCursorPositionSCO() {
|
||||
return appendEscapeSequence('u');
|
||||
}
|
||||
|
||||
// DEC command
|
||||
public Ansi restoreCursorPositionDEC() {
|
||||
builder.append(FIRST_ESC_CHAR);
|
||||
builder.append('8');
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi reset() {
|
||||
return a(Attribute.RESET);
|
||||
}
|
||||
|
||||
public Ansi bold() {
|
||||
return a(Attribute.INTENSITY_BOLD);
|
||||
}
|
||||
|
||||
public Ansi boldOff() {
|
||||
return a(Attribute.INTENSITY_BOLD_OFF);
|
||||
}
|
||||
|
||||
public Ansi a(String value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(boolean value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(char value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(char[] value, int offset, int len) {
|
||||
flushAttributes();
|
||||
builder.append(value, offset, len);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(char[] value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(CharSequence value, int start, int end) {
|
||||
flushAttributes();
|
||||
builder.append(value, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(CharSequence value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(double value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(float value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(int value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(long value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(Object value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi a(StringBuffer value) {
|
||||
flushAttributes();
|
||||
builder.append(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi newline() {
|
||||
flushAttributes();
|
||||
builder.append(System.getProperty("line.separator"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ansi format(String pattern, Object... args) {
|
||||
flushAttributes();
|
||||
builder.append(String.format(pattern, args));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies another function to this Ansi instance.
|
||||
*
|
||||
* @param fun the function to apply
|
||||
* @return this Ansi instance
|
||||
* @since 2.2
|
||||
*/
|
||||
public Ansi apply(Consumer fun) {
|
||||
fun.apply(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the {@link org.jline.jansi.AnsiRenderer}
|
||||
* to generate the ANSI escape sequences for the supplied text.
|
||||
*
|
||||
* @param text text
|
||||
* @return this
|
||||
* @since 2.2
|
||||
*/
|
||||
public Ansi render(final String text) {
|
||||
a(new org.jline.jansi.Ansi().render(text).toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* String formats and renders the supplied arguments. Uses the {@link org.jline.jansi.AnsiRenderer}
|
||||
* to generate the ANSI escape sequences.
|
||||
*
|
||||
* @param text format
|
||||
* @param args arguments
|
||||
* @return this
|
||||
* @since 2.2
|
||||
*/
|
||||
public Ansi render(final String text, Object... args) {
|
||||
a(String.format(new org.jline.jansi.Ansi().render(text).toString(), args));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
flushAttributes();
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Private Helper Methods
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private Ansi appendEscapeSequence(char command) {
|
||||
flushAttributes();
|
||||
builder.append(FIRST_ESC_CHAR);
|
||||
builder.append(SECOND_ESC_CHAR);
|
||||
builder.append(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
private Ansi appendEscapeSequence(char command, int option) {
|
||||
flushAttributes();
|
||||
builder.append(FIRST_ESC_CHAR);
|
||||
builder.append(SECOND_ESC_CHAR);
|
||||
builder.append(option);
|
||||
builder.append(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
private Ansi appendEscapeSequence(char command, Object... options) {
|
||||
flushAttributes();
|
||||
return doAppendEscapeSequence(command, options);
|
||||
}
|
||||
|
||||
private void flushAttributes() {
|
||||
if (attributeOptions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (attributeOptions.size() == 1 && attributeOptions.get(0) == 0) {
|
||||
builder.append(FIRST_ESC_CHAR);
|
||||
builder.append(SECOND_ESC_CHAR);
|
||||
builder.append('m');
|
||||
} else {
|
||||
doAppendEscapeSequence('m', attributeOptions.toArray());
|
||||
}
|
||||
attributeOptions.clear();
|
||||
}
|
||||
|
||||
private Ansi doAppendEscapeSequence(char command, Object... options) {
|
||||
builder.append(FIRST_ESC_CHAR);
|
||||
builder.append(SECOND_ESC_CHAR);
|
||||
int size = options.length;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (i != 0) {
|
||||
builder.append(';');
|
||||
}
|
||||
if (options[i] != null) {
|
||||
builder.append(options[i]);
|
||||
}
|
||||
}
|
||||
builder.append(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi append(CharSequence csq) {
|
||||
builder.append(csq);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi append(CharSequence csq, int start, int end) {
|
||||
builder.append(csq, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ansi append(char c) {
|
||||
builder.append(c);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ import org.apache.commons.cli.Option;
|
|||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.maven.Maven;
|
||||
import org.apache.maven.cli.jansi.MessageUtils;
|
||||
import org.apache.maven.cli.jline.MessageUtils;
|
||||
import org.apache.maven.cli.transfer.ConsoleMavenTransferListener;
|
||||
import org.apache.maven.cli.transfer.QuietMavenTransferListener;
|
||||
import org.apache.maven.cli.transfer.Slf4jMavenTransferListener;
|
||||
|
@ -500,7 +500,7 @@ class MavenCliTest {
|
|||
String versionOut = new String(systemOut.toByteArray(), StandardCharsets.UTF_8);
|
||||
|
||||
// then
|
||||
assertEquals(MessageUtils.stripAnsiCodes(versionOut), versionOut);
|
||||
assertEquals(stripAnsiCodes(versionOut), versionOut);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -675,4 +675,8 @@ class MavenCliTest {
|
|||
project.setArtifactId(artifactId);
|
||||
return project;
|
||||
}
|
||||
|
||||
static String stripAnsiCodes(String msg) {
|
||||
return msg.replaceAll("\u001b\\[[;\\d]*[ -/]*[@-~]", "");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.io.File;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.maven.cli.jansi.JansiMessageBuilderFactory;
|
||||
import org.apache.maven.cli.jansi.MessageUtils;
|
||||
import org.apache.maven.cli.jline.JLineMessageBuilderFactory;
|
||||
import org.apache.maven.cli.jline.MessageUtils;
|
||||
import org.apache.maven.execution.ExecutionEvent;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
|
@ -45,7 +45,7 @@ class ExecutionEventLoggerTest {
|
|||
|
||||
private Logger logger;
|
||||
private ExecutionEventLogger executionEventLogger;
|
||||
private JansiMessageBuilderFactory messageBuilderFactory = new JansiMessageBuilderFactory();
|
||||
private JLineMessageBuilderFactory messageBuilderFactory = new JLineMessageBuilderFactory();
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() {
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.apache.maven.cli.jline.JLineMessageBuilderFactory;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.transfer.TransferCancelledException;
|
||||
import org.eclipse.aether.transfer.TransferEvent;
|
||||
|
@ -48,6 +49,7 @@ class ConsoleMavenTransferListenerTest {
|
|||
Map<String, String> output = new ConcurrentHashMap<String, String>();
|
||||
|
||||
ConsoleMavenTransferListener listener = new ConsoleMavenTransferListener(
|
||||
new JLineMessageBuilderFactory(),
|
||||
new PrintStream(System.out) {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.io.PrintStream;
|
|||
|
||||
import org.apache.maven.api.services.MessageBuilder;
|
||||
|
||||
import static org.apache.maven.cli.jansi.MessageUtils.builder;
|
||||
import static org.apache.maven.cli.jline.MessageUtils.builder;
|
||||
|
||||
/**
|
||||
* Logger for Maven, that support colorization of levels and stacktraces. This class implements 2 methods introduced in
|
||||
|
|
|
@ -24,6 +24,9 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.apache.maven.cli.jline.MessageUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
|
||||
|
@ -32,6 +35,19 @@ import static org.junit.jupiter.api.Assertions.assertLinesMatch;
|
|||
|
||||
class MavenSimpleLoggerTest {
|
||||
|
||||
boolean colorEnabled;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
colorEnabled = MessageUtils.isColorEnabled();
|
||||
MessageUtils.setColorEnabled(false);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void taerdown() {
|
||||
MessageUtils.setColorEnabled(colorEnabled);
|
||||
}
|
||||
|
||||
@Test
|
||||
void includesCauseAndSuppressedExceptionsWhenWritingThrowables(TestInfo testInfo) throws Exception {
|
||||
Exception causeOfSuppressed = new NoSuchElementException("cause of suppressed");
|
||||
|
|
17
pom.xml
17
pom.xml
|
@ -167,12 +167,13 @@ under the License.
|
|||
<guavafailureaccessVersion>1.0.1</guavafailureaccessVersion>
|
||||
<hamcrestVersion>2.2</hamcrestVersion>
|
||||
<jakartaInjectApiVersion>2.0.1</jakartaInjectApiVersion>
|
||||
<jansiVersion>2.4.1</jansiVersion>
|
||||
<javaxAnnotationApiVersion>1.3.2</javaxAnnotationApiVersion>
|
||||
<jlineVersion>3.25.0</jlineVersion>
|
||||
<junitVersion>5.10.1</junitVersion>
|
||||
<jxpathVersion>1.3</jxpathVersion>
|
||||
<logbackClassicVersion>1.2.13</logbackClassicVersion>
|
||||
<mockitoVersion>5.7.0</mockitoVersion>
|
||||
<plexusInteractivityVersion>1.1</plexusInteractivityVersion>
|
||||
<plexusInterpolationVersion>1.26</plexusInterpolationVersion>
|
||||
<plexusTestingVersion>1.0.0</plexusTestingVersion>
|
||||
<plexusXmlVersion>4.0.1</plexusXmlVersion>
|
||||
|
@ -309,9 +310,14 @@ under the License.
|
|||
<version>${plexusInterpolationVersion}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
<artifactId>jansi</artifactId>
|
||||
<version>${jansiVersion}</version>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-interactivity-api</artifactId>
|
||||
<version>${plexusInteractivityVersion}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jline</groupId>
|
||||
<artifactId>jline</artifactId>
|
||||
<version>${jlineVersion}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
@ -690,6 +696,9 @@ under the License.
|
|||
<ignoredScopes>
|
||||
<ignoredScope>test</ignoredScope>
|
||||
</ignoredScopes>
|
||||
<excludes>
|
||||
<exclude>org.jline:jline</exclude>
|
||||
</excludes>
|
||||
</enforceBytecodeVersion>
|
||||
</rules>
|
||||
<fail>true</fail>
|
||||
|
|
Loading…
Reference in New Issue