Wednesday 8 February 2012

HTML colorize script

I found the following script to colorize a script:
REBOL [
    Title: "Color REBOL Code in HTML"
    Date: 23-Oct-2009
    File: %color-code.r
    Author: "Carl Sassenrath"
    Purpose: {
        Colorize source code based on datatype.   Result is HTML <pre> block.
        Works with R3
        Sample CSS: http://www.ross-gill.com/styles/rebol-code.css
    }
    History: [
        29-May-2003 "Fixed deep parse rule bug."
    ]    
]

color-code: use [out emit emit-var rule value] [
    out: none
    envelop: func [data] [either block? data [data] [compose [(data)]]]
    emit: func [data] [data: reduce envelop data until [append out take data empty? data]]

    emit-var: func [value start stop /local type] [
        either none? :value [type: "cmt"] [
            if path? :value [value: first :value]
            type: either word? :value [
                any [
                    all [value? :value any-function? get :value "function"]
                    all [value? :value datatype? get :value "datatype"]
                ]
            ] [
                any [replace to-string type?/word :value "!" ""]
            ]
        ]
        either type [; (Done this way so script can color itself.)
            emit ["-[" {-var class="dt-} type {"-} "]-"
                copy/part start stop "-[" "-/var-" "]-"]
        ] [
            emit copy/part start stop
        ]
    ]

    rule: use [str new] [
        [
            some [
                str:
                some [" " | tab] new: (emit copy/part str new) |
                newline (emit "^/") |
                #";" [thru newline | to end] new:
                (emit-var none str new) |
                [#"[" | #"("] (emit first str) rule |
                [#"]" | #")"] (emit first str) break |
                skip (
                    set [value new] load/next str
                    emit-var :value str new
                ) :new
            ]
        ]
    ]

    func [
        "Return color source code as HTML."
        text [string!] "Source code text"
    ] [
        out: make binary! 3 * length? text
        set [value text] load/next/header detab text
        emit copy/part head text text
        parse/all text rule
        out: to-string out

        foreach [from to] reduce [; (join avoids the pattern)
            "&" "&amp;" "<" "&lt;" ">" "&gt;"
            join "-[" "-" "<" join "-" "]-" ">"
        ] [
            replace/all out from to
        ]

        insert out {<pre class="rebol-script">}
        append out {</pre>}
    ]
]

;write %color-code.html color-code read %color-code.r ;uncomment to see how it woks



It works with the following CSS, it has a dark and a white version; you can choos which one to prefer:

/* Embedded REBOL Header
-------------------------------------------------------
[REBOL [title: "Colour Code Stylesheet"
date: 24-Nov-2003
author: "Christopher Ross-Gill"
rights: http://creativecommons.org/licenses/by-sa/1.0/]]
------------------------------------------------------- */

/* Script Style
------------------------------------------------------- */
body.script {background: #fff url(/images/topgrey.png) repeat-x 0 0; margin: 2em; text-align: center;}
body.script .rebol-script {width: 90%; margin: 2em auto; text-align: left;}
body.script.dark {background: #222; color: #ffe9b5;}


/* Colours (white)
------------------------------------------------------- */
.rebol-script {color: #000; font-weight: normal; font-style: normal;}
.rebol-script var {font-weight: normal; font-style: normal;}
.rebol-script .dt-function {color: #900;}
.rebol-script .dt-datatype {color: #736;}
.rebol-script .dt-bitset {color: #072;}
.rebol-script .dt-binary {color: #041;}
.rebol-script .dt-char {color: #072;}
.rebol-script .dt-date {color: #079;}
.rebol-script .dt-decimal {color: #079;}
.rebol-script .dt-email {color: #072;}
.rebol-script .dt-file {color: #072;}
.rebol-script .dt-integer {color: #079;}
.rebol-script .dt-issue {color: #072;}
.rebol-script .dt-lit-word {color: #606;}
.rebol-script .dt-money {color: #079;}
.rebol-script .dt-pair {color: #079;}
.rebol-script .dt-string {color: #072;}
.rebol-script .dt-bitset {color: #072;}
.rebol-script .dt-tag {color: #09A;}
.rebol-script .dt-time {color: #079;}
.rebol-script .dt-tuple {color: #079;}
.rebol-script .dt-url {color: #072;}
.rebol-script .dt-refinement {color: #972;}
.rebol-script .dt-set-word {color: #004; font-weight: bold;}
.rebol-script .dt-set-path {color: #004; font-weight: bold;}
.rebol-script .dt-cmt {color: #999; font-style: italic;}
.rebol-script a, .rebol-script a:link, .rebol-script a:visited {
color: #00c; text-decoration: underline;
}
.rebol-script a:active, .rebol-script a:hover {color: #c00;}

/* Colours (black)
-------------------------------------------------------*/
.rebol-script.dark var {font-weight: normal; font-style: normal;}
.dark .rebol-script, .rebol-script.dark {background: #222; color: #ffe9b5; padding: 1em; font-weight: normal; font-style: normal;}
.rebol-script.dark .dt-function {color: #ffde2d;}
.rebol-script.dark .dt-datatype {color: #ffde2d;}
.rebol-script.dark .dt-bitset {color: #93fe64;}
.rebol-script.dark .dt-binary {color: #93fe64;}
.rebol-script.dark .dt-char {color: #93fe64;}
.rebol-script.dark .dt-date {color: #fff;}
.rebol-script.dark .dt-decimal {color: #fff;}
.rebol-script.dark .dt-email {color: #93fe64;}
.rebol-script.dark .dt-file {color: #93fe64;}
.rebol-script.dark .dt-integer {color: #fff;}
.rebol-script.dark .dt-issue {color: #93fe64;}
.rebol-script.dark .dt-lit-word {color: #fff;}
.rebol-script.dark .dt-logic {color: #fff;}
.rebol-script.dark .dt-money {color: #fff;}
.rebol-script.dark .dt-none {color: #fff;}
.rebol-script.dark .dt-pair {color: #fff;}
.rebol-script.dark .dt-string {color: #93fe64;}
.rebol-script.dark .dt-tag {color: #93fe64;}
.rebol-script.dark .dt-time {color: #fff;}
.rebol-script.dark .dt-tuple {color: #fff;}
.rebol-script.dark .dt-url {color: #93fe64;}
.rebol-script.dark .dt-refinement {color: #ffe9b5;}
.rebol-script.dark .dt-set-word {color: #f66; font-weight: bold;}
.rebol-script.dark .dt-set-path {color: #f66; font-weight: bold;}
.rebol-script.dark .dt-cmt {background: #000; color: #bbb; font-style: italic;}
.rebol-script.dark a, .rebol-script.dark a:link, .rebol-script.dark a:visited {
color: #ccf; text-decoration: underline;
}
.rebol-script.dark a:active, .rebol-script.dark a:hover {color: #fcc;}

However I don't like to use the pre tag, because it doesn't break lines automatically, so I modified the script to use the code tag this way:

REBOL [
    Title: "Color REBOL Code in HTML"
    Date: 8-Feb-2012
    File: %color-code.r
    Author: ["Carl Sassenrath" "Ross Gill" "Massimilano Vessi"]
    Purpose: {
        Colorize source code based on datatype.   Result is HTML a good <code> block.
        Works with R3        
    }
    version: 3.0.3
    History: [
        29-May-2003 "Fixed deep parse rule bug."
        8-Feb-2012 "<code> insead of <pre>"
    ]
]
;colorize function
color-code: use [out emit emit-var rule value] [
    out: none
    envelop: func [data] [either block? data [data] [compose [(data)]]]
    emit: func [data] [data: reduce envelop data until [append out take data empty? data]]
    emit-var: func [value start stop /local type] [
        either none? :value [type: "cmt"] [
            if path? :value [value: first :value]
            type: either word? :value [
                any [
                    all [value? :value any-function? get :value "function"]
                    all [value? :value datatype? get :value "datatype"]
                ]
            ] [
                any [replace to-string type?/word :value "!" ""]
            ]
        ]
        either type [; (Done this way so script can color itself.)
            emit ["-[" {-var class="dt-} type {"-} "]-"
                copy/part start stop "-[" "-/var-" "]-"]
        ] [emit copy/part start stop ]
    ]
    rule: use [str new] [
        [
            some [
                str:
                some [" " | tab] new: (emit copy/part str new) |
                newline (emit "^/") |
                #";" [thru newline | to end] new:
                (emit-var none str new) |
                [#"[" | #"("] (emit first str) rule |
                [#"]" | #")"] (emit first str) break |
                skip (
                    set [value new] load/next str
                    emit-var :value str new
                ) :new
            ]
        ]
    ]
   
    func [
        "Return color source code as HTML."
        text [string!] "Source code text"
        /br "Add <br> tag."
        /hd "Add rebol header"
    ] [
        if hd [insert text "Rebol[]" ]
        append text "^/" ;avoid errors      
        ;these put on one line all simple code, to enhance readability
        tutto: copy " "
        appendi: func [temp] [if temp [append tutto temp ] ]
        veryclean-script: func [temp ] [
            either   (parse temp [ "^/" thru "^/" end ]   ) [appendi   replace/all   (trim temp)   "^/"   " " ] [appendi temp]    
            ]      
        parse text [
            some [ copy temp3   thru "[" (appendi temp3   )   copy temp   to   "]"   (if temp [veryclean-script temp])   ]  
            copy temp2   to end   (appendi temp2)
            ]  
        text: copy tutto    
        ;here start rebol to html converter
        out: make binary! 3 * length? text
        set [value text] load/next/header detab text        
        emit copy/part head text text
        parse/all text rule
        out: to-string out
        foreach [from to] reduce [; (join avoids the pattern)
            "&" "&amp;" "<" "&lt;" ">" "&gt;"
            join "-[" "-" "<" join "-" "]-" ">"
        ] [replace/all out from to ]
        if hd [remove/part out 9 ]      
        while [find out "^/^/"] [replace/all out "^/^/" "^/"] ;removing empty lines
        insert out {<code class="rebol-script">}
        append out {</code>}
        replace/all out "   "   " &nbsp;   "      
        if br [replace/all out "^/"   " <br>^/   "]   ; if you can't see new lines
        return out
    ]
]
;GUI
view layout [
    across
    a: area
    return
    b: check false
    text "Add <br> tag"
    c: check false
    text "Add rebol header"
    return
    button 80x35 "Convert in HTML" [
        temp2: copy "a/text: color-code"
        if b/data [append temp2 "/br"]
        if c/data [append temp2 "/hd"]
        append temp2 " a/text"
        do temp2        
        show a
        write clipboard://   a/text
        ]
    text italic 300 {It automatically copy to clipboard, but you can use CTRL+C to copy, CTRL+V to paste, CTRL+A to select all, and more...}
    return
    button "CLEAR" [a/text: copy " "
        show a
        ]
    ]
   





It uses clean-script-heavy, I'll speak of it in the next post.
I use the following CSS:

code {
margin: 10px 0 10px 0;
background-color:#767676;
display: block;
overflow: auto;
}

.rebol-script pre {
margin: 10px 0 10px 0;

display: block;
overflow: auto;
}

.rebol-script var {font-weight: normal; font-style: normal;}
.rebol-script {
background: #222;
color: #ffe9b5;
padding: 1em;
margin: 10px 0 10px 0;
display: block;
overflow: auto;
}
.rebol-script .dt-function {color: #ffde2d;}
.rebol-script .dt-datatype {color: #0baccf;}
.rebol-script .dt-bitset {color: #93fe64;}
.rebol-script .dt-binary {color: #3ca010;}
.rebol-script .dt-char {color: #93fe64;}
.rebol-script .dt-date {color: #93ff69;}
.rebol-script .dt-decimal {color: #069d66;}
.rebol-script .dt-email {color: #069d2b;}
.rebol-script .dt-file {color: #fc39e5;}
.rebol-script .dt-integer {color: #069d66;}
.rebol-script .dt-issue {color: #93fe64;}
.rebol-script .dt-lit-word {color: #93fe67;}
.rebol-script .dt-logic {color: #93fe68;}
.rebol-script .dt-money {color: #169b0d;}
.rebol-script .dt-none {color: #ff0000;}
.rebol-script .dt-pair {color: #93ff69;}
.rebol-script .dt-string {color: #93fe64;}
.rebol-script .dt-tag {color: #93fe64;}
.rebol-script .dt-time {color: #93ff69;}
.rebol-script .dt-tuple {color: #93ff70;}
.rebol-script .dt-url {color: #fc39e5;}
.rebol-script .dt-refinement {color: #ffe9b5;}
.rebol-script .dt-set-word {color: #f66; font-weight: bold;}
.rebol-script .dt-set-path {color: #f66; font-weight: bold;}
.rebol-script .dt-cmt {background: #151515; color: #bbb; font-style: italic;}
.rebol-script a, .rebol-script a:link, .rebol-script a:visited {
color: #ccf; text-decoration: underline;
}
.rebol-script a:active, .rebol-script a:hover {color: #fcc;}

No comments:

Post a Comment