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

org.dflib.jjava.jupyter.kernel.util.StringStyler Maven / Gradle / Ivy

The newest version!
package org.dflib.jjava.jupyter.kernel.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringStyler {
    private static final Pattern NEWLINE_PATTERN = Pattern.compile("\\R|$");

    public static List splitLines(String src) {
        return Arrays.asList(NEWLINE_PATTERN.split(src));
    }

    public static class Builder {
        private String primaryStyle = "";
        private String secondaryStyle = "";
        private String hlStyle = "";
        private Function linePrefix = null;

        public Builder addPrimaryStyle(String style) {
            this.primaryStyle += style;
            return this;
        }

        public Builder addPrimaryStyle(TextColor style) {
            this.primaryStyle += style;
            return this;
        }

        public Builder addSecondaryStyle(String style) {
            this.secondaryStyle += style;
            return this;
        }

        public Builder addSecondaryStyle(TextColor style) {
            this.secondaryStyle += style;
            return this;
        }

        public Builder addHighlightStyle(String style) {
            this.hlStyle += style;
            return this;
        }

        public Builder addHighlightStyle(TextColor style) {
            this.hlStyle += style;
            return this;
        }

        public Builder withLinePrefix(Function linePrefix) {
            this.linePrefix = linePrefix;
            return this;
        }

        public Builder withLinePrefix(String linePrefix) {
            this.linePrefix = line -> linePrefix;
            return this;
        }

        public StringStyler build() {
            return new StringStyler(
                    this.primaryStyle,
                    this.secondaryStyle,
                    this.hlStyle,
                    this.linePrefix != null ? this.linePrefix : line -> ""
            );
        }
    }

    private String primaryStyle;
    private String secondaryStyle;
    private String hlStyle;
    private Function linePrefix;

    public StringStyler(String primaryStyle, String secondaryStyle, String hlStyle, Function linePrefix) {
        this.primaryStyle = primaryStyle;
        this.secondaryStyle = secondaryStyle;
        this.hlStyle = hlStyle;
        this.linePrefix = linePrefix;
    }

    public String primary(String src) {
        return this.primaryStyle + src + TextColor.RESET_ALL;
    }

    public String secondary(String src) {
        return this.secondaryStyle + src + TextColor.RESET_ALL;
    }

    public String highlight(String src) {
        return this.hlStyle + src + TextColor.RESET_ALL;
    }

    public String highlightSubstring(String src, int start, int end) {
        String prefix = src.substring(0, start);
        String hlRegion = src.substring(start, end);
        String suffix = src.substring(end);

        StringBuilder combined = new StringBuilder();

        if (!prefix.isEmpty())
            combined.append(this.primary(prefix));
        if (!hlRegion.isEmpty())
            combined.append(this.highlight(hlRegion));
        if (!suffix.isEmpty())
            combined.append(this.primary(suffix));

        return combined.toString();
    }

    public String primaryLine(int lineNum, String line) {
        return this.linePrefix.apply(lineNum) + this.primary(line);
    }

    public String secondaryLine(int lineNum, String line) {
        return this.linePrefix.apply(lineNum) + this.secondary(line);
    }

    public String highlightLine(int lineNum, String line) {
        return this.linePrefix.apply(lineNum)
                + this.hlStyle
                + line
                + TextColor.RESET_ALL;
    }

    private List lines(String src, BiFunction styler) {
        String[] lines = NEWLINE_PATTERN.split(src);
        List styled = new ArrayList<>(lines.length);

        for (int i = 0; i < lines.length; i++)
            styled.add(styler.apply(i, lines[i]));

        return styled;
    }

    public List primaryLines(String src) {
        return this.lines(src, this::primaryLine);
    }

    public List secondaryLines(String src) {
        return this.lines(src, this::secondaryLine);
    }

    public List highlightLines(String src) {
        return this.lines(src, this::highlightLine);
    }

    public List highlightSubstringLines(String src, int start, int end) {
        List fmt = new LinkedList<>();

        int lastLinePos = 0;
        int line = 0;
        boolean foundStart = false;

        Matcher srcLineBreak = NEWLINE_PATTERN.matcher(src);
        while (srcLineBreak.find()) {
            if (!foundStart && srcLineBreak.start() >= start) {
                // The lastLinePos is the beginning of the line containing the start
                foundStart = true;
                StringBuilder hlLine = new StringBuilder();

                // Append the start of the line, not highlighted
                hlLine.append(this.primaryLine(line, src.substring(lastLinePos, start)));

                // Append the highlighted portion
                hlLine.append(this.highlight(src.substring(start, Math.min(srcLineBreak.start(), end))));

                // If the line contains the end of the highlight then finish off
                // the highlighting and finish.
                if (end <= srcLineBreak.start())
                    hlLine.append(this.primary(src.substring(end, srcLineBreak.start())));

                fmt.add(hlLine.toString());
            } else if (foundStart && srcLineBreak.start() <= end) {
                // This entire line should be highlighted
                fmt.add(this.highlightLine(line, src.substring(lastLinePos, srcLineBreak.start())));
            } else if (foundStart && end <= srcLineBreak.start()) {
                // This is the last line containing the highlighted region
                fmt.add(this.highlightLine(line, src.substring(lastLinePos, end))
                        + this.primary(src.substring(end, srcLineBreak.start())));
            }

            lastLinePos = srcLineBreak.end();
            line++;

            // If we are at the end of the hl region we are done
            if (end <= srcLineBreak.start()) break;
        }

        return fmt;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy