All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pkl.thirdparty.jansiio.AnsiProcessor Maven / Gradle / Ivy

Go to download

Fat Jar containing pkl-cli, pkl-codegen-java, pkl-codegen-kotlin, pkl-config-java, pkl-core, pkl-doc, and their shaded third-party dependencies.

There is a newer version: 0.27.1
Show newest version
/*
 * Copyright (C) 2009-2023 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.pkl.thirdparty.jansiio;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * ANSI processor providing process* corresponding to ANSI escape codes.
 * This class methods implementations are empty: subclasses should actually perform the
 * ANSI escape behaviors by implementing active code in process* methods.
 *
 * 

For more information about ANSI escape codes, see * Wikipedia article * * @since 1.19 */ @SuppressWarnings("unused") public class AnsiProcessor { protected final OutputStream os; public AnsiProcessor(OutputStream os) { this.os = os; } /** * Helper for processEscapeCommand() to iterate over integer options * @param optionsIterator the underlying iterator * @throws IOException if no more non-null values left */ protected int getNextOptionInt(Iterator optionsIterator) throws IOException { for (; ; ) { if (!optionsIterator.hasNext()) throw new IllegalArgumentException(); Object arg = optionsIterator.next(); if (arg != null) return (Integer) arg; } } /** * @return true if the escape command was processed. */ protected boolean processEscapeCommand(ArrayList options, int command) throws IOException { try { switch (command) { case 'A': processCursorUp(optionInt(options, 0, 1)); return true; case 'B': processCursorDown(optionInt(options, 0, 1)); return true; case 'C': processCursorRight(optionInt(options, 0, 1)); return true; case 'D': processCursorLeft(optionInt(options, 0, 1)); return true; case 'E': processCursorDownLine(optionInt(options, 0, 1)); return true; case 'F': processCursorUpLine(optionInt(options, 0, 1)); return true; case 'G': processCursorToColumn(optionInt(options, 0)); return true; case 'H': case 'f': processCursorTo(optionInt(options, 0, 1), optionInt(options, 1, 1)); return true; case 'J': processEraseScreen(optionInt(options, 0, 0)); return true; case 'K': processEraseLine(optionInt(options, 0, 0)); return true; case 'L': processInsertLine(optionInt(options, 0, 1)); return true; case 'M': processDeleteLine(optionInt(options, 0, 1)); return true; case 'S': processScrollUp(optionInt(options, 0, 1)); return true; case 'T': processScrollDown(optionInt(options, 0, 1)); return true; case 'm': // Validate all options are ints... for (Object next : options) { if (next != null && next.getClass() != Integer.class) { throw new IllegalArgumentException(); } } int count = 0; Iterator optionsIterator = options.iterator(); while (optionsIterator.hasNext()) { Object next = optionsIterator.next(); if (next != null) { count++; int value = (Integer) next; if (30 <= value && value <= 37) { processSetForegroundColor(value - 30); } else if (40 <= value && value <= 47) { processSetBackgroundColor(value - 40); } else if (90 <= value && value <= 97) { processSetForegroundColor(value - 90, true); } else if (100 <= value && value <= 107) { processSetBackgroundColor(value - 100, true); } else if (value == 38 || value == 48) { if (!optionsIterator.hasNext()) { continue; } // extended color like `esc[38;5;m` or `esc[38;2;;;m` int arg2or5 = getNextOptionInt(optionsIterator); if (arg2or5 == 2) { // 24 bit color style like `esc[38;2;;;m` int r = getNextOptionInt(optionsIterator); int g = getNextOptionInt(optionsIterator); int b = getNextOptionInt(optionsIterator); if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) { if (value == 38) processSetForegroundColorExt(r, g, b); else processSetBackgroundColorExt(r, g, b); } else { throw new IllegalArgumentException(); } } else if (arg2or5 == 5) { // 256 color style like `esc[38;5;m` int paletteIndex = getNextOptionInt(optionsIterator); if (paletteIndex >= 0 && paletteIndex <= 255) { if (value == 38) processSetForegroundColorExt(paletteIndex); else processSetBackgroundColorExt(paletteIndex); } else { throw new IllegalArgumentException(); } } else { throw new IllegalArgumentException(); } } else { switch (value) { case 39: processDefaultTextColor(); break; case 49: processDefaultBackgroundColor(); break; case 0: processAttributeReset(); break; default: processSetAttribute(value); } } } } if (count == 0) { processAttributeReset(); } return true; case 's': processSaveCursorPosition(); return true; case 'u': processRestoreCursorPosition(); return true; default: if ('a' <= command && command <= 'z') { processUnknownExtension(options, command); return true; } if ('A' <= command && command <= 'Z') { processUnknownExtension(options, command); return true; } return false; } } catch (IllegalArgumentException ignore) { } return false; } /** * @return true if the operating system command was processed. */ protected boolean processOperatingSystemCommand(ArrayList options) { int command = optionInt(options, 0); String label = (String) options.get(1); // for command > 2 label could be composed (i.e. contain ';'), but we'll leave // it to processUnknownOperatingSystemCommand implementations to handle that try { switch (command) { case 0: processChangeIconNameAndWindowTitle(label); return true; case 1: processChangeIconName(label); return true; case 2: processChangeWindowTitle(label); return true; default: // not exactly unknown, but not supported through dedicated process methods: processUnknownOperatingSystemCommand(command, label); return true; } } catch (IllegalArgumentException ignore) { } return false; } /** * Process character set sequence. * @param options options * @return true if the charcter set select command was processed. */ protected boolean processCharsetSelect(ArrayList options) { int set = optionInt(options, 0); char seq = (Character) options.get(1); processCharsetSelect(set, seq); return true; } private int optionInt(ArrayList options, int index) { if (options.size() <= index) throw new IllegalArgumentException(); Object value = options.get(index); if (value == null) throw new IllegalArgumentException(); if (!value.getClass().equals(Integer.class)) throw new IllegalArgumentException(); return (Integer) value; } private int optionInt(ArrayList options, int index, int defaultValue) { if (options.size() > index) { Object value = options.get(index); if (value == null) { return defaultValue; } return (Integer) value; } return defaultValue; } /** * Process CSI u ANSI code, corresponding to RCP – Restore Cursor Position * @throws IOException IOException */ protected void processRestoreCursorPosition() throws IOException {} /** * Process CSI s ANSI code, corresponding to SCP – Save Cursor Position * @throws IOException IOException */ protected void processSaveCursorPosition() throws IOException {} /** * Process CSI L ANSI code, corresponding to IL – Insert Line * @param optionInt option * @throws IOException IOException * @since 1.16 */ protected void processInsertLine(int optionInt) throws IOException {} /** * Process CSI M ANSI code, corresponding to DL – Delete Line * @param optionInt option * @throws IOException IOException * @since 1.16 */ protected void processDeleteLine(int optionInt) throws IOException {} /** * Process CSI n T ANSI code, corresponding to SD – Scroll Down * @param optionInt option * @throws IOException IOException */ protected void processScrollDown(int optionInt) throws IOException {} /** * Process CSI n U ANSI code, corresponding to SU – Scroll Up * @param optionInt option * @throws IOException IOException */ protected void processScrollUp(int optionInt) throws IOException {} protected static final int ERASE_SCREEN_TO_END = 0; protected static final int ERASE_SCREEN_TO_BEGINING = 1; protected static final int ERASE_SCREEN = 2; /** * Process CSI n J ANSI code, corresponding to ED – Erase in Display * @param eraseOption eraseOption * @throws IOException IOException */ protected void processEraseScreen(int eraseOption) throws IOException {} protected static final int ERASE_LINE_TO_END = 0; protected static final int ERASE_LINE_TO_BEGINING = 1; protected static final int ERASE_LINE = 2; /** * Process CSI n K ANSI code, corresponding to ED – Erase in Line * @param eraseOption eraseOption * @throws IOException IOException */ protected void processEraseLine(int eraseOption) throws IOException {} protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported protected static final int ATTRIBUTE_ITALIC = 3; // Italic; on not widely supported. Sometimes treated as inverse. protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more protected static final int ATTRIBUTE_NEGATIVE_ON = 7; // Image; Negative inverse or reverse; swap foreground and background protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off protected static final int ATTRIBUTE_NEGATIVE_OFF = 27; // Image; Positive protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off /** * process SGR other than 0 (reset), 30-39 (foreground), * 40-49 (background), 90-97 (foreground high intensity) or * 100-107 (background high intensity) * @param attribute attribute * @throws IOException IOException * @see #processAttributeReset() * @see #processSetForegroundColor(int) * @see #processSetForegroundColor(int, boolean) * @see #processSetForegroundColorExt(int) * @see #processSetForegroundColorExt(int, int, int) * @see #processDefaultTextColor() * @see #processDefaultBackgroundColor() */ protected void processSetAttribute(int attribute) throws IOException {} protected static final int BLACK = 0; protected static final int RED = 1; protected static final int GREEN = 2; protected static final int YELLOW = 3; protected static final int BLUE = 4; protected static final int MAGENTA = 5; protected static final int CYAN = 6; protected static final int WHITE = 7; /** * process SGR 30-37 corresponding to Set text color (foreground). * @param color the text color * @throws IOException IOException */ protected void processSetForegroundColor(int color) throws IOException { processSetForegroundColor(color, false); } /** * process SGR 30-37 or SGR 90-97 corresponding to * Set text color (foreground) either in normal mode or high intensity. * @param color the text color * @param bright is high intensity? * @throws IOException IOException */ protected void processSetForegroundColor(int color, boolean bright) throws IOException {} /** * process SGR 38 corresponding to extended set text color (foreground) * with a palette of 255 colors. * @param paletteIndex the text color in the palette * @throws IOException IOException */ protected void processSetForegroundColorExt(int paletteIndex) throws IOException {} /** * process SGR 38 corresponding to extended set text color (foreground) * with a 24 bits RGB definition of the color. * @param r red * @param g green * @param b blue * @throws IOException IOException */ protected void processSetForegroundColorExt(int r, int g, int b) throws IOException {} /** * process SGR 40-47 corresponding to Set background color. * @param color the background color * @throws IOException IOException */ protected void processSetBackgroundColor(int color) throws IOException { processSetBackgroundColor(color, false); } /** * process SGR 40-47 or SGR 100-107 corresponding to * Set background color either in normal mode or high intensity. * @param color the background color * @param bright is high intensity? * @throws IOException IOException */ protected void processSetBackgroundColor(int color, boolean bright) throws IOException {} /** * process SGR 48 corresponding to extended set background color * with a palette of 255 colors. * @param paletteIndex the background color in the palette * @throws IOException IOException */ protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {} /** * process SGR 48 corresponding to extended set background color * with a 24 bits RGB definition of the color. * @param r red * @param g green * @param b blue * @throws IOException IOException */ protected void processSetBackgroundColorExt(int r, int g, int b) throws IOException {} /** * process SGR 39 corresponding to Default text color (foreground) * @throws IOException IOException */ protected void processDefaultTextColor() throws IOException {} /** * process SGR 49 corresponding to Default background color * @throws IOException IOException */ protected void processDefaultBackgroundColor() throws IOException {} /** * process SGR 0 corresponding to Reset / Normal * @throws IOException IOException */ protected void processAttributeReset() throws IOException {} /** * process CSI n ; m H corresponding to CUP – Cursor Position or * CSI n ; m f corresponding to HVP – Horizontal and Vertical Position * @param row row * @param col col * @throws IOException IOException */ protected void processCursorTo(int row, int col) throws IOException {} /** * process CSI n G corresponding to CHA – Cursor Horizontal Absolute * @param x the column * @throws IOException IOException */ protected void processCursorToColumn(int x) throws IOException {} /** * process CSI n F corresponding to CPL – Cursor Previous Line * @param count line count * @throws IOException IOException */ protected void processCursorUpLine(int count) throws IOException {} /** * process CSI n E corresponding to CNL – Cursor Next Line * @param count line count * @throws IOException IOException */ protected void processCursorDownLine(int count) throws IOException { // Poor mans impl.. for (int i = 0; i < count; i++) { os.write('\n'); } } /** * process CSI n D corresponding to CUB – Cursor Back * @param count count * @throws IOException IOException */ protected void processCursorLeft(int count) throws IOException {} /** * process CSI n C corresponding to CUF – Cursor Forward * @param count count * @throws IOException IOException */ protected void processCursorRight(int count) throws IOException { // Poor mans impl.. for (int i = 0; i < count; i++) { os.write(' '); } } /** * process CSI n B corresponding to CUD – Cursor Down * @param count count * @throws IOException IOException */ protected void processCursorDown(int count) throws IOException {} /** * process CSI n A corresponding to CUU – Cursor Up * @param count count * @throws IOException IOException */ protected void processCursorUp(int count) throws IOException {} /** * Process Unknown Extension * @param options options * @param command command */ protected void processUnknownExtension(ArrayList options, int command) {} /** * process OSC 0;text BEL corresponding to Change Window and Icon label * @param label window title name */ protected void processChangeIconNameAndWindowTitle(String label) { processChangeIconName(label); processChangeWindowTitle(label); } /** * process OSC 1;text BEL corresponding to Change Icon label * @param label icon label */ protected void processChangeIconName(String label) {} /** * process OSC 2;text BEL corresponding to Change Window title * @param label window title text */ protected void processChangeWindowTitle(String label) {} /** * Process unknown OSC command. * @param command command * @param param param */ protected void processUnknownOperatingSystemCommand(int command, String param) {} protected void processCharsetSelect(int set, char seq) {} }