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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package Torello.JavaDoc.SyntaxHiLite;

import Torello.Java.OSCommands;
import Torello.Java.OSExtras;
import Torello.Java.OSResponse;
import Torello.Java.StrCmpr;
import Torello.Java.OSJavaPipe;
import Torello.Java.FileRW;

import Torello.Java.ReadOnly.ReadOnlyArrayList;
import Torello.Java.ReadOnly.ReadOnlyList;
import Torello.JavaDoc.LinkJavaSource;
import Torello.HTML.HTMLNode;
import Torello.HTML.HTMLPage;
import Torello.HTML.Util;

import java.util.Objects;
import java.util.Vector;
import java.io.IOException;

/**
 * Java-Adapter for a Python-Tool which Hi-Lites Source Code.
 * 
 * <BR /><BR />Visit <A HREF='pygments.org' TARGET=_blank>http://Pygments.org</A> for details.
 * 
 * <EMBED CLASS='external-html' DATA-FILE-ID=CLI_HELP>
 * @see OSCommands
 * @see OSJavaPipe
 */
public class Pygmentize extends OSCommands
{
    public static final ReadOnlyList<String> CODE_TYPES = new ReadOnlyArrayList<>(
        "java", "html", "js", "css", "json", "properties", "xml", "py", "c", "cpp", "csharp", "go",
        "php", "ruby", "bash", "sh", "sql", "yaml", "toml", "ini", "docker", "make", "gradle",
        "swift", "kotlin", "rust", "scala", "perl", "r", "ts", "tsx", "jsx", "md", "txt"
    );


    // ********************************************************************************************
    // ********************************************************************************************
    // Constructor
    // ********************************************************************************************
    // ********************************************************************************************


    public static void main(String[] argv) throws IOException
    {
        if (argv.length != 1)
        {
            System.out.println("You must pass the file-name of a Java-File");
            System.exit(1);
        }

        final Pygmentize        p = new Pygmentize();
        final String            f = FileRW.loadFileToString(argv[0]);
        final Vector<HTMLNode>  h = p.hiLite(f, "java", true, (byte) 1);
        final String            s = Util.pageToString(h);

        System.out.println(s);
    }

    public Pygmentize() { super(null, null); }

    public Pygmentize clone()
    { throw new RuntimeException(new CloneNotSupportedException()); }


    // ********************************************************************************************
    // ********************************************************************************************
    // Convert Source-Code (as a String) into an HiLited HTML-String
    // ********************************************************************************************
    // ********************************************************************************************


    // NON-HTML-TEXT Output Save ...
    //  new String[] { "pygmentize", "-l", codeTypeParam,  "-O", dashO }

    @LinkJavaSource(handle="CleanHTML", name="clean")
    public synchronized Vector<HTMLNode> hiLite(
            final String    codeText,
            final String    codeTypeParam,
            final boolean   useLineNumbers,
            final byte      styleNum
        )
        throws IOException
    {
        Objects.requireNonNull(codeText,        "'codeText' Parameter has been passed null.");
        Objects.requireNonNull(codeTypeParam,   "'codeTypeParam' Parameter has been passed null.");

        final String dashO =
            "classprefix=H" + styleNum + "-" +
            (useLineNumbers ? ",linenos=table" : "");

        final String[] cmdArr =
            { "pygmentize", "-l", codeTypeParam, "-f", "html",  "-O", dashO };

        // This "Pipes" the input to the CLI Command
        this.osExtras           = new OSExtras();
        this.osExtras.javaPipe  = new OSJavaPipe(codeText);

        // Run Python's "pygmentize" - downloaded via 'pip' from Pygments.org
        final OSResponse osr = super.printAndRun(cmdArr);

        if (osr.response != 0) throw new PygmentizeException(
            "The O/S Process for 'pygmentize' has returned a non-zero Status\n" +
            THROW.HORIZ_SEP +
            "OSResponse.response: " +       osr.response + '\n' +
            "OSResponse.errorOutpu:\n" +    osr.errorOutput + '\n' +
            THROW.paramsAsStr(codeText, codeTypeParam, styleNum, useLineNumbers)
        );

        try 
        {
            final String html               = osr.standardOutput;
            final Vector<HTMLNode> retVec   = HTMLPage.getPageTokens(html, false);

            CleanHTML.clean(retVec, useLineNumbers);

            return retVec;
        }

        catch (Exception e) 
        {
            throw new PygmentizeException(
                "An error has occured while attempting to parse and simplify the returned HTML" +
                THROW.paramsAsStr(codeText, codeTypeParam, styleNum, useLineNumbers),
                e
            );
        }
    }

    public synchronized Vector<HTMLNode> hiLite(
            final String        codeText,
            final String        codeTypeParam,
            final boolean       includeLineNumbers,
            final byte          styleNum,
            final HiLiteCache   cache
        )
        throws IOException
    {
        Objects.requireNonNull(codeText,        "'codeText' Parameter has been passed null.");
        Objects.requireNonNull(codeTypeParam,   "'codeTypeParam' Parameter has been passed null.");
        Objects.requireNonNull(cache,           "'cache' Parameter has been passed null.");

        // FIRST: Check the Cache, to see if the exact String has been hilited!
        final String cached =
            cache.get(codeText, codeTypeParam, includeLineNumbers, styleNum);

        // If there was a Cache hit -> return that String rather than querying the server.
        if (cached != null) return HTMLPage.getPageTokens(cached, false);


        // NO?  ==>  Then query the server.
        // 
        // final Vector<HTMLNode> retVec = RESTToVector.run
        //     (codeText, codeTypeParam, styleTypeParam, includeLineNumbers);

        final Vector<HTMLNode> html =
            this.hiLite(codeText, codeTypeParam, includeLineNumbers, styleNum);

        // Make sure to save the response in the Cache for next time
        cache.checkIn
            (codeText, Util.pageToString(html), codeTypeParam, includeLineNumbers, styleNum);

        return html;
    }
}