Function summary auto-doc generator

Carl Sassenrath, CTO
REBOL Technologies
6-Nov-2009 6:29 GMT

Article #0291
Main page || Index || Prior Article [0290] || Next Article [0292] || 5 Comments || Send feedback

One task on the project list is to review all function refinements. In order to make that task easier, I revived and enhanced an old script from R2 called words.r. It generates a nice HTML summary of all functions directly from REBOL's embedded function specs.

Here's what its Function Summary output looks like. Note that function names are linked to their R3 document reference pages.

You might find the script useful as a small example of using language reflection to generate an HTML document.

    Title: "REBOL 3 Auto-Doc Function Summarizer"
    Version: 3.0.0
    Author: "Carl Sassenrath"
    Purpose: {Generates an HTML document of REBOL functions.}

title: "REBOL 3 - Function Summary"

html: make string! 120000
emit: func [data] [repend html data]

get-next: func ['series] [first back set series next get series]

special-file: charset "!?*+/=<>"

word-to-file: func [file /local f][

    file: lowercase form file

    if all [
        f: find file #"!"
        not head? f
    ][remove f] ; datatype!

    if all [
        f: find file #"/"
        file <> "/"
        file <> "//"
    ][remove f] ; refinements

    if find file special-file [
        ; very bad performance! (replace this)
        replace/all file "!" "-ex"
        replace/all file "?" "-q"
        replace/all file "*" "-mul"
        replace/all file "+" "-plu"
        replace/all file "/" "-div"
        replace/all file "=" "-eq"
        replace/all file "<" "-gt"
        replace/all file ">" "-lt"

    if #"-" = file/1 [insert file #"z"]
    append file ".html"

emit [
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <title> title </title>
    <style type="text/css"> {
    body {font-family: arial, sans-serif; font-size: 10pt;}
    .name {color: #000; font-weight: bold; font-size: 14pt; text-decoration: none;}
    .arg  {color: #248; font-weight: bold; font-size: 14pt; font-style: italic}
    .args {color: #248; font-weight: bold;}
    .refs {color: #822; font-weight: bold;}
    .type {color: #765;}
    .desc  {margin-left: 1cm}
    } </style>
    <h2> title </h2>
    <p> "For version: " system/version
    <br> "Click word for full documentation" </p>

foreach word sort words-of system/contexts/exports [
    value: attempt [get in system/contexts/exports word]
    unless any-function? :value [continue]

    args: words-of :value ; function's arg list
    spec: spec-of :value ; function's specification

    if loc: find args refinement! [args: copy/part args loc]

    emit [
        {<a href="} join url word-to-file word {" class="name">} word </a> " "
        <span class="arg"> args </span>
        <p class="desc">
        either string? spec/1 [get-next spec]["undocumented function."]
        <span class="type"> " [" type? :value "]" </span>

    ; spec format: argument [types] "description"
    while [not empty? spec] [
        unless block? arg: get-next spec [
            if any [arg = /local number? arg] [break]
            types: if block? spec/1 [get-next spec]
            description: either string? spec/1 [get-next spec][""]
            emit [
                pick [<span class="refs"><span class="args">] refinement? arg
                mold :arg </span>
                " -- " description
                <span class="type"> " [" any [types "any value"] "]" </span>
            emit <br>
    emit [<p> newline]

emit [</body></html>]

write file: %r3-funcs.html html
browse join file:// to-local-file/full file

PS: You can also see in this example why I want a replace-each function. I do that kind of mass substitution a lot.


Updated 28-May-2017 - Edit - Copyright REBOL Technologies -