api_proc_documentation (public)

 api_proc_documentation [ -format format ] [ -script ] [ -source ] \
    [ -xql ] [ -label label ] [ -first_line_tag first_line_tag ] \
    [ -proc_type proc_type ] proc_name

Defined in packages/acs-api-browser/tcl/acs-api-documentation-procs.tcl

Generates formatted documentation for a procedure.

Switches:
-format (optional)
the type of documentation to generate. This parameter is deprecated and has no effect.
-script (optional, boolean)
include information about what script this proc lives in?
-source (optional, boolean)
include the source code for the script?
-xql (optional, boolean)
include the source code for the related xql files?
-label (optional)
the label printed for the proc in the header line
-first_line_tag (optional, defaults to "<h3>")
tag for the markup of the first line
-proc_type (optional)
Parameters:
proc_name (required)
the name of the procedure for which to generate documentation.
Returns:
the formatted documentation string.
Error:
if the procedure is not defined.

Partial Call Graph (max 5 caller/called nodes):
%3 test_acs_api_browser_api_proc_documentation acs_api_browser_api_proc_documentation (test acs-api-browser) api_proc_documentation api_proc_documentation test_acs_api_browser_api_proc_documentation->api_proc_documentation aa_test_running_p aa_test_running_p (public) api_proc_documentation->aa_test_running_p ad_log ad_log (public) api_proc_documentation->ad_log api_call_graph_snippet api_call_graph_snippet (private) api_proc_documentation->api_call_graph_snippet api_get_body api_get_body (public) api_proc_documentation->api_get_body api_proc_format_switch api_proc_format_switch (private) api_proc_documentation->api_proc_format_switch api_describe_function api_describe_function (public) api_describe_function->api_proc_documentation packages/acs-api-browser/www/proc-view.tcl packages/acs-api-browser/ www/proc-view.tcl packages/acs-api-browser/www/proc-view.tcl->api_proc_documentation packages/acs-api-browser/www/procs-file-view.tcl packages/acs-api-browser/ www/procs-file-view.tcl packages/acs-api-browser/www/procs-file-view.tcl->api_proc_documentation packages/xotcl-core/www/show-object.tcl packages/xotcl-core/ www/show-object.tcl packages/xotcl-core/www/show-object.tcl->api_proc_documentation system.methodHelp system.methodHelp (public) system.methodHelp->api_proc_documentation

Testcases:
acs_api_browser_api_proc_documentation
Source code:
    #
    # Sanitize input
    #
    if {[string match *::::* $proc_name]} {
        ad_log warning "api_proc_documentation: received invalid proc_name <$proc_name>, try to sanitize"
        regsub -all -- {::::} $proc_name :: proc_name
    }
    if {[info exists format] && ![aa_test_running_p]} {
        ad_log warning "-format flag is deprecated and has no effect"
    }
    array set doc_elements {
        flags ""
        default_values ""
        switches0 ""
        switches1 ""
        positionals ""
        varargs_p 0
        script ""
        deprecated_p 0
        main ""
    }
    array set doc_elements [nsv_get api_proc_doc $proc_name]
    array set flags $doc_elements(flags)
    array set default_values $doc_elements(default_values)

    if {![info exists label]} {
        if {[llength $proc_name] > 1 && [namespace which ::xo::api] ne ""} {
            set label [::xo::api method_label $proc_name]
        } else {
            set label $proc_name
        }
    }

    if { $script_p } {
        set pretty_name [api_proc_pretty_name  -include_debug_controls  -proc_type $proc_type  -label $label  $proc_name]
    } else {
        set pretty_name [api_proc_pretty_name  -include_debug_controls  -link  -proc_type $proc_type  -label $label  $proc_name]
    }
    if {[regexp {<([^ >]+)} $first_line_tag match tag]} {
        set end_tag "</$tag>"
    } else {
        set first_line_tag "<h3>"
        set end_tag "</h3>"
    }
    append out $first_line_tag$pretty_name$end_tag

    if {[regexp {^(.*) (inst)?proc (.*)$} $proc_name match cl prefix method]
        && [namespace which ::xo::api] ne ""
    } {
        set xotclArgs 1
        set scope ""
        #
        # Since we get "method" via regexp, we have to remove the
        # curly brackets for ensemble methods
        #
        set method [lindex $method 0]
        regexp {^(.+) (.+)$} $cl match scope cl
        if {$prefix eq ""} {
            set pretty_proc_name "[::xo::api object_link $scope $cl$method"
        } else {
            set pretty_proc_name [subst {<i>&lt;instance of [::xo::api object_link $scope $cl]&gt;</i> $method}]
        }
        #
        # Make sure we have the newest update in the nsv
        #
        ::xo::api update_object_doc $scope [expr {[string match ::* $cl] ? $cl :"::$cl"}] ""
    } else {
        set xotclArgs 0
        if {[namespace which ::xo::api] ne "" && [::xo::api isobject "" [lindex $proc_name 1]]} {
            set name [lindex $proc_name 1]
            set pretty_proc_name "[$name info class] [::xo::api object_link {} $name]"
        } else {
            set pretty_proc_name $proc_name
        }
    }

    lappend command_line $pretty_proc_name
    foreach switch $doc_elements(switches0) {
        lappend command_line [api_proc_format_switch $xotclArgs $flags($switch) $switch]
    }

    set counter 0
    foreach positional $doc_elements(positionals) {
        if { [info exists default_values($positional)] } {
            lappend command_line "\[ <i>$positional</i> \]"
        } else {
            lappend command_line "<i>$positional</i>"
        }
    }
    if { $doc_elements(varargs_p) } {
        lappend command_line "\[ <i>args</i>... \]"
    }
    foreach switch $doc_elements(switches1) {
        lappend command_line [api_proc_format_switch $xotclArgs $flags($switch) $switch]
    }

    append out [util_wrap_list $command_line]

    set intro_out ""
    if { $script_p } {
        append intro_out [subst {<p>Defined in
            <a href="/api-doc/procs-file-view?path=[ns_urlencode $doc_elements(script)]">$doc_elements(script)</a>
            <p>}]
    }

    if { $doc_elements(deprecated_p) } {
        append intro_out "<b><i>Deprecated."
        if { $doc_elements(warn_p) } {
            append intro_out " Invoking this procedure generates a warning."
        }
        append intro_out "</i></b><p>\n"
    }

    set main [lindex $doc_elements(main) 0]
    if {$main ne ""} {
        append intro_out "<p>[lindex $doc_elements(main) 0]\n<p>\n"
    }

    set blocks_out "<dl>\n"

    if { [info exists doc_elements(param)] } {
        foreach param $doc_elements(param) {
            if { [regexp {^([^ \t\n]+)[ \t\n]+(.*)$} $param "" name value] } {
                set params($name$value
            }
        }
    }

    set switches [concat $doc_elements(switches0) $doc_elements(switches1)]
    if { [llength $switches] > 0 } {
        append blocks_out "<dt>Switches:</dt><dd><dl class='api-doc-parameter-list'>\n"
        foreach switch $switches {
            #ns_log notice "==== switch '$switch': flags <$flags($switch)>"
            set details [api_proc_pretty_param_details  -flags $flags($switch)  {*}[expr {[info exists default_values($switch)]
                                       ? [list -default_value $default_values($switch)]
                                       : {}}]  
                        ]
            append blocks_out  "<dt>-$switch <i style='font-weight: normal;'>$details</i></dt>"
            if { [info exists params($switch)] } {
                append blocks_out "<dd>$params($switch)</dd>"
            }
        }
        append blocks_out "</dl></dd>\n"
    }

    if { [llength $doc_elements(positionals)] > 0 } {
        append blocks_out "<dt>Parameters:</dt><dd><dl class='api-doc-parameter-list'>\n"
        foreach positional $doc_elements(positionals) {
            #ns_log notice "==== parameter '$positional': info exists flags($positional): [info exists flags($positional)]"
            set pflags [expr {[info exists flags($positional)] ? $flags($positional) : {}}]
            if {![info exists default_values($positional)]} {
                lappend pflags required
            }
            set details [api_proc_pretty_param_details  -flags $pflags  {*}[expr {[info exists default_values($positional)]
                                       ? [list -default_value $default_values($positional)]
                                       : {}}]  ]
            append blocks_out  "<dt>$positional <i style='font-weight: normal;'>$details</i></dt><dd>"
            if { [info exists params($positional)] } {
                append blocks_out $params($positional)
            }
            append blocks_out "</dd>\n"
        }
        append blocks_out "</dl></dd>\n"
    }


    # @option is used in  template:: and cms:: (and maybe should be used in some other
    # things like ad_form which have internal arg parsers.  although an option
    # and a switch are the same thing, just one is parsed in the proc itself rather than
    # by ad_proc.

    if { [info exists doc_elements(option)] } {
        append blocks_out "<b>Options:</b><dl>"
        foreach param $doc_elements(option) {
            if { [regexp {^([^ \t]+)[ \t](.+)$} $param "" name value] } {
                append blocks_out "<dt>-$name</dt><dd>$value<br></dd>"
            }
        }
        append blocks_out "</dl>"
    }


    if { [info exists doc_elements(return)] } {
        append blocks_out "<dt>Returns:</dt><dd>[join $doc_elements(return) "<br>"]</dd>\n"
    }

    if { [info exists doc_elements(error)] } {
        append blocks_out "<dt>Error:</dt><dd>[join $doc_elements(error) "<br>"]</dd>\n"
    }

    append blocks_out [::apidoc::format_common_elements doc_elements]
    set css {
        /*svg g a:link {text-decoration: none;}*/
        div.inner svg {width: 100%; margin: 0 auto;}
        svg g polygon {fill: transparent;}
        svg g g ellipse {fill: #eeeef4;}
        svg g g polygon {fill: #f4f4e4;}
    }

    if {![regexp { (Class|Object) } $proc_name]} {
        if {![regexp { (inst)?proc } $proc_name]} {
            #ns_log notice "Compute call graph from <$proc_name>"
            set callgraph [util::inline_svg_from_dot -css $css  [api_call_graph_snippet -proc_name $proc_name -maxnodes 5]]
            if {$callgraph ne ""} {
                append blocks_out "<p><dt>Partial Call Graph (max 5 caller/called nodes):</dt><dd>$callgraph</dd>\n"
            }
        }
    } else {
        set objName [::xo::api object_from_proc_index $proc_name]
        if {[nsf::is object,type=::nx::Object $objName] && ![nsf::is object,type=::nx::Class $objName]} {
            append blocks_out <blockquote><ul>
            foreach m [$objName info lookup methods -callprotection public -source application] {
                set definition [nx::Object info method definition [$objName info lookup method $m]]
                #
                # Currently, "info lookup syntax" does not work for aliases
                #
                if {[lindex $definition end-2] eq "alias"} {
                    set targetMethod [lindex $definition end]
                    unset -nocomplain methodSyntax
                    if {[nsf::cmd::info type $targetMethod] eq "cmd"} {
                        #
                        # We have an alias to a plain command. Try
                        # executing the plain command and let's hope,
                        # it gives us a syntax.
                        #
                        try {
                            $targetMethod
                        } on error {errorMsg} {
                            if {[regexp {"([^\"]+)"} [lindex [split $errorMsg \n] 0] . syntax]} {
                                set methodSyntax "$objName $m [lrange $syntax 1 end]"
                            }
                        }
                    } else {
                        ns_log notice "unknown type '[nsf::cmd::info type $targetMethod]'"  "for alias for '$targetMethod'"  "used in [list $objName info lookup syntax $m]"                             
                    }
                    if {![info exists methodSyntax]} {
                        set methodSyntax "$objName $m ..."                        
                    }
                } else {
                    set methodSyntax "$objName $m [$objName info lookup syntax $m]"
                }
                set containerObject [lindex $definition 0]
                if {$containerObject ne $objName} {
                    #
                    # The method is defined on a class
                    #
                    set methodSyntax [xo::api method_link -label $methodSyntax $containerObject instproc $m]
                } else {
                    set methodSyntax [xo::api method_link -label $methodSyntax $containerObject proc $m]
                }
                append blocks_out "<li><i>$methodSyntax</i></li>\n"
            }
            append blocks_out </ul></blockquote>
        }
    }

    append blocks_out "<p><dt>Testcases:</dt><dd>\n"

    if {[info exists doc_elements(testcase)]} {
        set cases {}
        foreach testcase_pair $doc_elements(testcase) {
            set url [api_test_case_url $testcase_pair]
            lappend cases [subst {<a href="[ns_quotehtml $url]">[ns_quotehtml [lindex $testcase_pair 0]]</a>}]
        }
        append blocks_out [join $cases {, }]
    } else {
        append blocks_out "No testcase defined."
    }
    append blocks_out "</dd>\n</dl>\n"


    if { $source_p } {
        if {[parameter::get_from_package_key  -package_key acs-api-browser  -parameter FancySourceFormattingP  -default 1]} {
            set source_out [subst {<dt>Source code:</dt><dd>
                <pre class="code">[::apidoc::tcl_to_html $proc_name]</pre>
                </dd>
            }]
        } else {
            set source_out [subst {<dt>Source code:</dt><dd>
                <pre class="code">[ns_quotehtml [api_get_body $proc_name]]</pre>
                </dd>
            }]
        }
    } else {
        set source_out ""
    }

    set xql_base_name $::acs::rootdir/
    append xql_base_name [file rootname $doc_elements(script)]
    if { $xql_p } {
        set there {}
        set missing {}
        set xql_fn [file rootname $doc_elements(script)].xql
        if { [file exists $::acs::rootdir/$xql_fn] } {
            set content [apidoc::get_xql_snippet -proc_name $proc_name -xql_file $xql_fn]
            if {$content ne ""} {set content "<pre class='code'>$content</pre>"}
            append there [subst {<dt>Generic XQL file:</dt>
                <dd>$content
                <a href="[ns_quotehtml [export_vars -base content-page-view {{source_p 1} {path $xql_fn}}]]">$xql_fn</a>
                <p>
                </dd>

            }]
        } else {
            lappend missing Generic
        }
        set xql_fn [file rootname $doc_elements(script)]-postgresql.xql
        if { [file exists $::acs::rootdir/$xql_fn] } {
            set content [apidoc::get_xql_snippet -proc_name $proc_name -xql_file $xql_fn]
            if {$content ne ""} {set content "<pre class='code'>$content</pre>"}
            set href [export_vars -base content-page-view {{source_p 1} {path $xql_fn}}]
            append there [subst {<dt>PostgreSQL XQL file:</dt>
                <dd>$content
                <a href="[ns_quotehtml $href]">$xql_fn</a>
                <p>
                </dd>
            }]
        } else {
            lappend missing PostgreSQL
        }
        set xql_fn [file rootname $doc_elements(script)]-oracle.xql

        if { [file exists $::acs::rootdir/$xql_fn] } {
            set content [apidoc::get_xql_snippet -proc_name $proc_name -xql_file $xql_fn]
            if {$content ne ""} {set content "<pre class='code'>$content</pre>"}
            set href [export_vars -base content-page-view {{source_p 1} {path $xql_fn}}]
            append there [subst {<dt>Oracle XQL file:</dt>
                <dd>$content
                <a href="[ns_quotehtml $href]">$xql_fn</a>
                <p>
                </dd>
            }]
        } else {
            lappend missing Oracle
        }
        if {[llength $missing] > 0} {
            set xql_out [subst {<dt>XQL Not present:</dt><dd>[join $missing ", "]</dd>}]
        }
        append xql_out $there
    } else {
        set xql_out ""
    }

    set out_sections $intro_out$blocks_out$source_out$xql_out
    if {$out_sections ne ""} {
        append out <blockquote>$out_sections</blockquote>
    }
    # No "see also" yet.

    return $out
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: