SkillAgentSearch skills...

Ansi4j

Techsenger ANSI4J is a library that includes Java parser for processing text with ANSI escape codes (ISO/IEC 6429 control functions) and a CSS extension for styling the text.

Install / Use

/learn @techsenger/Ansi4j

README

Techsenger ANSI4J

Techsenger ANSI4J is a Java library that parses ANSI escape codes in full accordance with ISO/IEC 6429:1992. It supports all functions of all five types. At the same time parser architecture allows to add easily any other custom types of functions and mechanism to process them.

Techsenger ANSI4J consists of a core that includes parser and CSS extension that allows to create CSS declaration using function arguments.

Table of Contents

Core <a name="core"></a>

Overview <a name="core-overview"></a>

Core contains all base classes for working with control functions, parsers and text.

Base components <a name="core-base"></a>

  • ParserFactory is thread-safe instance of factory, that can be used for creating N parsers for parsing N texts. So, usually there is only one factory.
  • Parser is a non thread-safe object that reads text, manages finder and handlers and returns parsed fragment. There are two types of parsers:
    • StringParser for parsing String. StringParser is very light, so it is possible to create it for every text line.
    • StreamParser for parsing InputStream. One instance of StreamParser is created for one instance of InputStream.
  • FunctionFinder finds function in a text and resolves found function.
  • FragmentHandler is a thread-safe object for processing fragment of text. There are two types of handlers:
    • TextHandler is a handler for processing a text that doesn't contain any control functions in it. This handler allows to modify this text within system. Default implementation doesn't modify text and just wraps it in TextFragment.
    • FunctionHandler is a handler for processing functions in a text. For every type of function separate function handler exists. As a result FunctionHandler returns FunctionFragment.
  • Fragment is a processed piece of text. There are two types of fragments:
    • TextFragment that contains information about text pieces without functions.
    • FunctionFragment that contains information about functions in text.
  • ControlFunction is the base interface implemented by all enumerations used for ANSI function identification. These enumerations contain short function names in accordance with the standard. At the same time, for each enumeration X, there is an XAlias interface that provides the full function names. These aliases can be used by those who do not remember the short names.

Dependencies <a name="core-dependencies"></a>

This project is available on Maven Central:

<dependency>
    <groupId>com.techsenger.ansi4j</groupId>
    <artifactId>ansi4j-core-api</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>com.techsenger.ansi4j</groupId>
    <artifactId>ansi4j-core-impl</artifactId>
    <version>2.0.0</version>
</dependency>

Usage <a name="core-usage"></a>

Step 0 - Creating ParserFactory

ParserFactory factory = new ParserFactory.Builder()
        .environment(Environment._7_BIT)
        //specify only the types you need
        .functionTypes(
                ControlFunctionType.C0_SET,
                ControlFunctionType.C1_SET,
                ControlFunctionType.CONTROL_SEQUENCE,
                ControlFunctionType.INDEPENDENT_FUNCTION,
                ControlFunctionType.CONTROL_STRING)
        .build();

Step 1A - Creating StringParser

//this is the text we are going to parse
String text = ...;

//we need a parser
var parser = factory.createParser(text);

Step 1B - Creating StreamParser

//this is the stream we are going to parse
InputStream stream = ...;

//we need a parser, one parser for one stream
try (var parser = factory.createParser(stream, StandardCharsets.UTF_8, 1024)) {
    ...
} catch (IOException ex) {
    ...
}

Step 2 - Parsing

//so, let's go
Fragment fragment = null;
while ((fragment = parser.parse()) != null) {
    if (fragment.getType() == FragmentType.TEXT) {
        TextFragment textFragment = (TextFragment) fragment;
        ...
    } else if (fragment.getType() == FragmentType.FUNCTION) {
        FunctionFragment functionFragment = (FunctionFragment) fragment;
        //or functionFragment.getFunction() == ControlSequenceFunctionAlias.SELECT_GRAPHIC_RENDITION
        if (functionFragment.getFunction() == ControlSequenceFunction.SGR) {
            ...
        }
    }
}

Thread-safety <a name="core-thread"></a>

ParserFactory is thread-safe. StringParser and StreamParser are not thread-safe. FunctionFinder, TextHandler and FunctionHandlers are thread-safe. Detailed information about thread-safety is provided in every interface in core API module.

CSS extension <a name="css"></a>

Overview <a name="css-overview"></a>

The CSS extension allows you to style text using CSS in a way that mirrors the styling applied by SGR functions. For example, this extension can be used to style program outputs, log messages, documentation, and more.

To display styled text, you can use components from any platform (JavaFX, Swing), as neither the core library nor the CSS extension (except for the demo module) depend on the classes of these platforms.

Out of the box, the library provides three style generators for JavaFX WebView, JavaFX TextFlow, and RichTextFX InlineCssTextArea. These generators are located in the API module and can be easily modified. A table listing the features supported by each of these components is available in the demo application. We recommend using InlineCssTextArea because: 1) it supports nearly all features, 2) it is lightweight, and 3) it allows text editing.

Currently, the following text attributes are supported: intensity, italic, underline, blink, reverse video, visibility, strikethrough, font, foreground color, and background color.

Demo <a name="css-demo"></a>

The demo application showcases examples of styling the output of common programs:

css text

The demo application also allows you to see which styles are generated for each attribute across different controls

css attr

To run the demo application, execute the following commands in the project root:

cd ansi4j-css-demo
mvn javafx:run

Base components <a name="css-base"></a>

  • AttributeRegistry stores model attributes, separated into groups.
  • AttributeGroup contains a group of logically related attributes. Currently, there is only one group for the SGR function.
  • GroupStyleGenerator generates CSS declarations based on attribute value changes of a specific group. Thus, each generator is used for only one attribute group.
  • StyleProcessor, which is called for each SGR function, updates the attribute values and returns the generated CSS declarations.
  • Palette - ISO 6429 supports only 8 colors (3 bits). However, today many terminals supports 4, 8 and 24 bit colors. However, these extra colors are not included in the standard. So, to support them use extraColorsEnabled() method in config. Palette is an interface, so it is easy to add custom 8, 16, 256 color palette.

How it works:

Each attribute in the registry has a default value. Therefore, initially, you need to set values that correspond to your settings. For example, if the default is italicized text with a red color, you should set the default values for the italic and fgColor attributes:

TextAttributeGroupConfig.Builder()
        .defaultItalic(true)
        .defaultFgColor(new Color(0xff0000))
        ...

When text parsing begins, each SGR function is passed to the StyleProcessor. Based on the arguments of this function, the attribute values are updated. Then, the generator identifies the attributes whose values differ from the default ones and generates a style for a single span, which will be closed before the next SGR function. Thus, the generated styles will only be applied to the text between the current SGR function and the next one.

Important notes:

  • To enable blink for WebView is is necessary to add the following keyframes to your stylesheet:

      @keyframes ansi4j-blinker {50% { opacity: 0; }}.
    
  • RichTextFX InlineCssTextArea will support blink when this issue is resolved.

Dependencies <a name="css-dependencies"></a>

This project is available on Maven Central:

<dependency>
    <groupId>com.techsenger.ansi4j</groupId>
    <artifactId>ansi4j-css-api</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>com.techsenger.ansi4j</groupId>
    <artifactId>ansi4j-css-impl</artifactId>
    <version>2.0.0</version>
</dependency>

Usage <a name="css-usage"></a>

//First of all we 
View on GitHub
GitHub Stars35
CategoryDevelopment
Updated5mo ago
Forks2

Languages

Java

Security Score

92/100

Audited on Oct 18, 2025

No findings