Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Adam Williamson
e4c48ff630 Backport patch to bring back AnsiRenderer 2021-12-13 21:24:01 -08:00
2 changed files with 444 additions and 1 deletions

View file

@ -0,0 +1,436 @@
From faf93318be3cda0b3a3894ae9d2032835601bc73 Mon Sep 17 00:00:00 2001
From: Guillaume Nodet <gnodet@gmail.com>
Date: Wed, 20 Jan 2021 12:08:59 +0100
Subject: [PATCH] Bring back the AnsiRenderer, fixes #184
---
src/main/java/org/fusesource/jansi/Ansi.java | 27 ++
.../org/fusesource/jansi/AnsiRenderer.java | 253 ++++++++++++++++++
.../fusesource/jansi/AnsiRendererTest.java | 115 ++++++++
3 files changed, 395 insertions(+)
create mode 100644 src/main/java/org/fusesource/jansi/AnsiRenderer.java
create mode 100644 src/test/java/org/fusesource/jansi/AnsiRendererTest.java
diff --git a/src/main/java/org/fusesource/jansi/Ansi.java b/src/main/java/org/fusesource/jansi/Ansi.java
index 84976e0..a882705 100644
--- a/src/main/java/org/fusesource/jansi/Ansi.java
+++ b/src/main/java/org/fusesource/jansi/Ansi.java
@@ -818,6 +818,33 @@ public class Ansi implements Appendable {
return this;
}
+ /**
+ * Uses the {@link 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(AnsiRenderer.render(text));
+ return this;
+ }
+
+ /**
+ * String formats and renders the supplied arguments. Uses the {@link 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(AnsiRenderer.render(text), args));
+ return this;
+ }
+
@Override
public String toString() {
flushAttributes();
diff --git a/src/main/java/org/fusesource/jansi/AnsiRenderer.java b/src/main/java/org/fusesource/jansi/AnsiRenderer.java
new file mode 100644
index 0000000..7565ae4
--- /dev/null
+++ b/src/main/java/org/fusesource/jansi/AnsiRenderer.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2009-2021 the original author(s).
+ *
+ * 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.fusesource.jansi;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import org.fusesource.jansi.Ansi.Attribute;
+import org.fusesource.jansi.Ansi.Color;
+
+/**
+ * Renders ANSI color escape-codes in strings by parsing out some special syntax to pick up the correct fluff to use.
+ *
+ * The syntax for embedded ANSI codes is:
+ *
+ * <pre>
+ * &#64;|<em>code</em>(,<em>code</em>)* <em>text</em>|&#64;
+ * </pre>
+ *
+ * Examples:
+ *
+ * <pre>
+ * &#64;|bold Hello|&#64;
+ * </pre>
+ *
+ * <pre>
+ * &#64;|bold,red Warning!|&#64;
+ * </pre>
+ *
+ * @since 2.2
+ */
+public class AnsiRenderer {
+
+ public static final String BEGIN_TOKEN = "@|";
+
+ public static final String END_TOKEN = "|@";
+
+ public static final String CODE_TEXT_SEPARATOR = " ";
+
+ public static final String CODE_LIST_SEPARATOR = ",";
+
+ private static final int BEGIN_TOKEN_LEN = 2;
+
+ private static final int END_TOKEN_LEN = 2;
+
+ public static String render(final String input) throws IllegalArgumentException {
+ try {
+ return render(input, new StringBuilder()).toString();
+ } catch (IOException e) {
+ // Cannot happen because StringBuilder does not throw IOException
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Renders the given input to the target Appendable.
+ *
+ * @param input
+ * source to render
+ * @param target
+ * render onto this target Appendable.
+ * @return the given Appendable
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ public static Appendable render(final String input, Appendable target) throws IOException {
+
+ int i = 0;
+ int j, k;
+
+ while (true) {
+ j = input.indexOf(BEGIN_TOKEN, i);
+ if (j == -1) {
+ if (i == 0) {
+ target.append(input);
+ return target;
+ }
+ target.append(input.substring(i));
+ return target;
+ }
+ target.append(input.substring(i, j));
+ k = input.indexOf(END_TOKEN, j);
+
+ if (k == -1) {
+ target.append(input);
+ return target;
+ }
+ j += BEGIN_TOKEN_LEN;
+ String spec = input.substring(j, k);
+
+ String[] items = spec.split(CODE_TEXT_SEPARATOR, 2);
+ if (items.length == 1) {
+ target.append(input);
+ return target;
+ }
+ String replacement = render(items[1], items[0].split(CODE_LIST_SEPARATOR));
+
+ target.append(replacement);
+
+ i = k + END_TOKEN_LEN;
+ }
+ }
+
+ public static String render(final String text, final String... codes) {
+ return render(Ansi.ansi(), codes)
+ .a(text).reset().toString();
+ }
+
+ /**
+ * Renders {@link Code} names as an ANSI escape string.
+ * @param codes The code names to render
+ * @return an ANSI escape string.
+ */
+ public static String renderCodes(final String... codes) {
+ return render(Ansi.ansi(), codes).toString();
+ }
+
+ /**
+ * Renders {@link Code} names as an ANSI escape string.
+ * @param codes A space separated list of code names to render
+ * @return an ANSI escape string.
+ */
+ public static String renderCodes(final String codes) {
+ return renderCodes(codes.split("\\s"));
+ }
+
+ private static Ansi render(Ansi ansi, String... names) {
+ for (String name : names) {
+ Code code = Code.valueOf(name.toUpperCase(Locale.ENGLISH));
+ if (code.isColor()) {
+ if (code.isBackground()) {
+ ansi.bg(code.getColor());
+ } else {
+ ansi.fg(code.getColor());
+ }
+ } else if (code.isAttribute()) {
+ ansi.a(code.getAttribute());
+ }
+ }
+ return ansi;
+ }
+
+ public static boolean test(final String text) {
+ return text != null && text.contains(BEGIN_TOKEN);
+ }
+
+ @SuppressWarnings("unused")
+ public enum Code {
+ //
+ // TODO: Find a better way to keep Code in sync with Color/Attribute/Erase
+ //
+
+ // Colors
+ BLACK(Color.BLACK),
+ RED(Color.RED),
+ GREEN(Color.GREEN),
+ YELLOW(Color.YELLOW),
+ BLUE(Color.BLUE),
+ MAGENTA(Color.MAGENTA),
+ CYAN(Color.CYAN),
+ WHITE(Color.WHITE),
+
+ // Foreground Colors
+ FG_BLACK(Color.BLACK, false),
+ FG_RED(Color.RED, false),
+ FG_GREEN(Color.GREEN, false),
+ FG_YELLOW(Color.YELLOW, false),
+ FG_BLUE(Color.BLUE, false),
+ FG_MAGENTA(Color.MAGENTA, false),
+ FG_CYAN(Color.CYAN, false),
+ FG_WHITE(Color.WHITE, false),
+
+ // Background Colors
+ BG_BLACK(Color.BLACK, true),
+ BG_RED(Color.RED, true),
+ BG_GREEN(Color.GREEN, true),
+ BG_YELLOW(Color.YELLOW, true),
+ BG_BLUE(Color.BLUE, true),
+ BG_MAGENTA(Color.MAGENTA, true),
+ BG_CYAN(Color.CYAN, true),
+ BG_WHITE(Color.WHITE, true),
+
+ // Attributes
+ RESET(Attribute.RESET),
+ INTENSITY_BOLD(Attribute.INTENSITY_BOLD),
+ INTENSITY_FAINT(Attribute.INTENSITY_FAINT),
+ ITALIC(Attribute.ITALIC),
+ UNDERLINE(Attribute.UNDERLINE),
+ BLINK_SLOW(Attribute.BLINK_SLOW),
+ BLINK_FAST(Attribute.BLINK_FAST),
+ BLINK_OFF(Attribute.BLINK_OFF),
+ NEGATIVE_ON(Attribute.NEGATIVE_ON),
+ NEGATIVE_OFF(Attribute.NEGATIVE_OFF),
+ CONCEAL_ON(Attribute.CONCEAL_ON),
+ CONCEAL_OFF(Attribute.CONCEAL_OFF),
+ UNDERLINE_DOUBLE(Attribute.UNDERLINE_DOUBLE),
+ UNDERLINE_OFF(Attribute.UNDERLINE_OFF),
+
+ // Aliases
+ BOLD(Attribute.INTENSITY_BOLD),
+ FAINT(Attribute.INTENSITY_FAINT),;
+
+ private final Enum<?> n;
+
+ private final boolean background;
+
+ Code(final Enum<?> n, boolean background) {
+ this.n = n;
+ this.background = background;
+ }
+
+ Code(final Enum<?> n) {
+ this(n, false);
+ }
+
+ public boolean isColor() {
+ return n instanceof Ansi.Color;
+ }
+
+ public Ansi.Color getColor() {
+ return (Ansi.Color) n;
+ }
+
+ public boolean isAttribute() {
+ return n instanceof Attribute;
+ }
+
+ public Attribute getAttribute() {
+ return (Attribute) n;
+ }
+
+ public boolean isBackground() {
+ return background;
+ }
+ }
+
+ private AnsiRenderer() {
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/fusesource/jansi/AnsiRendererTest.java b/src/test/java/org/fusesource/jansi/AnsiRendererTest.java
new file mode 100644
index 0000000..590a96b
--- /dev/null
+++ b/src/test/java/org/fusesource/jansi/AnsiRendererTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2009-2021 the original author(s).
+ *
+ * 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.fusesource.jansi;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.fusesource.jansi.Ansi.*;
+import static org.fusesource.jansi.Ansi.Attribute.*;
+import static org.fusesource.jansi.Ansi.Color.*;
+import static org.fusesource.jansi.AnsiRenderer.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for the {@link AnsiRenderer} class.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ */
+public class AnsiRendererTest {
+
+ @BeforeAll
+ static void setUp() {
+ Ansi.setEnabled(true);
+ }
+
+ @Test
+ public void testTest() throws Exception {
+ assertFalse(test("foo"));
+ assertTrue(test("@|foo|"));
+ assertTrue(test("@|foo"));
+ }
+
+ @Test
+ public void testRender() {
+ String str = render("@|bold foo|@");
+ System.out.println(str);
+ assertEquals(ansi().a(INTENSITY_BOLD).a("foo").reset().toString(), str);
+ assertEquals(ansi().bold().a("foo").reset().toString(), str);
+ }
+
+ @Test
+ public void testRenderCodes() {
+ String str = renderCodes("bold red");
+ System.out.println(str);
+ assertEquals(ansi().bold().fg(Color.RED).toString(), str);
+ }
+
+ @Test
+ public void testRender2() {
+ String str = render("@|bold,red foo|@");
+ System.out.println(str);
+ assertEquals(Ansi.ansi().a(INTENSITY_BOLD).fg(RED).a("foo").reset().toString(), str);
+ assertEquals(Ansi.ansi().bold().fgRed().a("foo").reset().toString(), str);
+ }
+
+ @Test
+ public void testRender3() {
+ String str = render("@|bold,red foo bar baz|@");
+ System.out.println(str);
+ assertEquals(ansi().a(INTENSITY_BOLD).fg(RED).a("foo bar baz").reset().toString(), str);
+ assertEquals(ansi().bold().fgRed().a("foo bar baz").reset().toString(), str);
+ }
+
+ @Test
+ public void testRender4() {
+ String str = render("@|bold,red foo bar baz|@ ick @|bold,red foo bar baz|@");
+ System.out.println(str);
+ assertEquals(ansi()
+ .a(INTENSITY_BOLD).fg(RED).a("foo bar baz").reset()
+ .a(" ick ")
+ .a(INTENSITY_BOLD).fg(RED).a("foo bar baz").reset()
+ .toString(), str);
+ }
+
+ @Test
+ public void testRender5() {
+ // Check the ansi() render method.
+ String str = ansi().render("@|bold Hello|@").toString();
+ System.out.println(str);
+ assertEquals(ansi().a(INTENSITY_BOLD).a("Hello").reset().toString(), str);
+ }
+
+
+ @Test
+ public void testRenderNothing() {
+ assertEquals("foo", render("foo"));
+ }
+
+ @Test
+ public void testRenderInvalidMissingEnd() {
+ String str = render("@|bold foo");
+ assertEquals("@|bold foo", str);
+ }
+
+ @Test
+ public void testRenderInvalidMissingText() {
+ String str = render("@|bold|@");
+ assertEquals("@|bold|@", str);
+ }
+}
\ No newline at end of file
--
2.33.1

View file

@ -1,6 +1,6 @@
Name: jansi
Version: 2.1.1
Release: 3%{?dist}
Release: 4%{?dist}
Summary: Generate and interpret ANSI escape sequences in Java
License: ASL 2.0
@ -8,6 +8,10 @@ URL: http://fusesource.github.io/jansi/
Source0: https://github.com/fusesource/jansi/archive/jansi-%{version}.tar.gz
# Change the location of the native artifact to where Fedora wants it
Patch0: %{name}-jni.patch
# Bring back AnsiRenderer
# https://github.com/fusesource/jansi/commit/faf9331
# Needed to build newer log4j
Patch1: 0001-Bring-back-the-AnsiRenderer-fixes-184.patch
BuildRequires: gcc
BuildRequires: maven-local
@ -92,6 +96,9 @@ cp -p src/main/native/libjansi.so %{buildroot}%{_libdir}/%{name}
%license license.txt
%changelog
* Mon Dec 13 2021 Adam Williamson <awilliam@redhat.com> - 2.1.1-4
- Backport patch to bring back AnsiRenderer
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.1.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild