Formatear con color sentencias SQL o código fuente en la terminal con Java y Jansi

Escrito por el .
java planeta-codigo programacion
Enlace permanente Comentarios

Java

Usando la librería Jansi es posible hacer que un programa Java emita texto en color en la terminal. Emitir color en la terminal sirve para identificar más fácilmente y visualmente ciertas partes del texto, por ejemplo, emitiendo en rojo mensajes importantes o con color amarillo de fondo algún dato. Una utilidad práctica es formatear con color una sentencia SQL que se va a ejecutar en una aplicación a modo de traza o con colores el código fuente de un archivo Java u otro tipo de archivo de texto.

Una forma sencilla para formatear con colores un archivo de código fuente Java o una sentencia SQL sin llegar a hacer un procesador de sintaxis de ese lenguaje o formato es utilizar expresiones regulares y grupos de captura. En ambos casos hay partes que son palabras claves, números o cadenas en definitiva elementos que se deseen destacar. Con las clases Pattern y Matcher de Java se van obteniendo los diferentes grupos de captura de forma secuencial. Según sea el grupo capturado del elemento actual se utiliza Jansi para formatearlo con el color que le corresponde.

Una formateador simple para cada uno de estos casos serían los siguientes donde se utiliza una expresión regular con diferentes grupos de captura con nombre. El primer caso es para formatear con color una sentencia SQL sencilla en el método printSql() y el segundo el programa Hola mundo de Java en el método printJava().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package io.github.picodotdev.blogbitix.javaregexformatter;

import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    private static final String SQL_REGEXP_REFERENCEGROPUS = "(?<keyword>select|from|where|and)|(?<string>'[^']*')|(?<number>\\d+)|(?<other>.)";
    private static final String JAVA_REGEXP_REFERENCEGROPUS = "(?<keyword>public|static|void|class)|(?<type>String|int)(?<typequalifier>\\[\\]|\\s)|(?<string>\"[^\"]*\")|(?<number>\\d+)|(?<other>[\\s\\S])";

    public static void main(String[] args) {
        AnsiConsole.systemInstall();
        AnsiConsole.out().println(Ansi.ansi().reset());

        printSql();
        System.out.println();
        printJava();

        AnsiConsole.out().println(Ansi.ansi().reset());
        AnsiConsole.systemUninstall();
    }

    private static void printSql() {
        Pattern p = Pattern.compile(SQL_REGEXP_REFERENCEGROPUS);
        Matcher m = p.matcher("select * from dual where a = '1' and b = 23");

        StringBuffer formatedSql = new StringBuffer();
        while (m.find()) {
            String keyword = m.group("keyword");
            String string = m.group("string");
            String number = m.group("number");
            String other = m.group("other");
            if (keyword != null) {
                formatedSql.append(Ansi.ansi().fg(Ansi.Color.MAGENTA).a(keyword));
            }
            if (string != null) {
                formatedSql.append(Ansi.ansi().fg(Ansi.Color.YELLOW).a(string));
            }
            if (number != null) {
                formatedSql.append(Ansi.ansi().fg(Ansi.Color.BLUE).a(number));
            }
            if (other != null) {
                formatedSql.append(Ansi.ansi().reset().a(other));
            }
        }
        AnsiConsole.out().println(Ansi.ansi().reset().a(formatedSql.toString()));
    }

    private static void printJava() {
        Pattern p = Pattern.compile(JAVA_REGEXP_REFERENCEGROPUS);
        Matcher m = p.matcher("public class Main {\n\tpublic static void main(String[] args) {\n\t\tint number = 3;\n\t\tSystem.out.println(\"Hello World!\");\n\t}\n}");

        StringBuffer formatedSql = new StringBuffer();
        while (m.find()) {
            String keyword = m.group("keyword");
            String type = m.group("type");
            String typeQualifier = m.group("typequalifier");
            String string = m.group("string");
            String number = m.group("number");
            String other = m.group("other");

            if (keyword != null) {
                formatedSql.append(Ansi.ansi().fg(Ansi.Color.MAGENTA).a(keyword));
            }
            if (type != null) {
                formatedSql.append(Ansi.ansi().fg(Ansi.Color.CYAN).a(type));
            }
            if (typeQualifier != null) {
                formatedSql.append(Ansi.ansi().reset().a(typeQualifier));
            }
            if (string != null) {
                formatedSql.append(Ansi.ansi().fg(Ansi.Color.YELLOW).a(string));
            }
            if (number != null) {
                formatedSql.append(Ansi.ansi().fg(Ansi.Color.BLUE).a(number));
            }
            if (other != null) {
                formatedSql.append(Ansi.ansi().reset().a(other));
            }
        }
        AnsiConsole.out().println(Ansi.ansi().reset().a(formatedSql.toString()));
    }
}
Main.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
plugins {
    id 'java'
    id 'application'
}

application {
    mainClass = 'io.github.picodotdev.blogbitix.javaregexformatter.Main'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.fusesource.jansi:jansi:2.3.2'
}
build.gradle

El resultado en la terminal es el siguiente.

Formateado de sentencia SQL y código Java

Formateado de sentencia SQL y código Java

Este ejemplo es una aplicación útil de las expresiones regulares. En este caso he usado Jansi para emitir en la terminal texto con color pero de forma similar esto se puede usar para formatear en una web el mismo texto transformándolo y generando el HTML con las clases CSS adecuadas.

Terminal

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
./gradlew installDist, ./build/install/JavaRegexFormatter/bin/JavaRegexFormatter


Comparte el artículo: