Highlight
Usage:
[rexx] highlight [options] file
The utility can run in one of three modes, namely, ANSI mode, HTML mode, and LaTeX mode; every mode determines how the file will be highlighted.
When calling highlight
as a command, the default mode is
ANSI; otherwise, the default mode is HTML.
When file is a single dash ("-") which is the last option in
the command line argument, input is taken from stdin. In all other
cases, file has to refer to a filesystem file; when the
extension of that file is .md
, .htm
or
.html
, the utility processes all Rexx fenced code blocks in
file and highlights them. Otherwise, the utility assumes that
file is a Rexx file, it is highlighted accordingly.
Options:
-a , --ansi |
Select ANSI SGR terminal highlighting |
--css |
Include links to css files (HTML only) |
-h , --html |
Select HTML highlighting |
-l , --latex |
Select LaTeX highlighting |
--noprolog |
Don't print a prolog |
-n ,
--numberlines |
Print line numbers |
--patch= patches |
Apply the semicolon-separated list of patches. |
--patchfile= file |
Apply the patches contained in file. |
--prolog |
Print a prolog (LaTeX driver only) |
--startFrom= n |
Start line numbers at n. |
-s ,
--style= style |
Use the rexx-style.css style sheet |
--tutor |
Enable TUTOR-flavored Unicode |
-u ,
--unicode |
Enable TUTOR-flavored Unicode |
-w ,
--width=n |
Ensure that lines have width n (ANSI only) |
-a, --ansi
Selects ANSI highlighting using ANSI SGR (Select Graphic Rendition) codes.
--css
When generating HTML highlighting, the css
option adds a
skeleton HTML5 envelope to the generated code. This envelope includes,
in its head
tag, up to three links to the style file
referenced in the -s
or --style
options: one
to a possible version stored in the https://rexx.epbcn.com/ site, another one to a path
relative to the highlight
utility, and an optional third
one pointing to the style file, if such a file exists in the current
directory.
Note: The css
option is a quick and
dirty hack intended to facilitate development in RAD scenarios, not a
way to generate distribution-ready or production files.
-h, --html
Selects HTML highlighting.
See also --css.
-l, --latex
Selects LaTeX highlighting.
--noprolog
Don't print a prolog (LaTeX only).
See also --prolog.
-n, --numberlines
Print line numbers.
See also --startFrom.
--patch="patches"
Apply the semicolon-separated list of patches.
See also --patchFile.
--patchFile=file
Apply the patches contained in file.
See also --patch.
--prolog
Print a prolog (LaTeX driver only).
See also --latex and --noprolog.
--startFrom=n
Start numbering lines at line n.
See also --numberlines
-s, --style=style
Use the rexx-style.css
style sheet. The default
is rexx-dark.css
.
--tutor
Enable TUTOR-flavored Unicode.
See also --unicode.
--u, --unicode
Enable TUTOR-flavored Unicode.
See also --tutor.
-w, --width=n
Ensure that lines have a minimum width of n characters (ANSI highlighting only).
See also --ansi.
Example:
The following command
highlight --css --style=mystyle sample.html
could generate the following head
section:
<head> <link rel='stylesheet' href='https://rexx.epbcn.com/rexx-parser/css/rexx-mystyle.css'> <link rel='stylesheet' href='file:///C:/path/rexx-parser/bin/../css/rexx-mystyle.css'> <link rel='stylesheet' href='rexx-mystyle.css'> </head>
where path
is the path where the
rexx-parser
resides, and the third link would only be
generated if the rexx-mystyle.css
file was places in the
directory where the highlight utility was run.
Program source:
#!/usr/bin/env rexx
/******************************************************************************/
/* */
/* highlight.rex - Rexx highlighting example */
/* ========================================= */
/* */
/* This program is part of the Rexx Parser package */
/* [See https://rexx.epbcn.com/rexx-parser/] */
/* */
/* Copyright (c) 2024-2025 Josep Maria Blasco <josep.maria.blasco@epbcn.com> */
/* */
/* License: Apache License 2.0 (https://www.apache.org/licenses/LICENSE-2.0) */
/* */
/* Date Version Details */
/* -------- ------- --------------------------------------------------------- */
/* 20241228 0.1d First public release */
/* 20241229 0.1e Add support for ANSI highlighing */
/* 20241231 Add support for LaTeX highlighing */
/* 20250102 0.1f Add --prolog and --noprolog options */
/* 20250103 Add -u --tutor and --unicode options */
/* 20250105 Add --patch="patch specs" and --patchfile=file */
/* 20250107 Change -t and --term for -a and --ansi */
/* 20250108 Add --pad= option */
/* 20250328 0.2 Main dir is now rexx-parser instead of rexx.parser */
/* 20250526 0.2b Add --css opt. & "-" to select stdin (thanks, Rony!) */
/* 20250529 0.2c Add support for detailed string and number highlighting */
/* */
/******************************************************************************/
Parse Arg fn
-- Remember how we were called
Parse Source . how myself
myPath = FileSpec("Drive",myself)FileSpec("Path",myself)
myPath = FileSpec("Drive",myself)FileSpec("Path",myself)
sep = .File~separator
-- We will store our processed options in a stem
options. = 0
-- Set default mode to ANSI if called from the command line...
If how == Command Then options.mode = ANSI
-- ...otherwise, assume HTML.
Else options.mode = HTML
-- Process user options, if any
patch = .Nil
Loop
Parse var fn op value rest
If op[1] \== "-" | fn == "-" Then Leave
If op~contains("=") Then Do
fn = Strip(value rest)
Parse Var op op"="value
Select Case Lower(op)
When "--startfrom" Then options.startFrom = Natural(value)
When "--style" Then options.style = value
When "--width" Then options.width = Natural(value)
When "--pad" Then options.pad = Natural(value)
When "--patch" Then Do
Call AllowQuotes
If value = "" Then patch = .Nil
Else patch = .StylePatch~of( value )
End
When "--patchfile" Then Do
Call AllowQuotes
If value = "" Then Do
Say "Invalid option '"op"'."
Exit 1
End
file = Stream(value,"C", "Q Exists")
If file == "" Then Do
Say "File '"value"' not found."
Exit 1
End
value = CharIn( file, 1, Chars(file) )~makeArray
Call Stream file, "C", "Close"
patch = .StylePatch~of( value )
End
Otherwise Do
Say "Invalid option '"op"'."
Exit 1
End
End
Iterate
End
gotAValue = 1
Select Case Lower(op)
When "-s" Then options.style = value
When "-w" Then options.width = Natural(value)
Otherwise gotAValue = 0
End
If gotAValue Then Do
fn = rest
Iterate
End
Select Case Lower(op)
When "-h", "--html" Then options.mode = HTML
When "-l", "--latex" Then options.mode = LaTeX
When "-n", "--numberlines" Then options.numberlines = .True
When "-a", "--ansi" Then options.mode = ANSI
When "--css" Then options.css = 1
When "--tutor" Then options.unicode = 1
When "-u", "--unicode" Then options.unicode = 1
When "--noprolog" Then options.prolog = 0
When "--prolog" Then options.prolog = 1
Otherwise Do
Say "Invalid option '"op"'."
Exit 1
End
End
fn = Strip(value rest)
End
-- We need an argument
If fn = "" Then Do
Say .Resources[Help]
Exit 1
End
If fn == "-" Then source = .StdIn~ArrayIn
Else Do
-- Process filenames containing blanks
fn = Strip(fn)
c = fn[1]
If """'"~contains( c ) Then Do
Parse Var fn (c)fn2(c)extra
If extra \== "" Then Do
Say "Invalid filename '"fn"'."
Exit 1
End
fn = fn2
End
-- Check that the file exists
file = Stream(fn, 'c', 'q exists')
If file == "" Then Do
Say "File '"fn"' not found."
Exit 1
End
-- Load the whole file in the "source" array
source = CharIn(file,1,Chars(file))~makeArray
Call Stream file,"c","close"
End
If Options.css == 0 Then Do
Say ProcessSource()
Exit
End
-- Pick selected style
If Options.style == 0 Then mystyle = "dark"
Else mystyle = Options.style
-- A possible copy could reside in our rexx-parser installation
cssPath = ChangeStr("\",mypath".."sep"css"sep"rexx-"mystyle".css","/")
-- A possible copy could reside in the current directory
local = Stream(Directory()||sep"rexx-"mystyle".css","c","query exists")
Do line Over .Resources[HTML]
Select Case line
When "[*CSS*]" Then Do
Say " <link rel='stylesheet' href='https://rexx.epbcn.com/rexx-parser/css/rexx-"mystyle".css'></link>"
Say " <link rel='stylesheet' href='file:///"cssPath"'></link>"
If local \== "" Then Say " <link rel='stylesheet' href='rexx-"mystyle".css'></link>"
End
When "[*CONTENTS*]" Then Say ProcessSource()
Otherwise Say line
End
End
Exit
ProcessSource:
-- Markdown? Process the fenced code blocks and display the result
If file~caselessEndsWith(".md") Then Return FencedCode( fn, source )
-- HTML? Process the fenced code blocks and display the result
If file~caselessEndsWith(".html") | file~caselessEndsWith(".htm") Then
Return FencedCode( fn, source )
-- Assume it's Rexx
hl = .Highlighter~new(fn, source, options.)
Return hl~parse( patch )
AllowQuotes:
q = value[1]
If """'"~contains( q ) Then Do
fn = value fn
Parse Var fn (q)value(q)fn
End
Return
Natural:
If DataType(Arg(1),"W"), Arg(1) >= 0 Then Return Arg(1)
Say "Invalid value" Arg(1)"."
Exit 1
--------------------------------------------------------------------------------
::Requires "Highlighter.cls"
::Requires "FencedCode.cls"
::Resource Help
Usage: highlight [OPTIONS] FILE
If FILE has a .md or .html extension, process all Rexx fenced code blocks
in FILE and highlight them. Otherwise, we assume that this is a Rexx file,
and we highlight it directly.
Options:
-a, --ansi Select ANSI mode
--css Include links to css files (HTML only)
-h, --html Select HTML mode
-l, --latex Select LaTeX mode
--noprolog Do not print a prolog (LaTeX only)
-n, --numberlines Print line numbers
--patch="PATCHES" Apply semicolon-separated PATCHES
--patchfile=FILE Load patches from FILE
--pad=N Pad doc-comments and ::resources to N characters
--prolog Print a prolog (LaTeX only)
--startFrom=N Start line numbers at N
-s, --style=STYLE Use "rexx-STYLE.css" (default is "dark")
--tutor Enable TUTOR-flavored Unicode
-u, --unicode Enable TUTOR-flavored Unicode
-w, --width=N Ensure that all lines have width >= N (ANSI only)
The 'highlight' program is part of the Rexx Parser package, and is distributed
under the Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0).
Copyright (c) 2024, 2025 Josep Maria Blasco <josep.maria.blasco@epbcn.com>.
::END
::Resource HTML
<!doctype html>
<html lang='en'>
<head>
[*CSS*]
</head>
<body>
[*CONTENTS*]
</body>
</html>
::END