Skip to content

JLine 3 appender for Log4j2, allows extending command line apps using colors and command completion

License

Notifications You must be signed in to change notification settings

CraftersMC/TerminalConsoleAppender

 
 

Repository files navigation

TerminalConsoleAppender

TerminalConsoleAppender is a custom Log4j2 Appender that prints all messages to a JLine 3 Terminal. JLine can be used to extend the regular console using ANSI colors as well as command history or command completion.

Supported environments

Not all environments can support all the features. By default, TerminalConsoleAppender only enables JLine output and console colors when running in an environment with an attached terminal session (so usually only when starting the application from an interactive console session). It will automatically disable the features if the console output is redirected to a file or to another application (e.g. in web control panels).

Some unsupported environments may still support a subset of the features (e.g. ANSI console colors). In these cases, extra system properties exist to override the default behaviour. They can be added on the command line or in the application itself:

Name Description
-Dterminal.jline=<true/false> Enables/disables the extended JLine input (persistent input line, command completion)
-Dterminal.ansi=<true/false> Enables/disables the output of ANSI escapes codes (used for colors)
-Dterminal.keepMinecraftFormatting=true Output raw Minecraft formatting codes to the console output.

Usage

  1. Add a dependency on TerminalConsoleAppender:

    net.minecrell:terminalconsoleappender:1.3.0
    

    If you package all dependencies into a single JAR file, ensure that all transitive dependencies are included:

    org.jline:jline-terminal
    org.jline:jline-reader
    

    JLine 3 provides different native terminal implementations that are required for Windows support and extend the terminal with some advanced features on Linux. You can choose between JNA and Jansi. There should be no functional difference, so it is mostly a matter of preference.

    For full functionality, you need to add an explicit dependency on one of the terminal implementations:

    Jansi JNA
    Dependencies org.jline:jline-terminal-jansi:3.20.0 org.jline:jline-terminal-jna:3.20.0
    (org.fusesource.jansi:jansi) (net.java.dev.jna:jna)
    Size ~280KB ~1400KB
  2. Configure TerminalConsoleAppender in your Log4j configuration:

    <TerminalConsole name="Console">
        <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n"/>
    </TerminalConsole>

    The TerminalConsole appender replaces the regular Console appender in your configuration file.

    Note: To avoid JLine from blocking your application in some edge cases, it is recommended that you make use of Async Loggers or Async Appenders to write messages asynchronously.

Console input

The appender is designed to be used in an application with simultaneous input and output. JLine can extend your console with a persistent input line as well as command history and command completion.

TerminalConsoleAppender includes SimpleTerminalConsole as a base class handling console input with opinionated defaults. It also serves as a reference implementation if you would like to have a custom implementation.

To use it, extend SimpleTerminalConsole and implement the methods:

public class ExampleConsole extends SimpleTerminalConsole {

    @Override
    protected boolean isRunning() {
        // TODO: Return true if your application is still running
    }

    @Override
    protected void runCommand(String command) {
        // TODO: Run command
    }

    @Override
    protected void shutdown() {
        // TODO: Shutdown your application cleanly (e.g. because CTRL+C was pressed)
    }
    
}

You can then start reading commands. Note that this method won't return unless your application is stopping or an error occurred, so you should start it in a separate console thread.

new ExampleConsole().start();

This setup will automatically handle the persistent input line and command history for you. If you'd like to use command completion you need to implement JLine's Completer interface (or use one of the builtin completers). You can then set it using .completer(Completer) when building the LineReader.

Override the buildReader method in your ExampleConsole to set additional options:

    @Override
    protected LineReader buildReader(LineReaderBuilder builder) {
        return super.buildReader(builder
                .appName("Example") // TODO: Replace with your application name
                .completer(new ExampleCommandCompleter())
        );
    }

If you'd like to use a custom console input implementation, take a look at the source code of SimpleTerminalConsole to see how it works (as the name says, it's pretty simple!).

Colorizing console output

JLine will automatically render ANSI color escape codes in supported terminals under Windows, Mac and Linux. To use them, you need to instruct Log4j to insert them into log messages:

  • You can use the patterns included in Log4j in your PatternLayout, e.g. %highlight or %style. It is recommended to use the disableAnsi option together with the ${tca:disableAnsi} variable. This will ensure that ANSI colors are disabled automatically in unsupported environments or with the system properties mentioned above:

    <TerminalConsole>
        <PatternLayout pattern="%highlight{[%d{HH:mm:ss} %level]: %msg%n%xEx}" disableAnsi="${tca:disableAnsi}"/>
    </TerminalConsole>
  • You can use the simplified %highlightError pattern bundled with TerminalConsoleAppender. It will only mark errors red and warnings yellow and keep all other messages as-is. It will automatically disable itself in unsupported environments.

    <TerminalConsole>
        <PatternLayout pattern="%highlightError{[%d{HH:mm:ss} %level]: %msg%n%xEx}"/>
    </TerminalConsole>
  • You can implement custom PatternConverters that add colors to the logging output. TerminalConsoleAppender contains an example implementation for Minecraft formatting codes that replaces them with appropriate ANSI colors:

    <TerminalConsole>
        <PatternLayout pattern="[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n"/>
    </TerminalConsole>

    It can be also configured with the strip option to strip all formatting codes instead (e.g. for the log file):

    <TerminalConsole>
        <PatternLayout pattern="[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}{strip}%n"/>
    </TerminalConsole>

    NOTE: The MinecraftFormattingConverter is deprecated and may be removed in future versions of TerminalConsoleAppender. There are no plans to extend it with new features like RGB color codes. Please see issue #18 for details.

About

JLine 3 appender for Log4j2, allows extending command line apps using colors and command completion

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 93.6%
  • Kotlin 6.4%