Skip to main content

JLine Style

The jline-style module provides a powerful styling API for terminal output. It allows you to define and apply styles to text, create color schemes, and maintain consistent styling across your application.

Maven Dependency​

To use the style module, add the following dependency to your project:

<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-style</artifactId>
<version>3.29.0</version>
</dependency>

Basic Styling​

The style module provides a high-level API for styling text:

BasicStylingExample.java
import org.jline.style.StyleExpression;
import org.jline.style.StyleResolver;
import org.jline.style.Styler;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedString;

import java.io.IOException;
import java.io.PrintWriter;

public class BasicStylingExample {
public static void main(String[] args) throws IOException {
Terminal terminal = TerminalBuilder.builder().build();
PrintWriter writer = terminal.writer();

// Create a styler
Styler styler = Styler.defaultStyler();

// Style text using style expressions
AttributedString styledText = styler.style("This is @{bold,fg:red}red bold text@{} and this is @{italic,fg:blue}blue italic text@{}.");

// Print the styled text
styledText.println(terminal);
writer.flush();
}
}

Style Expressions​

Style expressions use a simple syntax to define text styles:

@{style-attributes}text@{}

Where style-attributes is a comma-separated list of style attributes:

StyleExpressionExample.java
import org.jline.style.Styler;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

import java.io.IOException;

public class StyleExpressionExample {
public static void main(String[] args) throws IOException {
Terminal terminal = TerminalBuilder.builder().build();
Styler styler = Styler.defaultStyler();

// Basic foreground and background colors
styler.style("@{fg:red}Red text@{}").println(terminal);
styler.style("@{bg:blue}Blue background@{}").println(terminal);

// Text attributes
styler.style("@{bold}Bold text@{}").println(terminal);
styler.style("@{italic}Italic text@{}").println(terminal);
styler.style("@{underline}Underlined text@{}").println(terminal);
styler.style("@{blink}Blinking text@{}").println(terminal);
styler.style("@{inverse}Inverse text@{}").println(terminal);

// Combining attributes
styler.style("@{bold,fg:green,bg:black}Bold green text on black background@{}").println(terminal);

// Named styles (defined in the styler)
styler.style("@{error}Error message@{}").println(terminal);
styler.style("@{warning}Warning message@{}").println(terminal);
styler.style("@{info}Info message@{}").println(terminal);

terminal.flush();
}
}

Style Resolver​

The StyleResolver allows you to define named styles and resolve style expressions:

StyleResolverExample.java
import org.jline.style.StyleExpression;
import org.jline.style.StyleResolver;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStyle;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class StyleResolverExample {
public static void main(String[] args) throws IOException {
Terminal terminal = TerminalBuilder.builder().build();

// Create a map of named styles
Map<String, AttributedStyle> styles = new HashMap<>();
styles.put("error", AttributedStyle.DEFAULT.foreground(AttributedStyle.RED).bold());
styles.put("warning", AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW));
styles.put("info", AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE));
styles.put("success", AttributedStyle.DEFAULT.foreground(AttributedStyle.GREEN));

// Create a style resolver with the named styles
StyleResolver resolver = new StyleResolver(styles);

// Resolve style expressions
AttributedString errorMessage = resolver.resolve("@{error}Something went wrong!@{}");
AttributedString warningMessage = resolver.resolve("@{warning}Be careful!@{}");
AttributedString infoMessage = resolver.resolve("@{info}Just so you know...@{}");
AttributedString successMessage = resolver.resolve("@{success}Operation completed successfully.@{}");

// Print the styled messages
errorMessage.println(terminal);
warningMessage.println(terminal);
infoMessage.println(terminal);
successMessage.println(terminal);

// Combine named styles with inline styles
AttributedString combinedStyle = resolver.resolve(
"@{error}Error:@{} @{bold,fg:white}Cannot open file @{italic}'example.txt'@{}");
combinedStyle.println(terminal);

terminal.flush();
}
}

Style Configuration​

You can load style definitions from configuration files:

StyleConfigurationExample.java
import org.jline.style.StyleExpression;
import org.jline.style.StyleResolver;
import org.jline.style.Styler;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedString;

import java.io.IOException;
import java.io.StringReader;
import java.util.Properties;

public class StyleConfigurationExample {
public static void main(String[] args) throws IOException {
Terminal terminal = TerminalBuilder.builder().build();

// Define styles in a properties format
String styleConfig =
"error = fg:red,bold\n" +
"warning = fg:yellow\n" +
"info = fg:blue\n" +
"success = fg:green\n" +
"header = fg:cyan,underline\n" +
"highlight = bg:yellow,fg:black";

// Load the styles
Properties props = new Properties();
props.load(new StringReader(styleConfig));

// Create a styler with the loaded styles
Styler styler = Styler.create(props);

// Use the configured styles
styler.style("@{header}System Information@{}").println(terminal);
styler.style("@{info}OS: @{highlight}Linux@{}").println(terminal);
styler.style("@{info}User: @{highlight}admin@{}").println(terminal);
styler.style("@{success}All systems operational@{}").println(terminal);

terminal.flush();
}
}

Styling Tables and Structured Output​

The style module works well with structured output like tables:

StyledTableExample.java
import org.jline.builtins.Tables;
import org.jline.builtins.Tables.Column;
import org.jline.builtins.Tables.ColumnType;
import org.jline.style.Styler;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedString;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

public class StyledTableExample {
public static void main(String[] args) throws IOException {
Terminal terminal = TerminalBuilder.builder().build();

// Define styles
Properties styleProps = new Properties();
styleProps.setProperty("header", "fg:cyan,bold");
styleProps.setProperty("error", "fg:red");
styleProps.setProperty("warning", "fg:yellow");
styleProps.setProperty("ok", "fg:green");

Styler styler = Styler.create(styleProps);

// Define table columns
List<Column> columns = Arrays.asList(
new Column("Service", ColumnType.String),
new Column("Status", ColumnType.String),
new Column("Message", ColumnType.String)
);

// Create table data with styled content
List<List<AttributedString>> data = new ArrayList<>();
data.add(Arrays.asList(
new AttributedString("Database"),
styler.style("@{ok}Running@{}"),
new AttributedString("Connected to MySQL 8.0")
));
data.add(Arrays.asList(
new AttributedString("Web Server"),
styler.style("@{warning}Degraded@{}"),
new AttributedString("High load detected")
));
data.add(Arrays.asList(
new AttributedString("Cache"),
styler.style("@{error}Down@{}"),
new AttributedString("Connection refused")
));

// Build and display the table
Tables.TableBuilder tableBuilder = new Tables.TableBuilder(columns);
tableBuilder.addAllAttributedString(data);

Tables.Table table = tableBuilder.build();
AttributedString tableString = table.toAttributedString(
terminal.getWidth(),
true, // display borders
true // display header
);

tableString.println(terminal);
terminal.flush();
}
}

Styling Progress Indicators​

You can use the style module to create styled progress indicators:

StyledProgressExample.java
import org.jline.style.Styler;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedStringBuilder;
import org.jline.utils.InfoCmp.Capability;

import java.io.IOException;

public class StyledProgressExample {
public static void main(String[] args) throws IOException {
Terminal terminal = TerminalBuilder.builder().build();
Styler styler = Styler.defaultStyler();

// Clear screen
terminal.puts(Capability.clear_screen);

// Create a styled progress bar
for (int i = 0; i <= 100; i++) {
// Calculate progress bar width
int width = 50;
int completed = width * i / 100;

// Build the progress bar
AttributedStringBuilder builder = new AttributedStringBuilder();
builder.append("\r");
builder.append(styler.style("@{bold}Progress: @{fg:green}["));

// Completed portion
builder.append(styler.style("@{fg:green}" + "=".repeat(completed)));

// Remaining portion
builder.append(styler.style("@{fg:black,bg:white}" + " ".repeat(width - completed)));

builder.append(styler.style("@{fg:green}]@{} "));
builder.append(styler.style("@{bold}" + i + "%"));

// Print the progress bar
terminal.writer().print(builder.toAnsi(terminal));
terminal.flush();

// Simulate work
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

terminal.writer().println();
terminal.writer().println(styler.style("@{bold,fg:green}Complete!@{}"));
terminal.flush();
}
}

Best Practices​

When using the JLine style module, consider these best practices:

  1. Define a Consistent Style Palette: Create a set of named styles for your application and use them consistently.

  2. Load Styles from Configuration: Allow users to customize styles by loading style definitions from configuration files.

  3. Use Semantic Style Names: Name styles based on their semantic meaning (e.g., "error", "warning", "info") rather than their appearance.

  4. Check Terminal Capabilities: Some terminals may not support all styling features, so check capabilities before using advanced styles.

  5. Provide Fallbacks: Define fallback styles for terminals with limited capabilities.

  6. Separate Style from Content: Keep style definitions separate from content to make it easier to change the appearance without modifying the code.

  7. Use Style Expressions for Complex Styling: Style expressions provide a concise way to apply multiple style attributes.

  8. Consider Accessibility: Choose colors and styles that are accessible to users with visual impairments.