Index: Makefile.in =================================================================== diff -u -rd72a757e0aa13c9e34e5e8d284a6a3a833b9f6e6 -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa --- Makefile.in (.../Makefile.in) (revision d72a757e0aa13c9e34e5e8d284a6a3a833b9f6e6) +++ Makefile.in (.../Makefile.in) (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -194,7 +194,7 @@ TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \ @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ - TCLLIBPATH="$(top_builddir) ${srcdir}" + TCLLIBPATH="$(top_builddir) ${srcdir} $(TCLLIBPATH)" TCLSH_PROG = @TCLSH_PROG@ TCLSH = $(TCLSH_ENV) $(TCLSH_PROG) #TCLSH = $(TCLSH_ENV) valgrind --dsymutil=yes $(TCLSH_PROG) @@ -276,6 +276,45 @@ # use language reference as sample file to trigger generation of documentation files doc: $(xotcl_target_doc_dir)/langRef-xotcl.html +YUIDOC_OUTPUT = \ + $(target_doc_dir)/$(PACKAGE_NAME)/index.html \ + $(target_doc_dir)/nx/index.html \ + $(xotcl_target_doc_dir)/XOTcl-langRef/index.html + +yuidoc: pkgIndex.tcl $(YUIDOC_OUTPUT) + +$(target_doc_dir)/$(PACKAGE_NAME)/index.html: + $(TCLSH) $(src_app_dir_native)/utils/nxdoc -doctitle $(PACKAGE_NAME) \ + -docurl "http://next-scripting.org/" -docversion $(PACKAGE_VERSION) \ + -outdir $(target_doc_dir) "package:$(PACKAGE_NAME)" + +$(target_doc_dir)/nx/index.html: + $(TCLSH) $(src_app_dir_native)/utils/nxdoc -doctitle nx \ + -docurl "http://next-scripting.org/" -docversion $(PACKAGE_VERSION) \ + -outdir $(target_doc_dir) "package:nx" + +$(xotcl_target_doc_dir)/XOTcl-langRef/index.html: + $(TCLSH) $(src_app_dir_native)/utils/nxdoc -doctitle XOTcl-langRef \ + -docurl "http://next-scripting.org/" -docversion $(PACKAGE_VERSION) \ + -outdir $(xotcl_target_doc_dir) "@package:XOTcl-langRef" + +XOWIKI_OUTPUT = \ + $(target_doc_dir)/$(PACKAGE_NAME).xowiki \ + $(target_doc_dir)/nx.xowiki \ + $(xotcl_target_doc_dir)/XOTcl-langRef.xowiki + +xowiki: pkgIndex.tcl $(XOWIKI_OUTPUT) + +$(xotcl_target_doc_dir)/XOTcl-langRef.xowiki : + $(TCLSH) $(src_app_dir_native)/utils/nxdoc -doctitle $(basename $(notdir $@)) \ + -docurl "http://next-scripting.org/" -docversion $(PACKAGE_VERSION) \ + -outdir $(@D) -format xowiki -layout many-to-1 "@package:$(basename $(notdir $@))" + +%.xowiki : + $(TCLSH) $(src_app_dir_native)/utils/nxdoc -doctitle $(*F) \ + -docurl "http://next-scripting.org/" -docversion $(PACKAGE_VERSION) \ + -outdir $(@D) -format xowiki -layout many-to-1 "package:$(*F)" + example-doc: $(EXAMPLE_SCRIPTS) $(xotcl_target_doc_dir)/langRef-xotcl.html: pkgIndex.tcl $(xotcl_src_doc_dir)/langRef.xotcl $(XODOC_SOURCE) @@ -616,9 +655,12 @@ # variable in configure.in #======================================================================== -clean: - -rm -rf $(BINARIES) $(CLEANFILES) $(installed_shells) pkgIndex.tcl ./receiver \ - $(xotcl_target_doc_dir)/*-xotcl.html +cleandoc: + -rm -rf $(xotcl_target_doc_dir)/*-xotcl.html $(dir $(YUIDOC_OUTPUT)) $(XOWIKI_OUTPUT) + +clean: cleandoc + -rm -rf $(BINARIES) $(CLEANFILES) $(installed_shells) pkgIndex.tcl ./receiver + find ${srcdir} -type f -name \*~ -exec rm \{} \; @if test ! "x$(subdirs)" = "x" ; then dirs="$(subdirs)" ; \ for dir in $$dirs ; do \ Index: apps/utils/nxdoc =================================================================== diff -u --- apps/utils/nxdoc (revision 0) +++ apps/utils/nxdoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,84 @@ +#!/usr/local/src/tcl8.6-fossil/unix/tclsh +#!/bin/env tclsh + +package req nx::doc 1.0 + +namespace eval ::nx::doc { + namespace import -force ::nx::* + Class create CLI { + + # + # rendering + # + :property {outdir "."} + :property {format "html"} + :property {theme "yuidoc"} + :property {layout "many-to-many"} + + # + # doc project + # + :property doctitle + :property {docversion 0.1} + :property docurl + :property docbaseurl + :property {validation:switch false} + + # + # input + # + :property sourcepath + :property {includes ""} + :property {excludes ""} + :protected property sources:1..* { + set :config false + } + + # + # auxiliary + # + + :protected method ... args { + :sources [concat {*}[split $args :]] + } + + :protected class method objectparameter {} { + foreach slot [:info slot objects -type ::nx::VariableSlot] { + lappend defs([$slot position]) [$slot getParameterSpec] + } + set parameterdefinitions [list] + foreach p [lsort [array names defs]] { + lappend parameterdefinitions {*}$defs($p) + } + return [concat $parameterdefinitions ...:alias,args] + } + + :protected method init {} { + set prj [@project new \ + -name ${:doctitle} \ + -url ${:docurl} \ + -version ${:docversion} \ + -sources ${:sources}] + + processor process \ + -sandboxed \ + {*}[expr {${:validation}?"-validate":""}] \ + -include ${:includes} $prj + + make doc \ + -format ${:format} \ + $prj \ + -theme ${:theme} \ + -layout ${:layout} \ + -outdir ${:outdir} + } + } + namespace export CLI +} + +namespace import -force ::nx::doc::CLI +# +# nxdoc -outdir /tmp/ -format html -theme yuidoc package:nsf +# +CLI new {*}$argv + Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@class.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@class.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@command.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@command.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@method.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@method.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@object.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@object.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@package.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@package.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@project.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/@project.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/asciidoc/xhtml11.css'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/attributemethod.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/attributemethod.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/body-chunked.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/body.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/filter.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/glossary.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/hookmethod.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/leftbar.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/link.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/link.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/listing.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/listing.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/overview.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/status.svg'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/submethod.html.asciidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/submethod.html.yuidoc'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/yuidoc/ac.js'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/yuidoc/api-next.css'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/yuidoc/api.css'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/yuidoc/api.js'. Fisheye: No comparison available. Pass `N' to diff? Index: library/lib/doc-assets/yuidoc/bg_hd.gif =================================================================== diff -u -r77c371a2e4a1bd85367d11869de6e2dc9fac4771 -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa Binary files differ Index: library/lib/doc-assets/yuidoc/nx.png =================================================================== diff -u -r77c371a2e4a1bd85367d11869de6e2dc9fac4771 -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa Binary files differ Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-assets/yuidoc/reset-fonts-grids-min.css'. Fisheye: No comparison available. Pass `N' to diff? Index: library/lib/doc-assets/yuidoc/status.png =================================================================== diff -u -r77c371a2e4a1bd85367d11869de6e2dc9fac4771 -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa Binary files differ Fisheye: Tag fa7635cbfe2309b8e6282e2c7925fa2617b061aa refers to a dead (removed) revision in file `library/lib/doc-tools.tcl'. Fisheye: No comparison available. Pass `N' to diff? Index: library/lib/nxdoc-assets/@class.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@class.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/@class.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,106 @@ +
+[:as_text] +
+[:?var :@class-attribute { +[:!let class_attrs [:!get -sortedby name -with name @class-attribute]] +}] + +
+

Provided Parameters

+ [:? {[info exists class_attrs]} { +

+ + [:for attr [dict values $class_attrs] { + [$attr name] + }] + +

+ }] + [:!let iattrs [:inherited @class-attribute]] + [:? {$iattrs ne ""} { + [:for superclass [dict keys $iattrs] { + [:!let attrs [dict values [dict get $iattrs $superclass]]] +
Parameters inherited from [$superclass name]
+

+ + [:for a $attrs { + [$a name] + }] + +

+ }] + }] + + [:? {[info exists class_attrs]} { +
+ [:for attr [dict values $class_attrs] { +
+
+ [$attr name] +
+

[$attr as_text]

+ }] +
+ }] +
+ + +[:?var :@class-method { +[:!let class_methods [:!get -sortedby name @class-method]] +}] + +
+

Provided Methods

+ [:? {[info exists class_methods]} { +

+ + [:for m $class_methods { + [$m name] + }] + +

+ }] + [:!let imethods [:inherited @class-method]] + [:? {$imethods ne ""} { + [:for superclass [dict keys $imethods] { + [:!let ms [dict values [dict get $imethods $superclass]]] +
Methods inherited from [$superclass name]
+

+ + [:for m $ms { + [$m name] + }] + +

+ }] + }] + + [:? {[info exists class_methods]} { + [:for m $class_methods { + [:? {[info exists class_attrs] && [dict exists $class_attrs [$m name]]} { + [$m render -initscript [list set owning_attribute [dict get $class_attrs [$m name]]] attributemethod] + } - { + [$m render] + }] + }] + }] +
+ + +[:?var :@object-method { +[:!let omethods [:!get -sortedby name @object-method]] +
+

Per-Object Methods

+

+ + [:for om $omethods { + [$om name] + }] + +

+ [:for om $omethods { + [$om render] + }] +
+}] + Index: library/lib/nxdoc-assets/@class.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@class.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/@class.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,289 @@ +[:include filter] +

+ Class + [:print_name -status] + [:?var :@superclass { + + - subclass of + [:for super ${:@superclass} { + [$super name] + }] + + }] +

+
+ + ${:name} + create + obj + [:pinfo get -default "" bundle parametersyntax] + +
+ +[:?var :@see { +
See also:${:@see}
+}] + +
+ [:as_text] +
+[:? {[:pinfo exists validation]} { +[join [:pinfo get validation]] +}] + + +[:?var :@class-attribute { +[:!let class_attrs [:!get -sortedby name -with name @class-attribute]] +
+
+

Provided Parameters

+
+
+ These parameters can be used to configure instances of this class: + + [:for attr [dict values $class_attrs] { + [:!let depr [expr {[$attr !get @deprecated]?"deprecated":""}]] + + [$attr name] + + }] + +
+
+
+
+ [:for attr [dict values $class_attrs] { + [:!let depr [expr {[$attr !get @deprecated]?"deprecated":""}]] +
+

[$attr print_name -status] +

+
+
+ [:? {[$attr pinfo exists validation]} { + [$attr pinfo get validation] + }] + [$attr as_text] +
+
+ + + [:?objvar $attr default { +
+ Default Value: $default +
+ }] + + [:? {[$attr eval {info exists :deprecated}]} { +
+ Deprecated: [$attr default] +
+ }] + +
+
+ }] +
+
+
+}] + +[:!let iattrs [:inherited @class-attribute]] +[:? {$iattrs ne ""} { +
+ [:for superclass [dict keys $iattrs] { + [:!let attrs [dict values [dict get $iattrs $superclass]]] +
+

Inherited Parameters + from [$superclass name]:

+
+ + [:for a $attrs { + [:!let depr [expr {[$a !get @deprecated]?"deprecated":""}]] + + [$a name] + + }] + +
+
+ }] +
+ }] + +[:?var :@object-attribute { +
+
+

Per-object parameters

+
+ + [:for attr ${:@object-attribute} { + [:!let depr [expr {[$attr !get @deprecated]?"deprecated":""}]] +
+

[$attr name] +

+
+
+ [$attr as_text] +
+
+ + + [:? {[$attr eval {info exists :default}]} { +
+ Default Value: [$attr default] +
+ }] + + [:? {[$attr eval {info exists :deprecated}]} { +
+ Deprecated: [$attr] +
+ }] + +
+
+ + }] +
+
+
+}] + +[:?var :@class-method { +[:!let class_methods [:!get -sortedby name @class-method]] +
+
+

Provided Methods

+
+
+ + [:for m $class_methods { + [:!let modifier [expr {[$m pinfo get -default 0 bundle call-protected]?"protected":""}]] + [:!let depr [expr {[$m !get @deprecated]?"deprecated":""}]] + + [$m name] + + }] + +
+
+
+
+ [:for method $class_methods { + [:? {[info exists class_attrs] && [dict exists $class_attrs [$method name]]} { + [$method render -initscript [list set owning_attribute [dict get $class_attrs [$method name]]] attributemethod] + } - { + [$method render] + }] + }] +
+
+
+}] + + [:!let imethods [:inherited @class-method]] + [:? {$imethods ne ""} { +
+ [:for superclass [dict keys $imethods] { + [:!let ms [dict values [dict get $imethods $superclass]]] +
+

Inherited Methods + from [$superclass name]:

+
+ + [:for m $ms { + [:!let depr [expr {[$m !get @deprecated]?"deprecated":""}]] + + [$m name] + + }] + +
+
+ }] +
+}] + + +[:?var :@object-method { +[:!let omethods [:!get -sortedby name @object-method]] +
+
+

Per-object methods

+
+ + [:for m $omethods { + [:!let depr [expr {[$m !get @deprecated]?"deprecated":""}]] + + [$m name] + + }] + +
+
+
+ [:for omethod $omethods { + [$omethod render] + }] +
+
+
}] + +[:!let hooks [:!get -sortedby name @class-hook]] +[:? {[llength $hooks] > 0} { +
+
+

Hook methods

+
+
+ + [:for m $hooks { + [:!let modifier [expr {[$m pinfo get -default 0 bundle call-protected]?"protected":""}]] + [:!let depr [expr {[$m !get @deprecated]?"deprecated":""}]] + + [$m name] + + }] + +
+
+
+
+ [:for method $hooks { + [$method render hookmethod] + }] +
+
+
+}] Index: library/lib/nxdoc-assets/@command.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@command.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/@command.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,62 @@ +
+ [:as_text] +
+
Usage
+
${:name} + [:pinfo get -default "" bundle parametersyntax] + +
+[:?var :@command { +[:!let subs [:!get -sortedby name @command]] +[:for sub $subs { +
+
+
+ ${:name} [$sub name] +
+
+

[$sub as_text]

+
Usage
+
${:name} [$sub name] [:pinfo get -default "" bundle parametersyntax] +
+ [:?objvar $sub @parameter { +
Parameters
+
+ [:for param [$sub !get @parameter] { +
[$param print_name]
+

[$param as_text]

+ }] +
+ }] + [:?objvar $sub @return { +
Return
+ [:!let ret [$sub !get @return]] + [$ret as_text] + }] + + + +}] +} - { +[:?var :@parameter { +
Parameters
+
+ [:for param [:!get @parameter] { +
[$param print_name]
+

[$param as_text]

+ }] +
+}] +[:?var :@return { +
Return
+[:!let ret [:!get @return]] +[$ret as_text] +}] +}] + + + + + + + Index: library/lib/nxdoc-assets/@command.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@command.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/@command.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,117 @@ +

+ Command [:print_name -status] +

+
+ [:as_text] +
+[join [:pinfo get -default "" validation]
]
+
+ [:? {[info exists :@return] && [${:@return} @spec] ne ""} {<[${:@return} @spec]>} ] + ${:name} + [:pinfo get -default "" bundle parametersyntax] + + [:?var :@command { +
+
+
+

Subcommands

+
+
+ + [:for sub [:!get -sortedby name @command] { + + [$sub name] + + }] + +
+
+
+
+ [:for sub [:!get -sortedby name @command] { +
+

[$sub print_name] +

+
+ [:? {[$sub eval {info exists :@return}] && [[$sub @return] @spec] ne ""} {<[[$sub @return] @spec]>} ] + ${:name} [$sub name] + [$sub pinfo get -default "" bundle parametersyntax] + +
+ [$sub as_text] + [:?objvar $sub @parameter { +
+
Parameters:
+ [:for param [$sub !get @parameter] { +
+ [$param name] + [:? {[$param eval {info exists :@spec}] && [$param @spec] ne ""} {<[$param @spec]>}] + + [$param as_text] + [join [$param pinfo get -default "" validation]
]
+
+ }] +
+ }] + [:?objvar $sub @return { + [:!let subreturn [$sub @return]] +
+
Returns: + +
+
[$subreturn as_text][join [$subreturn pinfo get -default "" validation]
]
+
+ }] +
+
+
+
+ }] +
+
+
+
+ } - { +
+
+ [:?var :@parameter { +
+
Parameters:
+ [:for param [:!get @parameter] { +
+ [$param name] + [:? {[$param eval {info exists :@spec}] && [$param @spec] ne ""} {<[$param @spec]>}] + + [$param statusmark] + [$param as_text] + [join [$param pinfo get -default "" validation]
]
+
+ }] +
+ }] + + [:?var :@return { +
+
Returns: + +
+
[${:@return} as_text]
+
+ }] +
+
+ }] +
+ + + + + + + + Index: library/lib/nxdoc-assets/@method.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@method.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/@method.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,31 @@ +[:!let prefix [expr {[[:get_owning_partof] pinfo get -default 0 bundle ismetaclass] ? "cls": "obj"}]] +
+
+
+ [:name] +
+
+

$prefix [:name] [:pinfo get -default "" bundle parametersyntax] +

+ [:?var :@method { + [:for sm [:get_sub_methods] { + [$sm render -initscript [list set supermethod [current]] submethod] + }] + } - { + [:?var :@parameter { +
Parameters
+
+ [:for param [:!get @parameter] { +
[$param print_name]
+
[$param as_text]
+ }] +
+ }] + [:?var :@return { +
Return
+ [:!let ret [:!get @return]] + [$ret as_text] + }] + }] +
+
Index: library/lib/nxdoc-assets/@method.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@method.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/@method.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,87 @@ +[:!let modifier [expr {[:pinfo get -default 0 bundle call-protected]?"protected":""}]] +[:!let depr [expr {[:!get @deprecated]?"deprecated":""}]] +[:!let prefix [expr {[[:get_owning_partof] pinfo get -default 0 bundle ismetaclass] ? "cls": "obj"}]] +
+

+ [:print_name -status]

+
+ + $prefix + ${:name} + [:pinfo get -default "" bundle parametersyntax] + +
+ [:as_text] +
+ +
+ [:?var :@method { +
+ [:for sm [:get_sub_methods] { + [$sm render -initscript [list set supermethod [current]] submethod] + }] + } - { + [:?var :@parameter { +
+
Parameters:
+ [:for param [:!get @parameter] { +
+ [$param print_name] + [:? {[$param eval {info exists :@spec}] && [$param @spec] ne + ""} {: [$param @spec]}] + + [$param statusmark] + [$param as_text] + [join [$param pinfo get -default "" validation]] + [:? {[$param eval {info exists :default}]} { +
+ Default Value: [$param default] +
+ }] +
+ }] +
+ }] + + [:?var :@return { +
+
Returns: + [:!let ret [:!get @return]] + [:? {[$ret eval {info exists :@spec}] && [$ret @spec] ne ""} {[$ret @spec]}] +
+
+ [join [$ret pinfo get -default "" validation]] + [$ret as_text] +
+
+ }] + }] + + [:? {[:!get @deprecated]} { +
+ Deprecated +
+ }] + + [:? {[:!get @syshook] || [:pinfo exists bundle type]} { +
+
Implementation details:
+
[:pinfo get bundle type]
[:? {[:!get @syshook]} { +
+ internally called, redefinable hook
+ }] +
+ }] + + [:? {[:pinfo get -default 0 bundle redefine-protected]} { +
+
Protection:
+
redefine-protected
+
+ }] + + +
+
+
+
Index: library/lib/nxdoc-assets/@object.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@object.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/@object.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,20 @@ +
+ [:as_text] +
+ +[:?var :@object-method { +[:!let omethods [:!get -sortedby name @object-method]] +
+

Per-Object Methods

+

+ + [:for om $omethods { + [$om name] + }] + +

+ [:for om $omethods { + [$om render] + }] +
+}] Index: library/lib/nxdoc-assets/@object.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@object.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/@object.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,105 @@ +[:include filter] +

+ Object + [:print_name -status] +

+ +[:?var :@see { +
See also:${:@see}
+}] + +
+ [:as_text] +
+ +[:? {[:pinfo exists validation]} { +[join [:pinfo get validation]] +}] + +[:?var :@object-attribute { +[:!let obj_attrs [:!get -sortedby name -with name @object-attribute]] +
+
+

Per-object parameters

+
+
+ + [:for attr [dict values $obj_attrs] { + [:!let depr [expr {[$attr !get @deprecated]?"deprecated":""}]] + + [$attr name] + + }] + +
+
+
+
+ [:for attr [dict values $obj_attrs] { + [:!let depr [expr {[$attr !get @deprecated]?"deprecated":""}]] +
+

[$attr print_name -status] +

+
+
+ [:? {[$attr pinfo exists validation]} { + [$attr pinfo get validation] + }] + [$attr as_text] +
+
+ + + [:?objvar $attr default { +
+ Default Value: $default +
+ }] + + [:? {[$attr eval {info exists :deprecated}]} { +
+ Deprecated: [$attr default] +
+ }] + +
+
+ }] +
+
+
+}] + +[:?var :@object-method { +[:!let omethods [:!get -sortedby name @object-method]] +
+
+

Per-object methods

+
+ + [:for m $omethods { + [:!let depr [expr {[$m !get @deprecated]?"deprecated":""}]] + + [$m name] + + }] + +
+
+
+ [:for omethod $omethods { + [$omethod render] + }] +
+
+
+}] Index: library/lib/nxdoc-assets/@package.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@package.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/@package.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,45 @@ + +

+ [:as_text] +

+ +[:?var :@require { +
Required packages
+

${:@require}

+}] + +[:?var :@class { +
Contained classes
+
+ +
+}] + +[:?var :@object { +
Contained objects
+
+ +
+}] + +[:?var :@command { +
Contained commands
+
+ +
+}] + + Index: library/lib/nxdoc-assets/@package.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@package.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/@package.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,12 @@ + +

Package: ${:name}

+
+ [:as_text] +
+[:?var :@require { +
+ Package requires: ${:@require} +
+}] +[:include overview] Index: library/lib/nxdoc-assets/@project.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@project.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/@project.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,102 @@ + + + + + + API: ${:name} [:?var classname {$classname}] [:?var filename {$filename}] (A Next Library) + + + + + + +[:!let tmpls [dict create ::nx::doc::@class class.html.asciidoc ::nx::doc::@package package.html.asciidoc ::nx::doc::@object object.html.asciidoc ::nx::doc::@command command.html.asciidoc]] +
+ [:for feature [dict keys $project_entities] { + [:for inst [dict get $project_entities $feature] { +
+

[$feature pretty_name] [$inst name]

+
+ [:? {[dict exists $tmpls [$inst info class]]} { + [$inst render] + }] +
+
+ }] + }] + [:?var :@glossary { +
+

Glossary

+
+ [:!let entries [sorted [:@glossary] name]] + [:for entry $entries { + [:!let ddesc [$entry as_text]] + [:?objvar $entry @acronym { + [:!let dtext [$entry @acronym]] + [:? {$ddesc ne ""} { + [:!let ddesc "[$entry @pretty_name] — $ddesc"] + } - { + [:!let ddesc "[$entry @pretty_name]"] + }] + } - { + [:!let dtext [$entry @pretty_name]] + }] +
+ $dtext +
+
+

$ddesc

+ [:?objvar $entry refs { + [:? {[$entry eval [concat dict exists \${:refs} [current]]]} { +

+ [:!let refs [sort_by_value [$entry eval [concat dict get \${:refs} [current]]]]] + [:for src [dict keys $refs] { + + [$src make_link [current]] +  ([dict get $refs $src]) + + }] +

+ }] + }] +
+ }] +
+
+ }] +
+ + + Index: library/lib/nxdoc-assets/@project.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/@project.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/@project.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,16 @@ + + + + + API: ${:name} [:?var classname {$classname}] [:?var filename {$filename}] (A Next Library) + + + + + + + + +[:include body] + + Index: library/lib/nxdoc-assets/asciidoc/xhtml11.css =================================================================== diff -u --- library/lib/nxdoc-assets/asciidoc/xhtml11.css (revision 0) +++ library/lib/nxdoc-assets/asciidoc/xhtml11.css (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,388 @@ +/* Sans-serif font. */ +h1, h2, h3, h4, h5, h6, +div.title, caption.title, +thead, p.table.header, +div#toctitle, +span#author, span#revnumber, span#revdate, span#revremark, +div#footer { + font-family: Arial,Helvetica,sans-serif; +} + +/* Serif font. */ +div.sectionbody { + font-family: Georgia,"Times New Roman",Times,serif; +} + +/* Monospace font. */ +tt { + font-size: inherit; +} + +body { + margin: 1em 5% 1em 5%; +} + +a { + color: blue; + text-decoration: underline; +} +a:visited { + color: fuchsia; +} + +em { + font-style: italic; + color: navy; +} + +strong { + font-weight: bold; + color: #083194; +} + +tt { + font-size: inherit; + color: navy; +} + +h1, h2, h3, h4, h5, h6 { + color: #527bbd; + margin-top: 1.2em; + margin-bottom: 0.5em; + line-height: 1.3; +} + +h1, h2, h3 { + border-bottom: 2px solid silver; +} +h2 { + padding-top: 0.5em; +} +h3 { + float: left; +} +h3 + * { + clear: left; +} + +div.sectionbody { + margin-left: 0; +} + +hr { + border: 1px solid silver; +} + +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +ul, ol, li > p { + margin-top: 0; +} +ul > li { color: #aaa; } +ul > li > * { color: black; } + +pre { + padding: 0; + margin: 0; +} + +span#author { + color: #527bbd; + font-weight: bold; + font-size: 1.1em; +} +span#email { +} +span#revnumber, span#revdate, span#revremark { +} + +div#footer { + font-size: small; + border-top: 2px solid silver; + padding-top: 0.5em; + margin-top: 4.0em; +} +div#footer-text { + float: left; + padding-bottom: 0.5em; +} +div#footer-badges { + float: right; + padding-bottom: 0.5em; +} + +div#preamble { + margin-top: 1.5em; + margin-bottom: 1.5em; +} +div.tableblock, div.imageblock, div.exampleblock, div.verseblock, +div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, +div.admonitionblock { + margin-top: 1.0em; + margin-bottom: 1.5em; +} +div.admonitionblock { + margin-top: 2.0em; + margin-bottom: 2.0em; + margin-right: 10%; + color: #606060; +} + +div.content { /* Block element content. */ + padding: 0; +} + +/* Block element titles. */ +div.title, caption.title { + color: #527bbd; + font-weight: bold; + text-align: left; + margin-top: 1.0em; + margin-bottom: 0.5em; +} +div.title + * { + margin-top: 0; +} + +td div.title:first-child { + margin-top: 0.0em; +} +div.content div.title:first-child { + margin-top: 0.0em; +} +div.content + div.title { + margin-top: 0.0em; +} + +div.sidebarblock > div.content { + background: #ffffee; + border: 1px solid #dddddd; + border-left: 4px solid #f0f0f0; + padding: 0.5em; +} + +div.listingblock > div.content { + border: 1px solid #dddddd; + border-left: 5px solid #f0f0f0; + background: #f8f8f8; + padding: 0.5em; +} + +div.quoteblock, div.verseblock { + padding-left: 1.0em; + margin-left: 1.0em; + margin-right: 10%; + border-left: 5px solid #f0f0f0; + color: #777777; +} + +div.quoteblock > div.attribution { + padding-top: 0.5em; + text-align: right; +} + +div.verseblock > pre.content { + font-family: inherit; + font-size: inherit; +} +div.verseblock > div.attribution { + padding-top: 0.75em; + text-align: left; +} +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */ +div.verseblock + div.attribution { + text-align: left; +} + +div.admonitionblock .icon { + vertical-align: top; + font-size: 1.1em; + font-weight: bold; + text-decoration: underline; + color: #527bbd; + padding-right: 0.5em; +} +div.admonitionblock td.content { + padding-left: 0.5em; + border-left: 3px solid #dddddd; +} + +div.exampleblock > div.content { + border-left: 3px solid #dddddd; + padding-left: 0.5em; +} + +div.imageblock div.content { padding-left: 0; } +span.image img { border-style: none; } +a.image:visited { color: white; } + +dl { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +dt { + margin-top: 0.5em; + margin-bottom: 0; + font-style: normal; + color: navy; +} +dd > *:first-child { + margin-top: 0.1em; +} + +ul, ol { + list-style-position: outside; +} +ol.arabic { + list-style-type: decimal; +} +ol.loweralpha { + list-style-type: lower-alpha; +} +ol.upperalpha { + list-style-type: upper-alpha; +} +ol.lowerroman { + list-style-type: lower-roman; +} +ol.upperroman { + list-style-type: upper-roman; +} + +div.compact ul, div.compact ol, +div.compact p, div.compact p, +div.compact div, div.compact div { + margin-top: 0.1em; + margin-bottom: 0.1em; +} + +div.tableblock > table { + border: 3px solid #527bbd; +} +thead, p.table.header { + font-weight: bold; + color: #527bbd; +} +tfoot { + font-weight: bold; +} +td > div.verse { + white-space: pre; +} +p.table { + margin-top: 0; +} +/* Because the table frame attribute is overriden by CSS in most browsers. */ +div.tableblock > table[frame="void"] { + border-style: none; +} +div.tableblock > table[frame="hsides"] { + border-left-style: none; + border-right-style: none; +} +div.tableblock > table[frame="vsides"] { + border-top-style: none; + border-bottom-style: none; +} + + +div.hdlist { + margin-top: 0.8em; + margin-bottom: 0.8em; +} +div.hdlist tr { + padding-bottom: 15px; +} +dt.hdlist1.strong, td.hdlist1.strong { + font-weight: bold; +} +td.hdlist1 { + vertical-align: top; + font-style: normal; + padding-right: 0.8em; + color: navy; +} +td.hdlist2 { + vertical-align: top; +} +div.hdlist.compact tr { + margin: 0; + padding-bottom: 0; +} + +.comment { + background: yellow; +} + +.footnote, .footnoteref { + font-size: 0.8em; +} + +span.footnote, span.footnoteref { + vertical-align: super; +} + +#footnotes { + margin: 20px 0 20px 0; + padding: 7px 0 0 0; +} + +#footnotes div.footnote { + margin: 0 0 5px 0; +} + +#footnotes hr { + border: none; + border-top: 1px solid silver; + height: 1px; + text-align: left; + margin-left: 0; + width: 20%; + min-width: 100px; +} + +div.colist td { + padding-right: 0.5em; + padding-bottom: 0.3em; + vertical-align: top; +} +div.colist td img { + margin-top: 0.3em; +} + +@media print { + div#footer-badges { display: none; } +} + +div#toc { + margin-bottom: 2.5em; +} + +div#toctitle { + color: #527bbd; + font-size: 1.1em; + font-weight: bold; + margin-top: 1.0em; + margin-bottom: 0.1em; +} + +div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { + margin-top: 0; + margin-bottom: 0; +} +div.toclevel2 { + margin-left: 2em; + font-size: 0.9em; +} +div.toclevel3 { + margin-left: 4em; + font-size: 0.9em; +} +div.toclevel4 { + margin-left: 6em; + font-size: 0.9em; +} + Index: library/lib/nxdoc-assets/attributemethod.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/attributemethod.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/attributemethod.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,52 @@ +[:!let prefix [expr {[[:get_owning_partof] pinfo get -default 0 bundle ismetaclass] ? "cls": "obj"}]] +
+
+
+ ${:name} +
+
+

$prefix ${:name} + ?value?

+ [$owning_attribute as_text] +
Parameters
+
+
value
+

If provided, list of values to be set for the attribute ${:name}

+
+ [:?objvar $owning_attribute @return { +
Return
+ [:!let ret [$owning_attribute !get @return]] + [$ret as_text] + }] + [:? {[$owning_attribute pinfo get -default 0 bundle incremental]} { +
+
+
+ ${:name} add +
+
+

$prefix ${:name} add value

+
Parameters
+
+
value
+

...

+
+
+
+
+
+
+ ${:name} delete +
+
+

$prefix ${:name} delete value

+
Parameters
+
+
value
+

...

+
+
+
+ }] +
+
Index: library/lib/nxdoc-assets/attributemethod.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/attributemethod.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/attributemethod.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,131 @@ +[:!let modifier [expr {[:pinfo get -default 0 bundle call-protected]?"protected":""}]] +[:!let prefix [expr {[[:get_owning_partof] pinfo get -default 0 bundle ismetaclass] ? "cls": "obj"}]] +[:!let depr [expr {[:!get @deprecated]?"deprecated":""}]] + +
+

+ [$owning_attribute print_name -status]

+
+ + $prefix ${:name} ?value? +
+
+
+ [:? {[$owning_attribute pinfo exists validation]} { + [$owning_attribute pinfo get validation] + }] + [$owning_attribute as_text] + +
+ +
+ [:? {[$owning_attribute eval {set :@deprecated}]} { +
+ Deprecated +
+ }] + +
+
Parameters:
+
+ [:!let spec "optional"] + [:?objvar $owning_attribute @spec { + [:!let spec [join [list $spec {*}[$owning_attribute @spec]] ,]] + }] + value : $spec + + If provided, the + attribute ${:name} is set to value. If omitted, the current attribute + value is returned. +
+
+ [:?objvar $owning_attribute @spec { +
+
Returns: + [:? {[$owning_attribute @spec] ne ""} {[$owning_attribute @spec]}] +
+
+ }] + +
+
Implementation details:
+
[:pinfo get bundle type]
attribute getter/setter
+
+ +
+ [:? {[:pinfo get -default 0 bundle redefine-protected]} { +
Protection:
+
redefine-protected
+
+ }] + [:? {[$owning_attribute pinfo get -default 0 bundle incremental]} { +
+ +
+

${:name} add +

+
+ + $prefix + ${:name} add + value + +
+
+
Parameters:
+
+ value + [:?objvar $owning_attribute @spec { + [:? {[$owning_attribute @spec] ne ""} { :  [$owning_attribute @spec]}] + }] + + + +
+
+ +
+
+
+
+ +
+

${:name} delete +

+
+ + obj + ${:name} delete + value + +
+
+
Parameters:
+
+ value + [:?objvar $owning_attribute @spec { + [:? {[$owning_attribute @spec] ne ""} { :  [$owning_attribute @spec]}] + }] + + +
+
+ +
+
+
+ }] + +
+ +
+
+
Index: library/lib/nxdoc-assets/body-chunked.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/body-chunked.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/body-chunked.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,29 @@ +\[\[css:api.css|_|-order 15\]\] +\[\[css:api-next.css|_|-order 16\]\] +\[\[js:api.js\]\] +\[\[js:ac.js\]\] +
+
+ [:include leftbar] +
+
+ [:? {[info exists include]} { + [:include $include] + } ? {[:info has type ::nx::doc::@project]} { +
+ This is the API documentation for the + [:name] project. +

Choose a package, class, object or command name from the list for more information.

+
+ [:!let parts $project_entities] + [:include overview] + } - { + + [:include] + }] +
+
+ + Index: library/lib/nxdoc-assets/body.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/body.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/body.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,53 @@ +
+
+

[$project name]

+

${:name} + [:? {[:info has type ::nx::doc::@package]} { + [:?var :@version {${:@version}} ] + } - { + [$project version] + }] +

+ [$project name] + [:? {[:info has type ::nx::doc::@package]} { + > ${:name} + } ? {[:info has type ::nx::doc::@class]} { + > [:?var :partof {[${:partof} name] >}] ${:name} + }] +
+
+ Search: +
+   +
+
+
+
+
+
+
+ [:? {[:info has type ::nx::doc::@project]} { +
+ This is the API documentation for the + [:name] project. +

Choose a package, object or command name from the list for more information.

+
+ [:include glossary] + } - { + + [:include] + }] +
+
+
+ [:include leftbar] +
+
+
+
+ Copyright © [clock format [clock seconds] -format "%Y"] +
+
+ Index: library/lib/nxdoc-assets/filter.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/filter.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/filter.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,11 @@ +[:!let filter_available 1] +
+
+ Filters + + + + + +
+
Index: library/lib/nxdoc-assets/glossary.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/glossary.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/glossary.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,52 @@ +[:?var :@glossary { +
+
+

Glossary

+[:!let gls [:@glossary]] +[:? {$gls ne ""} { +[:!let entries [sorted $gls name]] +
+ [:for entry $entries { + [:!let ddesc [$entry as_text]] + [:?objvar $entry @acronym { + [:!let dtext [$entry @acronym]] + [:? {$ddesc ne ""} { + [:!let ddesc "[$entry @pretty_name] — $ddesc"] + } - { + [:!let ddesc "[$entry @pretty_name]"] + }] + + } - { + [:!let dtext [$entry @pretty_name]] + }] +
+ + $dtext
+
$ddesc + [:?objvar $entry refs { + [:? {[$entry eval [concat dict exists \${:refs} [current]]]} { + [:!let refs [sort_by_value [$entry eval [concat dict get \${:refs} [current]]]]] +
+
+ + [:for src [dict keys $refs] { + + [$src make_link [current]] +  ([dict get $refs $src]) + + }] + +
+
+ }] + }] +
+ }] + }] +
+
+ }] Index: library/lib/nxdoc-assets/hookmethod.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/hookmethod.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/hookmethod.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,88 @@ +[:!let modifier [expr {[:pinfo get -default 0 bundle call-protected]?"protected":""}]] +[:!let depr [expr {[:!get @deprecated]?"deprecated":""}]] +
+ [:!let status [:statusmark]] + [:!let paramspec [:pinfo get -default "" bundle parametersyntax]] + [:? {[:statustoken] eq "extra"} { + [:!let status ""] + [:!let paramspec "args"] + }] +

+ [:print_name]$status

+
+ [:? {[info exists :@return] && [${:@return} @spec] ne ""} {<[${:@return} @spec]>} ] + obj + ${:name} + $paramspec + +
+ [:as_text] +
+ +
+ [:?var :@parameter { +
+
Parameters:
+ [:for param [:!get @parameter] { +
+ [$param print_name] + [:? {[$param eval {info exists :@spec}] && [$param @spec] ne ""} {<[$param @spec]>}] + + [:? {[:statustoken] ne "extra"} { + [$param statusmark] + }] + [$param as_text] + [join [$param pinfo get -default "" validation]] + [:? {[$param eval {info exists :default}]} { +
+ Default Value: [$param default] +
+ }] +
+ }] +
+ }] + + [:?var :@return { +
+
Returns: + [:!let ret [:!get @return]] + [:? {[$ret eval {info exists :@spec}] && [$ret @spec] ne ""} {[$ret @spec]}] +
+
+ [join [$ret pinfo get -default "" validation]] + [$ret as_text] +
+
+ }] + + [:? {[:!get @deprecated]} { +
+ Deprecated +
+ }] + +
+
Type:
+ [:? {[:statustoken] eq "extra"} { +
deferred implementation, lazily registrable as a method
+ } - { +
[:pinfo get bundle type]
+ }] +
+ internally called, redefinable hook +
+
+ + [:? {[:pinfo get -default 0 bundle redefine-protected]} { +
+
Protection:
+
redefine-protected
+
+ }] + + +
+
+
+
Index: library/lib/nxdoc-assets/leftbar.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/leftbar.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/leftbar.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,26 @@ +[:!let self_owned_parts [:navigatable_parts]] +[:!let owned_parts [dict merge $project_entities $self_owned_parts]] + Index: library/lib/nxdoc-assets/link.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/link.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/link.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,4 @@ +[:? {![info exists cssclass]} { +[:!let cssclass nsfdoc-link] +}] +$source_anchor Index: library/lib/nxdoc-assets/link.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/link.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/link.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,4 @@ +[:? {![info exists cssclass]} { +[:!let cssclass nsfdoc-link] +}] +$source_anchor Index: library/lib/nxdoc-assets/listing.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/listing.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/listing.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,3 @@ +[:? {$inline} {$script} - {
+
$script
+
}] Index: library/lib/nxdoc-assets/listing.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/listing.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/listing.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1 @@ +[:? {$inline} {$script} - {$script}] Index: library/lib/nxdoc-assets/overview.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/overview.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/overview.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,17 @@ +[:? {![info exists parts]} { +[:!let parts [:navigatable_parts]] +}] +[:for feature [dict keys $parts] { +[:!let f [dict get $parts $feature]] +

Contained [string tolower [$feature pretty_plural]]: [llength $f]

+
+ +
+}] Index: library/lib/nxdoc-assets/status.svg =================================================================== diff -u --- library/lib/nxdoc-assets/status.svg (revision 0) +++ library/lib/nxdoc-assets/status.svg (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-11-01 + + + Jean-Victor Balin + + + jean.victor.balin@gmail.com + + + + icon + arrow + + + fr-FR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: library/lib/nxdoc-assets/submethod.html.asciidoc =================================================================== diff -u --- library/lib/nxdoc-assets/submethod.html.asciidoc (revision 0) +++ library/lib/nxdoc-assets/submethod.html.asciidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,26 @@ +[:!let prefix [expr {[[:get_owning_partof] pinfo get -default 0 bundle ismetaclass] ? "cls": "obj"}]] +[:!let name [:get_combined name]] +
+
+
+ $name +
+
+

$prefix $name [:pinfo get -default "" bundle parametersyntax] +

+ [:?var :@parameter { +
Parameters
+
+ [:for param [:!get @parameter] { +
[$param print_name]
+

[$param as_text]

+ }] +
+ }] + [:?var :@return { +
Return
+ [:!let ret [:!get @return]] + [$ret as_text] + }] +
+
Index: library/lib/nxdoc-assets/submethod.html.yuidoc =================================================================== diff -u --- library/lib/nxdoc-assets/submethod.html.yuidoc (revision 0) +++ library/lib/nxdoc-assets/submethod.html.yuidoc (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,40 @@ +[:!let name [:get_combined name]] +[:!let prefix [expr {[[:get_owning_partof] pinfo get -default 0 bundle ismetaclass] ? "cls": "obj"}]] +
+

$name[:statusmark] +

+
+ [:? {[info exists :@return] && [${:@return} @spec] ne ""} { : [${:@return} @spec]} ] + $prefix + $name + [:pinfo get -default "" bundle parametersyntax] + +
+ [:as_text] + [:? {[info exists :@parameter]} { +
+
Parameters:
+ [:for param ${:@parameter} { +
+ [$param name] + [:? {[$param eval {info exists :@spec}] && [$param @spec] ne ""} { : [$param @spec]}] + + [$param statusmark] + [$param as_text] + [$param pinfo get -default "" validation] +
+ }] +
+ }] + [:? {[info exists :@return]} { +
+
Returns: + +
+
[${:@return} as_text]
+
+ }] +
+
+
+
Index: library/lib/nxdoc-assets/yuidoc/ac.js =================================================================== diff -u --- library/lib/nxdoc-assets/yuidoc/ac.js (revision 0) +++ library/lib/nxdoc-assets/yuidoc/ac.js (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,167 @@ +(function() { + var Event=YAHOO.util.Event, + Dom=YAHOO.util.Dom, + oACDS, oAutoComp, + show = { + 'missing': true, + 'mismatch': true, + 'extra': true, + 'protected': false, + 'deprecated': false + }; + +Event.onAvailable('yui-classopts-form', function() { +/*Event.onDOMReady(function() {*/ + //Checkboxes are available.. + var handleClick = function(e,onReady) { + var id, checked = false; + if (YAHOO.lang.isString(e)) { + id = e; + } else { + var tar = Event.getTarget(e); + id = tar.id; + } + var el = Dom.get(id); + checked = el.checked; + + var className = id; + if (checked) { + show[id.replace('show_', '')] = true; + Dom.addClass(document.body, className); + YAHOO.util.Cookie.setSub('yuidoc', id, 'checked'); + } else { + show[id.replace('show_', '')] = false; + Dom.removeClass(document.body, className); + YAHOO.util.Cookie.setSub('yuidoc', id, ''); + } + }; + + var checkCookie = function(id) { + var value = YAHOO.util.Cookie.getSub('yuidoc', id), + el = Dom.get(id), checked = false; + if (value === null) { + /* there is no (sub-)cookie set, apply defaults */ + checked = el.defaultChecked; + } else { + checked = (value === 'checked'); + } + el.checked = checked; + return checked; + }; + + var els = [ + 'show_protected', + 'show_missing', + 'show_mismatch', + 'show_extra', + 'show_deprecated'], + reapplyHash = false; + + for (var i = 0; i < els.length; i++) { + Event.on(els[i], 'click', handleClick); + reapplyHash = checkCookie(els[i]) || reapplyHash; + handleClick(els[i]); + } + + // If we dynamically show private/protected/etc items during + // load, we need to reapply anchors so that the search feature + // works correctly for items that are initially hidden. + if (reapplyHash) { + var dl = document.location, hash = dl.hash; + if (hash) { + dl.hash = hash; + } + } + +}); + +//Starting the AutoComplete code + var getResults = function(query) { + var results = []; + if(query && query.length > 0) { + + var q = query.toLowerCase(); + + for (var i=0, len=ALL_YUI_PROPS.length; i -1 ) { + results.push([query, prop]); + } + } + } + } + + return results; + }; + + // Define Custom Event handlers + var myOnDataReturn = function(sType, aArgs) { + var oAutoComp = aArgs[0]; + var query = aArgs[1]; + var aResults = aArgs[2]; + + if(aResults.length == 0) { + if (query.length > 0) { + oAutoComp.setBody("
Not found
"); + } + } + }; + + var myOnItemSelect = function(sType, aArgs) { + var ac = aArgs[0]; + var item = aArgs[2]; + location.href = item[1].url; + }; + + + Event.onAvailable("searchresults", function() { + + // Instantiate JS Function DataSource + oACDS = new YAHOO.widget.DS_JSFunction(getResults); + oACDS.maxCacheEntries = 30; + + // Instantiate AutoComplete + oAutoComp = new YAHOO.widget.AutoComplete('searchinput','searchresults', oACDS); + //oAutoComp.alwaysShowContainer = true; + oAutoComp.queryDelay = 0.2; + oAutoComp.maxResultsDisplayed = 200; + oAutoComp.minQueryLength = 0; + oAutoComp.formatResult = function(oResultItem, query) { + var sMarkup = "" + oResultItem[1].host + ' ' + oResultItem[1].name + ' (' + oResultItem[1].type.toLowerCase() +')'; + return sMarkup; + }; + + // Subscribe to Custom Events + oAutoComp.dataReturnEvent.subscribe(myOnDataReturn); + oAutoComp.itemSelectEvent.subscribe(myOnItemSelect); + + // Set initial content in the container + oAutoComp.sendQuery(Dom.get("searchinput").value); + + }); + + var validateForm = function() { + return false; + }; + + YAHOO.util.Event.onAvailable('classTab', function() { + var tabs = new YAHOO.widget.TabView('classTab'); + }); + /* + YAHOO.util.Event.onAvailable('codeTree', function() { + var tree1 = new YAHOO.widget.TreeView('codeTree'); + tree1.render(); + }); + */ + +})(); Index: library/lib/nxdoc-assets/yuidoc/api-next.css =================================================================== diff -u --- library/lib/nxdoc-assets/yuidoc/api-next.css (revision 0) +++ library/lib/nxdoc-assets/yuidoc/api-next.css (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,46 @@ +#bd { + border:none; +} + +#yui-main .yui-b { + /*float:left;*/ +} +#ft { + background:none; + border:none; +} +#yui-main .yui-b { + /*margin-left:327px;*/ +} +h1 { + border-bottom:1px solid #89A618; + font-weight:bold; + margin-left:327px; + margin-top:0; + padding:0 0 25px; + font-size:123.1%; + margin-bottom:2em; + text-transform:uppercase; +} + +#doc3 #bd { + margin-bottom:0; +} +.nav .module h4 { + background:transparent; + text-transform:uppercase; + color:#89A618; + font-weight:bold; + border:none; + border-bottom:1px solid #89A618; + display:block; +} +.nav .module { + border:none; +} +.summary { + background:#E7EDD3 url(/resources/openacs-nsf-theme/images/boxarrow.png) no-repeat scroll left 10px; + border-bottom:3px solid #89a618; + margin-bottom:1.5em; + padding:0.5em 40px; +} Index: library/lib/nxdoc-assets/yuidoc/api.css =================================================================== diff -u --- library/lib/nxdoc-assets/yuidoc/api.css (revision 0) +++ library/lib/nxdoc-assets/yuidoc/api.css (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,312 @@ + + +body { background-color: #ECF0F6; } + +/* main page */ +a:link { color: #003399; } +a:visited { color: #003399;} + +#doc3 #hd { margin-bottom:1em; position: relative; zoom: 1; } +#doc3 #hd h1 { color: #545454; font-size: 170%; padding: 0px 0 8px 180px; background: url(nx.png) 15px 9px no-repeat; height: 60px; font-weight: bold; } +#doc3 #hd h1 a { position: relative; top: 14px; } +#doc3 #hd a { text-decoration: none; color: black; } +#doc3 #hd h3 { + background: #98AAB1; background-image: url(bg_hd.gif); color: #000; font-size: 100%; padding: 4px 10px; margin: 0 0 7px 0; + border: 1px solid #98AAB1; +} +#ft hr { + display: none; +} +#ft { + background: #98AAB1; background-image: url(bg_hd.gif); color: #000; font-size: 100%; padding: 4px 10px; margin: 7px 0 0 0; border: 1px solid #98AAB1; +} +#doc3 #hd h3 A { color: #FFF; text-decoration: none; } +#doc3 #hd .breadcrumbs { font-size: 85%; margin-bottom:10px;} +#doc3 #hd .subtitle {position: absolute; right:1em; padding: 0px;margin:0px} + +#doc3 dl { margin: 2px 0; } +#doc3 dd { margin-left: 20px; } +#doc3 .requires dt { font-style: italic; } +#doc3 .default { margin-top:6px; } +#doc3 .detail .deprecated { margin-top:4px; padding:4px; background-color: #EFECCA } +#doc3 .detail .deprecated strong { color:#441054; } +#doc3 code, pre {font-size:85%} + +#doc3 #hd h1 { + border: 1px solid #98AAB1; + background-color: #fff; + margin-bottom: .5em; + +} +#bd { + border: 1px solid #98AAB1; + background-color: #fff; +} + +.submodules dd { + font-size: 93%; + font-weight: italic; +} + + +#doc3 .classopts { font-size: 85%; float:right; margin:2px; padding: 2px; background-color:#ECF0F6;border: 1px solid #98AAB1;} +#yui-classopts-form fieldset legend { display: none; } + +/* undo reset.css styles for description block formatting */ +#doc3 .description ul { padding: 10px 0 10px 28px; font-size: 90%; list-style: disc} +#doc3 .description li { list-style: disc} +#doc3 .description p { padding-bottom: 10px} +#doc3 .description strong { font-weight: bold;} +#doc3 .description em {padding: 2px; background-color: #EFECCA} +#doc3 pre { padding: 10px;} + +#doc3 .summary { margin: 0px 10px 10px 0; padding:10px; background-color:#ECF0F6; border:1px solid #98AAB1; } +#doc3 .extends {font-weight: normal; font-size: 90%} + +#doc3 .nav {min-height: 400px;} +#doc3 .nav .module { + width:100%; + border-right: 1px solid #98AAB1; + border-bottom: 1px solid #98AAB1; + padding: 0; overflow:hidden; +} +#doc3 .nav .module h4 { + padding: 3px 5px; + border-bottom: 1px solid #98AAB1; + background-image: url(bg_hd.gif); +} +#doc3 .nav .module h4 A { color: #000; text-decoration: none; } +#doc3 .nav .module .content { padding: 2px; } +#doc3 .nav .module UL.content LI { font-size: 90%; } +#doc3 .nav .module UL.content A { text-decoration: none; color: black; display: block; padding: 2px 4px 2px 4px; } +#doc3 .nav .module LI, +#doc3 .nav .module LI A { + zoom: 1; +} +#doc3 .nav .module LI.selected A, +#doc3 .nav .module LI A:hover { + background-color: #ECF0F6; + zoom: 1; +} + +#doc3 .section { margin: 0 7px 7px 0; } +#doc3 .section strong { font-weight: bold;} +#doc3 .section hr { border: none 0; border-top: 1px solid #ccc; } +#doc3 .section h4 { font-size:110%;} +#doc3 .section h3 { background: #98AAB1; background-image: url(bg_hd.gif); width: 98%; color: #000; padding: 3px; margin: 0 0 7px 0; + border: 1px solid #98AAB1; + +} +#doc3 .section h3 .top { font-size: 60%; font-weight: normal; width: 100%; font-family: verdana; padding-left: 20px; } +#doc3 .section h3 .top A { color: #000; text-decoration: none; } + +#doc3 .section.details .content { padding: 0 0 0 10px; } +#doc3 .section.details .description { padding: 10px 0 0 20px; } +#doc3 .section.details .description dt { font-weight: bold; } +#doc3 .section.details .description td { border:1px solid #ccc; margin:2px;padding:2px;} + +#doc3 .members { padding:10px; border:1px solid #98AAB1; } +#doc3 .members h4 { font-size: 100%;} + +#doc3 .inheritance { padding:10px; background-color:#ECF0F6; border:1px solid #98AAB1; } +#doc3 .inheritance h4 { font-size: 100%;} + +/* index page autocomplete */ +/* +#propertysearch {;position:absolute;margin:1em;width:35em;} +#searchinput {position:absolute;width:100%;height:1.4em;} +#searchresults {position:absolute;top:1.7em;width:100%;} +#searchresults .yui-ac-content {position:absolute;top:4px; left:0px; width:100%;height:20em;border:1px solid #aaa;background:#fff;overflow:auto;overflow-x:hidden;z-index:9050;} +#searchresults .yui-ac-shadow {position:absolute;margin:.3em;width:100%;background:#a0a0a0;z-index:9049;}: +#searchresults ul {padding:5px 0;width:100%;} +#searchresults li {padding:0 5px;cursor:default;white-space:nowrap;} +#searchresults li.yui-ac-highlight {background:#D1C6DA;} +#searchresults li em { position:absolute; width:44%; overflow:hidden; color:#654D6C;} +#searchresults li span { position:relative; left:46% } +*/ + +#propertysearch { + width: 25em; + position: absolute; + right: 5px; + bottom: -4px; +} +#searchinput { + width: 83%; + height: 1.4em; +} +#searchresults { + position: absolute; + right: 25em; + top: 25px; + height: 0; +} +#searchresults .yui-ac-content { + position: absolute; + top: 0; + left: 0; + width: 25em; + height: 20em; + border: 1px solid #98AAB1; + background: #fff; + overflow: auto; + overflow-x: hidden; + z-index: 9050; +} +#searchresults li.yui-ac-highlight { + background-color: #ECF0F6; +} +#searchresults li em { + width:44%; + overflow: hidden; + color: #98AAB1; +} + + +.filter.deprecated, +.filter.protected, +.filter.missing, +.filter.extra, +.filter.extra, +.filter.mismatch { + /*display: inherit;*/ + display: none; +} + +body.show_deprecated .filter.deprecated, +body.show_protected .filter.protected, +body.show_missing .filter.missing, +body.show_extra .filter.extra, +body.show_mismatch .filter.mismatch { + display: inherit; +} + + +#splash_classList ul { + margin: 1em; + margin-left:2em; +} +#splash_classList ul li { + list-style: disc outside; +} + + +/* source code view */ +#srcout {min-width: 580px; } +*html #srcout { width: 100%; padding-bottom:1em; overflow-x:auto } + +.highlight .c { color: #60a0b0; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #808080 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +#.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #007020; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #40a070 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .mf { color: #40a070 } /* Literal.Number.Float */ +.highlight .mh { color: #40a070 } /* Literal.Number.Hex */ +.highlight .mi { color: #40a070 } /* Literal.Number.Integer */ +.highlight .mo { color: #40a070 } /* Literal.Number.Oct */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */ + +/* additions */ + +#glossary dt { + font-weight:bold; +} + +#glossary dt, dd { + line-height:1.8em; +} + +a:link.nsfdoc-gloss, +a:visited.nsfdoc-gloss, +a:hover.nsfdoc-gloss, +a:active.nsfdoc-gloss { + color: #000000; /* should be the same color as text */ + text-decoration: none; + border-bottom-width: 1px; + border-bottom-style: dotted; + border-bottom-color: #000000; /* for IE 5, same color as above */ + font-style: normal; /* for use with dfn */ +} + +a:link.nsfdoc-link, +a:visited.nsfdoc-link, +a:hover.nsfdoc-link, +a:active.nsfdoc-link { + text-decoration: none; + border-bottom-style: none; + border-bottom-color: #000000; /* for IE 5, same color as above */ + font-family:"Courier New",Courier,mono; + font-style: normal; /* for use with dfn */ +} + +span.status { + display:none; + padding: 0 5px 0 5px; + background:url(status.png) no-repeat scroll 0 0; +} + +span.missing { + display:inline; + background-position: -12px 0; +} + +span.extra { + display:inline; + background-position: 2px 0; +} + +span.mismatch { + display:inline; + background-position: -24px 0; +} + +code span.var { + font-style: italic; +} \ No newline at end of file Index: library/lib/nxdoc-assets/yuidoc/api.js =================================================================== diff -u --- library/lib/nxdoc-assets/yuidoc/api.js (revision 0) +++ library/lib/nxdoc-assets/yuidoc/api.js (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,42 @@ +/* +Copyright (c) 2008, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.6.0 +*/ +if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C0)?A.dump(D[F],I-1):L);}else{K.push(D[F]);}K.push(J);}if(K.length>1){K.pop();}K.push("]");}else{K.push("{");for(F in D){if(A.hasOwnProperty(D,F)){K.push(F+G);if(A.isObject(D[F])){K.push((I>0)?A.dump(D[F],I-1):L);}else{K.push(D[F]);}K.push(J);}}if(K.length>1){K.pop();}K.push("}");}return K.join("");},substitute:function(S,E,L){var I,H,G,O,P,R,N=[],F,J="dump",M=" ",D="{",Q="}";for(;;){I=S.lastIndexOf(D);if(I<0){break;}H=S.indexOf(Q,I);if(I+1>=H){break;}F=S.substring(I+1,H);O=F;R=null;G=O.indexOf(M);if(G>-1){R=O.substring(G+1);O=O.substring(0,G);}P=E[O];if(L){P=L(O,P,R);}if(A.isObject(P)){if(A.isArray(P)){P=A.dump(P,parseInt(R,10));}else{R=R||"";var K=R.indexOf(J);if(K>-1){R=R.substring(4);}if(P.toString===Object.prototype.toString||K>-1){P=A.dump(P,parseInt(R,10));}else{P=P.toString();}}}else{if(!A.isString(P)&&!A.isNumber(P)){P="~-"+N.length+"-~";N[N.length]=F;}}S=S.substring(0,I)+P+S.substring(H+1);}for(I=N.length-1;I>=0;I=I-1){S=S.replace(new RegExp("~-"+I+"-~"),"{"+N[I]+"}","g");}return S;},trim:function(D){try{return D.replace(/^\s+|\s+$/g,"");}catch(E){return D;}},merge:function(){var G={},E=arguments;for(var F=0,D=E.length;F=this.left&&A.right<=this.right&&A.top>=this.top&&A.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(E){var C=Math.max(this.top,E.top);var D=Math.min(this.right,E.right);var A=Math.min(this.bottom,E.bottom);var B=Math.max(this.left,E.left);if(A>=C&&D>=B){return new YAHOO.util.Region(C,D,A,B);}else{return null;}};YAHOO.util.Region.prototype.union=function(E){var C=Math.min(this.top,E.top);var D=Math.max(this.right,E.right);var A=Math.max(this.bottom,E.bottom);var B=Math.min(this.left,E.left);return new YAHOO.util.Region(C,D,A,B);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+"}");};YAHOO.util.Region.getRegion=function(D){var F=YAHOO.util.Dom.getXY(D);var C=F[1];var E=F[0]+D.offsetWidth;var A=F[1]+D.offsetHeight;var B=F[0];return new YAHOO.util.Region(C,E,A,B);};YAHOO.util.Point=function(A,B){if(YAHOO.lang.isArray(A)){B=A[1];A=A[0];}this.x=this.right=this.left=this[0]=A;this.y=this.top=this.bottom=this[1]=B;};YAHOO.util.Point.prototype=new YAHOO.util.Region();YAHOO.register("dom",YAHOO.util.Dom,{version:"2.6.0",build:"1321"});YAHOO.util.CustomEvent=function(D,B,C,A){this.type=D;this.scope=B||window;this.silent=C;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var E="_YUICEOnSubscribe";if(D!==E){this.subscribeEvent=new YAHOO.util.CustomEvent(E,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,A){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,A);}this.subscribers.push(new YAHOO.util.Subscriber(B,C,A));},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B0){B=I[0];}try{G=M.fn.call(L,B,M.obj);}catch(F){this.lastError=F;if(A){throw F;}}}else{try{G=M.fn.call(L,this.type,I,M.obj);}catch(H){this.lastError=H;if(A){throw H;}}}if(false===G){if(!this.silent){}break;}}}return(G!==false);},unsubscribeAll:function(){for(var A=this.subscribers.length-1;A>-1;A--){this._delete(A);}this.subscribers=[];return A;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers.splice(A,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"scope: "+this.scope;}};YAHOO.util.Subscriber=function(B,C,A){this.fn=B;this.obj=YAHOO.lang.isUndefined(C)?null:C;this.override=A;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.override){if(this.override===true){return this.obj;}else{return this.override;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", override: "+(this.override||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var H=false;var I=[];var J=[];var G=[];var E=[];var C=0;var F=[];var B=[];var A=0;var D={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9};var K=YAHOO.env.ua.ie?"focusin":"focus";var L=YAHOO.env.ua.ie?"focusout":"blur";return{POLL_RETRYS:2000,POLL_INTERVAL:20,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:YAHOO.env.ua.ie,_interval:null,_dri:null,DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){var M=this;var N=function(){M._tryPreloadAttach();};this._interval=setInterval(N,this.POLL_INTERVAL);}},onAvailable:function(R,O,S,Q,P){var M=(YAHOO.lang.isString(R))?[R]:R;for(var N=0;N-1;Q--){W=(this._removeListener(N[Q],M,V,Y)&&W);}return W;}}if(!V||!V.call){return this.purgeElement(N,false,M);}if("unload"==M){for(Q=J.length-1;Q>-1;Q--){X=J[Q];if(X&&X[0]==N&&X[1]==M&&X[2]==V){J.splice(Q,1);return true;}}return false;}var R=null;var S=arguments[4];if("undefined"===typeof S){S=this._getCacheIndex(N,M,V);}if(S>=0){R=I[S];}if(!N||!R){return false;}if(this.useLegacyEvent(N,M)){var P=this.getLegacyIndex(N,M);var O=E[P];if(O){for(Q=0,T=O.length;Q0&&F.length>0);}var R=[];var T=function(V,W){var U=V;if(W.override){if(W.override===true){U=W.obj;}else{U=W.override;}}W.fn.call(U,W.obj);};var N,M,Q,P,O=[];for(N=0,M=F.length;N-1;N--){Q=F[N];if(!Q||!Q.id){F.splice(N,1);}}this.startInterval();}else{clearInterval(this._interval);this._interval=null;}this.locked=false;},purgeElement:function(Q,R,T){var O=(YAHOO.lang.isString(Q))?this.getEl(Q):Q;var S=this.getListeners(O,T),P,M;if(S){for(P=S.length-1;P>-1;P--){var N=S[P];this._removeListener(O,N.type,N.fn,N.capture);}}if(R&&O&&O.childNodes){for(P=0,M=O.childNodes.length;P-1;O--){N=I[O];if(N){M._removeListener(N[M.EL],N[M.TYPE],N[M.FN],N[M.CAPTURE],O);}}N=null;}G=null;M._simpleRemove(window,"unload",M._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var M=document.documentElement,N=document.body;if(M&&(M.scrollTop||M.scrollLeft)){return[M.scrollTop,M.scrollLeft];}else{if(N){return[N.scrollTop,N.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(O,P,N,M){O.addEventListener(P,N,(M));};}else{if(window.attachEvent){return function(O,P,N,M){O.attachEvent("on"+P,N);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(O,P,N,M){O.removeEventListener(P,N,(M));};}else{if(window.detachEvent){return function(N,O,M){N.detachEvent("on"+O,M);};}else{return function(){};}}}()};}();(function(){var EU=YAHOO.util.Event;EU.on=EU.addListener;EU.onFocus=EU.addFocusListener;EU.onBlur=EU.addBlurListener; +/* DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller */ +if(EU.isIE){YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var n=document.createElement("p");EU._dri=setInterval(function(){try{n.doScroll("left");clearInterval(EU._dri);EU._dri=null;EU._ready();n=null;}catch(ex){}},EU.POLL_INTERVAL);}else{if(EU.webkit&&EU.webkit<525){EU._dri=setInterval(function(){var rs=document.readyState;if("loaded"==rs||"complete"==rs){clearInterval(EU._dri);EU._dri=null;EU._ready();}},EU.POLL_INTERVAL);}else{EU._simpleAdd(document,"DOMContentLoaded",EU._ready);}}EU._simpleAdd(window,"load",EU._load);EU._simpleAdd(window,"unload",EU._unload);EU._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{}; +var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,override:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);},createEvent:function(G,D){this.__yui_events=this.__yui_events||{};var A=D||{};var I=this.__yui_events;if(I[G]){}else{var H=A.scope||this;var E=(A.silent);var B=new YAHOO.util.CustomEvent(G,H,E,YAHOO.util.CustomEvent.FLAT);I[G]=B;if(A.onSubscribeCallback){B.subscribeEvent.subscribe(A.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var F=this.__yui_subscribers[G];if(F){for(var C=0;C0){if(!aCache){this._aCache=[];}else{var nCacheLength=aCache.length;if(nCacheLength>0){var oResponse=null;this.fireEvent("cacheRequestEvent",{request:oRequest,callback:oCallback,caller:oCaller});for(var i=nCacheLength-1;i>=0;i--){var oCacheElem=aCache[i];if(this.isCacheHit(oRequest,oCacheElem.request)){oResponse=oCacheElem.response;this.fireEvent("cacheResponseEvent",{request:oRequest,response:oResponse,callback:oCallback,caller:oCaller});if(i=this.maxCacheEntries){aCache.shift();}var oCacheElem={request:oRequest,response:oResponse};aCache[aCache.length]=oCacheElem;this.fireEvent("responseCacheEvent",{request:oRequest,response:oResponse});},flushCache:function(){if(this._aCache){this._aCache=[];this.fireEvent("cacheFlushEvent");}},setInterval:function(nMsec,oRequest,oCallback,oCaller){if(lang.isNumber(nMsec)&&(nMsec>=0)){var oSelf=this;var nId=setInterval(function(){oSelf.makeConnection(oRequest,oCallback,oCaller);},nMsec);this._aIntervals.push(nId);return nId;}else{}},clearInterval:function(nId){var tracker=this._aIntervals||[];for(var i=tracker.length-1;i>-1;i--){if(tracker[i]===nId){tracker.splice(i,1);clearInterval(nId);}}},clearAllIntervals:function(){var tracker=this._aIntervals||[];for(var i=tracker.length-1;i>-1;i--){clearInterval(tracker[i]);}tracker=[];},sendRequest:function(oRequest,oCallback,oCaller){var oCachedResponse=this.getCachedResponse(oRequest,oCallback,oCaller);if(oCachedResponse){DS.issueCallback(oCallback,[oRequest,oCachedResponse],false,oCaller);return null;}return this.makeConnection(oRequest,oCallback,oCaller);},makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oRawResponse=this.liveData;this.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);return tId;},handleResponse:function(oRequest,oRawResponse,oCallback,oCaller,tId){this.fireEvent("responseEvent",{tId:tId,request:oRequest,response:oRawResponse,callback:oCallback,caller:oCaller});var xhr=(this.dataType==DS.TYPE_XHR)?true:false;var oParsedResponse=null;var oFullResponse=oRawResponse;if(this.responseType===DS.TYPE_UNKNOWN){var ctype=(oRawResponse&&oRawResponse.getResponseHeader)?oRawResponse.getResponseHeader["Content-Type"]:null;if(ctype){if(ctype.indexOf("text/xml")>-1){this.responseType=DS.TYPE_XML;}else{if(ctype.indexOf("application/json")>-1){this.responseType=DS.TYPE_JSON;}else{if(ctype.indexOf("text/plain")>-1){this.responseType=DS.TYPE_TEXT;}}}}else{if(YAHOO.lang.isArray(oRawResponse)){this.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse&&oRawResponse.nodeType&&oRawResponse.nodeType==9){this.responseType=DS.TYPE_XML;}else{if(oRawResponse&&oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){this.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){this.responseType=DS.TYPE_TEXT;}}}}}}}switch(this.responseType){case DS.TYPE_JSARRAY:if(xhr&&oRawResponse&&oRawResponse.responseText){oFullResponse=oRawResponse.responseText;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseArrayData(oRequest,oFullResponse); +break;case DS.TYPE_JSON:if(xhr&&oRawResponse&&oRawResponse.responseText){oFullResponse=oRawResponse.responseText;}try{if(lang.isString(oFullResponse)){if(lang.JSON){oFullResponse=lang.JSON.parse(oFullResponse);}else{if(window.JSON&&JSON.parse){oFullResponse=JSON.parse(oFullResponse);}else{if(oFullResponse.parseJSON){oFullResponse=oFullResponse.parseJSON();}else{while(oFullResponse.length>0&&(oFullResponse.charAt(0)!="{")&&(oFullResponse.charAt(0)!="[")){oFullResponse=oFullResponse.substring(1,oFullResponse.length);}if(oFullResponse.length>0){var objEnd=Math.max(oFullResponse.lastIndexOf("]"),oFullResponse.lastIndexOf("}"));oFullResponse=oFullResponse.substring(0,objEnd+1);oFullResponse=eval("("+oFullResponse+")");}}}}}}catch(e){}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseJSONData(oRequest,oFullResponse);break;case DS.TYPE_HTMLTABLE:if(xhr&&oRawResponse.responseText){oFullResponse=oRawResponse.responseText;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseHTMLTableData(oRequest,oFullResponse);break;case DS.TYPE_XML:if(xhr&&oRawResponse.responseXML){oFullResponse=oRawResponse.responseXML;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseXMLData(oRequest,oFullResponse);break;case DS.TYPE_TEXT:if(xhr&&lang.isString(oRawResponse.responseText)){oFullResponse=oRawResponse.responseText;}oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseTextData(oRequest,oFullResponse);break;default:oFullResponse=this.doBeforeParseData(oRequest,oFullResponse,oCallback);oParsedResponse=this.parseData(oRequest,oFullResponse);break;}oParsedResponse=oParsedResponse||{};if(!oParsedResponse.results){oParsedResponse.results=[];}if(!oParsedResponse.meta){oParsedResponse.meta={};}if(oParsedResponse&&!oParsedResponse.error){oParsedResponse=this.doBeforeCallback(oRequest,oFullResponse,oParsedResponse,oCallback);this.fireEvent("responseParseEvent",{request:oRequest,response:oParsedResponse,callback:oCallback,caller:oCaller});this.addToCache(oRequest,oParsedResponse);}else{oParsedResponse.error=true;this.fireEvent("dataErrorEvent",{request:oRequest,response:oRawResponse,callback:oCallback,caller:oCaller,message:DS.ERROR_DATANULL});}oParsedResponse.tId=tId;DS.issueCallback(oCallback,[oRequest,oParsedResponse],oParsedResponse.error,oCaller);},doBeforeParseData:function(oRequest,oFullResponse,oCallback){return oFullResponse;},doBeforeCallback:function(oRequest,oFullResponse,oParsedResponse,oCallback){return oParsedResponse;},parseData:function(oRequest,oFullResponse){if(lang.isValue(oFullResponse)){var oParsedResponse={results:oFullResponse,meta:{}};return oParsedResponse;}return null;},parseArrayData:function(oRequest,oFullResponse){if(lang.isArray(oFullResponse)){var results=[],i,j,rec,field,data;if(lang.isArray(this.responseSchema.fields)){var fields=this.responseSchema.fields;for(i=fields.length-1;i>=0;--i){if(typeof fields[i]!=="object"){fields[i]={key:fields[i]};}}var parsers={},p;for(i=fields.length-1;i>=0;--i){p=(typeof fields[i].parser==="function"?fields[i].parser:DS.Parser[fields[i].parser+""])||fields[i].converter;if(p){parsers[fields[i].key]=p;}}var arrType=lang.isArray(oFullResponse[0]);for(i=oFullResponse.length-1;i>-1;i--){var oResult={};rec=oFullResponse[i];if(typeof rec==="object"){for(j=fields.length-1;j>-1;j--){field=fields[j];data=arrType?rec[j]:rec[field.key];if(parsers[field.key]){data=parsers[field.key].call(this,data);}if(data===undefined){data=null;}oResult[field.key]=data;}}else{if(lang.isString(rec)){for(j=fields.length-1;j>-1;j--){field=fields[j];data=rec;if(parsers[field.key]){data=parsers[field.key].call(this,data);}if(data===undefined){data=null;}oResult[field.key]=data;}}}results[i]=oResult;}}else{results=oFullResponse;}var oParsedResponse={results:results};return oParsedResponse;}return null;},parseTextData:function(oRequest,oFullResponse){if(lang.isString(oFullResponse)){if(lang.isString(this.responseSchema.recordDelim)&&lang.isString(this.responseSchema.fieldDelim)){var oParsedResponse={results:[]};var recDelim=this.responseSchema.recordDelim;var fieldDelim=this.responseSchema.fieldDelim;if(oFullResponse.length>0){var newLength=oFullResponse.length-recDelim.length;if(oFullResponse.substr(newLength)==recDelim){oFullResponse=oFullResponse.substr(0,newLength);}if(oFullResponse.length>0){var recordsarray=oFullResponse.split(recDelim);for(var i=0,len=recordsarray.length,recIdx=0;i0)){var fielddataarray=recordsarray[i].split(fieldDelim);var oResult={};if(lang.isArray(this.responseSchema.fields)){var fields=this.responseSchema.fields;for(var j=fields.length-1;j>-1;j--){try{var data=fielddataarray[j];if(lang.isString(data)){if(data.charAt(0)=='"'){data=data.substr(1);}if(data.charAt(data.length-1)=='"'){data=data.substr(0,data.length-1);}var field=fields[j];var key=(lang.isValue(field.key))?field.key:field;if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}else{bError=true;}}catch(e){bError=true;}}}else{oResult=fielddataarray;}if(!bError){oParsedResponse.results[recIdx++]=oResult;}}}}}return oParsedResponse;}}return null;},parseXMLResult:function(result){var oResult={},schema=this.responseSchema;try{for(var m=schema.fields.length-1;m>=0;m--){var field=schema.fields[m];var key=(lang.isValue(field.key))?field.key:field;var data=null;var xmlAttr=result.attributes.getNamedItem(key);if(xmlAttr){data=xmlAttr.value;}else{var xmlNode=result.getElementsByTagName(key);if(xmlNode&&xmlNode.item(0)&&xmlNode.item(0)){data=xmlNode.item(0).firstChild.nodeValue;var item=xmlNode.item(0);data=(item.text)?item.text:(item.textContent)?item.textContent:null; +if(!data){var datapieces=[];for(var j=0,len=item.childNodes.length;j0){data=datapieces.join("");}}}}if(data===null){data="";}if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}}catch(e){}return oResult;},parseXMLData:function(oRequest,oFullResponse){var bError=false,schema=this.responseSchema,oParsedResponse={meta:{}},xmlList=null,metaNode=schema.metaNode,metaLocators=schema.metaFields||{},i,k,loc,v;try{xmlList=(schema.resultNode)?oFullResponse.getElementsByTagName(schema.resultNode):null;metaNode=metaNode?oFullResponse.getElementsByTagName(metaNode)[0]:oFullResponse;if(metaNode){for(k in metaLocators){if(lang.hasOwnProperty(metaLocators,k)){loc=metaLocators[k];v=metaNode.getElementsByTagName(loc)[0];if(v){v=v.firstChild.nodeValue;}else{v=metaNode.attributes.getNamedItem(loc);if(v){v=v.value;}}if(lang.isValue(v)){oParsedResponse.meta[k]=v;}}}}}catch(e){}if(!xmlList||!lang.isArray(schema.fields)){bError=true;}else{oParsedResponse.results=[];for(i=xmlList.length-1;i>=0;--i){var oResult=this.parseXMLResult(xmlList.item(i));oParsedResponse.results[i]=oResult;}}if(bError){oParsedResponse.error=true;}else{}return oParsedResponse;},parseJSONData:function(oRequest,oFullResponse){var oParsedResponse={results:[],meta:{}};if(lang.isObject(oFullResponse)&&this.responseSchema.resultsList){var schema=this.responseSchema,fields=schema.fields,resultsList=oFullResponse,results=[],metaFields=schema.metaFields||{},fieldParsers=[],fieldPaths=[],simpleFields=[],bError=false,i,len,j,v,key,parser,path;var buildPath=function(needle){var path=null,keys=[],i=0;if(needle){needle=needle.replace(/\[(['"])(.*?)\1\]/g,function(x,$1,$2){keys[i]=$2;return".@"+(i++);}).replace(/\[(\d+)\]/g,function(x,$1){keys[i]=parseInt($1,10)|0;return".@"+(i++);}).replace(/^\./,"");if(!/[^\w\.\$@]/.test(needle)){path=needle.split(".");for(i=path.length-1;i>=0;--i){if(path[i].charAt(0)==="@"){path[i]=keys[parseInt(path[i].substr(1),10)];}}}else{}}return path;};var walkPath=function(path,origin){var v=origin,i=0,len=path.length;for(;i1){fieldPaths[fieldPaths.length]={key:key,path:path};}else{simpleFields[simpleFields.length]={key:key,path:path[0]};}}else{}}for(i=resultsList.length-1;i>=0;--i){var r=resultsList[i],rec={};for(j=simpleFields.length-1;j>=0;--j){rec[simpleFields[j].key]=(r[simpleFields[j].path]!==undefined)?r[simpleFields[j].path]:r[j];}for(j=fieldPaths.length-1;j>=0;--j){rec[fieldPaths[j].key]=walkPath(fieldPaths[j].path,r);}for(j=fieldParsers.length-1;j>=0;--j){var p=fieldParsers[j].key;rec[p]=fieldParsers[j].parser(rec[p]);if(rec[p]===undefined){rec[p]=null;}}results[i]=rec;}}else{results=resultsList;}for(key in metaFields){if(lang.hasOwnProperty(metaFields,key)){path=buildPath(metaFields[key]);if(path){v=walkPath(path,oFullResponse);oParsedResponse.meta[key]=v;}}}}else{oParsedResponse.error=true;}oParsedResponse.results=results;}else{oParsedResponse.error=true;}return oParsedResponse;},parseHTMLTableData:function(oRequest,oFullResponse){var bError=false;var elTable=oFullResponse;var fields=this.responseSchema.fields;var oParsedResponse={results:[]};for(var i=0;i-1;j--){var elRow=elTbody.rows[j];var oResult={};for(var k=fields.length-1;k>-1;k--){var field=fields[k];var key=(lang.isValue(field.key))?field.key:field;var data=elRow.cells[k].innerHTML;if(!field.parser&&field.converter){field.parser=field.converter;}var parser=(typeof field.parser==="function")?field.parser:DS.Parser[field.parser+""];if(parser){data=parser.call(this,data);}if(data===undefined){data=null;}oResult[key]=data;}oParsedResponse.results[j]=oResult;}}if(bError){oParsedResponse.error=true;}else{}return oParsedResponse;}};lang.augmentProto(DS,util.EventProvider);util.LocalDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_LOCAL;if(oLiveData){if(YAHOO.lang.isArray(oLiveData)){this.responseType=DS.TYPE_JSARRAY;}else{if(oLiveData.nodeType&&oLiveData.nodeType==9){this.responseType=DS.TYPE_XML;}else{if(oLiveData.nodeName&&(oLiveData.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;oLiveData=oLiveData.cloneNode(true);}else{if(YAHOO.lang.isString(oLiveData)){this.responseType=DS.TYPE_TEXT;}else{if(YAHOO.lang.isObject(oLiveData)){this.responseType=DS.TYPE_JSON;}}}}}}else{oLiveData=[];this.responseType=DS.TYPE_JSARRAY;}this.constructor.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.LocalDataSource,DS);lang.augmentObject(util.LocalDataSource,DS);util.FunctionDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_JSFUNCTION;oLiveData=oLiveData||function(){};this.constructor.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.FunctionDataSource,DS,{makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oRawResponse=this.liveData(oRequest);if(this.responseType===DS.TYPE_UNKNOWN){if(YAHOO.lang.isArray(oRawResponse)){this.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse&&oRawResponse.nodeType&&oRawResponse.nodeType==9){this.responseType=DS.TYPE_XML; +}else{if(oRawResponse&&oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){this.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){this.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){this.responseType=DS.TYPE_TEXT;}}}}}}this.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);return tId;}});lang.augmentObject(util.FunctionDataSource,DS);util.ScriptNodeDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_SCRIPTNODE;oLiveData=oLiveData||"";this.constructor.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.ScriptNodeDataSource,DS,{getUtility:util.Get,asyncMode:"allowAll",scriptCallbackParam:"callback",generateRequestCallback:function(id){return"&"+this.scriptCallbackParam+"=YAHOO.util.ScriptNodeDataSource.callbacks["+id+"]";},makeConnection:function(oRequest,oCallback,oCaller){var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});if(util.ScriptNodeDataSource._nPending===0){util.ScriptNodeDataSource.callbacks=[];util.ScriptNodeDataSource._nId=0;}var id=util.ScriptNodeDataSource._nId;util.ScriptNodeDataSource._nId++;var oSelf=this;util.ScriptNodeDataSource.callbacks[id]=function(oRawResponse){if((oSelf.asyncMode!=="ignoreStaleResponses")||(id===util.ScriptNodeDataSource.callbacks.length-1)){if(oSelf.responseType===DS.TYPE_UNKNOWN){if(YAHOO.lang.isArray(oRawResponse)){oSelf.responseType=DS.TYPE_JSARRAY;}else{if(oRawResponse.nodeType&&oRawResponse.nodeType==9){oSelf.responseType=DS.TYPE_XML;}else{if(oRawResponse.nodeName&&(oRawResponse.nodeName.toLowerCase()=="table")){oSelf.responseType=DS.TYPE_HTMLTABLE;}else{if(YAHOO.lang.isObject(oRawResponse)){oSelf.responseType=DS.TYPE_JSON;}else{if(YAHOO.lang.isString(oRawResponse)){oSelf.responseType=DS.TYPE_TEXT;}}}}}}oSelf.handleResponse(oRequest,oRawResponse,oCallback,oCaller,tId);}else{}delete util.ScriptNodeDataSource.callbacks[id];};util.ScriptNodeDataSource._nPending++;var sUri=this.liveData+oRequest+this.generateRequestCallback(id);this.getUtility.script(sUri,{autopurge:true,onsuccess:util.ScriptNodeDataSource._bumpPendingDown,onfail:util.ScriptNodeDataSource._bumpPendingDown});return tId;}});lang.augmentObject(util.ScriptNodeDataSource,DS);lang.augmentObject(util.ScriptNodeDataSource,{_nId:0,_nPending:0,callbacks:[]});util.XHRDataSource=function(oLiveData,oConfigs){this.dataType=DS.TYPE_XHR;this.connMgr=this.connMgr||util.Connect;oLiveData=oLiveData||"";this.constructor.superclass.constructor.call(this,oLiveData,oConfigs);};lang.extend(util.XHRDataSource,DS,{connMgr:null,connXhrMode:"allowAll",connMethodPost:false,connTimeout:0,makeConnection:function(oRequest,oCallback,oCaller){var oRawResponse=null;var tId=DS._nTransactionId++;this.fireEvent("requestEvent",{tId:tId,request:oRequest,callback:oCallback,caller:oCaller});var oSelf=this;var oConnMgr=this.connMgr;var oQueue=this._oQueue;var _xhrSuccess=function(oResponse){if(oResponse&&(this.asyncMode=="ignoreStaleResponses")&&(oResponse.tId!=oQueue.conn.tId)){return null;}else{if(!oResponse){this.fireEvent("dataErrorEvent",{request:oRequest,callback:oCallback,caller:oCaller,message:DS.ERROR_DATANULL});DS.issueCallback(oCallback,[oRequest,{error:true}],true,oCaller);return null;}else{if(this.responseType===DS.TYPE_UNKNOWN){var ctype=(oResponse.getResponseHeader)?oResponse.getResponseHeader["Content-Type"]:null;if(ctype){if(ctype.indexOf("text/xml")>-1){this.responseType=DS.TYPE_XML;}else{if(ctype.indexOf("application/json")>-1){this.responseType=DS.TYPE_JSON;}else{if(ctype.indexOf("text/plain")>-1){this.responseType=DS.TYPE_TEXT;}}}}}this.handleResponse(oRequest,oResponse,oCallback,oCaller,tId);}}};var _xhrFailure=function(oResponse){this.fireEvent("dataErrorEvent",{request:oRequest,callback:oCallback,caller:oCaller,message:DS.ERROR_DATAINVALID});if(lang.isString(this.liveData)&&lang.isString(oRequest)&&(this.liveData.lastIndexOf("?")!==this.liveData.length-1)&&(oRequest.indexOf("?")!==0)){}oResponse=oResponse||{};oResponse.error=true;DS.issueCallback(oCallback,[oRequest,oResponse],true,oCaller);return null;};var _xhrCallback={success:_xhrSuccess,failure:_xhrFailure,scope:this};if(lang.isNumber(this.connTimeout)){_xhrCallback.timeout=this.connTimeout;}if(this.connXhrMode=="cancelStaleRequests"){if(oQueue.conn){if(oConnMgr.abort){oConnMgr.abort(oQueue.conn);oQueue.conn=null;}else{}}}if(oConnMgr&&oConnMgr.asyncRequest){var sLiveData=this.liveData;var isPost=this.connMethodPost;var sMethod=(isPost)?"POST":"GET";var sUri=(isPost||!lang.isValue(oRequest))?sLiveData:sLiveData+oRequest;var sRequest=(isPost)?oRequest:null;if(this.connXhrMode!="queueRequests"){oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,_xhrCallback,sRequest);}else{if(oQueue.conn){var allRequests=oQueue.requests;allRequests.push({request:oRequest,callback:_xhrCallback});if(!oQueue.interval){oQueue.interval=setInterval(function(){if(oConnMgr.isCallInProgress(oQueue.conn)){return ;}else{if(allRequests.length>0){sUri=(isPost||!lang.isValue(allRequests[0].request))?sLiveData:sLiveData+allRequests[0].request;sRequest=(isPost)?allRequests[0].request:null;oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,allRequests[0].callback,sRequest);allRequests.shift();}else{clearInterval(oQueue.interval);oQueue.interval=null;}}},50);}}else{oQueue.conn=oConnMgr.asyncRequest(sMethod,sUri,_xhrCallback,sRequest);}}}else{DS.issueCallback(oCallback,[oRequest,{error:true}],true,oCaller);}return tId;}});lang.augmentObject(util.XHRDataSource,DS);util.DataSource=function(oLiveData,oConfigs){oConfigs=oConfigs||{};var dataType=oConfigs.dataType;if(dataType){if(dataType==DS.TYPE_LOCAL){lang.augmentObject(util.DataSource,util.LocalDataSource);return new util.LocalDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_XHR){lang.augmentObject(util.DataSource,util.XHRDataSource);return new util.XHRDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_SCRIPTNODE){lang.augmentObject(util.DataSource,util.ScriptNodeDataSource); +return new util.ScriptNodeDataSource(oLiveData,oConfigs);}else{if(dataType==DS.TYPE_JSFUNCTION){lang.augmentObject(util.DataSource,util.FunctionDataSource);return new util.FunctionDataSource(oLiveData,oConfigs);}}}}}if(YAHOO.lang.isString(oLiveData)){lang.augmentObject(util.DataSource,util.XHRDataSource);return new util.XHRDataSource(oLiveData,oConfigs);}else{if(YAHOO.lang.isFunction(oLiveData)){lang.augmentObject(util.DataSource,util.FunctionDataSource);return new util.FunctionDataSource(oLiveData,oConfigs);}else{lang.augmentObject(util.DataSource,util.LocalDataSource);return new util.LocalDataSource(oLiveData,oConfigs);}}};lang.augmentObject(util.DataSource,DS);})();YAHOO.util.Number={format:function(B,F){F=F||{};if(!YAHOO.lang.isNumber(B)){B*=1;}if(YAHOO.lang.isNumber(B)){var D=(B<0);var J=B+"";var G=(F.decimalSeparator)?F.decimalSeparator:".";var H;if(YAHOO.lang.isNumber(F.decimalPlaces)){var I=F.decimalPlaces;var C=Math.pow(10,I);J=Math.round(B*C)/C+"";H=J.lastIndexOf(".");if(I>0){if(H<0){J+=G;H=J.length-1;}else{if(G!=="."){J=J.replace(".",G);}}while((J.length-1-H)-1)?H:J.length;var K=J.substring(H);var A=-1;for(var E=H;E>0;E--){A++;if((A%3===0)&&(E!==H)&&(!D||(E>1))){K=L+K;}K=J.charAt(E-1)+K;}J=K;}J=(F.prefix)?F.prefix+J:J;J=(F.suffix)?J+F.suffix:J;return J;}else{return B;}}};(function(){var A=function(C,E,D){if(typeof D==="undefined"){D=10;}for(;parseInt(C,10)1;D/=10){C=E.toString()+C;}return C.toString();};var B={formats:{a:function(D,C){return C.a[D.getDay()];},A:function(D,C){return C.A[D.getDay()];},b:function(D,C){return C.b[D.getMonth()];},B:function(D,C){return C.B[D.getMonth()];},C:function(C){return A(parseInt(C.getFullYear()/100,10),0);},d:["getDate","0"],e:["getDate"," "],g:function(C){return A(parseInt(B.formats.G(C)%100,10),0);},G:function(E){var F=E.getFullYear();var D=parseInt(B.formats.V(E),10);var C=parseInt(B.formats.W(E),10);if(C>D){F++;}else{if(C===0&&D>=52){F--;}}return F;},H:["getHours","0"],I:function(D){var C=D.getHours()%12;return A(C===0?12:C,0);},j:function(G){var F=new Date(""+G.getFullYear()+"/1/1 GMT");var D=new Date(""+G.getFullYear()+"/"+(G.getMonth()+1)+"/"+G.getDate()+" GMT");var C=D-F;var E=parseInt(C/60000/60/24,10)+1;return A(E,0,100);},k:["getHours"," "],l:function(D){var C=D.getHours()%12;return A(C===0?12:C," ");},m:function(C){return A(C.getMonth()+1,0);},M:["getMinutes","0"],p:function(D,C){return C.p[D.getHours()>=12?1:0];},P:function(D,C){return C.P[D.getHours()>=12?1:0];},s:function(D,C){return parseInt(D.getTime()/1000,10);},S:["getSeconds","0"],u:function(C){var D=C.getDay();return D===0?7:D;},U:function(F){var C=parseInt(B.formats.j(F),10);var E=6-F.getDay();var D=parseInt((C+E)/7,10);return A(D,0);},V:function(F){var E=parseInt(B.formats.W(F),10);var C=(new Date(""+F.getFullYear()+"/1/1")).getDay();var D=E+(C>4||C<=1?0:1);if(D===53&&(new Date(""+F.getFullYear()+"/12/31")).getDay()<4){D=1;}else{if(D===0){D=B.formats.V(new Date(""+(F.getFullYear()-1)+"/12/31"));}}return A(D,0);},w:"getDay",W:function(F){var C=parseInt(B.formats.j(F),10);var E=7-B.formats.u(F);var D=parseInt((C+E)/7,10);return A(D,0,10);},y:function(C){return A(C.getFullYear()%100,0);},Y:"getFullYear",z:function(E){var D=E.getTimezoneOffset();var C=A(parseInt(Math.abs(D/60),10),0);var F=A(Math.abs(D%60),0);return(D>0?"-":"+")+C+F;},Z:function(C){var D=C.toString().replace(/^.*:\d\d( GMT[+-]\d+)? \(?([A-Za-z ]+)\)?\d*$/,"$2").replace(/[a-z ]/g,"");if(D.length>4){D=B.formats.z(C);}return D;},"%":function(C){return"%";}},aggregates:{c:"locale",D:"%m/%d/%y",F:"%Y-%m-%d",h:"%b",n:"\n",r:"locale",R:"%H:%M",t:"\t",T:"%H:%M:%S",x:"locale",X:"locale"},format:function(G,F,D){F=F||{};if(!(G instanceof Date)){return YAHOO.lang.isValue(G)?G:"";}var H=F.format||"%m/%d/%Y";if(H==="YYYY/MM/DD"){H="%Y/%m/%d";}else{if(H==="DD/MM/YYYY"){H="%d/%m/%Y";}else{if(H==="MM/DD/YYYY"){H="%m/%d/%Y";}}}D=D||"en";if(!(D in YAHOO.util.DateLocale)){if(D.replace(/-[a-zA-Z]+$/,"") in YAHOO.util.DateLocale){D=D.replace(/-[a-zA-Z]+$/,"");}else{D="en";}}var J=YAHOO.util.DateLocale[D];var C=function(L,K){var M=B.aggregates[K];return(M==="locale"?J[K]:M);};var E=function(L,K){var M=B.formats[K];if(typeof M==="string"){return G[M]();}else{if(typeof M==="function"){return M.call(G,G,J);}else{if(typeof M==="object"&&typeof M[0]==="string"){return A(G[M[0]](),M[1]);}else{return K;}}}};while(H.match(/%[cDFhnrRtTxX]/)){H=H.replace(/%([cDFhnrRtTxX])/g,C);}var I=H.replace(/%([aAbBCdegGHIjklmMpPsSuUVwWyYzZ%])/g,E);C=E=undefined;return I;}};YAHOO.namespace("YAHOO.util");YAHOO.util.Date=B;YAHOO.util.DateLocale={a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a %d %b %Y %T %Z",p:["AM","PM"],P:["am","pm"],r:"%I:%M:%S %p",x:"%d/%m/%y",X:"%T"};YAHOO.util.DateLocale["en"]=YAHOO.lang.merge(YAHOO.util.DateLocale,{});YAHOO.util.DateLocale["en-US"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"],{c:"%a %d %b %Y %I:%M:%S %p %Z",x:"%m/%d/%Y",X:"%I:%M:%S %p"});YAHOO.util.DateLocale["en-GB"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"],{r:"%l:%M:%S %P %Z"});YAHOO.util.DateLocale["en-AU"]=YAHOO.lang.merge(YAHOO.util.DateLocale["en"]);})();YAHOO.register("datasource",YAHOO.util.DataSource,{version:"2.6.0",build:"1321"});/* +Copyright (c) 2008, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.6.0 +*/ +YAHOO.widget.DS_JSArray=YAHOO.util.LocalDataSource;YAHOO.widget.DS_JSFunction=YAHOO.util.FunctionDataSource;YAHOO.widget.DS_XHR=function(B,A,D){var C=new YAHOO.util.XHRDataSource(B,D);C._aDeprecatedSchema=A;return C;};YAHOO.widget.DS_ScriptNode=function(B,A,D){var C=new YAHOO.util.ScriptNodeDataSource(B,D);C._aDeprecatedSchema=A;return C;};YAHOO.widget.DS_XHR.TYPE_JSON=YAHOO.util.DataSourceBase.TYPE_JSON;YAHOO.widget.DS_XHR.TYPE_XML=YAHOO.util.DataSourceBase.TYPE_XML;YAHOO.widget.DS_XHR.TYPE_FLAT=YAHOO.util.DataSourceBase.TYPE_TEXT;YAHOO.widget.AutoComplete=function(G,B,J,C){if(G&&B&&J){if(J instanceof YAHOO.util.DataSourceBase){this.dataSource=J;}else{return ;}this.key=0;var D=J.responseSchema;if(J._aDeprecatedSchema){var K=J._aDeprecatedSchema;if(YAHOO.lang.isArray(K)){if((J.responseType===YAHOO.util.DataSourceBase.TYPE_JSON)||(J.responseType===YAHOO.util.DataSourceBase.TYPE_UNKNOWN)){D.resultsList=K[0];this.key=K[1];D.fields=(K.length<3)?null:K.slice(1);}else{if(J.responseType===YAHOO.util.DataSourceBase.TYPE_XML){D.resultNode=K[0];this.key=K[1];D.fields=K.slice(1);}else{if(J.responseType===YAHOO.util.DataSourceBase.TYPE_TEXT){D.recordDelim=K[0];D.fieldDelim=K[1];}}}J.responseSchema=D;}}if(YAHOO.util.Dom.inDocument(G)){if(YAHOO.lang.isString(G)){this._sName="instance"+YAHOO.widget.AutoComplete._nIndex+" "+G;this._elTextbox=document.getElementById(G);}else{this._sName=(G.id)?"instance"+YAHOO.widget.AutoComplete._nIndex+" "+G.id:"instance"+YAHOO.widget.AutoComplete._nIndex;this._elTextbox=G;}YAHOO.util.Dom.addClass(this._elTextbox,"yui-ac-input");}else{return ;}if(YAHOO.util.Dom.inDocument(B)){if(YAHOO.lang.isString(B)){this._elContainer=document.getElementById(B);}else{this._elContainer=B;}if(this._elContainer.style.display=="none"){}var E=this._elContainer.parentNode;var A=E.tagName.toLowerCase();if(A=="div"){YAHOO.util.Dom.addClass(E,"yui-ac");}else{}}else{return ;}if(this.dataSource.dataType===YAHOO.util.DataSourceBase.TYPE_LOCAL){this.applyLocalFilter=true;}if(C&&(C.constructor==Object)){for(var I in C){if(I){this[I]=C[I];}}}this._initContainerEl();this._initProps();this._initListEl();this._initContainerHelperEls();var H=this;var F=this._elTextbox;YAHOO.util.Event.addListener(F,"keyup",H._onTextboxKeyUp,H);YAHOO.util.Event.addListener(F,"keydown",H._onTextboxKeyDown,H);YAHOO.util.Event.addListener(F,"focus",H._onTextboxFocus,H);YAHOO.util.Event.addListener(F,"blur",H._onTextboxBlur,H);YAHOO.util.Event.addListener(B,"mouseover",H._onContainerMouseover,H);YAHOO.util.Event.addListener(B,"mouseout",H._onContainerMouseout,H);YAHOO.util.Event.addListener(B,"click",H._onContainerClick,H);YAHOO.util.Event.addListener(B,"scroll",H._onContainerScroll,H);YAHOO.util.Event.addListener(B,"resize",H._onContainerResize,H);YAHOO.util.Event.addListener(F,"keypress",H._onTextboxKeyPress,H);YAHOO.util.Event.addListener(window,"unload",H._onWindowUnload,H);this.textboxFocusEvent=new YAHOO.util.CustomEvent("textboxFocus",this);this.textboxKeyEvent=new YAHOO.util.CustomEvent("textboxKey",this);this.dataRequestEvent=new YAHOO.util.CustomEvent("dataRequest",this);this.dataReturnEvent=new YAHOO.util.CustomEvent("dataReturn",this);this.dataErrorEvent=new YAHOO.util.CustomEvent("dataError",this);this.containerPopulateEvent=new YAHOO.util.CustomEvent("containerPopulate",this);this.containerExpandEvent=new YAHOO.util.CustomEvent("containerExpand",this);this.typeAheadEvent=new YAHOO.util.CustomEvent("typeAhead",this);this.itemMouseOverEvent=new YAHOO.util.CustomEvent("itemMouseOver",this);this.itemMouseOutEvent=new YAHOO.util.CustomEvent("itemMouseOut",this);this.itemArrowToEvent=new YAHOO.util.CustomEvent("itemArrowTo",this);this.itemArrowFromEvent=new YAHOO.util.CustomEvent("itemArrowFrom",this);this.itemSelectEvent=new YAHOO.util.CustomEvent("itemSelect",this);this.unmatchedItemSelectEvent=new YAHOO.util.CustomEvent("unmatchedItemSelect",this);this.selectionEnforceEvent=new YAHOO.util.CustomEvent("selectionEnforce",this);this.containerCollapseEvent=new YAHOO.util.CustomEvent("containerCollapse",this);this.textboxBlurEvent=new YAHOO.util.CustomEvent("textboxBlur",this);this.textboxChangeEvent=new YAHOO.util.CustomEvent("textboxChange",this);F.setAttribute("autocomplete","off");YAHOO.widget.AutoComplete._nIndex++;}else{}};YAHOO.widget.AutoComplete.prototype.dataSource=null;YAHOO.widget.AutoComplete.prototype.applyLocalFilter=null;YAHOO.widget.AutoComplete.prototype.queryMatchCase=false;YAHOO.widget.AutoComplete.prototype.queryMatchContains=false;YAHOO.widget.AutoComplete.prototype.queryMatchSubset=false;YAHOO.widget.AutoComplete.prototype.minQueryLength=1;YAHOO.widget.AutoComplete.prototype.maxResultsDisplayed=10;YAHOO.widget.AutoComplete.prototype.queryDelay=0.2;YAHOO.widget.AutoComplete.prototype.typeAheadDelay=0.5;YAHOO.widget.AutoComplete.prototype.queryInterval=500;YAHOO.widget.AutoComplete.prototype.highlightClassName="yui-ac-highlight";YAHOO.widget.AutoComplete.prototype.prehighlightClassName=null;YAHOO.widget.AutoComplete.prototype.delimChar=null;YAHOO.widget.AutoComplete.prototype.autoHighlight=true;YAHOO.widget.AutoComplete.prototype.typeAhead=false;YAHOO.widget.AutoComplete.prototype.animHoriz=false;YAHOO.widget.AutoComplete.prototype.animVert=true;YAHOO.widget.AutoComplete.prototype.animSpeed=0.3;YAHOO.widget.AutoComplete.prototype.forceSelection=false;YAHOO.widget.AutoComplete.prototype.allowBrowserAutocomplete=true;YAHOO.widget.AutoComplete.prototype.alwaysShowContainer=false;YAHOO.widget.AutoComplete.prototype.useIFrame=false;YAHOO.widget.AutoComplete.prototype.useShadow=false;YAHOO.widget.AutoComplete.prototype.suppressInputUpdate=false;YAHOO.widget.AutoComplete.prototype.resultTypeList=true;YAHOO.widget.AutoComplete.prototype.queryQuestionMark=true;YAHOO.widget.AutoComplete.prototype.toString=function(){return"AutoComplete "+this._sName;};YAHOO.widget.AutoComplete.prototype.getInputEl=function(){return this._elTextbox;};YAHOO.widget.AutoComplete.prototype.getContainerEl=function(){return this._elContainer; +};YAHOO.widget.AutoComplete.prototype.isFocused=function(){return(this._bFocused===null)?false:this._bFocused;};YAHOO.widget.AutoComplete.prototype.isContainerOpen=function(){return this._bContainerOpen;};YAHOO.widget.AutoComplete.prototype.getListEl=function(){return this._elList;};YAHOO.widget.AutoComplete.prototype.getListItemMatch=function(A){if(A._sResultMatch){return A._sResultMatch;}else{return null;}};YAHOO.widget.AutoComplete.prototype.getListItemData=function(A){if(A._oResultData){return A._oResultData;}else{return null;}};YAHOO.widget.AutoComplete.prototype.getListItemIndex=function(A){if(YAHOO.lang.isNumber(A._nItemIndex)){return A._nItemIndex;}else{return null;}};YAHOO.widget.AutoComplete.prototype.setHeader=function(B){if(this._elHeader){var A=this._elHeader;if(B){A.innerHTML=B;A.style.display="block";}else{A.innerHTML="";A.style.display="none";}}};YAHOO.widget.AutoComplete.prototype.setFooter=function(B){if(this._elFooter){var A=this._elFooter;if(B){A.innerHTML=B;A.style.display="block";}else{A.innerHTML="";A.style.display="none";}}};YAHOO.widget.AutoComplete.prototype.setBody=function(A){if(this._elBody){var B=this._elBody;YAHOO.util.Event.purgeElement(B,true);if(A){B.innerHTML=A;B.style.display="block";}else{B.innerHTML="";B.style.display="none";}this._elList=null;}};YAHOO.widget.AutoComplete.prototype.generateRequest=function(B){var A=this.dataSource.dataType;if(A===YAHOO.util.DataSourceBase.TYPE_XHR){if(!this.dataSource.connMethodPost){B=(this.queryQuestionMark?"?":"")+(this.dataSource.scriptQueryParam||"query")+"="+B+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}else{B=(this.dataSource.scriptQueryParam||"query")+"="+B+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}}else{if(A===YAHOO.util.DataSourceBase.TYPE_SCRIPTNODE){B="&"+(this.dataSource.scriptQueryParam||"query")+"="+B+(this.dataSource.scriptQueryAppend?("&"+this.dataSource.scriptQueryAppend):"");}}return B;};YAHOO.widget.AutoComplete.prototype.sendQuery=function(B){var A=(this.delimChar)?this._elTextbox.value+B:B;this._sendQuery(A);};YAHOO.widget.AutoComplete.prototype.collapseContainer=function(){this._toggleContainer(false);};YAHOO.widget.AutoComplete.prototype.getSubsetMatches=function(E){var D,C,A;for(var B=E.length;B>=this.minQueryLength;B--){A=this.generateRequest(E.substr(0,B));this.dataRequestEvent.fire(this,D,A);C=this.dataSource.getCachedResponse(A);if(C){return this.filterResults.apply(this.dataSource,[E,C,C,{scope:this}]);}}return null;};YAHOO.widget.AutoComplete.prototype.preparseRawResponse=function(C,B,A){var D=((this.responseStripAfter!=="")&&(B.indexOf))?B.indexOf(this.responseStripAfter):-1;if(D!=-1){B=B.substring(0,D);}return B;};YAHOO.widget.AutoComplete.prototype.filterResults=function(J,L,P,K){if(J&&J!==""){P=YAHOO.widget.AutoComplete._cloneObject(P);var H=K.scope,O=this,B=P.results,M=[],D=false,I=(O.queryMatchCase||H.queryMatchCase),A=(O.queryMatchContains||H.queryMatchContains);for(var C=B.length-1;C>=0;C--){var F=B[C];var E=null;if(YAHOO.lang.isString(F)){E=F;}else{if(YAHOO.lang.isArray(F)){E=F[0];}else{if(this.responseSchema.fields){var N=this.responseSchema.fields[0].key||this.responseSchema.fields[0];E=F[N];}else{if(this.key){E=F[this.key];}}}}if(YAHOO.lang.isString(E)){var G=(I)?E.indexOf(decodeURIComponent(J)):E.toLowerCase().indexOf(decodeURIComponent(J).toLowerCase());if((!A&&(G===0))||(A&&(G>-1))){M.unshift(F);}}}P.results=M;}else{}return P;};YAHOO.widget.AutoComplete.prototype.handleResponse=function(C,A,B){if((this instanceof YAHOO.widget.AutoComplete)&&this._sName){this._populateList(C,A,B);}};YAHOO.widget.AutoComplete.prototype.doBeforeLoadData=function(C,A,B){return true;};YAHOO.widget.AutoComplete.prototype.formatResult=function(B,D,A){var C=(A)?A:"";return C;};YAHOO.widget.AutoComplete.prototype.doBeforeExpandContainer=function(D,A,C,B){return true;};YAHOO.widget.AutoComplete.prototype.destroy=function(){var B=this.toString();var A=this._elTextbox;var D=this._elContainer;this.textboxFocusEvent.unsubscribeAll();this.textboxKeyEvent.unsubscribeAll();this.dataRequestEvent.unsubscribeAll();this.dataReturnEvent.unsubscribeAll();this.dataErrorEvent.unsubscribeAll();this.containerPopulateEvent.unsubscribeAll();this.containerExpandEvent.unsubscribeAll();this.typeAheadEvent.unsubscribeAll();this.itemMouseOverEvent.unsubscribeAll();this.itemMouseOutEvent.unsubscribeAll();this.itemArrowToEvent.unsubscribeAll();this.itemArrowFromEvent.unsubscribeAll();this.itemSelectEvent.unsubscribeAll();this.unmatchedItemSelectEvent.unsubscribeAll();this.selectionEnforceEvent.unsubscribeAll();this.containerCollapseEvent.unsubscribeAll();this.textboxBlurEvent.unsubscribeAll();this.textboxChangeEvent.unsubscribeAll();YAHOO.util.Event.purgeElement(A,true);YAHOO.util.Event.purgeElement(D,true);D.innerHTML="";for(var C in this){if(YAHOO.lang.hasOwnProperty(this,C)){this[C]=null;}}};YAHOO.widget.AutoComplete.prototype.textboxFocusEvent=null;YAHOO.widget.AutoComplete.prototype.textboxKeyEvent=null;YAHOO.widget.AutoComplete.prototype.dataRequestEvent=null;YAHOO.widget.AutoComplete.prototype.dataReturnEvent=null;YAHOO.widget.AutoComplete.prototype.dataErrorEvent=null;YAHOO.widget.AutoComplete.prototype.containerPopulateEvent=null;YAHOO.widget.AutoComplete.prototype.containerExpandEvent=null;YAHOO.widget.AutoComplete.prototype.typeAheadEvent=null;YAHOO.widget.AutoComplete.prototype.itemMouseOverEvent=null;YAHOO.widget.AutoComplete.prototype.itemMouseOutEvent=null;YAHOO.widget.AutoComplete.prototype.itemArrowToEvent=null;YAHOO.widget.AutoComplete.prototype.itemArrowFromEvent=null;YAHOO.widget.AutoComplete.prototype.itemSelectEvent=null;YAHOO.widget.AutoComplete.prototype.unmatchedItemSelectEvent=null;YAHOO.widget.AutoComplete.prototype.selectionEnforceEvent=null;YAHOO.widget.AutoComplete.prototype.containerCollapseEvent=null;YAHOO.widget.AutoComplete.prototype.textboxBlurEvent=null;YAHOO.widget.AutoComplete.prototype.textboxChangeEvent=null;YAHOO.widget.AutoComplete._nIndex=0; +YAHOO.widget.AutoComplete.prototype._sName=null;YAHOO.widget.AutoComplete.prototype._elTextbox=null;YAHOO.widget.AutoComplete.prototype._elContainer=null;YAHOO.widget.AutoComplete.prototype._elContent=null;YAHOO.widget.AutoComplete.prototype._elHeader=null;YAHOO.widget.AutoComplete.prototype._elBody=null;YAHOO.widget.AutoComplete.prototype._elFooter=null;YAHOO.widget.AutoComplete.prototype._elShadow=null;YAHOO.widget.AutoComplete.prototype._elIFrame=null;YAHOO.widget.AutoComplete.prototype._bFocused=null;YAHOO.widget.AutoComplete.prototype._oAnim=null;YAHOO.widget.AutoComplete.prototype._bContainerOpen=false;YAHOO.widget.AutoComplete.prototype._bOverContainer=false;YAHOO.widget.AutoComplete.prototype._elList=null;YAHOO.widget.AutoComplete.prototype._nDisplayedItems=0;YAHOO.widget.AutoComplete.prototype._sCurQuery=null;YAHOO.widget.AutoComplete.prototype._sPastSelections="";YAHOO.widget.AutoComplete.prototype._sInitInputValue=null;YAHOO.widget.AutoComplete.prototype._elCurListItem=null;YAHOO.widget.AutoComplete.prototype._bItemSelected=false;YAHOO.widget.AutoComplete.prototype._nKeyCode=null;YAHOO.widget.AutoComplete.prototype._nDelayID=-1;YAHOO.widget.AutoComplete.prototype._nTypeAheadDelayID=-1;YAHOO.widget.AutoComplete.prototype._iFrameSrc="javascript:false;";YAHOO.widget.AutoComplete.prototype._queryInterval=null;YAHOO.widget.AutoComplete.prototype._sLastTextboxValue=null;YAHOO.widget.AutoComplete.prototype._initProps=function(){var B=this.minQueryLength;if(!YAHOO.lang.isNumber(B)){this.minQueryLength=1;}var E=this.maxResultsDisplayed;if(!YAHOO.lang.isNumber(E)||(E<1)){this.maxResultsDisplayed=10;}var F=this.queryDelay;if(!YAHOO.lang.isNumber(F)||(F<0)){this.queryDelay=0.2;}var C=this.typeAheadDelay;if(!YAHOO.lang.isNumber(C)||(C<0)){this.typeAheadDelay=0.2;}var A=this.delimChar;if(YAHOO.lang.isString(A)&&(A.length>0)){this.delimChar=[A];}else{if(!YAHOO.lang.isArray(A)){this.delimChar=null;}}var D=this.animSpeed;if((this.animHoriz||this.animVert)&&YAHOO.util.Anim){if(!YAHOO.lang.isNumber(D)||(D<0)){this.animSpeed=0.3;}if(!this._oAnim){this._oAnim=new YAHOO.util.Anim(this._elContent,{},this.animSpeed);}else{this._oAnim.duration=this.animSpeed;}}if(this.forceSelection&&A){}};YAHOO.widget.AutoComplete.prototype._initContainerHelperEls=function(){if(this.useShadow&&!this._elShadow){var A=document.createElement("div");A.className="yui-ac-shadow";A.style.width=0;A.style.height=0;this._elShadow=this._elContainer.appendChild(A);}if(this.useIFrame&&!this._elIFrame){var B=document.createElement("iframe");B.src=this._iFrameSrc;B.frameBorder=0;B.scrolling="no";B.style.position="absolute";B.style.width=0;B.style.height=0;B.tabIndex=-1;B.style.padding=0;this._elIFrame=this._elContainer.appendChild(B);}};YAHOO.widget.AutoComplete.prototype._initContainerEl=function(){YAHOO.util.Dom.addClass(this._elContainer,"yui-ac-container");if(!this._elContent){var C=document.createElement("div");C.className="yui-ac-content";C.style.display="none";this._elContent=this._elContainer.appendChild(C);var B=document.createElement("div");B.className="yui-ac-hd";B.style.display="none";this._elHeader=this._elContent.appendChild(B);var D=document.createElement("div");D.className="yui-ac-bd";this._elBody=this._elContent.appendChild(D);var A=document.createElement("div");A.className="yui-ac-ft";A.style.display="none";this._elFooter=this._elContent.appendChild(A);}else{}};YAHOO.widget.AutoComplete.prototype._initListEl=function(){var C=this.maxResultsDisplayed;var A=this._elList||document.createElement("ul");var B;while(A.childNodes.length=18&&A<=20)||(A==27)||(A>=33&&A<=35)||(A>=36&&A<=40)||(A>=44&&A<=45)||(A==229)){return true;}return false;};YAHOO.widget.AutoComplete.prototype._sendQuery=function(G){if(this.minQueryLength<0){this._toggleContainer(false);return ;}var I=(this.delimChar)?this.delimChar:null;if(I){var B=-1;for(var F=I.length-1;F>=0;F--){var D=G.lastIndexOf(I[F]);if(D>B){B=D;}}if(I[F]==" "){for(var E=I.length-1;E>=0;E--){if(G[B-1]==I[E]){B--;break;}}}if(B>-1){var H=B+1;while(G.charAt(H)==" "){H+=1;}this._sPastSelections=G.substring(0,H);G=G.substr(H);}else{this._sPastSelections="";}}if((G&&(G.length0)){if(this._nDelayID!=-1){clearTimeout(this._nDelayID);}this._toggleContainer(false);return ;}G=encodeURIComponent(G);this._nDelayID=-1;if(this.dataSource.queryMatchSubset||this.queryMatchSubset){var A=this.getSubsetMatches(G);if(A){this.handleResponse(G,A,{query:G});return ;}}if(this.responseStripAfter){this.dataSource.doBeforeParseData=this.preparseRawResponse;}if(this.applyLocalFilter){this.dataSource.doBeforeCallback=this.filterResults;}var C=this.generateRequest(G);this.dataRequestEvent.fire(this,G,C);this.dataSource.sendRequest(C,{success:this.handleResponse,failure:this.handleResponse,scope:this,argument:{query:G}});};YAHOO.widget.AutoComplete.prototype._populateList=function(K,F,C){if(this._nTypeAheadDelayID!=-1){clearTimeout(this._nTypeAheadDelayID);}K=(C&&C.query)?C.query:K;var H=this.doBeforeLoadData(K,F,C);if(H&&!F.error){this.dataReturnEvent.fire(this,K,F.results);if(this._bFocused||(this._bFocused===null)){var M=decodeURIComponent(K); +this._sCurQuery=M;this._bItemSelected=false;var R=F.results,A=Math.min(R.length,this.maxResultsDisplayed),J=(this.dataSource.responseSchema.fields)?(this.dataSource.responseSchema.fields[0].key||this.dataSource.responseSchema.fields[0]):0;if(A>0){if(!this._elList||(this._elList.childNodes.length=0;Q--){var P=I[Q],E=R[Q];if(this.resultTypeList){var B=[];B[0]=(YAHOO.lang.isString(E))?E:E[J]||E[this.key];var L=this.dataSource.responseSchema.fields;if(YAHOO.lang.isArray(L)&&(L.length>1)){for(var N=1,S=L.length;N=A;O--){G=I[O];G.style.display="none";}}this._nDisplayedItems=A;this.containerPopulateEvent.fire(this,K,R);if(this.autoHighlight){var D=this._elList.firstChild;this._toggleHighlight(D,"to");this.itemArrowToEvent.fire(this,D);this._typeAhead(D,K);}else{this._toggleHighlight(this._elCurListItem,"from");}H=this.doBeforeExpandContainer(this._elTextbox,this._elContainer,K,R);this._toggleContainer(H);}else{this._toggleContainer(false);}return ;}}else{this.dataErrorEvent.fire(this,K);}};YAHOO.widget.AutoComplete.prototype._clearSelection=function(){var C=this._elTextbox.value;var B=(this.delimChar)?this.delimChar[0]:null;var A=(B)?C.lastIndexOf(B,C.length-2):-1;if(A>-1){this._elTextbox.value=C.substring(0,A);}else{this._elTextbox.value="";}this._sPastSelections=this._elTextbox.value;this.selectionEnforceEvent.fire(this);};YAHOO.widget.AutoComplete.prototype._textMatchesOption=function(){var A=null;for(var B=this._nDisplayedItems-1;B>=0;B--){var C=this._elList.childNodes[B];var D=(""+C._sResultMatch).toLowerCase();if(D==this._sCurQuery.toLowerCase()){A=C;break;}}return(A);};YAHOO.widget.AutoComplete.prototype._typeAhead=function(B,D){if(!this.typeAhead||(this._nKeyCode==8)){return ;}var A=this,C=this._elTextbox;if(C.setSelectionRange||C.createTextRange){this._nTypeAheadDelayID=setTimeout(function(){var F=C.value.length;A._updateValue(B);var G=C.value.length;A._selectText(C,F,G);var E=C.value.substr(F,G);A.typeAheadEvent.fire(A,D,E);},(this.typeAheadDelay*1000));}};YAHOO.widget.AutoComplete.prototype._selectText=function(D,A,B){if(D.setSelectionRange){D.setSelectionRange(A,B);}else{if(D.createTextRange){var C=D.createTextRange();C.moveStart("character",A);C.moveEnd("character",B-D.value.length);C.select();}else{D.select();}}};YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers=function(D){var E=this._elContent.offsetWidth+"px";var B=this._elContent.offsetHeight+"px";if(this.useIFrame&&this._elIFrame){var C=this._elIFrame;if(D){C.style.width=E;C.style.height=B;C.style.padding="";}else{C.style.width=0;C.style.height=0;C.style.padding=0;}}if(this.useShadow&&this._elShadow){var A=this._elShadow;if(D){A.style.width=E;A.style.height=B;}else{A.style.width=0;A.style.height=0;}}};YAHOO.widget.AutoComplete.prototype._toggleContainer=function(I){var D=this._elContainer;if(this.alwaysShowContainer&&this._bContainerOpen){return ;}if(!I){this._toggleHighlight(this._elCurListItem,"from");this._nDisplayedItems=0;this._sCurQuery=null;if(!this._bContainerOpen){this._elContent.style.display="none";return ;}}var A=this._oAnim;if(A&&A.getEl()&&(this.animHoriz||this.animVert)){if(A.isAnimated()){A.stop(true);}var G=this._elContent.cloneNode(true);D.appendChild(G);G.style.top="-9000px";G.style.width="";G.style.height="";G.style.display="";var F=G.offsetWidth;var C=G.offsetHeight;var B=(this.animHoriz)?0:F;var E=(this.animVert)?0:C;A.attributes=(I)?{width:{to:F},height:{to:C}}:{width:{to:B},height:{to:E}};if(I&&!this._bContainerOpen){this._elContent.style.width=B+"px";this._elContent.style.height=E+"px";}else{this._elContent.style.width=F+"px";this._elContent.style.height=C+"px";}D.removeChild(G);G=null;var H=this;var J=function(){A.onComplete.unsubscribeAll();if(I){H._toggleContainerHelpers(true);H._bContainerOpen=I;H.containerExpandEvent.fire(H);}else{H._elContent.style.display="none";H._bContainerOpen=I;H.containerCollapseEvent.fire(H);}};this._toggleContainerHelpers(false);this._elContent.style.display="";A.onComplete.subscribe(J);A.animate();}else{if(I){this._elContent.style.display="";this._toggleContainerHelpers(true);this._bContainerOpen=I;this.containerExpandEvent.fire(this);}else{this._toggleContainerHelpers(false);this._elContent.style.display="none";this._bContainerOpen=I;this.containerCollapseEvent.fire(this);}}};YAHOO.widget.AutoComplete.prototype._toggleHighlight=function(A,C){if(A){var B=this.highlightClassName;if(this._elCurListItem){YAHOO.util.Dom.removeClass(this._elCurListItem,B);this._elCurListItem=null;}if((C=="to")&&B){YAHOO.util.Dom.addClass(A,B);this._elCurListItem=A;}}};YAHOO.widget.AutoComplete.prototype._togglePrehighlight=function(B,C){if(B==this._elCurListItem){return ;}var A=this.prehighlightClassName;if((C=="mouseover")&&A){YAHOO.util.Dom.addClass(B,A);}else{YAHOO.util.Dom.removeClass(B,A);}};YAHOO.widget.AutoComplete.prototype._updateValue=function(C){if(!this.suppressInputUpdate){var F=this._elTextbox;var E=(this.delimChar)?(this.delimChar[0]||this.delimChar):null;var B=C._sResultMatch;var D="";if(E){D=this._sPastSelections;D+=B+E;if(E!=" "){D+=" ";}}else{D=B;}F.value=D;if(F.type=="textarea"){F.scrollTop=F.scrollHeight;}var A=F.value.length;this._selectText(F,A,A);this._elCurListItem=C;}};YAHOO.widget.AutoComplete.prototype._selectItem=function(A){this._bItemSelected=true;this._updateValue(A);this._sPastSelections=this._elTextbox.value;this._clearInterval();this.itemSelectEvent.fire(this,A,A._oResultData);this._toggleContainer(false);};YAHOO.widget.AutoComplete.prototype._jumpSelection=function(){if(this._elCurListItem){this._selectItem(this._elCurListItem); +}else{this._toggleContainer(false);}};YAHOO.widget.AutoComplete.prototype._moveSelection=function(G){if(this._bContainerOpen){var F=this._elCurListItem;var E=-1;if(F){E=F._nItemIndex;}var C=(G==40)?(E+1):(E-1);if(C<-2||C>=this._nDisplayedItems){return ;}if(F){this._toggleHighlight(F,"from");this.itemArrowFromEvent.fire(this,F);}if(C==-1){if(this.delimChar){this._elTextbox.value=this._sPastSelections+this._sCurQuery;}else{this._elTextbox.value=this._sCurQuery;}return ;}if(C==-2){this._toggleContainer(false);return ;}var D=this._elList.childNodes[C];var A=this._elContent;var B=((YAHOO.util.Dom.getStyle(A,"overflow")=="auto")||(YAHOO.util.Dom.getStyle(A,"overflowY")=="auto"));if(B&&(C>-1)&&(C(A.scrollTop+A.offsetHeight)){A.scrollTop=(D.offsetTop+D.offsetHeight)-A.offsetHeight;}else{if((D.offsetTop+D.offsetHeight)(A.scrollTop+A.offsetHeight)){this._elContent.scrollTop=(D.offsetTop+D.offsetHeight)-A.offsetHeight;}}}}this._toggleHighlight(D,"to");this.itemArrowToEvent.fire(this,D);if(this.typeAhead){this._updateValue(D);}}};YAHOO.widget.AutoComplete.prototype._onContainerMouseover=function(A,C){var D=YAHOO.util.Event.getTarget(A);var B=D.nodeName.toLowerCase();while(D&&(B!="table")){switch(B){case"body":return ;case"li":if(C.prehighlightClassName){C._togglePrehighlight(D,"mouseover");}else{C._toggleHighlight(D,"to");}C.itemMouseOverEvent.fire(C,D);break;case"div":if(YAHOO.util.Dom.hasClass(D,"yui-ac-container")){C._bOverContainer=true;return ;}break;default:break;}D=D.parentNode;if(D){B=D.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerMouseout=function(A,C){var D=YAHOO.util.Event.getTarget(A);var B=D.nodeName.toLowerCase();while(D&&(B!="table")){switch(B){case"body":return ;case"li":if(C.prehighlightClassName){C._togglePrehighlight(D,"mouseout");}else{C._toggleHighlight(D,"from");}C.itemMouseOutEvent.fire(C,D);break;case"ul":C._toggleHighlight(C._elCurListItem,"to");break;case"div":if(YAHOO.util.Dom.hasClass(D,"yui-ac-container")){C._bOverContainer=false;return ;}break;default:break;}D=D.parentNode;if(D){B=D.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerClick=function(A,C){var D=YAHOO.util.Event.getTarget(A);var B=D.nodeName.toLowerCase();while(D&&(B!="table")){switch(B){case"body":return ;case"li":C._toggleHighlight(D,"to");C._selectItem(D);return ;default:break;}D=D.parentNode;if(D){B=D.nodeName.toLowerCase();}}};YAHOO.widget.AutoComplete.prototype._onContainerScroll=function(A,B){B._elTextbox.focus();};YAHOO.widget.AutoComplete.prototype._onContainerResize=function(A,B){B._toggleContainerHelpers(B._bContainerOpen);};YAHOO.widget.AutoComplete.prototype._onTextboxKeyDown=function(A,B){var C=A.keyCode;if(B._nTypeAheadDelayID!=-1){clearTimeout(B._nTypeAheadDelayID);}switch(C){case 9:if(!YAHOO.env.ua.opera&&(navigator.userAgent.toLowerCase().indexOf("mac")==-1)||(YAHOO.env.ua.webkit>420)){if(B._elCurListItem){if(B.delimChar&&(B._nKeyCode!=C)){if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);}}B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;case 13:if(!YAHOO.env.ua.opera&&(navigator.userAgent.toLowerCase().indexOf("mac")==-1)||(YAHOO.env.ua.webkit>420)){if(B._elCurListItem){if(B._nKeyCode!=C){if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);}}B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;case 27:B._toggleContainer(false);return ;case 39:B._jumpSelection();break;case 38:if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);B._moveSelection(C);}break;case 40:if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);B._moveSelection(C);}break;default:B._bItemSelected=false;B._toggleHighlight(B._elCurListItem,"from");B.textboxKeyEvent.fire(B,C);break;}if(C===18){B._enableIntervalDetection();}B._nKeyCode=C;};YAHOO.widget.AutoComplete.prototype._onTextboxKeyPress=function(A,B){var C=A.keyCode;if(YAHOO.env.ua.opera||(navigator.userAgent.toLowerCase().indexOf("mac")!=-1)&&(YAHOO.env.ua.webkit<420)){switch(C){case 9:if(B._bContainerOpen){if(B.delimChar){YAHOO.util.Event.stopEvent(A);}if(B._elCurListItem){B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;case 13:if(B._bContainerOpen){YAHOO.util.Event.stopEvent(A);if(B._elCurListItem){B._selectItem(B._elCurListItem);}else{B._toggleContainer(false);}}break;default:break;}}else{if(C==229){B._enableIntervalDetection();}}};YAHOO.widget.AutoComplete.prototype._onTextboxKeyUp=function(A,C){var B=this.value;C._initProps();var D=A.keyCode;if(C._isIgnoreKey(D)){return ;}if(C._nDelayID!=-1){clearTimeout(C._nDelayID);}C._nDelayID=setTimeout(function(){C._sendQuery(B);},(C.queryDelay*1000));};YAHOO.widget.AutoComplete.prototype._onTextboxFocus=function(A,B){if(!B._bFocused){B._elTextbox.setAttribute("autocomplete","off");B._bFocused=true;B._sInitInputValue=B._elTextbox.value;B.textboxFocusEvent.fire(B);}};YAHOO.widget.AutoComplete.prototype._onTextboxBlur=function(A,C){if(!C._bOverContainer||(C._nKeyCode==9)){if(!C._bItemSelected){var B=C._textMatchesOption();if(!C._bContainerOpen||(C._bContainerOpen&&(B===null))){if(C.forceSelection){C._clearSelection();}else{C.unmatchedItemSelectEvent.fire(C,C._sCurQuery);}}else{if(C.forceSelection){C._selectItem(B);}}}if(C._bContainerOpen){C._toggleContainer(false);}C._clearInterval();C._bFocused=false;if(C._sInitInputValue!==C._elTextbox.value){C.textboxChangeEvent.fire(C);}C.textboxBlurEvent.fire(C);}};YAHOO.widget.AutoComplete.prototype._onWindowUnload=function(A,B){if(B&&B._elTextbox&&B.allowBrowserAutocomplete){B._elTextbox.setAttribute("autocomplete","on");}};YAHOO.widget.AutoComplete.prototype.doBeforeSendQuery=function(A){return this.generateRequest(A);};YAHOO.widget.AutoComplete.prototype.getListItems=function(){var C=[],B=this._elList.childNodes;for(var A=B.length-1;A>=0;A--){C[A]=B[A];}return C;};YAHOO.widget.AutoComplete._cloneObject=function(D){if(!YAHOO.lang.isValue(D)){return D; +}var F={};if(YAHOO.lang.isFunction(D)){F=D;}else{if(YAHOO.lang.isArray(D)){var E=[];for(var C=0,B=D.length;C0){for(var B=0,A=D.length;B0){var B=(A===false?function(K){return K;}:decodeURIComponent);if(/[^=]+=[^=;]?(?:; [^=]+=[^=]?)?/.test(I)){var G=I.split(/;\s/g);var H=null;var C=null;var E=null;for(var D=0,F=G.length;D '$names' points to a non-existing documentation entity: '@$last_axis' -> '$last_name'"] + } + if {$all} {lappend entity_path $entity [$entity name]} + set entity [$entity origin] + if {[$entity info lookup methods -source application @$axis] eq ""} { + return [list 1 "The tag '$axis' is not supported for the entity type '[namespace tail [$entity info class]]'"] + } + #puts stderr "$entity @$axis id $value" + set entity [$entity @$axis id $value] + set last_axis $axis + set last_name $value + } + } + + if {$strict && $entity ne "" && ![::nsf::object::exists $entity]} { + return [list 1 "The tag path '$tagpath' -> '$names' points to a non-existing documentation entity: '@$last_axis' -> '$last_name'"] + } + if {$all} {lappend entity_path $entity [$entity name]} + + + return [list 0 [expr {$all?$entity_path:$entity}]] + } + + # @method id + # + # A basic generator for the characteristic ideas, based on the + # root_namespace, the tag label, and the fully qualified name of + # the documented entity + # + # @param name The name of the documented entity + # @return An identifier string, e.g., {{{ ::nx::doc::entities::object::ns1::Foo }}} + # @see tag + # @see root_namespace + + :public method id { + -partof_name + {-scope ""} + name + } { + set subns [string trimleft [namespace tail [current]] @] + if {[info exists partof_name]} { + set partof_name [string trimleft $partof_name :] + return [join [list [:root_namespace] $subns $partof_name {*}$scope $name] ::] + } else { + set name [string trimleft $name :] + return "[:root_namespace]::${subns}::$name" + } + } + + :public method new { + -part_attribute + -partof:object,type=::nx::doc::Entity + -name:any,required + args + } { + # A refined frontend for object construction/resolution which + # provides for generating an explicit name, according to the + # rules specific to the entity type. + # + # @param name The of the documented entity + # @return The identifier of the newly generated or resolved entity object + # set fq_name [:get_fully_qualified_name $name] + set ingredients [list] + if {[info exists partof]} { + lappend ingredients -partof_name [$partof name] + lappend ingredients -scope [expr {[info exists part_attribute]?[$part_attribute scope]:""}] + } + lappend ingredients $name + :createOrConfigure [:id {*}$ingredients] -name $name {*}$args + } + + :method createOrConfigure {id args} { + namespace eval $id {} + if {[::nsf::object::exists $id]} { + $id configure {*}$args + } else { + :create $id {*}$args + } + return $id + } + + # @method get_unqualified_name + # + # @param qualified_name The fully qualified name (i.e., including the root namespace) + :public method get_unqualified_name {qualified_name} { + # TODO: danger, tcl-commands in comments + # similar to \[namespace tail], but the "tail" might be an object with a namespace + return [string trimleft [string map [list [:root_namespace] ""] $qualified_name] ":"] + } + :public method get_tail_name {qualified_name} { + #return [string trimleft [string map [list ${:tag} ""] [:get_unqualified_name $qualified_name]] ":"] + return [join [lrange [concat {*}[split [:get_unqualified_name $qualified_name] "::"]] 1 end] "::"] + } + } + + Class create QualifierTag -superclass Tag { + :method get_fully_qualified_name {name} { + if {![string match "::*" $name]} { + error "You need to provide a fully-qualified (absolute) entity name for '$name'." + } + return $name + } + + :public method id { + -partof_name + {-scope ""} + name + } { + if {[info exists partof_name]} { + #puts stderr "QUALIFIER=[join [list $partof_name $name] ::]" + #next [join [list $partof_name $name] ::] + next + } else { + set n [:get_fully_qualified_name $name] +# puts stderr FINALNAME=$n + next $n + } + } + + :public method new { + -part_attribute + -partof:object,type=::nx::doc::Entity + -name:any,required + args + } { + set id_name $name + if {[info exists partof]} { + #set name [join [list [$partof name] $name] ::] + set id_name ::[join [list [[$partof info class] get_tail_name $partof] $name] ::] + } else { + set name [:get_fully_qualified_name $name] + } + :createOrConfigure [:id $id_name] \ + {*}[expr {[info exists part_attribute]?"-part_attribute $part_attribute":""}] \ + {*}[expr {[info exists partof]?"-partof $partof":""}] \ + -name $name {*}$args + } + } + + Class create PartTag -superclass Tag { + :public method id {partof_name scope name} { + next [list -partof_name $partof_name -scope $scope -- $name] + } + + :public method new { + -part_attribute:required + -partof:object,type=::nx::doc::Entity + -name:any,required + args + } { + :createOrConfigure [:id [$partof name] [$part_attribute scope] $name] {*}[current args] + } + } + + # @object ::nx::doc::PartAttribute + # + # This special-purpose Attribute variant realises (1) a cumulative + # value management and (2) support for distinguishing between + # literal parts (e.g., @author, @see) and object parts (e.g., + # \@param). + # + # The cumulative value management adds the append() operation which + # translates into an add(...,end) operation. PartAttribute slots + # default to append() as their default setter operation. To draw a + # line between object and literal parts, PartAttribute slots either + # refer to a part_class (a subclass of Part) or they do not. If a + # part_class is given, the values will be transformed accordingly + # before being pushed into the internal storage. + + ::nx::MetaSlot create PartAttribute -superclass ::nx::VariableSlot { + + # @param part_class + # + # The property refers to a concrete subclass of Part which + # describes the parts being managed by the property. + :property part_class:optional,class + :property scope + + :property {pretty_name {[string totitle [string trimleft [namespace tail [current]] @]]}} + :property {pretty_plural {[string totitle [string trimleft [namespace tail [current]] @]]}} + + # :forward owning_entity_class {% [[:info parent] info parent] } + :method init args { + :defaultmethods [list get append] + :multiplicity 0..n + set :incremental true + # TODO: setting a default value leads to erratic behaviour; + # needs to be verified -> @author returns "" + # :default "" + if {![info exists :scope]} { + set :scope "" + regexp -- {@(.*)-.*} [namespace tail [current]] _ :scope + } + next + } + + :public method id {domain prop value} { + #puts stderr "PARTATTRIBUTE-ID: [current args]" + if {![info exists :part_class]} { + error "Requested id generation from a simple part property!" + } + return [${:part_class} id [$domain name] ${:scope} $value] + } + + :method require_part {domain prop value} { + if {[info exists :part_class]} { + if {[::nsf::is object $value] && \ + [$value info has type ${:part_class}]} { + return $value + } + # puts stderr "NEWWWWWW ${:part_class} new \ + # -name [lindex $value 0] \ + # -partof $domain \ + # -part_attribute [current] \ + # -@doc [lrange $value 1 end]" + return [${:part_class} new \ + -name [lindex $value 0] \ + -partof $domain \ + -part_attribute [current] \ + [lrange $value 1 end]] + #-@doc [lrange $value 1 end]] + } + return $value + } + :public method append {domain prop value} { + :add $domain $prop $value end + } + :public method assign {domain prop value} { + set parts [list] + foreach v $value { + lappend parts [:require_part $domain $prop $v] + } + next [list $domain $prop $parts] + } + :public method add {domain prop value {pos 0}} { + set p [:require_part $domain $prop $value] + if {![$domain eval [list info exists :$prop]] || $p ni [$domain $prop]} { + next [list $domain $prop $p $pos] + } + return $p + } + :public method delete {domain prop value} { + next [list $domain $prop [:require_part $domain $prop $value]] + } + } + + ::nx::MetaSlot create SwitchAttribute -superclass ::nx::VariableSlot { + :public method init args { + set :defaultmethods [list get get] + next + } + :public method get {obj prop} { + set def [expr {[info exists :default]?${:default}:0}] + if {[$obj eval [list set :$prop]] == $def} { + return [::nsf::var::set $obj $prop [expr {!$def}]] + } + return [next] + } + } + + Class create Entity { + # + # Entity is the base class for the documentation classes + # + + # @param name + # + # gives you the name (i.e., the Nx object identifier) of the documented entity + :property name:any,required + + # every Entity must be created with a "@doc" value and can have + # an optional initcmd + #:method objectparameter args { + #next [list [list @doc:optional __initcmd:initcmd,optional]] + #} + + :class property current_project:object,type=::nx::doc::@project,0..1 + :public forward current_project [current] %method + + :property partof:object,type=::nx::doc::StructuredEntity + :property part_attribute:object,type=::nx::doc::PartAttribute + + # + # TODO: the pdata/pinfo/validate combo only makes sense for + # entities which reflect Tcl program structures -> refactor into a + # dedicated PEntity class or the like + # + + :public method get_fqn_command_name {} { + return ${:name} + } + + :property pdata + :public method validate {} { + if {[info exists :pdata] && \ + [:pinfo get -default complete status] ne "missing"} { + if {[[:origin] as_list] eq ""} { + :pinfo propagate status mismatch + :pinfo lappend validation "Provide a short, summarising description!" + } + } + } + :public method "pinfo get" {{-default ?} args} { + if {![info exists :pdata] || ![dict exists ${:pdata} {*}$args]} { + return $default; + } + dict get ${:pdata} {*}$args + } + + :public method "pinfo exists" args { + if {![info exists :pdata]} {return 0} + dict exists ${:pdata} {*}$args + } + + :public method "pinfo lappend" args { + if {![info exists :pdata]} return; + dict lappend :pdata {*}$args + } + + :public method "pinfo set" args { + if {![info exists :pdata]} return; + dict set :pdata {*}$args + } + + + :public method "pinfo propagate" args { + set path [dict create {*}[:get_upward_path \ + -attribute {set :name}]] + foreach p [lreverse [dict keys $path]] { + # + # For now, we disallow upstream propagation if the receiving + # entity is missing ... as this would be pointless ... + # + if {[$p pinfo get -default "extra" status] eq "missing"} break; + $p pinfo set {*}$args + } + } + + :public method get_upward_path { + -relative:switch + {-attribute {set :name}} + {-type ::nx::doc::Entity} + } { + set path [list] + if {!$relative} { + lappend path [list [current] [:eval $attribute]] + } + + if {[info exists :partof] && [${:partof} info has type $type]} { + set path [concat [${:partof} [current method] -attribute $attribute -type $type] $path] + } + return [concat {*}$path] + } + + :property @doc:0..* { + set :incremental 1 + set :positional true + set :position 1 + } + + :property -class ::nx::doc::PartAttribute @see + + :property -class ::nx::doc::SwitchAttribute @deprecated:boolean { + set :default 0 + } + :property -class ::nx::doc::SwitchAttribute @stashed:boolean { + set :default 0 + } + :property -class ::nx::doc::SwitchAttribute @c-implemented:boolean { + set :default 0 + } + + # :property @properties -class ::nx::doc::PartAttribute + :public method @property {props} { + foreach prop $props { + :@$prop + } + } + + :property @use { + :public method assign {domain prop value} { + # @command nx + # + # @use ::nsf::command + + # or + + # class.method {X foo} + # + # @use {Class foo} + # @use object.method {Object foo} + + lassign $value pathspec pathnames + if {$pathnames eq ""} { + set pathnames $pathspec + # puts stderr PATH=[$domain get_upward_path \ + # -attribute {[:info class] tag}] + # puts stderr "dict create {*}[$domain get_upward_path \ + # -attribute {[:info class] tag}]" + set pathspec [dict create {*}[$domain get_upward_path \ + -attribute {[:info class] tag}]] + set pathspec [dict values $pathspec] + } else { + set pathspec [split $pathspec .] + } + lassign [::nx::doc::Tag normalise $pathspec $pathnames] err res + if {$err} { + error "Invalid @use values provided: $res" + } + + lassign $res pathspec pathnames + #puts stderr "PATHSPEC $pathspec PATHNAMES $pathnames" + lassign [::nx::doc::Tag find $pathspec $pathnames] err res + if {$err} { + error "Generating an entity handle failed: $res" + } + # puts stderr "NEXT $domain $prop $res" + next [list $domain $prop $res] + } + + } + + :public method origin {} { + if {[info exists :@use]} { + # puts stderr ORIGIN(${:@use})=isobj-[::nsf::object::exists ${:@use}] + if {![::nsf::object::exists ${:@use}] || ![${:@use} info has type [:info class]]} { + error "Referring to a non-existing doc entity or a doc entity of a different type." + } + return [${:@use} origin] + } + return [current] + } + + :public method as_list {} { + if {[info exists :@doc] && ${:@doc} ne ""} { + set non_empty_elements [lsearch -all -not -exact ${:@doc} ""] + return [lrange ${:@doc} [lindex $non_empty_elements 0] [lindex $non_empty_elements end]] + } + } + + # @method as_text + # + # text is used to access the content of doc of an Entity, and + # performs substitution on it. The substitution is not essential, + # but looks for now convenient. + + :public method as_text {} { + set doc [list] + set lines [:as_list] + foreach l $lines { + lappend doc [string trimleft $l] + } + return [subst [join $doc " "]] + } + } + + Tag create @glossary -superclass Entity { + :property @pretty_name + :property @pretty_plural + :property @acronym + } + + + Class create StructuredEntity -superclass Entity { + + :public method part_attributes {} { + set slots [:info lookup slots] + set attrs [list] + foreach s $slots { + if {![$s info has type ::nx::doc::PartAttribute] || ![$s eval {info exists :part_class}]} continue; + lappend attrs $s [$s part_class] + } + return $attrs + } + + :public method owned_parts { + {-class:object "::nx::Object"} + -where + } { + set __owned_parts [dict create] + foreach {s cls} [:part_attributes] { + # + # Note: For the time being, we skip over the bottom-most level of + # entities, i.e. those which are not structured entities + # themselves. + # + if {[info exists class] && \ + [[$s part_class] info superclass -closure $class] eq ""} continue; + set accessor [$s name] + if {[info exists :$accessor]} { + set items [sorted [:$accessor] name] + if {[info exists where]} { + set l [list] + foreach i $items { + if {[$i eval [list expr $where]]} { + lappend l $i + } + } + set items $l + } + if {$items ne ""} { + dict set __owned_parts $s $items + } + } + } + return $__owned_parts + } + + :public method validate {} { + next + dict for {s entities} [:owned_parts -where "!\${:@stashed}"] { + foreach e $entities { + # TODO: for now, it is sufficient to escape @use chains + # here. review later ... + if {![$e eval {info exists :@use}]} { + $e [current method] + } + } + } + } + } + + + Class create ContainerEntity -superclass StructuredEntity { + + Class create [current]::Resolvable { + :class property container:object,type=[:info parent] + :method get_fully_qualified_name {name} { + set container [[current class] container] + if {![string match "::*" $name]} { +# puts -nonewline stderr "--- EXPANDING name $name" + set name [$container @namespace]::$name +# puts stderr " to name $name" + } + next $name + } + } + + Class create [current]::Containable { + # TODO: check the interaction of required, per-object property and ::nsf::assertion + #:object property container:object,type=[:info parent],required + :property container:object,type=[:info parent] + :method create args { + # + # Note: preserve the container currently set at this callstack + # level. [next] will cause the container to change if another + # container entity is initialised in the following! + # + if {[[current class] eval {info exists :container}]} { + set container [[current class] container] + set obj [next] + if {![$obj eval {info exists :partof}]} { + $container register $obj + } + return $obj + } else { + next + } + } + :method create args { + # + # Note: preserve the container currently set at this callstack + # level. [next] will cause the container to change if another + # container entity is initialised in the following! + # + if {[info exists :container]} { + set cont ${:container} + set obj [next] + if {![$obj eval {info exists :partof}]} { + $cont register $obj + } + return $obj + } else { + next + } + } + + } + # Note: The default "" corresponds to the top-level namespace "::"! + :property {@namespace ""} + + :property -class ::nx::doc::PartAttribute @class { + :pretty_name "Class" + :pretty_plural "Classes" + set :part_class ::nx::doc::@class + } + + :property -class ::nx::doc::PartAttribute @object { + :pretty_name "Object" + :pretty_plural "Objects" + set :part_class ::nx::doc::@object + } + + :property -class ::nx::doc::PartAttribute @command { + :pretty_name "Command" + :pretty_plural "Commands" + set :part_class ::nx::doc::@command + } + + # :property @class:object,type=::nx::doc::@class,multivalued { + # set :incremental 1 + # } + + # :property @object:object,type=::nx::doc::@object,multivalued { + # set :incremental 1 + # } + + # :property @command:object,type=::nx::doc::@command,multivalued { + # set :incremental 1 + # } + + # :method init {} { + # next + + # QualifierTag mixin add [current class]::Resolvable + # [current class]::Resolvable container [current] + # foreach {attr part_class} [:part_attributes] { + # $part_class class mixin add [current class]::Containable + # $part_class container [current] + # } + # } + + :method destroy {} { + foreach {attr part_class} [:part_attributes] { + #$part_class class mixin add [current class]::Containable + if {[$part_class eval {info exists :container}] && \ + [$part_class container] eq [current]} { + $part_class eval {unset :container} + } + } + next + } + + :public method register {containable:object,type=::nx::doc::Entity} { + set tag [[$containable info class] tag] + if {[:info lookup methods -source application "@$tag"] ne ""} { + :@$tag $containable + } + } + } + + Tag create @project -superclass ContainerEntity { + + :property sandbox:object,type=::nx::doc::Sandbox + :property sources + + :property url + :property license + :property creationdate + :property {version ""} + + :property {is_validated 0} + :property depends:0..*,object,type=[current] + + :property -class ::nx::doc::PartAttribute @glossary { + set :part_class ::nx::doc::@glossary + :public method get {domain prop} { + set l [next] + if {[$domain eval {info exists :depends}]} { + foreach d [$domain depends] { + lappend l {*}[$d $prop] + } + } + return [lsort -unique $l] + } + } + + :property -class ::nx::doc::PartAttribute @package { + :pretty_name "Package" + :pretty_plural "Packages" + set :part_class ::nx::doc::@package + } + + :public method destroy {} { + # + # TODO: Using the auto-cleanup feature in [Test case ...] does + # not respect explicit destroy along object relations. Turn the + # test environment more passive by checking for the existance + # before calling destroy! + # + if {[info exists :sandbox] && [::nsf::object::exists ${:sandbox}]} { + ${:sandbox} destroy + } + :current_project "" + next + } + + :method init {} { + # + # TODO: the way we provide the project as a context object to + # all entities is not easily restricted. Review later ... + # + :current_project [current]; # sets a per-class-object variable on Entity! + next + } + } + + # + # Now, define some kinds of documentation entities. The toplevel + # docEntities are named objects in the ::nx::doc::entities namespace + # to ease access to it. + # + # For now, we define here the following toplevel docEntities: + # + # - @package + # - @command + # - @object + # - ... + # + # These can contain multiple parts. + # - @method + # - @param + # - ... + # + + Tag create @package -superclass ContainerEntity { + :property -class ::nx::doc::PartAttribute @require + :property -class ::nx::doc::PartAttribute @version + } + + QualifierTag create @command -superclass StructuredEntity { + :property -class ::nx::doc::PartAttribute @parameter { + set :part_class ::nx::doc::@param + } + :property -class ::nx::doc::PartAttribute @return { + :method require_part {domain prop value} { + set value [expr {![string match ":*" $value] ? "__out__: $value": "__out__$value"}] + next [list $domain $prop $value] + } + set :part_class ::nx::doc::@param + } + + :public forward @sub-command %self @command + + :property -class ::nx::doc::PartAttribute @command { + :pretty_name "Subcommand" + :pretty_plural "Subcommands" + :public method id {domain prop value} { + # TODO: [${:part_class}] resolves to the property slot + # object, not the global @command object. is this intended, in + # line with the intended semantics? + return [${:part_class} [current method] \ + -partof_name [$domain name] \ + -scope ${:scope} -- $value] + } + set :part_class ::nx::doc::@command + } + + :public method validate {} { + if {[info exists :pdata] && \ + [:pinfo get -default complete status] ne "missing"} { + + if {![info exists :@command]} { + set params [list] + set param_names [list] + if {[info exists :@parameter]} { + foreach p [:@parameter] { + set value [$p name] + lappend param_names $value + if {[$p eval {info exists :default}] || $value eq "args" } { + set value "?$value?" + } + lappend params $value + } + } + + set ps [:pinfo get -default "" bundle parameter] + dict for {actualparam paraminfo} $ps { + if {$actualparam ni $param_names} { + set p [:@parameter $actualparam] + $p pdata [lappend paraminfo status missing] + } + } + } + + if {![:pinfo exists bundle parametersyntax]} { + :pinfo set bundle parametersyntax $params + } + + # Note: [next] will cause the missing parameter created to + # be validated and will have the appropriate status + # propagated upstream! + next + } + } + } + + QualifierTag create @object \ + -superclass StructuredEntity \ + -mixin ContainerEntity::Containable { + + :property -class ::nx::doc::PartAttribute @author + + :public forward @object %self @child-object + + :property -class ::nx::doc::PartAttribute @child-object { + set :part_class ::nx::doc::@object + :public method id {domain prop value} { +# puts stderr "CHILD-OBJECT: [current args]" + # if {![info exists :part_class]} { + # error "Requested id generation from a simple part property!" + # } + return [${:part_class} id [join [list [$domain name] $value] ::]] +# return [${:part_class} id -partof_name [$domain name] -scope ${:scope} $value] + } + + } + + :public forward @class %self @child-class + + :property -class ::nx::doc::PartAttribute @child-class { + set :part_class ::nx::doc::@class + :public method id {domain prop value} { + #puts stderr "CHILD-CLASS: [current args]" + # if {![info exists :part_class]} { + # error "Requested id generation from a simple part property!" + # } + return [${:part_class} id [join [list [$domain name] $value] ::]] + #return [${:part_class} id -partof_name [$domain name] -scope ${:scope} $value] + } + } + + :public forward @method %self @object-method + + :property -class ::nx::doc::PartAttribute @object-method { + :pretty_name "Object method" + :pretty_plural "Object methods" + set :part_class ::nx::doc::@method + } + + :public forward @property %self @object-property + #:forward @param %self @object-param + + :property -class ::nx::doc::PartAttribute @object-property { + set :part_class ::nx::doc::@param + } + + :method undocumented {} { + # TODO: for object methods and class methods + if {![::nsf::object::exists ${:name}]} {return ""} + foreach m [${:name} info methods -callprotection public] {set available_method($m) 1} + set methods ${:@method} + if {[info exists :@param]} {set methods [concat ${:@method} ${:@param}]} + foreach m $methods { + set mn [namespace tail $m] + if {[info exists available_method($mn)]} {unset available_method($mn)} + } + return [lsort [array names available_method]] + } + } + + QualifierTag create @class \ + -superclass @object { + + :property -class ::nx::doc::PartAttribute @superclass + + :public forward @property %self @class-property + + :property -class ::nx::doc::PartAttribute @class-property { + :pretty_name "Per-class attribute" + :pretty_plural "Per-class attributes" + set :part_class ::nx::doc::@param + } + + :public forward @class-object-method %self @object-method + :public forward @class-object-property %self @object-property + + :public forward @hook %self @class-hook + + :property -class ::nx::doc::PartAttribute @class-hook { + :pretty_name "Hook method" + :pretty_plural "Hook methods" + set :part_class ::nx::doc::@method + } + + :public forward @method %self @class-method + + :property -class ::nx::doc::PartAttribute @class-method { + :pretty_name "Provided method" + :pretty_plural "Provided methods" + set :part_class ::nx::doc::@method + :method require_part {domain prop value} { + # TODO: verify whether these scoping checks are sufficient + # and/or generalisable: For instance, is the scope + # requested (from the part_attribute) applicable to the + # partof object, which is the object behind [$domain name]? + + # TODO: disable for the moment ... how to rewrite to fit + # the sandboxed environment? + # if {[info exists :scope] && + # ![::nsf::is ${:scope} [$domain name]]} { + # error "The entity '[$domain name]' does not qualify as '${:scope}'" + # } + next + } + } + :public method validate {} { + next + # + # TODO: Certain metadata could also be valid in "missing" + # state, e.g., paramtersyntax? Re-arrange later ... + # + if {[info exists :pdata] && + [:pinfo get -default complete status] ne "missing"} { + # + # Note: Some metadata on classes cannot be retrieved from + # within the tracers, as they might not be set local to the + # class definition. Hence, we gather them at this point. + # + set prj [:current_project] + set box [$prj sandbox] + set statement [list ::nsf::dispatch ${:name} \ + ::nsf::methods::class::info::objectparameter \ + parametersyntax] + :pinfo set bundle parametersyntax [$box eval $statement] + } + } + } + + Class create PartEntity -superclass Entity { + :property partof:object,type=::nx::doc::StructuredEntity,required + :property part_attribute:object,type=::nx::doc::PartAttribute,required + } + + + # @object ::nx::doc::@method + # + # "@method" is a named entity, which is part of some other + # docEntity (a class or an object). We might be able to use the + # "use" parameter for registered aliases to be able to refer to the + # documentation of the original method. + # + PartTag create @method \ + -superclass StructuredEntity { + + :property -class ::nx::doc::SwitchAttribute @syshook:boolean { + set :default 0 + } + :property -class ::nx::doc::PartAttribute @parameter { + set :part_class ::nx::doc::@param + } + :property -class ::nx::doc::PartAttribute @return { + # + # TODO: @return spec fragments should be nameless, + # conceptually. They represent "out" parameters with each + # @method being allowed to have one only. For now, we fix + # this by injecting a dummy name "__out__" which should not + # be displayed. I shall fix this later and refactor it to a + # shared place between @method and @command. + # + :method require_part {domain prop value} { + set value [expr {![string match ":*" $value] ? "__out__: $value": "__out__$value"}] + next [list $domain $prop $value] + } + set :part_class ::nx::doc::@param + } + + :public class method new { + -part_attribute:required + -partof:object,type=::nx::doc::Entity + -name:any,required + args + } { + # 1) Are we in a sub-method? + if {[$partof info has type [current]]} { + :createOrConfigure [:id [:get_tail_name $partof] "" $name] {*}[current args] + } else { + next + } + } + + + + :public forward @class-method %self @method + :public forward @class-object-method %self @method + :public forward @sub-method %self @method + + :property -class ::nx::doc::PartAttribute @method { + set :part_class ::nx::doc::@method + :public method id {domain prop name} { + # TODO: ${:part_class} resolves to the local slot + # [current], rather than ::nx::doc::@method. Why? + if {[$domain info has type ::nx::doc::@method]} { + set id [::nx::doc::@method id [::nx::doc::@method get_tail_name $domain] "" $name] + return $id + } else { + return [::nx::doc::@method id [$domain name] ${:scope} $name] + } + } + } + + :public method get_fqn_command_name {} { + set scope [expr {[${:part_attribute} scope] eq "class"?"classes":"objects"}] + return ::nsf::${scope}::[string trimleft [[:partof] name] :]::${:name} + } + + # @method->validate() + :public method validate {} { + set partof [:get_owning_partof] + if {[info exists :pdata] && + [:pinfo get -default complete status] ne "missing"} { + # + # Note: Some information on methods cannot be retrieved from + # within the tracers as they might not be set local to the + # method definition. Hence, we gather them at this point. I + # will review whether there is a more appropriate way of + # dealing with this issue ... + # + set prj [:current_project] + set box [$prj sandbox] + set obj [$partof name] + + if {[:pinfo exists bundle handle]} { + set handle [:pinfo get bundle handle] + :pinfo set bundle redefine-protected [$box eval [list ::nsf::method::property $obj $handle redefine-protected]] + :pinfo set bundle call-protected [$box eval [list ::nsf::method::property $obj $handle call-protected]] + } + + set params [list] + set param_names [list] + if {[info exists :@parameter]} { + foreach p [:@parameter] { + set value [$p name] + lappend param_names $value + if {[$p eval {info exists :default}] || $value eq "args" } { + set value "?$value?" + } + lappend params $value + } + } + + dict for {actualparam paraminfo} [:pinfo get -default "" bundle parameter] { + if {$actualparam ni $param_names} { + set p [:@parameter $actualparam] + $p pdata [lappend paraminfo status missing] + } + } + + if {![:pinfo exists bundle parametersyntax]} { + :pinfo set bundle parametersyntax $params + } + + # Note: [next] will cause the missing parameter created to + # be validated and will have the appropriate status + # upstream! + next + } else { + # To realise upward status propagation for submethods, use: + # ${:partof} pinfo propagate status mismatch + $partof pinfo propagate status mismatch + } + } + + :public method get_sub_methods {} { + if {[info exists :@method]} { + set leaves [list] + foreach m ${:@method} { + if {![$m eval {info exists :@method}]} { + lappend leaves $m + } else { + lappend leaves {*}[$m get_sub_methods] + } + } + return $leaves + } + } + + :public method get_combined {what} { + set result [list] + if {[info exists :partof] && [${:partof} info has type [current class]]} { + set result [${:partof} get_combined $what] + } + return [lappend result [:$what]] + } + + :public method get_owning_object {} { + return [[:get_owning_partof] name] + } + + :public method get_owning_partof {} { + if {[${:partof} info has type [current class]]} { + return [${:partof} [current method]] + } else { + return ${:partof} + } + } + + + + }; # @method + + # PartTag create @subcommand -superclass {Part @command} + # PartTag create @subcommand -superclass {Part @command} + + # @object ::nx::doc::@param + # + # The entity type "@param" represents the documentation unit + # for several parameter types, e.g., object, method, and + # command parameters. + # + PartTag create @param \ + -superclass PartEntity { + + #:property spec + :property -class ::nx::doc::PartAttribute @spec + :property default + + :public class method id {partof_name scope name} { + next [list [:get_unqualified_name ${partof_name}] $scope $name] + } + + # :class method id {partof_name name} { + # # The method contains the parameter-specific name production rules. + # # + # # @param partof Refers to the entity object which contains this part + # # @param name Stores the name of the documented parameter + + # set partof_fragment [:get_unqualified_name ${partof_name}] + # return [:root_namespace]::${:tag}::${partof_fragment}::${name} + # } + + # @class-object-method new + # + # The per-object method refinement indirects entity creation + # to feed the necessary ingredients to the name generator + # + # @param -part_attribute + # @param -partof + # @param -name + # @param args + + :public class method new { + -part_attribute + -partof:required + -name:any,required + args + } { + lassign $name name def + set spec "" + regexp {^(.*):(.*)$} $name _ name spec + :createOrConfigure [:id $partof [$part_attribute scope] $name] \ + -@spec $spec \ + -name $name \ + -partof $partof \ + {*}[expr {$def ne "" ? "-default $def" : ""}] \ + -part_attribute $part_attribute {*}$args + + } + + :public method get_fqn_command_name {} { + # ::nx::Object::slot::class + if {[${:partof} info has type ::nx::doc::@object]} { + return "[${:partof} name]::slot::${:name}" + } else { + next + } + } + + + # @param->validate() + :public method validate {} { + # + # TODO: For now, we escape from @param validaton on command + # parameters. There is no equivalent to [info parameter] + # available, so we would need to cook a substitute based on + # the parametersyntax. Review later ... + # + if {${:name} eq "__out__" && \ + [${:partof} info has type ::nx::doc::@command]} return; + + # + # Here, we escape from any parameter verification for + # parameters on forwards & alias, as there is no basis for + # comparison! + # + if {[${:partof} info has type ::nx::doc::@method] && \ + [${:partof} pinfo get bundle type] in [list forward alias]} { + dict set :pdata status "" + return; + } + + if {[info exists :pdata] && \ + [:pinfo get -default complete status] ne "missing"} { + + # valid for both object and method parameters + set pspec [:pinfo get -default "" bundle spec] + if {[info exists :spec] && \ + ${:spec} ne $pspec} { + :pinfo propagate status mismatch + :pinfo lappend validation "Specification mismatch. Expected: \ + '${:spec}' Got: '$pspec'." + } + next + } else { + ${:partof} pinfo propagate status mismatch + } + } + } + + # + # Provide two interp-wide aliases for @param. This is mere syntactic + # sugar! + # + interp alias {} ::nx::doc::@property {} ::nx::doc::@param + interp alias {} ::nx::doc::@parameter {} ::nx::doc::@param + + # + # Providing interp-wide aliases for @glossary. For most processing + # steps, this is syntactic sugar, however, the aliases cause + # different rendering behaviour for glossary references and entries. + # + + interp alias {} ::nx::doc::@gls {} ::nx::doc::@glossary + interp alias {} ::nx::doc::@Gls {} ::nx::doc::@glossary + interp alias {} ::nx::doc::@glspl {} ::nx::doc::@glossary + interp alias {} ::nx::doc::@Glspl {} ::nx::doc::@glossary + interp alias {} ::nx::doc::@acr {} ::nx::doc::@glossary + interp alias {} ::nx::doc::@acrfirst {} ::nx::doc::@glossary + + namespace export CommentBlockParser @command @object @class @package \ + @project @method @property @parameter @ MixinLayer +} + + + +namespace eval ::nx::doc { + + Class create TemplateData { + + :class property renderer + :public forward renderer [current] %method + + :public forward rendered [current] %method + :class method "rendered push" {e:object,type=::nx::doc::Entity} { + if {![info exists :__rendered_entity]} { + set :__rendered_entity [list] + } + set :__rendered_entity [concat $e {*}${:__rendered_entity}] + } + + :class method "rendered pop" {} { + set :__rendered_entity [lassign ${:__rendered_entity} e] + return $e + } + + :class method "rendered top" {} { + return [lindex ${:__rendered_entity} 0] + } + + :public method render_start {} {;} + :public method render_end {} {;} + + # This mixin class realises a rudimentary templating language to + # be used in nx::doc templates. It realises language expressions + # to verify the existence of variables and simple loop constructs + :public method render { + {-initscript ""} + -theme + {name:substdefault "[namespace tail [:info class]]"} + } { + :rendered push [current] + # Here, we assume the -nonleaf mode being active for {{{[eval]}}}. + # set tmplscript [list subst [:read_tmpl $template]] + set tmplscript [list subst [[:renderer] getTemplate $name \ + {*}[expr {[info exists theme]?$theme:""}]]] + # + # TODO: This looks awkward, however, till all requirements are + # figured out (as for the origin mechanism) we so keep track + # of the actual rendered entity ... review later ... + # + :render_start + set content [:eval [subst -nocommands { + $initscript + $tmplscript + }]] + :render_end + :rendered pop + return [string trim $content \n] + } + + + # + # some instructions for a dwarfish, embedded templating language + # + :method !let {var value} { + # uplevel 1 [list ::set $var [expr {[info exists value]?$value:""}]] + uplevel 1 [list ::set $var $value] + return + } + + :method ! {cmd args} { + uplevel 1 [list ::$cmd {*}$args] + return + } + + :public method !get {-sortedby -with -where varname} { + set origin [:origin] + if {![$origin eval [list info exists :$varname]]} return + if {[info exists sortedby]} { + set r [uplevel 1 [list ::nx::doc::sorted [$origin eval [list ::set :$varname]] $sortedby]] + } else { + set r [uplevel 1 [list $origin eval [list ::set :$varname] ]] + } + + set where_clause "!\${:@stashed}" + if {[info exists where]} { + append where_clause "&& $where" + } + set l [list] + foreach item $r { + if {![::nsf::object::exists $item] || ![$item info has type ::nx::doc::Entity]} { + lappend l $item + } else { + if {[[$item origin] eval [list expr $where_clause]]} { + lappend l $item + } + } + } + set r $l + + if {[info exists with]} { + set l [list] + foreach item $r { + lappend l [[$item origin] eval [list set :$with]] $item + } + set r $l + } + + return $r + } + + :method for {var list body} { + set rendered "" + ::foreach $var $list { + uplevel 1 [list ::set $var [set $var]] + #uplevel 1 [list ::lassign [set $var] {*}$var] + append rendered [uplevel 1 [list subst $body]] + } + return $rendered + } + + :method ?objvar {obj varname args} { + uplevel 1 [list :? -ops [list [::nsf::current method] -] \ + "\[$obj eval {info exists :$varname}\]" {*}$args] + } + + :public method ?var {varname args} { + set cmd [expr {[string match ":*" $varname]?"\[[:origin] eval {info exists $varname}\]":"\[info exists $varname\]"}] + uplevel 1 [list :? -ops [list [::nsf::current method] -] \ + $cmd {*}$args] + } + :method ? { + {-ops {? -}} + expr + then + next:optional + args + } { + if {[info exists next] && $next ni $ops} { + return -code error "Invalid control operator '$next', we expect one of $ops" + } + if {[uplevel 1 [list expr $expr]]} { + return [uplevel 1 [list subst $then]] + } elseif {[info exists next]} { + if {$next eq "-"} { + set args [lassign $args next_then] + if {$next_then eq ""} { + return -code error "A then script is missing for '-'" + } + if {$args ne ""} { + return -code error "Too many arguments: $args" + } + return [uplevel 1 [list subst $next_then]] + } + return [uplevel 1 [list [current] $next {*}$args]] + } + } + + :method include { + -theme + {name:substdefault "[namespace tail [:info class]]"} + } { + uplevel 1 [list subst [[:renderer] getTemplate $name \ + {*}[expr {[info exists theme]?$theme:""}]]] + } + + :method listing {{-inline true} script} { + set iscript [join [list [list set inline $inline] [list set script $script]] \n] + :render -initscript $iscript [current method] + } + + :method link args { + error "Subclass responsibility: You must provide a method definition of '[current method]' in a proper subclass" + } + + set :markup_map(sub) { + "'''" "\[:listing \{" + "'''" "\}\]" + "<<" "\[:link " + ">>" "\]" + } + + set :markup_map(unescape) { + "\\{" "{" + "\\}" "}" + "\\#" "#" + "\\<" "<" + "\\>" ">" + "\\'" "'" + } + + :method unescape {line} { + set line [string map [[::nsf::current class] eval [list set :markup_map(unescape)]] $line] + } + + :method map {line} { + regsub -all -- {('''([^']+?)''')} $line {[:listing {\2}]} line + regsub -all -- {(<<([^<]+?)>>)} $line {[:link \2]} line + return $line + } + + + :method as_list {} { + set preprocessed [list] + set is_code_block 0 + foreach line [next] { + if {(!${is_code_block} && [regsub -- {^\s*(''')\s*$} $line "\[:listing -inline false \{" line]) || \ + (${is_code_block} && [regsub -- {^\s*(''')\s*$} $line "\}\]" line])} { + set is_code_block [expr {!$is_code_block}] + append line \n + } elseif {${is_code_block}} { + # set line [:map $line unescape] + append line \n + } else { + # set line [:map $line sub] + # set line [:map $line unescape] + set line [string trimleft $line] + if {$line eq {}} { + set line "\n\n" + } + } + lappend preprocessed $line + } + return $preprocessed + } + + :public method as_text {} { + set preprocessed [join [:as_list] " "] + set preprocessed [:map $preprocessed] + set preprocessed [:unescape $preprocessed] + # TODO: For now, we take a passive approach: Some docstrings + # might fail because they contain substitution characters + # ($,[]); see nx.tcl. The same goes for legacy xodoc docstrings, + # and their code listing (see langRef.xotcl). Catching + # evaluations errors here makes it unnecessary to + # escape/unescape evaluation chars; at the same time, we can't + # distinguish errors on unintended and intended evaluations. + # ... + if {[catch {set preprocessed [subst $preprocessed]} msg]} { + puts stderr SELF=[current] + puts stderr MSG=$msg + puts stderr IN->$preprocessed + puts stderr errorInfo->$::errorInfo + } + return $preprocessed + } + + } + + # + # A Renderer base class ... + # + Class create Renderer -superclass MixinLayer { + + :property {extension "[namespace tail [current]]"} + :property extends:object,type=[current] + + # + # mixin-layer management + # + + :method init args { + set :prefix "::nx::doc" + next + } + + :public method apply {} { + if {[info exists :extends]} { + ${:extends} [current method] + } + next + } + + :public method revoke {} { + next + if {[info exists :extends]} { + ${:extends} [current method] + } + } + + # + # template management + # + + :property current_theme + :protected property {templates {[dict create]}} + + :public method addTemplate {name theme body} { + dict set :templates $theme $name $body + return $body + } + :public method deleteTemplate {name theme} { + dict remove ${:templates} $theme $name + } + :public method getTemplate { + name + {theme:substdefault "${:current_theme}"} + } { + if {[dict exists ${:templates} $theme $name]} { + return [dict get ${:templates} $theme $name] + } else { + # + # 1) if available, read-in template file lazily + # + set templateName $name.${:extension}.$theme + set body [:readAsset $templateName] + if {$body ne ""} { + return [:addTemplate $name $theme $body] + } + # + # 2) resolve the template along the "extends" chain + # + if {[info exists :extends]} { + return [${:extends} [current method] $name $theme] + } + # + # 3) if ending up here, report a missing template! + # + error "The template '$templateName' requested for \ + renderer '[namespace tail [current]]' is \ + not available." + } + } + + :method readAsset {assetName} { + set assetDir [find_asset_path] + set assetPath [file join $assetDir $assetName] + return [:read $assetPath] + } + + :method read {-binary:switch path} { + if {[file exists $path] && [file isfile $path]} { + set fh [open $path r] + if {$binary} { + fconfigure $fh -encoding binary -translation binary + } + set body [read $fh] + catch {close $fh} + return $body + } + } + + # + # rendering + # + + :method write {content path} { + set fh [open $path a] + puts $fh $content + catch {close $fh} + } + :method remove {{-nocomplain:switch} path} { + if {![file exists $path] && !$nocomplain} { + error "Path does not exists: '$path'." + } + file delete -force $path + } + + :method installAssets {project theme targetDir} { + error "Not implemented. Instance responsibility!" + } + + :method "layout many-to-1" { + project + theme + {-outdir [::nsf::tmpdir]} + } { + set fn [file join $outdir "[$project name].${:extension}"] + :remove -nocomplain $fn + + set values [concat {*}[dict values [$project navigatable_parts]]] + lappend values $project + + set output [list] + foreach e $values { + lappend output [:render $project $e $theme] + } + :write [join $output \n\n] $fn + :installAssets $project $theme $fn + puts stderr "$e written to $fn" + } + + :method "layout many-to-many" { + project + theme + {-outdir [::nsf::tmpdir]} + } { + set ext ${:extension} + + # + # 1) provide a per-project output directory + # + set project_path [file join $outdir [string trimleft [$project name] :]] + :remove -nocomplain $project_path + + if {![catch {file mkdir $project_path} msg]} { + # + # 2) place the theme-specifc assets into the project directory + # + set target $project_path/assets + :installAssets $project $theme $target + + # + # 3) Set-up the list of entities to be processed. Note that in + # this layout, the @project entity is processed along with all + # the other entities, but *last*. + # + set values [concat {*}[dict values [$project navigatable_parts]]] + lappend values $project + + foreach e $values { + # + # TODO: For now, in templates we (silently) assume that we act + # upon structured entities only ... + # + set content [:render $project $e $theme @project] + :write $content [file join $project_path "[$e filename].$ext"] + puts stderr "$e written to [file join $project_path [$e filename].$ext]" + } + } + } + + :method "layout 1-to-1" { + project + theme + {-outdir "[::nsf::tmpdir]"} + } { + set ext ${:extension} + set fn [file join $outdir "[$project name].$ext"] + + :remove -nocomplain $fn + set content [:render $project $project $theme] + :installAssets $project $theme $outdir + :write $content $fn + puts stderr "$project written to $fn" + } + + :public method run { + -project + {-layout many-to-many} + {-theme yuidoc} + args + } { + # TODO: Relocate trigger validation! + $project validate + # -- + :apply + :current_theme $theme + :layout $layout $project $theme {*}$args + :revoke + } + + :method render {project entity theme {tmplName ""}} { + error "Not implemented. Instance responsibility!" + } + } +} + +# +# sandboxing +# + +namespace eval ::nx::doc { + namespace import -force ::nx::* + Class create Sandbox { + + :public class method type=in {name value arg} { + if {$value ni [split $arg |]} { + error "The value '$value' provided for parameter $name not permissible." + } + return $value + } + + :public class method type=fqn {name value} { + if {[string first "::" $value] != 0} { + error "The value '$value' must be a fully-qualified Tcl name." + } + return $value + } + + :public class method type=fpathtype {name value arg} { + # + # Note: We might receive empty strings in case of [eval]s! + # + set pt [file pathtype $value] + if {$value ne "" && $pt ne $arg} { + error "The filepath '$value' must be $arg, rather than $pt." + } + return $value + } + + :public class method type=nonempty {name value} { + if {$value eq ""} { + return \ + -code error \ + "An empty value is not allowed for parameter '$name'." + } + return $value + } + + :protected property {current_packages "*"} + :property {permissive_pkgs:1..* "*"} { + set :incremental 1 + } + + # + # some callbacks invoked from within the sandbox interp + # + + :public method "cpackage pop" {} { + set :current_packages [lrange ${:current_packages} 0 end-1] + } + :public method "cpackage push" {p} { + lappend :current_packages [string tolower $p] + } + :public method "cpackage top" {} { + return [lindex ${:current_packages} end] + } + + :public method at_source {filepath} { + set cpackage [:cpackage top] + if {$cpackage in ${:permissive_pkgs}} { + lappend :source $cpackage $filepath + } else { + dict set :deps $filepath $cpackage + } + } + + :public method at_load {filepath} { + set cpackage [:cpackage top] + if {$cpackage ne ${:permissive_pkgs}} { + dict set :deps $filepath $cpackage + } + } + + + :public method at_register_package {pkg_name version} { + dict set :registered_packages $pkg_name version $version + } +# :public method at_deregister_package {} { +# set :current_packages [lrange ${:current_packages} 0 end-1] +# } + # [list ->status:in,arg=complete|missing|prototype|mismatch,slot=[current] missing] + :public method at_register_command [list \ + name:fqn,slot=[current] \ + ->cmdtype:in,arg=@object|@class|@command|@method,slot=[current] \ + ->source:fpathtype,arg=absolute,slot=[current] \ + {->nsexported:boolean 0} \ + {->nsimported:boolean 0} \ + ->docstring:optional,slot=[current] \ + ->bundle + ] { + # peek the currently processed package (if any) + set storable_vars [info vars >*] + # set cpackage [lindex ${:current_packages} end] + set cpackage [:cpackage top] + if {$cpackage in ${:permissive_pkgs}} { + dict set :registered_commands $name package $cpackage + foreach svar $storable_vars { + dict set :registered_commands $name [string trimleft $svar >] [set $svar] + } + } + } + + :public method at_deregister_command [list name:fqn,slot=[current]] { + set cpackage [:cpackage top] + if {$cpackage in ${:permissive_pkgs}} { + dict unset :registered_commands $name + } + } + + :public method init args { + :do { + + # + # hide selected built-in Tcl commands and put simple + # forwarding proxies in place ... + # + # TODO: refactor the proxy handling ... + # + interp hide "" proc + interp hide "" namespace + interp hide "" source + interp hide "" load + interp hide "" package + interp hide "" auto_import + + interp invokehidden "" proc ::proc args { + #set ns [uplevel [list interp invokehidden "" namespace current]] + uplevel [list interp invokehidden "" proc {*}$args] + } + + proc ::namespace args { + #set ns [uplevel [list interp invokehidden "" namespace current]] + #interp invokehidden "" -namespace $ns namespace {*}$args + uplevel [list interp invokehidden "" namespace {*}$args] + } + + proc ::source args { + uplevel [list interp invokehidden "" source {*}$args] + } + + proc ::load args { + # set ns [uplevel [list interp invokehidden "" namespace current]] + # interp invokehidden "" -namespace $ns load {*}$args + uplevel [list interp invokehidden "" load {*}$args] + + } + + proc ::package args { + # set ns [uplevel [list interp invokehidden "" namespace current]] + # interp invokehidden "" -namespace $ns package {*}$args + uplevel [list interp invokehidden "" package {*}$args] + } + + proc ::auto_import args { + # set ns [uplevel [list interp invokehidden "" namespace current]] + # interp invokehidden "" -namespace $ns auto_import {*}$args + uplevel [list interp invokehidden "" auto_import {*}$args] + } + + namespace eval ::nx::doc { + + proc is_exported {name} { + # + # ! ISSUE: The built-in [namespace] command is hidden in our + # ! sandbox interp when [is_exported] is used during a + # ! 2pass!!!! + # + set calling_ns [uplevel [list interp invokehidden "" namespace current]] + set ns [interp invokehidden "" namespace current]::_?_ + interp invokehidden "" namespace eval $ns \ + [list interp invokehidden "" namespace import -force $name] + set is [expr {[info commands ${ns}::[interp invokehidden "" namespace tail $name]] ne ""}] + interp invokehidden "" namespace delete $ns + return $is + } + + ::interp invokehidden "" proc ::nx::doc::paraminfo { + value {default ""} + } { + set colon [string first : $value] + set spec "" + if {$colon == -1} { + set name $value + } else { + set spec [string range $value [expr {$colon+1}] end] + set name [string range $value 0 [expr {$colon -1}]] + } + return [list $name [list $spec $default]] + } + + proc __trace_pkg {} { + + # ::interp hide "" source + ::proc ::source {path} { + set ns [uplevel [list namespace current]] + if {[file tail $path] ne "pkgIndex.tcl"} { + ::nx::doc::__at_source [file normalize $path] + } + uplevel [list interp invokehidden "" source $path] + } + + proc list_commands {{parent ""}} { + set ns [dict create] + #set cmds [string trim "[join [info commands ${parent}::*] \" 0 \"] 0" 0] + # + # Note: We trigger a [namespace import] for the + # currently processed namespace before requesting the + # command list in order to have the auto_load feature + # initialise commands otherwise found too late, + # i.e. after having computed the [info + # commands] snapshot! + # +# namespace eval ::nx::doc::__x [list namespace import -force ${parent}::*] + set cmds [info commands ${parent}::*] + + set exported [list] + foreach cmd $cmds { + dict set ns ::[string trimleft $parent :] $cmd [is_exported $cmd] + +#[expr {[info commands ::nx::doc::__x::[namespace tail $cmd]] ne ""}] + } + + foreach nsp [namespace children ${parent}::] { + set ns [dict merge $ns [list_commands ${nsp}]] + } + return $ns + } + + + ::proc ::load args { + + set ns [uplevel [list namespace current]] + + # + # pre-state + # + # set pre_loaded [dict values \ + # [dict create {*}[concat {*}[info loaded ""]]]] + set pre_loaded [lreverse [concat {*}[info loaded ""]]] + set pre [::nx::doc::list_commands] + set pre_commands [dict create {*}[concat {*}[dict values $pre]]] + set pre_namespaces [dict keys $pre] + + interp invokehidden "" -namespace $ns load {*}$args + + # + # post-state + # + #set post_loaded [dict create {*}[concat {*}[info loaded ""]]] + set post_loaded [lreverse [concat {*}[info loaded ""]]] + set post [::nx::doc::list_commands] + set post_commands [dict create {*}[concat {*}[dict values $post]]] + set post_namespaces [dict keys $post] + + # + # deltas + # + set delta_commands [dict remove $post_commands {*}[dict keys $pre_commands]] + + set delta_namespaces [dict keys [dict remove [dict create {*}"[join $post_namespaces " _ "] _"] {*}$pre_namespaces]] + + set delta_pkg [dict remove \ + [dict create {*}$post_loaded] \ + [dict keys [dict create {*}$pre_loaded]]] + + #puts stderr "DELTAS pkg $delta_pkg" + #puts stderr "DELTAS namespace $delta_namespaces" + #puts stderr "DELTAS commands $delta_commands" + + lassign $delta_pkg pkg_name filepath + set filepath [file normalize $filepath] + + ::nx::doc::__at_load $filepath + + # TODO: Temporary hack to reflect that we provide for a + # helper objsys to retrieve command parameter specs and + # parametersyntax prints. + if {[info commands ::nsf::objectsystem::create] ne "" && \ + [::nsf::configure objectsystem] eq ""} { + set rootclass ::nx::doc::_%&obj + set rootmclass ::nx::doc::_%&cls + ::nsf::objectsystem::create $rootclass $rootmclass + } else { + lassign {*}[::nsf::configure objectsystem] rootclass rootmclass + } + + foreach {cmd isexported} $delta_commands { + set bundle [dict create] + set infoMethod ::nsf::methods::object::info::method + if {[::nsf::object::exists $cmd]} { + # + # TODO: Only classes are provided with parametersyntax + # info. Is this sufficient?! + # + if {[::nsf::is class $cmd]} { + + dict set bundle parametersyntax [::nsf::dispatch $cmd \ + ::nsf::methods::class::info::objectparameter \ + parametersyntax] + # + # TODO: Are the parameters needed for objects??? + # + # dict set bundle parameter [::nsf::dispatch $cmd \ + # ::nsf::methods::class::info::objectparameter \ + # parameter] + } + } else { + if {![catch {set syntax [::nsf::dispatch $rootclass $infoMethod \ + parametersyntax $cmd]} _]} { + dict set bundle parametersyntax $syntax + } + + if {![catch {set pa [::nsf::dispatch $rootclass $infoMethod \ + parameter $cmd]} _]} { + foreach pspec $pa { + dict set bundle parameter {*}[::nx::doc::paraminfo {*}$pspec] + } + } + } + + ::nx::doc::__at_register_command $cmd \ + ->cmdtype @command \ + ->source $filepath \ + ->nsexported $isexported \ + ->bundle $bundle + } + } + + ::proc ::package {subcmd args} { + set ns [uplevel [list namespace current]] + set was_registered 0 + switch -glob -- $subcmd { + ifneeded { + lassign $args pkg_name version script + append wrapped_script "::nx::doc::__cpackage push $pkg_name;\n" $script "\n::nx::doc::__cpackage pop;" + set args [list $pkg_name $version $wrapped_script] + ::nx::doc::__at_register_package $pkg_name $version + } + } + interp invokehidden "" -namespace $ns package $subcmd {*}$args + # uplevel [list interp invokehidden "" package $subcmd {*}$args] +# if {$was_registered} { +# ::nx::doc::__at_deregister_package +# } + } + + # + # Note that we have to wrap up Tcl's auto_import due to + # our practise of [namespace import]'ing application + # namespaces to verify whether commands are actually + # exported; see list_commands. Currently, we escape to a + # generic package called TCL_LIBRARY to filter out + # commands lazily acquired through the auto_load + # mechanism, triggered by the [namespace import] + # probing. + # + #::interp hide "" auto_import + ::proc ::auto_import {pattern} { + set ns [uplevel [list namespace current]] + ::nx::doc::__cpackage push TCL_LIBRARY; + interp invokehidden "" -namespace $ns auto_import $pattern + ::nx::doc::__cpackage pop; + } + } + proc __init {} { + # 1) provide for tracing NSF objects + if {[info commands ::nsf::configure] ne "" && \ + [::nsf::configure objectsystem] ne ""} { + set objsys [lindex [::nsf::configure objectsystem] 0] + set m [lassign $objsys rootclass rootmclass] + # + # TODO: Temporary hack to reflect that we provide for a + # helper objsys to retrieve command parameter specs and + # parametersyntax prints. + # + if {$rootclass ne "::nx::doc::_%&obj"} { + + ::nsf::configure keepinitcmd true; + + array set sysmeths [concat {*}$m] + set ::nx::doc::rootns [namespace qualifier $rootmclass] + $rootmclass $sysmeths(-class.create) ${::nx::doc::rootns}::__Tracer + ::nsf::method::create ${::nx::doc::rootns}::__Tracer \ + $sysmeths(-class.create) {name args} { + set obj [::nsf::next]; + set bundle [dict create] + if {[info commands "::nx::Class"] ne ""} { + if {[::nsf::dispatch $obj ::nsf::methods::object::info::hastype ::nx::Slot]} { + dict set bundle objtype slot + dict set bundle incremental [expr {[::nsf::dispatch $obj ::nsf::methods::object::info::hastype ::nx::RelationSlot] || ([::nsf::dispatch $obj ::nsf::methods::object::info::hastype ::nx::VariableSlot] && [::nsf::var::exists $obj incremental] && [::nsf::var::set $obj incremental])}] + } + if {[::nsf::dispatch $obj ::nsf::methods::object::info::hastype ::nx::EnsembleObject]} { + dict set bundle objtype ensemble + } + dict set bundle ismetaclass [::nsf::is metaclass $obj] + } + set cmdtype [expr {[::nsf::is class $obj]?"@class":"@object"}] + ::nx::doc::__at_register_command $obj \ + ->cmdtype $cmdtype \ + ->source [file normalize [info script]] \ + ->nsexported [::nx::doc::is_exported $obj] \ + ->bundle $bundle \ + {*}[expr {[::nsf::var::exists $obj __initcmd] && [::nsf::var::set $obj __initcmd] ne ""?[list ->docstring [::nsf::var::set $obj __initcmd]]:[list]}] + return $obj + } + ::nsf::mixin $rootmclass ${::nx::doc::rootns}::__Tracer + # ::nsf::relation $rootmclass class-mixin ${::nx::doc::rootns}::__Tracer + + if {[info commands "::nx::Object"] ne ""} { + $rootmclass $sysmeths(-class.create) ${::nx::doc::rootns}::__ObjTracer + ::nsf::method::create ${::nx::doc::rootns}::__ObjTracer \ + __resolve_method_path { + -per-object:switch + -verbose:switch + path + } { + array set "" [::nsf::next] + set l [llength $path] + if {$l > 1} { + set target $(object) + set objects [list] + for {set j 1} {$j < [expr {$l-1}]} {incr j} { + set target [namespace qualifiers $target] + lappend objects $target + } + lappend objects [::nsf::current object] + set first 1 + foreach leg [lrange $path 0 end-1] obj [lreverse $objects] { + if {$first} { + set scope [expr {${per-object}?"object":"class"}] + set first 0 + } else { + set scope object + } + + set handle [::nsf::dispatch $obj \ + ::nsf::methods::${scope}::info::method \ + handle $leg] + if {![::nsf::var::exists [::nsf::current class] handles] || ![[::nsf::current class] eval [concat dict exists \${:handles} $handle]]} { + dict set bundle handle $handle + dict set bundle handleinfo [::nx::doc::handleinfo $handle] + dict set bundle type [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::${scope}::info::method type $handle] + if {![catch {set pa [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::${scope}::info::method parameter $handle]} _]} { + foreach pspec $pa { + dict set bundle parameter {*}[::nx::doc::paraminfo {*}$pspec] + } + } + if {![catch {set psyn [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::${scope}::info::method parametersyntax $handle]} _]} { + dict set bundle parametersyntax $psyn + } + ::nx::doc::__at_register_command $handle \ + ->cmdtype @method \ + ->source [file normalize [info script]] \ + ->bundle $bundle + [::nsf::current class] eval [list dict set :handles $handle _] + } + } + } + + return [array get ""] + } + ::nsf::mixin $rootclass ${::nx::doc::rootns}::__ObjTracer + #::nsf::relation $rootclass class-mixin ${::nx::doc::rootns}::__ObjTracer + } + } + ::interp invokehidden "" proc ::nx::doc::handleinfo {handle} { + set definition [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method definition $handle] + if {$definition ne ""} { + set obj [lindex $definition 0] + set modifier [lindex $definition 2] + if {[lindex $definition 1] eq "create"} { + set obj $modifier + set scope "" + set name "" + } elseif {$modifier eq "class"} { + set scope $modifier + set name [lindex $definition 4] + } else { + set scope "" + set name [lindex $definition 3] + } + } + if {$scope eq ""} { + set is_method 0 + set obj [concat {*}[split [string trimleft $obj :] "::"]] + foreach label $obj { + if {$label eq "slot"} {set is_method 1; continue;} + if {$is_method} { + lappend method_name [string trimleft $label _] + } else { + lappend obj_name $label + } + } + set name [lappend method_name {*}$name] + set obj ::[join $obj_name "::"] + } + return [list $obj $scope $name] + } + + + rename ::nsf::method::create ::nsf::_%&method + ::interp invokehidden "" proc ::nsf::method::create { + object + args + } { + set handle [uplevel [list ::nsf::_%&method $object {*}$args]] + if {$handle ne ""} { + set bundle [dict create] + dict set bundle handle $handle + dict set bundle handleinfo [::nx::doc::handleinfo $handle] + foreach pspec [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method parameter $handle] { + dict set bundle parameter {*}[::nx::doc::paraminfo {*}$pspec] + } + dict set bundle parametersyntax [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method parametersyntax $handle] + dict set bundle type [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method type $handle] + dict set bundle returns [::nsf::method::property ${::nx::doc::rootns}::__Tracer $handle returns] + ::nx::doc::__at_register_command $handle \ + ->cmdtype @method \ + ->source [file normalize [info script]] \ + ->bundle $bundle + } + return $handle + } + + rename ::nsf::method::alias ::nsf::_%&alias + ::interp invokehidden "" proc ::nsf::method::alias { + args + } { + set handle [uplevel [list ::nsf::_%&alias {*}$args]] + if {$handle ne ""} { + dict set bundle handle $handle + dict set bundle handleinfo [::nx::doc::handleinfo $handle] + dict set bundle returns [::nsf::method::property ${::nx::doc::rootns}::__Tracer $handle returns] + dict set bundle type [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method type $handle] + if {![catch {set pa [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method parameter $handle]} _]} { + foreach pspec $pa { + dict set bundle parameter {*}[::nx::doc::paraminfo {*}$pspec] + } + } + if {![catch {set psyn [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method parametersyntax $handle]} _]} { + dict set bundle parametersyntax $psyn + } + + ::nx::doc::__at_register_command $handle \ + ->cmdtype @method \ + ->source [file normalize [info script]] \ + ->bundle $bundle + } + return $handle + } + + # if {[$object info method type ${:name}] eq "forward"} { + # set cmd "" + # foreach w [lrange [$object info method definition ${:name}] 2 end] { + # if {[string match ::* $w]} { + # set cmd $w + # break + # } + # } + # if {$cmd ne "" && [string match ::nsf::* $cmd]} { + # # TODO: we assume here, the cmd is a primitive + # # command and we intend only to handle cases from + # # predefined or xotcl2. Make sure this is working + # # reasonable for other cases, such as forwards to + # # other objects, as well + # if {![catch {set actualParams [::nx::Object info method parameter $cmd]}]} { + # # drop usual object + # set actualParams [lrange $actualParams 1 end] + # # drop per object ; TODO: always? + # if {[lindex $actualParams 0] eq "-per-object"} { + # set actualParams [lrange $actualParams 1 end] + # set syntax [lrange [::nx::Object info method parametersyntax $cmd] 2 end] + # } else { + # set syntax [lrange [::nx::Object info method parametersyntax $cmd] 1 end] + # } + # } + # } + # } + + + rename ::nsf::method::forward ::nsf::_%&forward + ::interp invokehidden "" proc ::nsf::method::forward { + args + } { + set handle [uplevel [list ::nsf::_%&forward {*}$args]] + if {$handle ne ""} { + dict set bundle handle $handle + dict set bundle handleinfo [::nx::doc::handleinfo $handle] + dict set bundle type [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method type $handle] + if {![catch {set psyn [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method parametersyntax $handle]} _]} { + dict set bundle parametersyntax $psyn + } + + ::nx::doc::__at_register_command $handle \ + ->cmdtype @method \ + ->source [file normalize [info script]] \ + ->bundle $bundle + } + return $handle + } + + rename ::nsf::method::setter ::nsf::_%&setter + ::interp invokehidden "" proc ::nsf::method::setter { + args + } { + set handle [uplevel [list ::nsf::_%&setter {*}$args]] + if {$handle ne ""} { + dict set bundle handle $handle + dict set bundle handleinfo [::nx::doc::handleinfo $handle] + dict set bundle type [::nsf::dispatch ${::nx::doc::rootns}::__Tracer ::nsf::methods::object::info::method type $handle] + + ::nx::doc::__at_register_command $handle \ + ->cmdtype @method \ + ->source [file normalize [info script]] \ + ->bundle $bundle + } + return $handle + } + + rename ::nsf::objectsystem::create ::nsf::_%&createobjectsystem + ::interp invokehidden "" proc ::nsf::objectsystem::create { + rootclass + rootmclass + args + } { + uplevel [list ::nsf::_%&createobjectsystem $rootclass $rootmclass {*}$args] + + foreach r [list $rootclass $rootmclass] { + dict set bundle ismetaclass [::nsf::is metaclass $r] + ::nx::doc::__at_register_command $r \ + ->cmdtype @class \ + ->source [file normalize [info script]] \ + ->nsexported [::nx::doc::is_exported $r] \ + {*}[expr {[::nsf::var::exists $r __initcmd] && [::nsf::var::set $obj __initcmd] ne ""?[list ->docstring [::nsf::var::set $r __initcmd]]:[list]}] \ + ->bundle $bundle + } + } + + } + # 2) provide for tracing Tcl procs declared at "sourcing time" -> [proc] + #::interp hide "" proc + ::interp invokehidden "" proc ::proc {name arguments body} { + set ns [uplevel [list namespace current]] + interp invokehidden "" -namespace $ns proc $name $arguments $body + set fqn $name + if {[string first "::" $name] != 0} { + set fqn [string trimright $ns :]::$name + } + if {$arguments eq "" && $body eq ""} { + ::nx::doc::__at_deregister_command $fqn + } else { + ::nx::doc::__at_register_command $fqn \ + ->cmdtype @command \ + ->source [file normalize [info script]] \ + ->nsexported [::nx::doc::is_exported $fqn] \ + ->docstring $body + } + + } + # 3) provide for tracing commands namespace-imported at "sourcing time" + #::interp hide "" namespace + ::interp invokehidden "" proc ::namespace {subcmd args} { + set ns [uplevel [list interp invokehidden "" namespace current]] + switch -glob -- $subcmd { + imp* { + foreach pattern $args { + if {[string match "-*" $pattern]} continue; + foreach cmd [info commands $pattern] { + if {![::nx::doc::is_exported $cmd]} continue; + set type @command + if {[info commands ::nsf::object::exists] ne "" &&\ + [::nsf::object::exists $cmd]} { + set type [expr {[::nsf::is class $cmd]?"@class":"@object"}] + } + set imported_name [string trimright $ns :]::[namespace tail $cmd] + ::nx::doc::__at_register_command $imported_name \ + ->cmdtype $type \ + ->source [file normalize [info script]] \ + ->nsexported [::nx::doc::is_exported $imported_name] \ + ->nsimported 1 + } + } + } + } + interp invokehidden "" -namespace $ns namespace $subcmd {*}$args + } + } + } + } + ::interp alias ${:interp} ::nx::doc::__at_register_command \ + "" [current] at_register_command + ::interp alias ${:interp} ::nx::doc::__at_deregister_command \ + "" [current] at_deregister_command + ::interp alias ${:interp} ::nx::doc::__cpackage \ + "" [current] cpackage + ::interp alias ${:interp} ::nx::doc::__at_register_package \ + "" [current] at_register_package + ::interp alias ${:interp} ::nx::doc::__at_source \ + "" [current] at_source + ::interp alias ${:interp} ::nx::doc::__at_load \ + "" [current] at_load + + next + } + :protected property {interp ""}; # the default empty string points to the current interp + + :property registered_commands + + :public method getCompanions {identifiers} { + set scripts [list] + dict for {source pkg} $identifiers { + set rootname [file rootname $source] + set dir [file dirname $source] + set companion $rootname.nxd + set srcs [dict create {*}"[join [list $source $rootname.nxd [file join $dir $pkg].nxd] " _ "] _"] + foreach src [dict keys $srcs] { + if {![file isfile $src] || ![file readable $src]} continue; + if {[file extension $src] eq [info sharedlibextension]} continue; + set fh [open $src r] + if {[catch {lappend scripts [read $fh]} msg]} { + catch {close $fh} + :log "error reading the file '$thing', i.e.: '$msg'" + } + catch {close $fh} + } + } + return $scripts + + } + + :public method get_companions {} { + set companions [dict create] + dict for {cmd props} ${:registered_commands} { + dict with props { + # $source, $package + dict set companions $source $package + } + } + return [:getCompanions $companions] + } + + :public method get_registered_commands { + -exported:switch + -types + -not:switch + nspatterns:optional + } { + if {[info exists nspatterns]} { + set opts [join $nspatterns |] + # set nspatterns "^($opts)\[^\:\]*\$" + set nspatterns "^($opts)\$" + } + dict filter ${:registered_commands} script {cmd props} { + dict with props { + expr {[expr {[info exists nspatterns]?[expr {[regexp -- $nspatterns $cmd _] != $not}]:1}] && \ + [expr {$exported?[expr {$nsexported == $exported}]:1}] && \ + [expr {[info exists types]?[expr {$cmdtype in $types}]:1}]} + } + } + #lsearch -inline -all -regexp $additions {^::nsf::[^\:]+$}] + } + + +# :forward do ::interp %1 {% set :interp} + :public method do {script} { + ::interp eval ${:interp} $script + } + + :public method destroy {} { + # + # TODO: Why am I called twice in doc.test? Because of the test + # enviroment (the auto-cleanup feature?) + # + # puts stderr "SELF [current object] interp ${:interp}" + # ::nsf::__db_show_stack + if {${:interp} ne ""} { + if {[interp exists ${:interp}]} { + interp delete ${:interp} + } + } else { + :do { + if {[info commands ::nsf::configure] ne ""} { + ::nsf::configure keepinitcmd false; + array set sysmeths [concat {*}[lassign {*}[::nsf::configure objectsystem] rootclass rootmclass]] + # TODO: some cleanup is only needed if __init has been called + # (which is not always the case). refactor the code + # accordingly. + set ::nx::doc::rootns [namespace qualifier $rootmclass] + if {[::nsf::object::exists ${::nx::doc::rootns}::__Tracer]} { + ${::nx::doc::rootns}::__Tracer $sysmeths(-object.destroy) + ::nsf::relation $rootmclass class-mixin {} + } + if {[info commands ::nsf::_%&createobjectsystem] ne ""} { + rename ::nsf::_%&createobjectsystem ::nsf::objectsystem::create + } + unset ::nx::doc::rootns + } + rename ::proc "" + interp expose "" proc + rename ::namespace "" + interp expose "" namespace + rename ::source "" + interp expose "" source + rename ::load "" + interp expose "" load + rename ::package "" + interp expose "" package + rename ::auto_import "" + interp expose "" auto_import + + proc ::nx::doc::__at_register_command {} {} + proc ::nx::doc::__at_deregister_command {} {} + proc ::nx::doc::__at_register_package {} {} + proc ::nx::doc::__at_deregister_package {} {} + } + } + next + } + } + namespace export Sandbox +} + + +namespace eval ::nx::doc::xodoc { + + namespace import -force ::nx::* + namespace import -force ::nx::doc::* + + # xodoc -> nxdoc + # - - - - - - - - - - - - - - - - + # MetadataToken Entity + # FileToken @package + # PackageToken @package + # ConstraintToken n/a + # MethodToken n/a + # ProcToken @method (scope = object) + # InstprocToken @method (scope = class) + # ObjToken @object + # ClassToken @class + # MetaClassToken n/a + + Class create MetadataToken { + :class property analyzer + :public forward analyzer [current] %method + :method as {partof:object,type=::nx::doc::StructuredEntity} \ + -returns object,type=::nx::doc::Entity { + error "Subclass responsibility" + } + :public method emit {partof:object,type=::nx::doc::StructuredEntity} \ + -returns object,type=::nx::doc::Entity { + set entity [:as $partof] + set props [:get_properties] + if {[dict exists $props description]} { + $entity @doc [dict get $props description] + } + return $entity + } + :method get_properties {} { + if {[info exists :properties]} { + set props [dict create] + foreach p ${:properties} { + if {[info exists :$p]} { + dict set props [string tolower $p] \ + [:format [set :$p]] + } + } + return $props + } + } + :method format {value} { + # + # 1. replace @-prefixed tags etc. + # + set value [[:analyzer] replaceFormatTags $value] + + # + # 2. escape Tcl evaluation chars in code listings + # + set value [string map { + "\\" "\\\\" + "{" "\\{" + "}" "\\}" + "\"" "\\\"" + "[" "\\[" + "]" "\\]" + "$" "\\$" + } $value] + + # + # 3. box the prop value in a list (this avoids unwanted + # interactions with the line-by-line as_text post-processor) + # + return [list $value] + } + } + + Class create PackageToken -superclass MetadataToken + Class create FileToken -superclass MetadataToken { + :method as {partof:object,type=::nx::doc::StructuredEntity} \ + -returns object,type=::nx::doc::Entity { + # + # TODO: Where to retrieve the package name from? + # + return [@package new -name XOTcl] + } + :public method emit {partof:object,type=::nx::doc::StructuredEntity} \ + -returns object,type=::nx::doc::Entity { + set entity [next] + set props [dict remove [:get_properties] description] + dict for {prop value} $props { + $entity @doc add "

$prop

[join $value]" end + } + $entity @namespace [[$entity current_project] @namespace] + return $entity + } + } + + # + # Note: For whatever reason, InstprocToken is provided but never + # used, at least in XOTcl-langRef. while most probably due to a lack + # of attention or a silent revocation of a design decision in xodoc, + # it forces us into code replication for differentiating the + # per-class and per-object scopes ... in xodoc, these scopes are + # double-encoded, both in proper token subclassifications as well as + # aggregation properties: procList, instprocList ... well, I will + # have to live with it. + # + + Class create MethodToken -superclass MetadataToken + + Class create ProcToken -superclass MethodToken { + :method as {scope partof:object,type=::nx::doc::StructuredEntity} \ + -returns object,type=::nx::doc::Entity { + return [$partof @${scope}-method [:name]] + } + :public method emit {scope partof:object,type=::nx::doc::StructuredEntity} { + set entity [:as $scope $partof] + set props [:get_properties] + if {[dict exists $props description]} { + $entity @doc [dict get $props description] + } + if {[dict exists $props return]} { + $entity @return [dict get $props return] + } + return $entity + } + } + + Class create InstprocToken -superclass MethodToken + + Class create ObjToken -superclass MetadataToken { + :method as {partof:object,type=::nx::doc::ContainerEntity} \ + -returns object,type=::nx::doc::Entity { + return [@object new -name [:name]] + } + :public method emit {entity:object,type=::nx::doc::Entity} \ + -returns object,type=::nx::doc::Entity { + set entity [next] + foreach p [:procList] { + $p emit object $entity + } + return $entity + } + } + + Class create ClassToken -superclass ObjToken { + :method as {partof:object,type=::nx::doc::ContainerEntity} \ + -returns object,type=::nx::doc::Entity { + return [@class new -name [:name]] + } + :public method emit {entity:object,type=::nx::doc::Entity} \ + -returns object,type=::nx::doc::Entity { + set entity [next] + foreach iproc [:instprocList] { + $iproc emit class $entity + } + return $entity + } + } + + Class create MetaClassToken -superclass ClassToken + + namespace export MetadataToken FileToken MethodToken ProcToken \ + InstprocToken ObjToken ClassToken MetaClassToken +} + + +# +# post processor for initcmds and method bodies +# +namespace eval ::nx { + + namespace import -force ::nx::doc::* + + MixinLayer create processor -prefix ::nx::doc { + namespace eval ::nx::doc { + namespace eval ::nx::doc::MixinLayer { + namespace export Mixin + } + namespace import -force ::nx::doc::MixinLayer::* + namespace export Mixin + } + + namespace import -force ::nx::doc::* + + Mixin create [current]::Entity { + :public method init args { + next + set prj [:current_project] + if {$prj ne ""} { + set box [$prj sandbox] + set cmdname [:get_fqn_command_name] + if {[$box eval {info exists :registered_commands}] && \ + [$box eval [concat dict exists \${:registered_commands} $cmdname]]} { + :pdata [$box eval [concat dict get \${:registered_commands} $cmdname]] + } + } + [[current class] info parent] at_processed [current] + } + } + + Mixin create [current]::ContainerEntity { + :method init {} { + next + ::nx::doc::QualifierTag mixin add ::nx::doc::ContainerEntity::Resolvable + ::nx::doc::ContainerEntity::Resolvable container [current] + foreach {attr part_class} [:part_attributes] { + $part_class class mixin add ::nx::doc::ContainerEntity::Containable + $part_class container [current] + } + } + } + + Mixin create [current]::@package { + :public method init args { + next + set prj [:current_project] + if {$prj ne ""} { + set box [$prj sandbox] + if {[$box eval [concat dict exists \${:registered_packages} ${:name}]]} { + :pdata [$box eval [concat dict get \${:registered_packages} ${:name}]] + } + } + } + } + + Mixin create [current]::@method -superclass [current]::Entity { + :method init args { + next + set scope [expr {[${:part_attribute} scope] eq "class"?"class":"object"}] + set obj [:get_owning_object] + set method_name [:get_combined name] + set prj [:current_project] + if {$prj ne ""} { + set box [$prj sandbox] + set script "if {\[::nsf::object::exists $obj\]} {array set \"\" \[$obj eval {:__resolve_method_path \"$method_name\"}\]; ::nsf::dispatch \$(object) ::nsf::methods::${scope}::info::method handle \$(methodName)}" + set cmdname [$box do $script] + if {$cmdname ne "" && [$box eval [concat dict exists \${:registered_commands} $cmdname]]} { + :pdata [$box eval [concat dict get \${:registered_commands} $cmdname]] + } + } + + } + } + + Mixin create [current]::@param -superclass [current]::Entity { + :public method init args { + next + if {${:name} eq "__out__"} { + if {[${:partof} pinfo exists bundle returns]} { + :pdata [list bundle [list spec [${:partof} pinfo get bundle returns]]] + } + } elseif {[${:partof} pinfo exists bundle parameter ${:name}]} { + lassign [${:partof} pinfo get bundle parameter ${:name}] spec default + :pdata [list bundle [list spec $spec default $default]] + } + } + } + + + # + # mixin layer interface + # + + :method apply {} { + unset -nocomplain :processed_entities + next + } + + :method revoke {} { + next + if {[info exists :processed_entities]} { + return [dict keys ${:processed_entities}] + } + } + + :public method at_processed {entity} { + dict set :processed_entities $entity _ + } + + # + # processor interface + # + + :method log {msg} { + puts stderr "[current]->[uplevel 1 [list ::nsf::current method]]: $msg" + } + + :public method process { + -sandboxed:switch + -validate:switch + {-type project} + -include + -exclude + thing + } { + if {$type ne "project"} { + # TODO: Fix the naming requirements ... + set project [@project new -name "_%@"] + $project sources [list $type $thing] + } else { + set project $thing + } + + set box [$project sandbox [Sandbox new \ + -interp [expr {$sandboxed?[interp create]:""}]]] + set sources [dict create] + foreach {type name} [$project sources] { + dict lappend sources $type $name + } + + set provided_entities [list] + dict for {type instances} $sources { + lappend provided_entities {*}[:[current method]=$type $project $instances] + } + + if {$validate} { + # + # TODO: is_validated to later to become a derived/computed + # property ... for now, we just need to escape from setting + # validation-related info in non-validated projects! + # + $project is_validated $validate; # is_validated = 1 + + set present_entities [::nx::doc::filtered $provided_entities {[[:origin] eval {info exists :pdata}]}] + # TODO: the nspatterns should be consumed from the source + # specification and should not be hardcoded here ... review + # later ... + #puts stderr "NSF: [join [dict keys [$box get_registered_commands -exported -types @command]] \n]" + # ISSUE: -exported turns out to be a weak filter criterion, it + # excludes slot objects from being processed! + set nsfilters [list] + if {[info exists include] && $include ne ""} { + set nsfilters [list $include] + } + if {[info exists exclude] && $exclude ne ""} { + set nsfilters [list -not $exclude] + } + + # + # TODO: Add support for "generated" packages and their + # validation later on, i.e. a @package.validate() method. + # + + set generated_commands [dict merge \ + [$box get_registered_commands -types { + @object + @class + @command + } {*}$nsfilters] \ + [$box get_registered_commands -types { + @method + } {*}$nsfilters]] + set map [dict create] + foreach pe $present_entities { + if {[$pe pinfo exists bundle handle]} { + set fqn [$pe pinfo get bundle handle] + } else { + set fqn [$pe get_fqn_command_name] + } + dict unset generated_commands $fqn + dict set map $fqn $pe + } + + # 2. generated entities (doc[no]->program[yes]) + dict for {cmd info} $generated_commands { + dict with info { + if {$cmdtype ni [list @command @object @class @method]} continue; + if {$cmdtype eq "@object" && [string match *::slot::* $cmd]} { + if {[dict exists $info bundle objtype] && [dict get $info bundle objtype] eq "ensemble"} continue; + set name [namespace tail $cmd] + set scope "" + set obj [namespace qualifiers [namespace qualifiers $cmd]] + if {![dict exists $map $obj]} continue; + set partof_entity [dict get $map $obj] + set entity [$partof_entity @[join [list {*}${scope} property] -] $name] + } elseif {$cmdtype eq "@method"} { + lassign [dict get $bundle handleinfo] obj scope name + # ! we assume the partof entity is present or has been generated + if {![dict exists $map $obj]} continue; + set partof_entity [dict get $map $obj] + if {![$partof_entity info has type ::nx::doc::@object]} continue; + set owning_entity $partof_entity + foreach subm $name { + set en [$partof_entity @[join [list {*}${scope} method] -] id $subm] + if {$en ni $provided_entities} { + set partof_entity [$partof_entity @[join [list {*}${scope} method] -] $subm] + } else { + set partof_entity $en + } + } + set entity $partof_entity + if {[dict exists $info bundle parameter]} { + dict for {pname paraminfo} [dict get $info bundle parameter] { + lassign $paraminfo spec default + set paramid [@parameter id $entity "" $pname] + set ppdata [list bundle [list spec $spec default $default]] + if {$paramid ni $provided_entities} { + set paramid [$entity @parameter $pname] + lappend ppdata status missing + } + $paramid pdata $ppdata + } + } + } else { + set entity [@ $cmdtype $cmd] + } + + #puts stderr "SETTING missing PDATA $entity $cmd" + $entity pdata [lappend info status missing] + dict set map [$entity get_fqn_command_name] $entity + } + } + } + return $project + } + + :protected method process=@package {project pkgs} { + set box [$project sandbox] + $box permissive_pkgs [string tolower $pkgs] + set 1pass "" + foreach pkg $pkgs { + if {[catch {namespace eval :: [list package req $pkg]} _]} { + error "Tcl package '$pkg' cannot be found." + } + append 1pass "package req $pkg\n" + } + + # + # a) 1-pass: requiring the packages first will provide + # all dependencies (also those not to be documented). + # + $box do "::nx::doc::__trace_pkg; $1pass" + + # + # b) 2-pass: [source] will re-evaluate the package scripts + # (note, [load]-based extension packages are not covered by this!) + #" + if {[$box eval {info exists :source}]} { + # + # Note: Expects the XOTcl2 utilities to be in place and + # accessible by the [package req] mechanism, use e.g.: + # export TCLLIBPATH=". ./library/xotcl/library/lib" + # + package req xotcl::xodoc + namespace eval :: {namespace import -force ::xotcl::@} + + set docdb [XODoc new] + ::@ set analyzerObj $docdb + foreach {pkg src} [$box eval {set :source}] { + $docdb analyzeFile $src + } + + foreach m [namespace eval ::nx::doc::xodoc {namespace export}] { + if {[::xotcl::Class info instances -closure ::xotcl::metadataAnalyzer::$m] ne ""} { + ::xotcl::metadataAnalyzer::$m instmixin add ::nx::doc::xodoc::$m + } + } + + ::nx::doc::xodoc::MetadataToken eval [list set :analyzer $docdb] + set provided_entites [list] + # + # as we analyze file by file, there is only one FileToken to + # be molded into an @package + # + set ft [::xotcl::metadataAnalyzer::FileToken allinstances] + if {[llength $ft] > 1} { + error "Too many xodoc file tokens processed. Expecting just one!" + } + + $project @namespace "::xotcl" + ::nx::doc::QualifierTag mixin add ::nx::doc::ContainerEntity::Resolvable + ::nx::doc::ContainerEntity::Resolvable container $project + + foreach {attr part_class} [$project part_attributes] { + $part_class class mixin add ::nx::doc::ContainerEntity::Containable + $part_class container $project + } + + set partof $project + if {$ft ne ""} { + set pkg [$ft emit $project] + lappend provided_entities $pkg + set partof $pkg + } + + foreach token [::xotcl::metadataAnalyzer::ObjToken allinstances] { + lappend provided_entities [$token emit $partof] + } + + return $provided_entities + } + } + + :protected method process=package {project pkgs} { + set box [$project sandbox] + $box permissive_pkgs $pkgs + set 1pass "" + foreach pkg $pkgs { + if {[catch {package req $pkg} _]} { + error "Tcl package '$pkg' cannot be found." + } + append 1pass "package req $pkg\n" + } + + # + # a) 1-pass: requiring the packages first will provide + # all dependencies (also those not to be documented). + # + $box do "::nx::doc::__trace_pkg; $1pass" + + # + # b) 2-pass: [source] will re-evaluate the package scripts + # (note, [load]-based extension packages are not covered by this!) + #" + if {[$box eval {info exists :source}]} { + foreach {pkg src} [$box eval {set :source}] { + # + # TODO: 2-pass [source]s should not trigger transitive [source]s. we + # have flattened the relevant [source] hierarchy in the + # 1-pass. + # + append 2pass \ + "::nx::doc::__cpackage push $pkg;\n" \ + "source $src;\n" \ + "::nx::doc::__cpackage pop;\n" + } + $box do "::nx::doc::__init; $2pass" + } + + foreach {attr part_class} [$project part_attributes] { + $part_class class mixin add ::nx::doc::ContainerEntity::Containable + $part_class container $project + } + + set deps_entities [list] + foreach dep [$box getCompanions [$box eval {set :deps}]] { + lappend deps_entities {*}[:readin $dep] + } + foreach de $deps_entities { + $de @stashed + } + + set scripts [$box get_companions] + set provided_entities [list] + foreach script $scripts { + lappend provided_entities {*}[:readin $script] + } + return $provided_entities + } + + :protected method process=source {project filepath} {;} + + :protected method process=eval {project scripts} { + set box [$project sandbox] + # + # 1a) 1pass ... TODO: should tracing be enabled in this scenario? ... + # + foreach script $scripts { + $box do $script + } + + # + # 2) 2pass ... + # + $box do [list ::nx::doc::__init] + + foreach script $scripts { + $box do $script + } + # + # 3) documentation processing + # + + # 3a) top-level processing + foreach script $scripts { + :readin $script + } + + # 3b) initcmds, proc bodies ... + + dict for {cmd info} [$box get_registered_commands] { + dict with info { + # + # TODO: for now, we assume objects beyond this point + # ... relax later! + # + if {$cmdtype ni [list @object @class]} continue; + if {[info exists docstring]} { + lassign [:readin \ + -docstring \ + -tag $cmdtype \ + -name $cmd \ + -parsing_level 1 \ + $docstring] entity processed_entities + unset docstring + } else { + set entity [@ $cmdtype $cmd] + } + :process=$cmdtype $project $entity + } + } + } + + :public method readin { + -docstring:switch + -tag + -name + -partof_entity:object,type=::nx::doc::StructuredEntity + {-parsing_level:integer 0} + script + } { + + set blocks [:comment_blocks $script] + set first_block 1 + set processed_entities [list] + foreach {line_offset block} $blocks { + array set arguments [list -initial_section context \ + -parsing_level $parsing_level] + + if {$docstring} { + if {[info exists partof_entity]} { + set arguments(-partof_entity) $partof_entity + } + if {![info exists tag] || ![info exists name]} { + error "In docstring mode, provide the tag and the name of + a docstring-owning documentation entity object." + } + if {$first_block} { + # + # TODO: Note that the two "creation procedures" are not + # idempotent; the relative one overwrites description + # blocks of pre-exisiting entities, the freestanding @ + # does not ... fix later when reviewing these parts of the + # program ... + # + set docentity [expr {[info exists partof_entity]?\ + [$partof_entity $tag $name]:[@ $tag $name]}] + set arguments(-partof_entity) $docentity + if {$line_offset <= 1} { + set arguments(-initial_section) description + set arguments(-entity) $docentity + } + } + } + + set args [array get arguments] + lappend args $block + # puts stderr "::nx::doc::CommentBlockParser process {*}$args" + #::nx::doc::Entity mixin add [current]::Entity + :apply + ::nx::doc::CommentBlockParser process {*}$args + lappend processed_entities {*}[:revoke] + set first_block 0 + } + if {$docstring && [info exists arguments(-partof_entity)]} { + return [list $arguments(-partof_entity) $processed_entities] + } else { + return $processed_entities + } + } + + :public method analyze_line {line} { + set regex {^[\s#]*#+(.*)$} + if {[regexp -- $regex $line --> comment]} { + return [list 1 [string trimright $comment]] + } else { + return [list 0 $line] + } + } + + :public method comment_blocks {script} { + set lines [split $script \n] + set comment_blocks [list] + set was_comment 0 + + set spec { + 0,1 { + set line_offset $line_counter; + set comment_block [list]; + lappend comment_block $text} + 1,0 { + lappend comment_blocks $line_offset $comment_block; + unset comment_block + } + 1,1 {lappend comment_block $text} + 0,0 {} + } + array set do $spec + set line_counter -1 + foreach line $lines { + incr line_counter + # foreach {is_comment text} [:analyze_line $line] break; + lassign [:analyze_line $line] is_comment text; + eval $do($was_comment,$is_comment) + set was_comment $is_comment + } + if {[info exists comment_block]} { + lappend comment_blocks $line_offset $comment_block + } + return $comment_blocks + } + + # TODO: how can I obtain some reuse here when later @class is + # distinguished from @object (dispatch along the inheritance + # hierarchy?) + + :public method process=@command {project entity} {;} + + :public method process=@class {project entity} { + set name [$entity name] + set box [$project sandbox] + # attributes + foreach slot [$box do [list $name info slot objects]] { + if {[$box do [list $slot eval {info exists :__initcmd}]]} { + # + # TODO: Here, we eagerly create doc entities, is this an issue? + # Should we mark them for removal if not further processed? + # This might be contradicting to the requirement of + # identifying documented/undocumented program structures. + # + # There are two alternatives: + # -> use a freestanding identity generator (preferred!) + # -> mark the entity for deletion + # + # set id [$entity @${scope}-attribute [$box do [list $slot name]]] + + set scope [expr {[$box do [list $slot per-object]]?"class-object":"class"}] + :readin \ + -partof_entity $entity \ + -docstring \ + -tag @${scope}-property \ + -name [$box do [list $slot name]] \ + -parsing_level 2 \ + [$box do [list $slot eval {set :__initcmd}]] + + } + } + + foreach methodName [$box do [list $name info methods \ + -methodtype scripted \ + -callprotection public]] { + :readin \ + -partof_entity $entity \ + -docstring \ + -tag @class-method \ + -name $methodName \ + -parsing_level 2 \ + [$box do [list ${name} info method body $methodName]] + } + + :process=@object $project $entity class + + } + + # + # TODO: how to resolve to the current project's context. For now, + # we pass a parameter value, revisit this decision once we decide + # on a location for this behaviour. + # + :public method process=@object {project entity {scope ""}} { + set name [$entity name] + set box [$project sandbox] + # methods + + foreach methodName [$box do [list ${name} {*}$scope info methods\ + -methodtype scripted \ + -callprotection public]] { + + set tag [join [list {*}[expr {$scope eq "class"?"class-object":""}] method] -] + # set id [$entity @$tag $methodName] + :readin \ + -partof_entity $entity \ + -docstring \ + -tag @$tag \ + -name $methodName \ + -parsing_level 2 \ + [$box do [list ${name} {*}$scope info method body $methodName]] + } + } + + } +} + + +# +# toplevel interface +# ::nx::doc::make all +# ::nx::doc::make doc +# +namespace eval ::nx::doc { + + Object create make { + + :method all {{-verbose:switch} {-class ::nx::Class}} { + foreach c [$class info instances -closure] { + if {$verbose} {puts "postprocess $c"} + ::nx::doc::postprocessor process $c + } + } + + :method write {content path} { + set fh [open $path w] + puts $fh $content + catch {close $fh} + } + + :public method doc { + {-format html} + project:object,type=::nx::doc::@project + args + } { + package req nx::doc::$format + $format run -project $project {*}$args + } + } + + # + # This is a mixin class which adds comment block parsing + # capabilities to documentation entities (Entity, ...), once + # identified. + # + # It acts as the event source external to the modal parser (i.e., + # the parsed entity). Expressing a modal behavioural design itself + # (around the line queue of a comment block), it produces certain + # events which are then signalled to the parsed entity. + # + Class create CommentBlockParser { + + :property {parsing_level:integer 0} + + :property {message ""} + :property {status:in "COMPLETED"} { + + set :incremental 1 + + set :statuscodes { + COMPLETED + INVALIDTAG + MISSINGPARTOF + STYLEVIOLATION + LEVELMISMATCH + } + + :public method type=in {name value} { + if {$value ni ${:statuscodes}} { + error "Invalid statuscode '$code'." + } + return $value + } + + :public method ? [list obj var value:in,slot=[current object]] { + return [expr {[:get $obj $var] eq $value}] + } + + :public method is {obj var value} { + return [expr {$value in ${:statuscodes}}] + } + } + + :property processed_section { + set :incremental 1 + :public method assign {domain prop value} { + set current_entity [$domain current_entity] + set scope [expr {[$current_entity info is class]?"class mixin":"mixin"}] + # puts stderr "Switching: [$current_entity {*}$scope] --> target $value" + if {[$domain eval [list info exists :$prop]] && [:get $domain $prop] in [$current_entity {*}$scope]} { + $current_entity {*}$scope delete [:get $domain $prop] + } + $current_entity {*}$scope add [next [list $domain $prop $value]] + } + } + :property current_entity:object + + :public class method process { + {-partof_entity ""} + {-initial_section context} + {-parsing_level 0} + -entity + block + } { + + if {![info exists entity]} { + set entity [Entity] + } + + set parser_obj [:new -current_entity $entity -parsing_level $parsing_level] + $parser_obj [current proc] \ + -partof_entity $partof_entity \ + -initial_section $initial_section \ + $block + return $parser_obj + } + + :public forward has_next expr {${:idx} < [llength ${:comment_block}]} + :public method dequeue {} { + set r [lindex ${:comment_block} ${:idx}] + incr :idx + return $r + } + :public forward rewind incr :idx -1 + :public forward fastforward set :idx {% llength ${:comment_block}} + + :public method cancel {statuscode {msg ""}} { + :fastforward + :status $statuscode + :message $msg + uplevel 1 [list ::return -code error $statuscode] + } + # + # everything below assumes that the current class is an active mixin + # on an instance of an Entity subclass! + # + + :public method process { + {-partof_entity ""} + {-initial_section context} + block + } { + + set :comment_block $block + set :idx 0 + + :processed_section [$initial_section] + + # TODO: currently, default values are not initialised for + # property slots defined in mixin classes; so do it manually + # for the time being. + ${:current_entity} current_comment_line_type "" + + ${:current_entity} block_parser [current] + ${:current_entity} eval [list set :partof_entity $partof_entity] + + set is_first_iteration 1 +# set failure "" + + # + # Note: Within the while-loop, two object variables constantly + # change (as "wanted" side-effects): processed_section: reflects + # the currently processed comment section; see event=next() + # current_entity: reflects the currently documentation entity + # (once resolved); see context->event=parse@tag() + # + while {[:has_next]} { + set line [:dequeue] + if {$is_first_iteration} { + ${:current_entity} on_enter $line + set is_first_iteration 0 + } + + if {[catch { + # puts stderr "PROCESS ${:current_entity} event=process $line" + ${:current_entity} event=process $line + } failure]} { + if {![:status is $failure]} { + ::return -code error -errorinfo $::errorInfo + } + } + } + if {!$is_first_iteration} { + ${:current_entity} on_exit $line + } + + # ISSUE: In case of some sub-method definitions (namely "info + # mixin"), the sub-method entity object for "mixin" replaces the + # forward handlers of the mixin relation slot. So, any slot-like + # interactions such as delete() won't work anymore. We need to + # bypass it by using ::nsf::relation, for the time being. This + # is a clear con of the explicit naming of entity objects (or at + # least the current scheme)! + + # if {[${:processed_section} info mixinof -scope object ${:current_entity}] ne ""} { + # ${:current_entity} {*}$scope mixin delete ${:processed_section} + # } + + set scope [expr {[${:current_entity} info is class]?"class":""}] + set mixins [${:current_entity} {*}$scope info mixin classes] + if {${:processed_section} in $mixins} { + set idx [lsearch -exact $mixins ${:processed_section}] + set mixins [lreplace $mixins $idx $idx] + ::nsf::relation ${:current_entity} object-mixin $mixins + } + + }; # CommentBlockParser->process() + + } + + Class create CommentBlockParsingState -superclass Class { + + :property next_comment_section + :property comment_line_transitions:required + + } + + Class create CommentSection { + + :property block_parser:object,type=::nx::doc::CommentBlockParser + :property {current_comment_line_type ""} + + set :line_types { + tag {regexp -- {^\s*@[^[:space:]@]+} $line} + text {regexp -- {^\s*([^[:space:]@]+|@[[:space:]@]+)} $line} + space {expr {$line eq {}}} + } + + :method get_transition {src_line_type tgt_line} { + set section [${:block_parser} processed_section] + array set transitions [$section comment_line_transitions] + # expected outcome + # 1. new state -> becomes current_comment_line + # 2. actions to be triggered from the transition + + foreach {line_type expression} [[current class] eval {set :line_types}] { + set line $tgt_line + if {[eval $expression]} { + set tgt_line_type $line_type + break + } + } + + if {![info exists tgt_line_type]} { + error "Could not resolve the type of line '$line'" + } + + if {![info exists transitions(${src_line_type}->${tgt_line_type})]} { + set msg "Style violation in a [namespace tail [:info class]] section:\n" + if {$src_line_type eq ""} { + append msg "Invalid first line ('${tgt_line_type}')" + } else { + append msg "A ${src_line_type} line is followed by a ${tgt_line_type} line" + } + ${:block_parser} cancel STYLEVIOLATION $msg + # [StyleViolation new -message $msg] throw + } + return [list $tgt_line_type $transitions(${src_line_type}->${tgt_line_type})] + } + + # the actual events to be signalled to and sensed within the + # super-states and sub-states + + :public method event=process {line} { + lassign [:get_transition ${:current_comment_line_type} $line] \ + :current_comment_line_type actions + foreach action $actions { + :event=$action $line + } + } + + :public forward event=parse %self {% subst {parse@${:current_comment_line_type}}} + :method event=next {line} { + set next_section [[${:block_parser} processed_section] next_comment_section] + :on_exit $line + + ${:block_parser} rewind + :current_comment_line_type "" + + ${:block_parser} processed_section [$next_section] + :on_enter $line + } + + + # realise the sub-state (a variant of METHOD-FOR-STATES) and their + # specific event handling + # set :lineproc {{tag args} {return [concat {*}$args]}} + # set :lineproc {{tag args} {puts stderr LINE=[list $tag {*}$args]; return [list $tag {*}$args]}} + set :lineproc {{tag args} {return [list $tag [expr {$args eq ""?$args:[list $args]}]]}} + :method parse@tag {line} { + lassign [apply [[current class] eval {set :lineproc}] {*}$line] tag line + #set line [lassign [apply [[current class] eval {set :lineproc}] {*}$line] tag] + if {[:info lookup methods -source application $tag] eq ""} { + set msg "The tag '$tag' is not supported for the entity type '[namespace tail [:info class]]" + ${:block_parser} cancel INVALIDTAG $msg + } + #:$tag [lrange $line 1 end] + #:$tag {*}[expr {$line eq ""?$line:[list $line]}] + #:$tag $line + :$tag {*}$line + } + + :method parse@text {line} { + #puts stderr "ADDLINE([current]) :@doc add $line end" + :@doc add $line end + } + :method parse@space {line} {;} + + # + # so far, we only need enter and exit handlers at the level of the + # superstates: context, description, part + # + :public method on_enter {line} {;} + :public method on_exit {line} {;} + } + + # NOTE: add these transitions for supporting multiple text lines for + # the context element + # tag->text parse + # text->text parse + # text->space "" + + + CommentBlockParsingState create context -superclass CommentSection \ + -next_comment_section description \ + -comment_line_transitions { + ->tag parse + tag->space "" + space->space "" + space->text next + space->tag next + } { + + :method resolve_partof_entity {tag name} { + # a) unqualified: attr1 + # b) qualified: Bar#attr1 + if {[regexp -- {([^\s#]*)#([^\s#]*)} $name _ qualifier nq_name]} { + # TODO: Currently, I only foresee @object and @command as + # possible qualifiers; however, this should be fixed asap, as + # soon as the variety of entities has been decided upon! + foreach entity_type {@class @command @object} { + set partof_entity [$entity_type id $qualifier] + # TODO: Also, we expect the qualifier to resolve against an + # already existing entity object? Is this intended? + if {[::nsf::is object $partof_entity]} { + return [list $nq_name $partof_entity] + } + } + return [list $nq_name ${:partof_entity}] + } else { + return [list $name ${:partof_entity}] + } + } + + set :lineproc {{tag name args} {return [list $tag $name $args]}} + :method parse@tag {line} { + lassign [apply [[current class] eval {set :lineproc}] {*}$line] axes names args + set entity ${:partof_entity} + set axes [split [string trimleft $axes @] .] + + # 1) get the parsing level from the comment block parser + set start_idx [lindex [lsearch -all -not -exact $axes ""] 0] + + set pl [${:block_parser} parsing_level] + if {$pl != $start_idx} { + ${:block_parser} cancel LEVELMISMATCH "Parsing level mismatch: Tag is meant for level '$start_idx', we are at '$pl'." + } + + # 2) stash away a number of empty axes according to the parsing level + set axes [lrange $axes $pl end] + + lassign [::nx::doc::Tag normalise $axes $names] err res + if {$err} { + ${:block_parser} cancel STYLEVIOLATION $res + } + + lassign $res tagpath names + + set leaf(axis) [lindex $tagpath end] + set tagpath [lrange $tagpath 0 end-1] + set leaf(name) [lindex $names end] + set names [lrange $names 0 end-1] + + lassign [::nx::doc::Tag find -strict $tagpath $names $entity] err res + if {$err} { + ${:block_parser} cancel INVALIDTAG $res + } + + set entity $res + + if {$entity eq ""} { + set cmd [info commands @$leaf(axis)] + + # TODO interp-aliasing objects under different command names + # is currently not transparent to some ::nsf::* helpers, + # such as ::nsf::object::exists. Should this be changed? + # + if {$cmd ne ""} { + set cmd [namespace origin $cmd] + set target [interp alias {} $cmd] + if {$target ne ""} { + set cmd $target + } + } + + if {$cmd eq "" || ![::nsf::object::exists $cmd] || \ + ![$cmd info has type Tag]} { + + ${:block_parser} cancel INVALIDTAG "The entity type '@$leaf(axis)' is not available." + } + + # VERIFY! Still an issue? TODO: @object-method raises some + # issues (at least when processed without a resolved + # context = its partof entity). It is not an entity type, + # because it merely is a "scoped" @method. It won't + # resolve then as a proper instance of Tag, hence we + # observe an InvalidTag exception. For now, we just ignore + # and bypass this issue by allowing InvalidTag exceptions + # in analyze() + + set entity [@$leaf(axis) new -name $leaf(name) {*}$args] + } else { + if {[$entity info lookup methods -source application @$leaf(axis)] eq ""} { + ${:block_parser} cancel INVALIDTAG \ + "The tag '$leaf(axis)' is not supported for the entity type '[namespace tail [$entity info class]]'" + } + set entity [$entity @$leaf(axis) [list $leaf(name) {*}$args]] + } + + ${:block_parser} current_entity $entity + ${:block_parser} processed_section [current class] + $entity current_comment_line_type ${:current_comment_line_type} + $entity block_parser ${:block_parser} + } + + # :method parse@text {line} { next } + # :method parse@space {line} { next } + + } + + CommentBlockParsingState create description -superclass CommentSection \ + -next_comment_section part \ + -comment_line_transitions { + ->text parse + ->tag next + text->text parse + text->space parse + space->text parse + space->space parse + space->tag next + } { + + :public method on_enter {line} { + unset -nocomplain :@doc + next + } + + # tag lines are not allowed in description blocks! + # :method parse@tag {line} {;} + :method parse@space {line} { + :@doc add "" end + next + } + + } + + CommentBlockParsingState create part -superclass CommentSection \ + -next_comment_section part \ + -comment_line_transitions { + ->tag parse + tag->text parse + text->text parse + text->tag next + text->space "" + space->space "" + tag->space "" + space->tag next + tag->tag next + } { + # realise the parse events specific to the substates of description + :public method on_enter {line} { +# puts stderr "ENTERING part $line, current section [${:block_parser} processed_section]" + unset -nocomplain :current_part + next + } + :method parse@tag {line} { + set r [next] +# puts stderr GOT=$r + if {[::nsf::object::exists $r] && [$r info has type ::nx::doc::Entity]} { + set :current_part $r + } + return $r + } + :method parse@text {line} { + if {[info exists :current_part]} { + ${:current_part} @doc add $line end + } else { + :event=next $line + } + } + # :method parse@space {line} {;} + } +} + +# puts stderr "Doc Tools loaded: [info command ::nx::doc::*]" \ No newline at end of file Index: library/lib/nxdoc-html.tcl =================================================================== diff -u --- library/lib/nxdoc-html.tcl (revision 0) +++ library/lib/nxdoc-html.tcl (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,390 @@ +package provide nx::doc::html 1.0 +namespace eval ::nx::doc {} + +package require nx::doc 1.0 + +namespace eval ::nx::doc { + + Renderer create html { + + :method render {project entity theme {tmplName ""}} { + set top_level_entities [$project navigatable_parts] + set init [subst { + set project $project + set project_entities \[list $top_level_entities\] + }] + $entity current_project $project + $entity renderer [current] + $entity render -initscript $init -theme $theme {*}$tmplName + } + + :method installAssets {project theme targetDir} { + set assets [glob -directory [file join [::nx::doc::find_asset_path] $theme] *] + file mkdir $targetDir + if {$assets eq ""} return; + file copy -force -- {*}$assets $targetDir + } + + # + # The actual refinements delivered by the mixin layer + # + + MixinLayer::Mixin create [current]::Entity -superclass TemplateData { + # + # TODO: Would it be useful to allow property slots to describe + # a per-class-object state, while the accessor/mutator methods + # are defined on the per-class level. It feels like the class + # instance variables in Smalltalk ... + # + # TODO: Why is call protection barfing when the protected target + # is called from within a public forward. This should qualify as + # a valid call site (from "within" the same object!), shouldn't it? + # :protected class property current_project:object,type=::nx::doc::@project + # :class property current_project:object,type=::nx::doc::@project + # :public forward current_project [current] %method + + # :public forward print_name %current name + + :public method statustoken {} { + set token "" + set obj [:origin] + set prj [:current_project] + if {[$prj is_validated]} { + if {[$obj eval {info exists :pdata}]} { + set token [$obj pinfo get -default "" status] + } else { + set token "extra" + } + } + return $token + } + + :public method statusmark {} { + set token [:statustoken] + set status_mark " " + } + :public method print_name {-status:switch} { + set status_mark [expr {$status?[:statusmark]:""}] + return "${:name}$status_mark" + } + + :method fit {str max {placeholder "..."}} { + if {[llength [split $str ""]] < $max} { + return $str; + } + set redux [llength [split $placeholder ""]] + set margin [expr {($max-$redux)/2}] + return "[string range $str 0 [expr {$margin-1}]]$placeholder[string range $str end-[expr {$margin+1}] end]" + } + + :public method as_dict {partof feature} { + set hash [dict create] + dict set hash access "" + dict set hash host [$partof name] + dict set hash name [:print_name] + # dict set hash url "[$partof filename].html#[string trimleft [$feature name] @]_${:name}" + dict set hash url "[:href $partof]" + dict set hash type [$feature pretty_name] + return $hash + } + + :method as_array_of_hashes {} { + set features [:navigatable_parts] + set js_array [list] + dict for {feature instances} $features { + foreach inst $instances { + set d [$inst as_dict [current] $feature] + set js_hash {{"access": "$access", "host": "$host", "name": "$name", "url": "$url", "type": "$type"}} + dict with d { + lappend js_array [subst $js_hash] + } + } + } + return "\[[join $js_array ,\n]\]" + } + + :public method navigatable_parts {} { + # + # TODO: Should I wrap up delegating calls to the originator + # entity behind a unified interface (a gatekeeper?) + # + return [[:origin] owned_parts \ + -where "!\${:@stashed}" \ + -class ::nx::doc::StructuredEntity] + } + + :method listing {{-inline true} script} { + set listing $script + if {!$inline} { + set listing [string trimright [nx::pp render [string trimright $script " \r\n"]] "\n"] + } + next [list -inline $inline $listing] + } + + :method link=tclcmd {cmd} { + # + # TODO: allow the parametrization of the reference URL at the + # project level ... + # + return "$cmd" + } + + :method link {tag value} { + set unresolvable "?" + if {[string first @ $tag] != 0} { + set m [current method]=$tag + if {[:info lookup methods \ + -source application \ + -callprotection public $m] eq ""} { + return $unresolvable + } + return [:$m $value] + } else { + set names $value + set tagpath [split [string trimleft $tag @] .] + lassign [::nx::doc::Tag normalise $tagpath $names] err res + if {$err} { + # puts stderr RES=$res + return $unresolvable; + } + lassign [::nx::doc::Tag find -all -strict {*}$res] err path + if {$err || $path eq ""} { + # puts stderr "FAILED res $path (err-$err-id-[expr {$path eq ""}])" + return $unresolvable; + } + + set path [dict create {*}$path] + set entities [dict keys $path] + set id [lindex $entities end] + return [$id render_link $tag [:rendered top] $path] + } + } + + :public method make_link {source} { + set path [dict create {*}[:get_upward_path -attribute {set :name}]] + set tag [[:info class] tag] + return [:render_link $tag $source $path] + } + + :public method render_link {tag source path} { + set id [current] + set pathnames [dict values $path] + set entities [dict keys $path] + set top_entity [lindex $entities 0] + set pof "" + if {$top_entity ne $id} { + set pof "[$top_entity name]#" + set pathnames [lrange $pathnames 1 end] + set entities [lrange $entities 1 end] + } + #return "$pof[join $pathnames .]" + # GN TODO: Maybe a nicer "title" property via method title? + #return "[join $pathnames { }]" + set iscript [join [list [list set title $pof[join $pathnames .]] \ + [list set source_anchor [join $pathnames { }]] \ + [list set top_entity $top_entity]] \n] + :render -initscript $iscript link + } + + :public method as_text {} { + set text [expr {[:origin] ne [current]?[[:origin] as_text]:[next]}] + return [string map {"\n\n" "

"} $text] + } + + :method getBase {top_entity:optional} { + set path [dict create {*}[:get_upward_path -attribute {set :name}]] + set originator_top_entity [lindex [dict keys $path] 0] + if {![info exists top_entity] || [dict size $path] == 1} { + set top_entity $originator_top_entity + } + dict unset path $originator_top_entity + set fragment_path [list] + #puts stderr FRAGMENTPATH=$path + dict for {entity name} $path { + lappend fragment_path [$entity filename] + } + return [list $top_entity $fragment_path] + } + + :public method href {-local:switch top_entity:optional} { + lassign [:getBase {*}[expr {[info exists top_entity]?$top_entity:""}]] base fragment_path + set fragments [join $fragment_path _] + if {$local} { + return $fragments + } else { + set href "[$base filename].html#$fragments" + #puts stderr HREF=$href + return $href + } + } + + :public method filename {} { + if {[info exists :partof]} { + return [string trimleft [${:part_attribute} name] @]_${:name} + } else { + return [[:info class] tag]_[string trimleft [string map {:: __} ${:name}] "_"] + } + } + + :public method as_tag_id {} { + set tagclass [:info class] + set tail [$tagclass get_tail_name [current]] + set tname [string trimleft [string map {:: _} $tail] "_"] + return [$tagclass tag]__$tname + } + + + }; # NxDocTemplating::Entity + + MixinLayer::Mixin create [current]::@project -superclass [current]::Entity { + :public method filename {} { + return "index" + } + :public method navigatable_parts {} { + # + # TODO: Should I wrap up delegating calls to the originator + # entity behind a unified interface (a gatekeeper?) + # + set top_level_entities [next] + dict for {feature instances} $top_level_entities { + if {[$feature name] eq "@package"} { + foreach pkg $instances { + dict for {pkg_feature pkg_feature_instances} [$pkg navigatable_parts] { + dict lappend top_level_entities $pkg_feature \ + {*}$pkg_feature_instances + } + } + } + } + return $top_level_entities + } + + } + + MixinLayer::Mixin create [current]::@glossary -superclass [current]::Entity { + + :public method print_name {} { + return [expr {[info exists :@acronym]?${:@acronym}:${:@pretty_name}}] + } + + array set :tags { + @gls { + set print_name [string tolower ${:@pretty_name} 0 0] + set title ${:@pretty_name} + } + @Gls { + set print_name [string toupper ${:@pretty_name} 0 0] + set title ${:@pretty_name} + } + @glspl { + set print_name [string tolower ${:@pretty_plural} 0 0] + set title ${:@pretty_plural} + } + @Glspl { + set print_name [string toupper ${:@pretty_plural} 0 0] + set title ${:@pretty_plural} + } + @acr { + set acronym(short) 1 + } + @acrfirst { + set acronym(long) 1 + } + + } + + :public method href {-local:switch top_entity:optional} { + set fragments "#${:name}" + if {$local} { + return $fragments + } else { + return "[[:current_project] filename].html$fragments" + } + + } + + :public method render_link {tag source path} { + # tag-specific rendering + set acronym(long) 0 + set acronym(short) 0 + set print_name ${:@pretty_name} + set title ${:@pretty_name} + if {[[current class] eval [list info exists :tags($tag)]]} { + eval [[current class] eval [list set :tags($tag)]] + } + if {[info exists :@acronym]} { + # + # First occurrance of an acronym entry! + # + if {!$acronym(short) && ($acronym(long) || ![info exists :refs] || \ + ![dict exists ${:refs} [:current_project] $source])} { + set print_name "$print_name (${:@acronym})" + } else { + set title $print_name + set print_name ${:@acronym} + set anchor "$print_name" + # TODO: Re-provide the environment + #set res "$anchor" + } + } + + # record for reverse references + if {![info exists :refs]} { + set :refs [dict create] + } + dict update :refs [:current_project] prj { + dict incr prj $source + } + + set iscript [join [list [list set title $title] \ + [list set source_anchor $print_name] \ + [list set top_entity [current]] \ + [list set cssclass nsfdoc-gloss]] \n] + set res [:render -initscript $iscript link] + return $res + } + }; # NxDocRenderer::@glossary + + MixinLayer::Mixin create [current]::@class -superclass [current]::Entity { + :method inherited {member} { + set inherited [dict create] + set prj [:current_project] + if {![$prj eval {info exists :sandbox}]} return; + set box [$prj sandbox] + set exp "expr {\[::nsf::is class ${:name}\]?\[lreverse \[${:name} info heritage\]\]:\"\"}" + set ipath [$box do $exp] + foreach c [concat $ipath ${:name}] { + set entity [[:info class] id $c] + if {![::nsf::is object $entity]} continue; + set origin [$entity origin] + if {$origin ni [concat {*}[dict values [$prj navigatable_parts]]]} continue; + + if {[$origin eval [list info exists :${member}]]} { + dict set inherited $entity [$entity !get \ + -sortedby name \ + -with name $member] + if {[info exists previous_entity]} { + dict set inherited $previous_entity \ + [dict remove [dict get $inherited $previous_entity] \ + {*}[dict keys [dict get $inherited $entity]]] + } + } + set previous_entity $entity + } + dict unset inherited [current] + return $inherited + } + } + + + MixinLayer::Mixin create [current]::@method -superclass [current]::Entity { + :public method as_dict {partof feature} { + set hash [next] + dict set hash access [expr {[:pinfo get -default 0 bundle call-protected]?"protected":""}] + return $hash + } + }; # html::@method + + }; # html renderer +} \ No newline at end of file Index: library/lib/nxdoc-xowiki.tcl =================================================================== diff -u --- library/lib/nxdoc-xowiki.tcl (revision 0) +++ library/lib/nxdoc-xowiki.tcl (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -0,0 +1,103 @@ +package provide nx::doc::xowiki 1.0 +namespace eval ::nx::doc {} + +package require nx::doc::html 1.0 +package require nx::serializer +package require base64 + +namespace eval ::nx::doc { + + Renderer create xowiki -extends [html] { + # + # yuidoc refinements + # + #$source_anchor + :addTemplate link yuidoc { + [:! lassign [:getBase {*}[expr {[info exists top_entity]?$top_entity:""}]] base fragment_path] + [:!let basename [expr {[$base info has type ::nx::doc::@glossary]?"en:glossary#[$base name]":"en:[$base filename]#[join $fragment_path _]"}]] + \[\[$basename|$source_anchor\]\] + } + + :method render {project entity theme {tmplName ""}} { + + + + set top_level_entities [$project navigatable_parts] + set init [subst { + set project $project + set project_entities \[list $top_level_entities\] + }] + $entity current_project $project + $entity renderer [current] + set content [$entity render -initscript $init -theme $theme body-chunked] + set p [::xowiki::Page new -name en:[$entity filename] \ + -title [$entity name] \ + -text [list $content text/html]] + return [$p serialize] + } + + :method installAssets {project theme targetDir} { + # + # render and append single glossary page to the output + # + + set top_level_entities [$project navigatable_parts] + set init [subst { + set project $project + set project_entities \[list $top_level_entities\] + set include glossary + }] + + set c [$project render \ + -initscript $init \ + -theme $theme \ + body-chunked] + set p [::xowiki::Page new \ + -name en:glossary \ + -title Glossary \ + -text [list $c text/html]] + :write [$p serialize] $targetDir + # + # TODO: assets (js, css, img must be wrapped as ::xowiki::Files) + # + set assets [glob -directory [file join [::nx::doc::find_asset_path] $theme] *] + + array set mime { + js application/x-javascript + css text/css + png image/png + gif image/gif + jpg image/jpg + } + foreach assetPath $assets { + set filename [file tail $assetPath] + set f [::xowiki::File new \ + -name file:$filename \ + -title $filename \ + -mime_type $mime([string trim [file extension $assetPath] "."])] + $f eval [list set :__file_content [::base64::encode [:read -binary $assetPath]]] + :write [$f serialize] $targetDir + } + } + }; # xowiki renderer + + # + # The necessary xowiki stubs + # + + namespace eval ::xowiki { + namespace import -force ::nx::* + Class create Page { + :property {lang en} + :property {description ""} + :property {text ""} + :property {nls_language en_US} + :property {mime_type text/html} + :property {title ""} + :property name + :property text + } + Class create File -superclass Page + } + +} \ No newline at end of file Index: library/lib/pkgIndex.tcl =================================================================== diff -u -ra4d79288048b336b38063dc0208ea220d460832f -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa --- library/lib/pkgIndex.tcl (.../pkgIndex.tcl) (revision a4d79288048b336b38063dc0208ea220d460832f) +++ library/lib/pkgIndex.tcl (.../pkgIndex.tcl) (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -8,6 +8,8 @@ # script is sourced, the variable $dir must contain the # full path name of this file's directory. -package ifneeded nx::doc 0.1 [list source [file join $dir doc-tools.tcl]] +package ifneeded nx::doc 1.0 [list source [file join $dir nxdoc-core.tcl]] +package ifneeded nx::doc::html 1.0 [list source [file join $dir nxdoc-html.tcl]] +package ifneeded nx::doc::xowiki 1.0 [list source [file join $dir nxdoc-xowiki.tcl]] package ifneeded nx::pp 1.0 [list source [file join $dir pp.tcl]] package ifneeded nx::test 1.0 [list source [file join $dir test.tcl]] Index: library/xotcl/doc/langRef.xotcl =================================================================== diff -u -ra24e1f836c3126d0a0e9467bde3a9fa8da901711 -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa --- library/xotcl/doc/langRef.xotcl (.../langRef.xotcl) (revision a24e1f836c3126d0a0e9467bde3a9fa8da901711) +++ library/xotcl/doc/langRef.xotcl (.../langRef.xotcl) (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -5,6 +5,20 @@ namespace eval ::xotcl {} namespace import -force ::xotcl::@ +# catch { +# @ XXX x x +# } msg + +# puts stderr $::errorInfo +if {$::tcl_version >= 8.6} { + # + # Without this [namespace which] (or any other [namespace *] + # command, the previously ::nxdoc::@ is called, rather than the + # imported ::xotcl::@?!?! + # + namespace which @ +} + @ @File { description { XOTcl language reference. Describes predefined objects and classes. Index: tests/doc.test =================================================================== diff -u -r8046b1da6bc0689f73d4dbdc3f8d1e03fd23acaf -rfa7635cbfe2309b8e6282e2c7925fa2617b061aa --- tests/doc.test (.../doc.test) (revision 8046b1da6bc0689f73d4dbdc3f8d1e03fd23acaf) +++ tests/doc.test (.../doc.test) (revision fa7635cbfe2309b8e6282e2c7925fa2617b061aa) @@ -82,1254 +82,1258 @@ set blocks {1 {{ @package o} { 1 2 3}} 5 {{ @object o} { 1 2 3} {} { 345} { @tag1 part1} { @tag2 part2}} 17 {{ @object o # ####} { 1 2 3} {} { 345} { @tag1 part1} { @tag2 part2}}} ? [list ::lcompare [processor comment_blocks $script] $blocks] 1 -} - -Test case parsing { - # - # TODO: Add tests for doc-parsing state machine. - # - set block { - {@command ::cc} } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 + Test case parsing { + # + # TODO: Add tests for doc-parsing state machine. + # + set block { + {@command ::cc} + } - set block { - {} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 0 - ? [list $cbp status ? STYLEVIOLATION] 1 - - # - # For now, a valid comment block must start with a non-space line - # (i.e., a tag or text line, depending on the section: context - # vs. description) - # - - set block { - {} - {@command ::cc} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + set block { + {} + } - set block { - {command ::cc} - {} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 0 + ? [list $cbp status ? STYLEVIOLATION] 1 + + # + # For now, a valid comment block must start with a non-space line + # (i.e., a tag or text line, depending on the section: context + # vs. description) + # + + set block { + {} + {@command ::cc} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + set block { + {command ::cc} + {} + } - set block { - {@command ::cc} - {some description} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - - set block { - {@command ::cc} - {} - {} - {} - {@see ::o} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 - ? [list $cbp status ? COMPLETED] 1 + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set block { - {@command ::cc} - {} - {some description} - {some description2} - {} - {} - } + set block { + {@command ::cc} + {some description} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + + set block { + {@command ::cc} + {} + {} + {} + {@see ::o} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 + ? [list $cbp status ? COMPLETED] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 + set block { + {@command ::cc} + {} + {some description} + {some description2} + {} + {} + } - # Note: We do allow description blocks with intermediate space - # lines, for now. - set block { - {@command ::cc} - {} - {some description} - {some description2} - {} - {an erroreneous description line, for now} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 - # - # TODO: Do not enforce space line between the context and immediate - # part block (when description is skipped)? - # - # OR: For absolutely object::qualifying parts (e.g., outside of an initcmd block), - # do we need sequences of _two_ (or more) tag lines, e.g. - # - # -- - # @object Foo - # @param attr1 - # -- - # - # THEN, we can only discriminate between the context and an - # immediate part section by requiring a space line! - # - # Alternatively, we can use the @see like syntax for object::qualifying: - # @param ::Foo#attr1 (I have a preference for this option). - set block { - {@command ::cc} - {@see someOtherEntity} - } + # Note: We do allow description blocks with intermediate space + # lines, for now. + set block { + {@command ::cc} + {} + {some description} + {some description2} + {} + {an erroreneous description line, for now} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - + # + # TODO: Do not enforce space line between the context and immediate + # part block (when description is skipped)? + # + # OR: For absolutely object::qualifying parts (e.g., outside of an initcmd block), + # do we need sequences of _two_ (or more) tag lines, e.g. + # + # -- + # @object Foo + # @param attr1 + # -- + # + # THEN, we can only discriminate between the context and an + # immediate part section by requiring a space line! + # + # Alternatively, we can use the @see like syntax for object::qualifying: + # @param ::Foo#attr1 (I have a preference for this option). + set block { + {@command ::cc} + {@see someOtherEntity} + } - # - # TODO: Disallow space lines between parts? Check back with Javadoc spec. - # - set block { - {@command ::cc} - {} - {@see SomeOtherEntity} - {add a line of description} - {} - {} - {@see SomeOtherEntity2} - {} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + # + # TODO: Disallow space lines between parts? Check back with Javadoc spec. + # + set block { + {@command ::cc} + {} + {@see SomeOtherEntity} + {add a line of description} + {} + {} + {@see SomeOtherEntity2} + {} + } - # - # TODO: Should we enforce a mandatory space line between description and part block? - # - set block { - {@command ::cc} - {} - {add a line of description} - {a second line of description} - {a third line of description} - {@see entity3} - {@see SomeOtherEntity2} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 + # + # TODO: Should we enforce a mandatory space line between description and part block? + # + set block { + {@command ::cc} + {} + {add a line of description} + {a second line of description} + {a third line of description} + {@see entity3} + {@see SomeOtherEntity2} + } - set block { - {@command ::cc} - {} - {add a line of description} - {a second line of description} - {a third line of description} - {} - {@see SomeOtherEntity2} - {} - {} - {an erroreneous description line, for now} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - - set block { - {@command ::cc} - {} - {add a line of description} - {a second line of description} - {} - {a third line of description} - {} - {@see SomeOtherEntity2} - } + set block { + {@command ::cc} + {} + {add a line of description} + {a second line of description} + {a third line of description} + {} + {@see SomeOtherEntity2} + {} + {} + {an erroreneous description line, for now} + } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 0 + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + + set block { + {@command ::cc} + {} + {add a line of description} + {a second line of description} + {} + {a third line of description} + {} + {@see SomeOtherEntity2} + } - set block { - {@object ::cc} - {} - {add a line of description} - {a second line of description} - {} - {@see SomeOtherEntity2} - {@xyz SomeOtherEntity2} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 0 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 + set block { + {@object ::cc} + {} + {add a line of description} + {a second line of description} + {} + {@see SomeOtherEntity2} + {@xyz SomeOtherEntity2} + } - set block { - {@class ::cc} - {} - {add a line of description} - {a second line of description} - {} - {@see SomeOtherEntity2} - {@xyz SomeOtherEntity2} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 + set block { + {@class ::cc} + {} + {add a line of description} + {a second line of description} + {} + {@see SomeOtherEntity2} + {@xyz SomeOtherEntity2} + } - # - # testing the doc object construction - # - set block { - {@object ::o} - {} - {some more text} - {and another line for the description} - {} - {@author stefan.sobernig@wu.ac.at} - {@author gustaf.neumann@wu-wien.ac.at} - } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity @author] "stefan.sobernig@wu.ac.at gustaf.neumann@wu-wien.ac.at"; - ? [list $entity as_text] "some more text and another line for the description"; - - set block { - {@command ::c} - {} - {some text on the command} - {} - {@see ::o} - } + # + # testing the doc object construction + # + set block { + {@object ::o} + {} + {some more text} + {and another line for the description} + {} + {@author stefan.sobernig@wu.ac.at} + {@author gustaf.neumann@wu-wien.ac.at} + } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity @author] "stefan.sobernig@wu.ac.at gustaf.neumann@wu-wien.ac.at"; + ? [list $entity as_text] "some more text and another line for the description"; + + set block { + {@command ::c} + {} + {some text on the command} + {} + {@see ::o} + } - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@command] 1 - ? [list $entity as_text] "some text on the command"; - ? [list $entity @see] "::o"; + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] - set block { - {@class ::C} - {} - {some text on the class entity} - {} - {@class-property attr1 Here! we check whether we can get a valid description block} - {for text spanning multiple lines} - } + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@command] 1 + ? [list $entity as_text] "some text on the command"; + ? [list $entity @see] "::o"; - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] + set block { + {@class ::C} + {} + {some text on the class entity} + {} + {@class-property attr1 Here! we check whether we can get a valid description block} + {for text spanning multiple lines} + } - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "some text on the class entity"; - ? [list llength [$entity @property]] 1 - ? [list [$entity @property] info has type ::nx::doc::@param] 1 - ? [list [$entity @property] as_text] "Here! we check whether we can get a valid description block for text spanning multiple lines" + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] -} + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "some text on the class entity"; + ? [list llength [$entity @property]] 1 + ? [list [$entity @property] info has type ::nx::doc::@param] 1 + ? [list [$entity @property] as_text] "Here! we check whether we can get a valid description block for text spanning multiple lines" -Test case in-situ-basics { - # - # basic test for in-situ documentation (initcmd block) - # - # - set script { - package req nx - namespace import -force ::nx::Class - Class create ::Foo { - # The class Foo defines the behaviour for all Foo objects + } + + Test case in-situ-basics { # - # @author gustaf.neumann@wu-wien.ac.at - # @author ssoberni@wu.ac.at - - # @.property attr1 + # basic test for in-situ documentation (initcmd block) + # # - # This property 1 is wonderful - # - # @see ::nx::VariableSlot - # @see ::nx::MetaSlot - :property attr1 - :property attr2 - :property attr3 + set script { + package req nx + namespace import -force ::nx::Class + Class create ::Foo { + # The class Foo defines the behaviour for all Foo objects + # + # @author gustaf.neumann@wu-wien.ac.at + # @author ssoberni@wu.ac.at + + # @.property attr1 + # + # This property 1 is wonderful + # + # @see ::nx::VariableSlot + # @see ::nx::MetaSlot + :property attr1 + :property attr2 + :property attr3 + + # @.method foo + # + # This describes the foo method + # + # @parameter a Provides a first value + # @parameter b Provides a second value + :method foo {a b} {;} + } + } - # @.method foo - # - # This describes the foo method - # - # @parameter a Provides a first value - # @parameter b Provides a second value - :method foo {a b} {;} + set prj [processor process -sandboxed -type eval $script] + + set entity [@class id ::Foo] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "The class Foo defines the behaviour for all Foo objects"; + ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" + # TODO: Fix the [@param id] programming scheme to allow (a) for + # entities to be passed and the (b) documented structures + set entity [@property id [@class id ::Foo] class attr1] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; + + set entity [@method id ::Foo class foo] + ? [list [@class id ::Foo] @method] $entity + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "This describes the foo method"; + + foreach p [$entity @parameter] expected { + "Provides a first value" + "Provides a second value" + } { + ? [list expr [list [$p as_text] eq $expected]] 1; + } + + $prj destroy } - } - - set prj [processor process -sandboxed -type eval $script] - - set entity [@class id ::Foo] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "The class Foo defines the behaviour for all Foo objects"; - ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" - # TODO: Fix the [@param id] programming scheme to allow (a) for - # entities to be passed and the (b) documented structures - set entity [@property id [@class id ::Foo] class attr1] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; - - set entity [@method id ::Foo class foo] - ? [list [@class id ::Foo] @method] $entity - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "This describes the foo method"; - - foreach p [$entity @parameter] expected { - "Provides a first value" - "Provides a second value" - } { - ? [list expr [list [$p as_text] eq $expected]] 1; - } - - $prj destroy -} -# TODO: how to realise scanning and parsing for mixed ex- and -# in-situ documentation? That is, how to differentiate between -# absolutely and relatively qualified comment blocks in line-based -# scanning phase (or later)? + # TODO: how to realise scanning and parsing for mixed ex- and + # in-situ documentation? That is, how to differentiate between + # absolutely and relatively qualified comment blocks in line-based + # scanning phase (or later)? -Test case mixed-mode-parsing { - - set script { - package req nx - namespace import -force ::nx::* - # @class ::Bar - # - # The class Bar defines the behaviour for all Bar objects - # - # @author gustaf.neumann@wu-wien.ac.at - # @author ssoberni@wu.ac.at - - # @class.property {::Bar attr1} - # - # This property 1 is wonderful - # - # @see ::nx::VariableSlot - # @see ::nx::MetaSlot - - # @class.class-method {::Bar foo} - # - # - # This describes the foo method - # - # @parameter a Provides a first value - # @parameter b Provides a second value - - # @class.object-method {::Bar foo} - # - # This describes the per-object foo method - # - # @parameter a Provides a first value - # @parameter b Provides a second value - - namespace eval ::ns1 { - ::nx::Object create ooo - } - Class create Bar { + Test case mixed-mode-parsing { - :property attr1 - :property attr2 - :property attr3 + set script { + package req nx + namespace import -force ::nx::* + # @class ::Bar + # + # The class Bar defines the behaviour for all Bar objects + # + # @author gustaf.neumann@wu-wien.ac.at + # @author ssoberni@wu.ac.at - # @.method foo - # - # This describes the foo method in the initcmd - # - # @parameter a Provides a first value - # @parameter b Provides a second value - - :public method foo {a b} { - # This describes the foo method in the method body + # @class.property {::Bar attr1} # - # @parameter a Provides a first value (refined) + # This property 1 is wonderful + # + # @see ::nx::VariableSlot + # @see ::nx::MetaSlot - } - - :public class method foo {a b c} { - # This describes the per-object foo method in the method body + # @class.class-method {::Bar foo} # - # @parameter b Provides a second value (refined) - # @parameter c Provides a third value (first time) + # + # This describes the foo method + # + # @parameter a Provides a first value + # @parameter b Provides a second value + # @class.object-method {::Bar foo} + # + # This describes the per-object foo method + # + # @parameter a Provides a first value + # @parameter b Provides a second value + + namespace eval ::ns1 { + ::nx::Object create ooo + } + Class create Bar { + + :property attr1 + :property attr2 + :property attr3 + + # @.method foo + # + # This describes the foo method in the initcmd + # + # @parameter a Provides a first value + # @parameter b Provides a second value + + :public method foo {a b} { + # This describes the foo method in the method body + # + # @parameter a Provides a first value (refined) + + } + + :public class method foo {a b c} { + # This describes the per-object foo method in the method body + # + # @parameter b Provides a second value (refined) + # @parameter c Provides a third value (first time) + + } + + } } - } - } - - set prj [processor process -sandboxed -type eval $script] - set entity [@class id ::Bar] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "The class Bar defines the behaviour for all Bar objects"; - ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" - - # TODO: Fix the [@param id] programming scheme to allow (a) for - # entities to be passed and the (b) documented structures - set entity [@property id [@class id ::Bar] class attr1] - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; - - set entity [@method id ::Bar class foo] - ? [list [@class id ::Bar] @method] $entity - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "This describes the foo method in the method body"; - - foreach p [$entity @parameter] expected { - "Provides a first value (refined)" - "Provides a second value" - } { - ? [list expr [list [$p as_text] eq $expected]] 1; - } - - - set entity [@method id ::Bar object foo] - ? [list [@class id ::Bar] @class-object-method] $entity - ? [list ::nsf::is object $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "This describes the per-object foo method in the method body"; - - foreach p [$entity @parameter] expected { - "Provides a first value" - "Provides a second value (refined)" - "Provides a third value (first time)" - } { - ? [list expr [list [$p as_text] eq $expected]] 1; - } - - $prj destroy -} - -Test case tag-notations-basics { - - # - # Some tests on structured/navigatable tag notations - # - - # adding support for parsing levels - - # -- @class.object.object {::D o1 o2} - set block { - {@..object o2 We have a tag notation sensitive to the parsing level} - } - - set entity [[@ @class ::D] @object o1] - set cbp [CommentBlockParser process -parsing_level 1 -partof_entity $entity $block] - ? [list $cbp status ? LEVELMISMATCH] 1 - set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] - ? [list $cbp status ? COMPLETED] 1 - set entity [$cbp current_entity] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity as_text] "We have a tag notation sensitive to the parsing level" - - set block { - {@..object {o2 o3} We still look for balanced specs} - } - - set entity [[@ @class ::D] @object o1] - set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - - # This fails because we do not allow uninitialised/non-existing - # entity objects (@object o) along the resolution path ... - set block { - {@class.object.property {::C o attr1} We have an invalid specification} - } - - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 - # ? [list $cbp message] "The tag 'object' is not supported for the entity type '@class'" - - set block { - {@class.method.property attr1 We have an imbalanced specification (the names are underspecified!)} - } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - ? [list $cbp message] "Imbalanced tag line spec: 'class method property' vs. 'attr1'" - - # For now, we do not verify and use a fixed scope of permissive tag - # names. So, punctuation errors or typos are most probably reported - # as imbalanced specs. In the mid-term run, this should rather - # become an INVALIDTAG condition. - set block { - {@cla.ss.method.parameter {::C foo p1} We mistyped a tag fragment} - } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? STYLEVIOLATION] 1 - ? [list $cbp message] "Imbalanced tag line spec: 'cla ss method parameter' vs. '::C foo p1'" - - set block { - {@cla,ss.method.parameter {::C foo p1} We mistyped a tag fragment} - } - set cbp [CommentBlockParser process $block] - ? [list $cbp status ? INVALIDTAG] 1 - ? [list $cbp message] "The entity type '@cla,ss' is not available." -} - -Test case tag-notations-extended { - set script { - # @class ::C - # - # The global description of ::C - # - # @property attr1 Here we can only provide a description block for object parameters - - # @class.object-method {::C sub} - # - # For now, we have to declare a family of sub methods explicitly - # (allows for providing some overview, shared description) - - - # @class.property {::C attr1} Here, we could also write '@class.class-property \{::C attr1\}', @property is a mere forwarder! In the context section, only one-liners are allowed! - - # @class.object.property {::C foo p1} A short description is ... - # - # .. is overruled by a long one ... - - # If addressing to a nested object, one strategy would be to use - # @object and provide the object identifier (which reflects the - # nesting, e.g. ::C::foo). However, we cannot distinguish between - # namespace qualifiers denoting an object, class or owning - # namespace! - # - # ISSUE: If specifying an axis ".object", we would have to define - # a part property @object on @class and @object. However, @object - # would be ambiguous now: It could be called in a freestanding - # (absolute) manner AND in a contextualised manner (in an initcmd - # script). In the latter case, it would fail because we would have - # to provide a FQ'ed name (which defeats the purpose of a nested = - # contextualised notation). - # - # SO: for now, we introduce a part property child-object (and - # child-class?) to discrimate between the two situations ... - # - # TODO: How to register this so created @object entity as nested - # object with the doc entity represented the parent object? - - Class create C { - # This is the initcmd-level description of ::C which overwrites the - # global description (see above) + set prj [processor process -sandboxed -type eval $script] + set entity [@class id ::Bar] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "The class Bar defines the behaviour for all Bar objects"; + ? [list $entity @author] "gustaf.neumann@wu-wien.ac.at ssoberni@wu.ac.at" - # @.property attr1 - # - # This is equivalent to writing "@class-property attr1" - :property attr1 { - # This description does not apply to the object parameter - # "attr1" owned by the ::C class, rather it is a description - # of the property slot object! How should we deal with this - # situation? Should this level overwrite the top-level and - # initcmd-level descriptions? + # TODO: Fix the [@param id] programming scheme to allow (a) for + # entities to be passed and the (b) documented structures + set entity [@property id [@class id ::Bar] class attr1] + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity @see] "::nx::VariableSlot ::nx::MetaSlot"; + + set entity [@method id ::Bar class foo] + ? [list [@class id ::Bar] @method] $entity + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "This describes the foo method in the method body"; + + foreach p [$entity @parameter] expected { + "Provides a first value (refined)" + "Provides a second value" + } { + ? [list expr [list [$p as_text] eq $expected]] 1; } - # @.class-object-property attr2 Carries a short desc only - :class property attr2 - # @.method foo - # - # @parameter p1 - set fooHandle [:public method foo {p1} { - # Here goes some method-body-level description - # - # @parameter p1 The most specific level! - return [current method]-$p1-[current] - }] + set entity [@method id ::Bar object foo] + ? [list [@class id ::Bar] @class-object-method] $entity + ? [list ::nsf::is object $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "This describes the per-object foo method in the method body"; - # @.object-method bar - # - # Before referring to its parts, an entity must exist; so - # declare eagerly ... + foreach p [$entity @parameter] expected { + "Provides a first value" + "Provides a second value (refined)" + "Provides a third value (first time)" + } { + ? [list expr [list [$p as_text] eq $expected]] 1; + } + + $prj destroy + } - # @.class-object-method.parameter {bar p1} + Test case tag-notations-basics { + # - # This extended form allows to describe a method parameter with all - # its structural features! - set barHandle [:public class method bar {p1} { - return [current method]-$p1-[current] - }] + # Some tests on structured/navigatable tag notations + # - # @.object foo 'foo' needs to be defined before referencing any of its parts! + # adding support for parsing levels - # @.object.property {foo p1} - # - # The first element in the name list is resolved into a fully - # qualified (absolute) entity, based on the object owning the - # initcmd! - Object create [current]::foo { - # Adding a line for the first time (not processed in the initcmd phase!) - - # @..property p1 - # - # This is equivalent to stating "@class-object-property p1" - :property p1 + # -- @class.object.object {::D o1 o2} + set block { + {@..object o2 We have a tag notation sensitive to the parsing level} } - # @.class Foo X - # - # By providing a fully-qualified identifier ("::Foo") you leave the - # context of the initcmd-owning object, i.e. you would NOT refer to - # a nested class object named "Foo" anymore! + set entity [[@ @class ::D] @object o1] + set cbp [CommentBlockParser process -parsing_level 1 -partof_entity $entity $block] + ? [list $cbp status ? LEVELMISMATCH] 1 + set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] + ? [list $cbp status ? COMPLETED] 1 + set entity [$cbp current_entity] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity as_text] "We have a tag notation sensitive to the parsing level" - # @.class.property {Foo p1} - # - # This is equivalent to stating "@child-class.class-property {Foo p1}" + set block { + {@..object {o2 o3} We still look for balanced specs} + } - # @.class.class-object-property {Foo p2} Y - Class create [current]::Foo { + set entity [[@ @class ::D] @object o1] + set cbp [CommentBlockParser process -parsing_level 2 -partof_entity $entity $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + + # This fails because we do not allow uninitialised/non-existing + # entity objects (@object o) along the resolution path ... + set block { + {@class.object.property {::C o attr1} We have an invalid specification} + } + + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 + # ? [list $cbp message] "The tag 'object' is not supported for the entity type '@class'" + + set block { + {@class.method.property attr1 We have an imbalanced specification (the names are underspecified!)} + } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + ? [list $cbp message] "Imbalanced tag line spec: 'class method property' vs. 'attr1'" + + # For now, we do not verify and use a fixed scope of permissive tag + # names. So, punctuation errors or typos are most probably reported + # as imbalanced specs. In the mid-term run, this should rather + # become an INVALIDTAG condition. + set block { + {@cla.ss.method.parameter {::C foo p1} We mistyped a tag fragment} + } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? STYLEVIOLATION] 1 + ? [list $cbp message] "Imbalanced tag line spec: 'cla ss method parameter' vs. '::C foo p1'" + + set block { + {@cla,ss.method.parameter {::C foo p1} We mistyped a tag fragment} + } + set cbp [CommentBlockParser process $block] + ? [list $cbp status ? INVALIDTAG] 1 + ? [list $cbp message] "The entity type '@cla,ss' is not available." + } + + Test case tag-notations-extended { + set script { + # @class ::C + # + # The global description of ::C + # + # @property attr1 Here we can only provide a description block for object parameters - # @..property p1 + # @class.object-method {::C sub} + # + # For now, we have to declare a family of sub methods explicitly + # (allows for providing some overview, shared description) + + + # @class.property {::C attr1} Here, we could also write '@class.class-property \{::C attr1\}', @property is a mere forwarder! In the context section, only one-liners are allowed! + + # @class.object.property {::C foo p1} A short description is ... + # + # .. is overruled by a long one ... + + # If addressing to a nested object, one strategy would be to use + # @object and provide the object identifier (which reflects the + # nesting, e.g. ::C::foo). However, we cannot distinguish between + # namespace qualifiers denoting an object, class or owning + # namespace! + # + # ISSUE: If specifying an axis ".object", we would have to define + # a part property @object on @class and @object. However, @object + # would be ambiguous now: It could be called in a freestanding + # (absolute) manner AND in a contextualised manner (in an initcmd + # script). In the latter case, it would fail because we would have + # to provide a FQ'ed name (which defeats the purpose of a nested = + # contextualised notation). # + # SO: for now, we introduce a part property child-object (and + # child-class?) to discrimate between the two situations ... # - # This is equivalent to stating "@class-property p1"; or - # '@class.object.property {::C Foo p1}' from the top-level. - :property p1 + # TODO: How to register this so created @object entity as nested + # object with the doc entity represented the parent object? - # @..class-object-property p2 - :class property p2 + Class create C { + # This is the initcmd-level description of ::C which overwrites the + # global description (see above) + + # @.property attr1 + # + # This is equivalent to writing "@class-property attr1" + :property attr1 { + # This description does not apply to the object parameter + # "attr1" owned by the ::C class, rather it is a description + # of the property slot object! How should we deal with this + # situation? Should this level overwrite the top-level and + # initcmd-level descriptions? + } + + # @.class-object-property attr2 Carries a short desc only + :class property attr2 + + # @.method foo + # + # @parameter p1 + set fooHandle [:public method foo {p1} { + # Here goes some method-body-level description + # + # @parameter p1 The most specific level! + return [current method]-$p1-[current] + }] + + # @.object-method bar + # + # Before referring to its parts, an entity must exist; so + # declare eagerly ... + + # @.class-object-method.parameter {bar p1} + # + # This extended form allows to describe a method parameter with all + # its structural features! + set barHandle [:public class method bar {p1} { + return [current method]-$p1-[current] + }] + + # @.object foo 'foo' needs to be defined before referencing any of its parts! + + # @.object.property {foo p1} + # + # The first element in the name list is resolved into a fully + # qualified (absolute) entity, based on the object owning the + # initcmd! + Object create [current]::foo { + # Adding a line for the first time (not processed in the initcmd phase!) + + # @..property p1 + # + # This is equivalent to stating "@class-object-property p1" + :property p1 + } + + # @.class Foo X + # + # By providing a fully-qualified identifier ("::Foo") you leave the + # context of the initcmd-owning object, i.e. you would NOT refer to + # a nested class object named "Foo" anymore! + + # @.class.property {Foo p1} + # + # This is equivalent to stating "@child-class.class-property {Foo p1}" + + # @.class.class-object-property {Foo p2} Y + Class create [current]::Foo { + + # @..property p1 + # + # + # This is equivalent to stating "@class-property p1"; or + # '@class.object.property {::C Foo p1}' from the top-level. + :property p1 + + # @..class-object-property p2 + :class property p2 + } + + + # @.class-object-method.sub-method {sub foo} + # + # ISSUE: Should submethods be navigatable through "method" (i.e., + # "@method.method.method ...") or "submethod" (i.e., + # "@method.submethod.submethod ...")? ISSUE: Should it be sub* with + # "-" (to correspond to "@class-object-method", "@class-method")? Also, we + # could allow both (@sub-method is the property name, @method is a + # forwarder in the context of an owning @method object!) + # + # @parameter p1 Some words on p1 + :class alias "sub foo" $fooHandle + + # @.method sub + # + # The desc of the ensemble object 'sub' + # + # @sub-method bar Only description available here ... + + # ISSUE: Should the helper object "sub" be documentable in its own + # right? This would be feasible with the dotted notation from + # within and outside the initcmd script block, e.g. "@object sub" or + # "@class.object {::C sub}" + # + # ISSUE: Is it correct to say the sub appears as per-object method + # and so do its submethods? Or is it misleading to document it that + # way? Having an "@class-object-submethod" would not make much sense to + # me?! + :alias "sub bar" $barHandle + + # @.class-object-method sub A brief desc + + # @.class-object-method {"sub foo2"} + # + # could allow both (@sub-method is the property name, @method is a + # forwarder in the context of an owning @method object!) + # + # @parameter p1 Some words on p1 + # @see anotherentity + # @author ss@thinkersfoot.net + :class alias "sub foo2" $fooHandle + } } - - # @.class-object-method.sub-method {sub foo} # - # ISSUE: Should submethods be navigatable through "method" (i.e., - # "@method.method.method ...") or "submethod" (i.e., - # "@method.submethod.submethod ...")? ISSUE: Should it be sub* with - # "-" (to correspond to "@class-object-method", "@class-method")? Also, we - # could allow both (@sub-method is the property name, @method is a - # forwarder in the context of an owning @method object!) - # - # @parameter p1 Some words on p1 - :class alias "sub foo" $fooHandle + # 1) process the top-level comments (PARSING LEVEL 0) + # - # @.method sub + processor readin $script + + + # --testing-- "@class ::C" + set entity [@class id ::C] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "The global description of ::C"; + # --testing-- "@class.property {::C attr1}" + set entity [@property id $entity class attr1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] "Here, we could also write '@class.class-property {::C attr1}', @property is a mere forwarder! In the context section, only one-liners are allowed!" + + # --testing-- "@class.object.property {::C foo p1} A short description is ..." + # set entity [@property id $entity class attr1] + # set entity [@object id -partof_name ::C -scope child foo] + # ? [list ::nsf::object::exists $entity] 1 + # ? [list $entity info has type ::nx::doc::@object] 1 + # ? [list $entity as_text] "" + # set entity [@property id $entity object p1] + # ? [list ::nsf::object::exists $entity] 1 + # ? [list $entity info has type ::nx::doc::@property] 1 + # ? [list $entity as_text] ".. is overruled by a long one ..." + + set entity [@object id ::C::foo] + ? [list ::nsf::object::exists $entity] 0 + set entity [@property id $entity class p1] + ? [list ::nsf::object::exists $entity] 0 + # ? [list $entity info has type ::nx::doc::@property] 1 + # ? [list $entity as_text] ".. is overruled by a long one ..." + + # --testing-- @class-object-property attr2 (its non-existance) + set entity [@property id [@class id ::C] object attr2] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @child-class Foo (its non-existance) + set entity [@class id ::C::Foo] + ? [list ::nsf::object::exists $entity] 0 + # --testing -- @method foo (its non-existance) + set entity [@method id ::C class foo] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @class-object-method.parameter {bar p1} (its non-existance) + set entity [@parameter id [@method id ::C class bar] "" p1] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @child-object.property {foo p1} (its non-existance) + set cl [@class id ::C::Foo] + ? [list ::nsf::object::exists $entity] 0 + set entity [@property id $cl class p1] + ? [list ::nsf::object::exists $entity] 0 + set entity [@property id $cl object p2] + ? [list ::nsf::object::exists $entity] 0 + # - # The desc of the ensemble object 'sub' + # 2) process the initcmd comments (PARSING LEVEL 1) # - # @sub-method bar Only description available here ... - # ISSUE: Should the helper object "sub" be documentable in its own - # right? This would be feasible with the dotted notation from - # within and outside the initcmd script block, e.g. "@object sub" or - # "@class.object {::C sub}" + puts stderr -----INITCMD------ + ::nsf::configure keepinitcmd true + eval $script + ::nsf::configure keepinitcmd false + lassign [processor readin \ + -parsing_level 1 \ + -docstring \ + -tag @class \ + -name ::C \ + [::C eval {set :__initcmd}]] _ processed_entities + # a) existing, but modified ... + + set entity [@class id ::C] + ? $_ $entity + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] "This is the initcmd-level description of ::C which overwrites the global description (see above)" + + set entity [@property id $entity class attr1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] {This is equivalent to writing "@class-property attr1"} + + + set entity [@object id ::C::foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity as_text] "'foo' needs to be defined before referencing any of its parts!"; # still empty! + set entity [@property id $entity object p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] "The first element in the name list is resolved into a fully qualified (absolute) entity, based on the object owning the initcmd!" + + # b) newly added ... + + # --testing-- @class-object-property attr2 + set entity [@property id [@class id ::C] object attr2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] "Carries a short desc only"; + + # --testing-- @child-class Foo + # TODO: provide a check against fully-qualified names in part specifications + set entity [@class id ::C::Foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@class] 1 + ? [list $entity as_text] {By providing a fully-qualified identifier ("::Foo") you leave the context of the initcmd-owning object, i.e. you would NOT refer to a nested class object named "Foo" anymore!} + + set entity [@property id [@class id ::C] class p1] + ? [list ::nsf::object::exists $entity] 0; # should be 0 at this stage! + + # --testing -- @method foo + set entity [@method id ::C class foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "" + # --testing-- @class-object-method.parameter {bar p1} (its non-existance) It + # still cannot exist as a documented entity, as the class method + # has not been initialised before! + set entity [@parameter id [@method id ::C class bar] "" p1] + ? [list ::nsf::object::exists $entity] 0 + # --testing-- @child-class.property {foo p1} (its non-existance) + # --testing-- @child-class.object-property {foo p2} (its non-existance) + set cl [@class id ::C::Foo] + ? [list ::nsf::object::exists $cl] 1 + set entity [@property id $cl class p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] {This is equivalent to stating "@child-class.class-property {Foo p1}"} + set entity [@property id $cl object p2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Y" + + set entity [@method id ::C class sub] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "The desc of the ensemble object 'sub'" + + set entity [@method id ::C class sub::bar] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Only description available here ..." + + set entity [@method id ::C object sub] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "A brief desc" + + set entity [@method id ::C object sub::foo2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@method] 1 + ? [list $entity as_text] "could allow both (@sub-method is the property name, @method is a forwarder in the context of an owning @method object!)" + ? [list $entity @see] "anotherentity" + # TODO: @author not supported for @method (fine so?) + # ? [list $entity @author] "ss@thinkersfoot" + set entity [@parameter id $entity "" p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Some words on p1" + # - # ISSUE: Is it correct to say the sub appears as per-object method - # and so do its submethods? Or is it misleading to document it that - # way? Having an "@class-object-submethod" would not make much sense to - # me?! - :alias "sub bar" $barHandle + # 3a) process the property initcmds and method bodies (PARSING LEVEL 2)! + # - # @.class-object-method sub A brief desc + set project [@project new -name "_%@"] + $project sandbox [Sandbox new] + processor process=@class $project [@class id ::C] - # @.class-object-method {"sub foo2"} + # methods ... + + set entity [@method id ::C class foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "Here goes some method-body-level description" + set entity [@parameter id [@method id ::C class foo] "" p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "The most specific level!" + + # attributes ... + + # attr1 + set entity [@property id [@class id ::C] class attr1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] {This description does not apply to the object parameter "attr1" owned by the ::C class, rather it is a description of the property slot object! How should we deal with this situation? Should this level overwrite the top-level and initcmd-level descriptions?} + # - # could allow both (@sub-method is the property name, @method is a - # forwarder in the context of an owning @method object!) + # 3b) nested objects/ classes (PARSING LEVEL 2)! # - # @parameter p1 Some words on p1 - # @see anotherentity - # @author ss@thinkersfoot.net - :class alias "sub foo2" $fooHandle - } - } - - # - # 1) process the top-level comments (PARSING LEVEL 0) - # - - processor readin $script - - - # --testing-- "@class ::C" - set entity [@class id ::C] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "The global description of ::C"; - # --testing-- "@class.property {::C attr1}" - set entity [@property id $entity class attr1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] "Here, we could also write '@class.class-property {::C attr1}', @property is a mere forwarder! In the context section, only one-liners are allowed!" + processor readin \ + -docstring \ + -parsing_level 2 \ + -tag @object \ + -name ::C::foo \ + [::C::foo eval {set :__initcmd}] + + processor process=@object $project [@object id ::C::foo] + + set entity [@object id ::C::foo] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@object] 1 + ? [list $entity as_text] "Adding a line for the first time (not processed in the initcmd phase!)"; # still empty! + set entity [@property id $entity object p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity info has type ::nx::doc::@property] 1 + ? [list $entity as_text] {This is equivalent to stating "@class-object-property p1"} + + processor readin \ + -docstring \ + -parsing_level 2 \ + -tag @class \ + -name ::C::Foo \ + [::C::Foo eval {set :__initcmd}] + processor process=@class $project [@class id ::C::Foo] + + set cl [@class id ::C::Foo] + ? [list ::nsf::object::exists $cl] 1 + set entity [@property id $cl class p1] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] {This is equivalent to stating "@class-property p1"; or '@class.object.property {::C Foo p1}' from the top-level.} + set entity [@property id $cl object p2] + ? [list ::nsf::object::exists $entity] 1 + ? [list $entity as_text] "" + + # + # basic testing of "properties" (switch attributes) + # - # --testing-- "@class.object.property {::C foo p1} A short description is ..." - # set entity [@property id $entity class attr1] - # set entity [@object id -partof_name ::C -scope child foo] - # ? [list ::nsf::object::exists $entity] 1 - # ? [list $entity info has type ::nx::doc::@object] 1 - # ? [list $entity as_text] "" - # set entity [@property id $entity object p1] - # ? [list ::nsf::object::exists $entity] 1 - # ? [list $entity info has type ::nx::doc::@property] 1 - # ? [list $entity as_text] ".. is overruled by a long one ..." + ? [list $cl eval {set :@deprecated}] 0 + ? [list $cl eval {set :@stashed}] 0 + ? [list $cl eval {set :@c-implemented}] 0 - set entity [@object id ::C::foo] - ? [list ::nsf::object::exists $entity] 0 - set entity [@property id $entity class p1] - ? [list ::nsf::object::exists $entity] 0 - # ? [list $entity info has type ::nx::doc::@property] 1 - # ? [list $entity as_text] ".. is overruled by a long one ..." + ? [list $cl @deprecated] 1 + ? [list $cl @stashed] 1 + ? [list $cl @c-implemented] 1 - # --testing-- @class-object-property attr2 (its non-existance) - set entity [@property id [@class id ::C] object attr2] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @child-class Foo (its non-existance) - set entity [@class id ::C::Foo] - ? [list ::nsf::object::exists $entity] 0 - # --testing -- @method foo (its non-existance) - set entity [@method id ::C class foo] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @class-object-method.parameter {bar p1} (its non-existance) - set entity [@parameter id [@method id ::C class bar] "" p1] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @child-object.property {foo p1} (its non-existance) - set cl [@class id ::C::Foo] - ? [list ::nsf::object::exists $entity] 0 - set entity [@property id $cl class p1] - ? [list ::nsf::object::exists $entity] 0 - set entity [@property id $cl object p2] - ? [list ::nsf::object::exists $entity] 0 + ? [list $cl eval {set :@deprecated}] 1 + ? [list $cl eval {set :@stashed}] 1 + ? [list $cl eval {set :@c-implemented}] 1 - # - # 2) process the initcmd comments (PARSING LEVEL 1) - # - - puts stderr -----INITCMD------ - ::nsf::configure keepinitcmd true - eval $script - ::nsf::configure keepinitcmd false - lassign [processor readin \ - -parsing_level 1 \ - -docstring \ - -tag @class \ - -name ::C \ - [::C eval {set :__initcmd}]] _ processed_entities - # a) existing, but modified ... - - set entity [@class id ::C] - ? $_ $entity - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] "This is the initcmd-level description of ::C which overwrites the global description (see above)" - - set entity [@property id $entity class attr1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] {This is equivalent to writing "@class-property attr1"} - - - set entity [@object id ::C::foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity as_text] "'foo' needs to be defined before referencing any of its parts!"; # still empty! - set entity [@property id $entity object p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] "The first element in the name list is resolved into a fully qualified (absolute) entity, based on the object owning the initcmd!" - - # b) newly added ... - - # --testing-- @class-object-property attr2 - set entity [@property id [@class id ::C] object attr2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] "Carries a short desc only"; - - # --testing-- @child-class Foo - # TODO: provide a check against fully-qualified names in part specifications - set entity [@class id ::C::Foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@class] 1 - ? [list $entity as_text] {By providing a fully-qualified identifier ("::Foo") you leave the context of the initcmd-owning object, i.e. you would NOT refer to a nested class object named "Foo" anymore!} - - set entity [@property id [@class id ::C] class p1] - ? [list ::nsf::object::exists $entity] 0; # should be 0 at this stage! - - # --testing -- @method foo - set entity [@method id ::C class foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "" - # --testing-- @class-object-method.parameter {bar p1} (its non-existance) It - # still cannot exist as a documented entity, as the class method - # has not been initialised before! - set entity [@parameter id [@method id ::C class bar] "" p1] - ? [list ::nsf::object::exists $entity] 0 - # --testing-- @child-class.property {foo p1} (its non-existance) - # --testing-- @child-class.object-property {foo p2} (its non-existance) - set cl [@class id ::C::Foo] - ? [list ::nsf::object::exists $cl] 1 - set entity [@property id $cl class p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] {This is equivalent to stating "@child-class.class-property {Foo p1}"} - set entity [@property id $cl object p2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Y" - - set entity [@method id ::C class sub] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "The desc of the ensemble object 'sub'" - - set entity [@method id ::C class sub::bar] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Only description available here ..." - - set entity [@method id ::C object sub] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "A brief desc" - - set entity [@method id ::C object sub::foo2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@method] 1 - ? [list $entity as_text] "could allow both (@sub-method is the property name, @method is a forwarder in the context of an owning @method object!)" - ? [list $entity @see] "anotherentity" - # TODO: @author not supported for @method (fine so?) - # ? [list $entity @author] "ss@thinkersfoot" - set entity [@parameter id $entity "" p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Some words on p1" - - # - # 3a) process the property initcmds and method bodies (PARSING LEVEL 2)! - # - - set project [@project new -name "_%@"] - $project sandbox [Sandbox new] - processor process=@class $project [@class id ::C] - - # methods ... - - set entity [@method id ::C class foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "Here goes some method-body-level description" - set entity [@parameter id [@method id ::C class foo] "" p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "The most specific level!" - - # attributes ... - - # attr1 - set entity [@property id [@class id ::C] class attr1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] {This description does not apply to the object parameter "attr1" owned by the ::C class, rather it is a description of the property slot object! How should we deal with this situation? Should this level overwrite the top-level and initcmd-level descriptions?} - - # - # 3b) nested objects/ classes (PARSING LEVEL 2)! - # - processor readin \ - -docstring \ - -parsing_level 2 \ - -tag @object \ - -name ::C::foo \ - [::C::foo eval {set :__initcmd}] - - processor process=@object $project [@object id ::C::foo] - - set entity [@object id ::C::foo] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@object] 1 - ? [list $entity as_text] "Adding a line for the first time (not processed in the initcmd phase!)"; # still empty! - set entity [@property id $entity object p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity info has type ::nx::doc::@property] 1 - ? [list $entity as_text] {This is equivalent to stating "@class-object-property p1"} - - processor readin \ - -docstring \ - -parsing_level 2 \ - -tag @class \ - -name ::C::Foo \ - [::C::Foo eval {set :__initcmd}] - processor process=@class $project [@class id ::C::Foo] - - set cl [@class id ::C::Foo] - ? [list ::nsf::object::exists $cl] 1 - set entity [@property id $cl class p1] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] {This is equivalent to stating "@class-property p1"; or '@class.object.property {::C Foo p1}' from the top-level.} - set entity [@property id $cl object p2] - ? [list ::nsf::object::exists $entity] 1 - ? [list $entity as_text] "" - - # - # basic testing of "properties" (switch attributes) - # + set entity [@method id ::C class foo] + ? [list $entity eval {set :@syshook}] 0 + ? [list $entity @syshook] 1 + ? [list $entity eval {set :@syshook}] 1 + ? [list $entity @syshook 0] {wrong # args: should be "get obj prop"} + ? [list $entity eval {set :@syshook 0}] 0 + ? [list $entity @syshook] 1 - ? [list $cl eval {set :@deprecated}] 0 - ? [list $cl eval {set :@stashed}] 0 - ? [list $cl eval {set :@c-implemented}] 0 - ? [list $cl @deprecated] 1 - ? [list $cl @stashed] 1 - ? [list $cl @c-implemented] 1 + } - ? [list $cl eval {set :@deprecated}] 1 - ? [list $cl eval {set :@stashed}] 1 - ? [list $cl eval {set :@c-implemented}] 1 - - set entity [@method id ::C class foo] - ? [list $entity eval {set :@syshook}] 0 - ? [list $entity @syshook] 1 - ? [list $entity eval {set :@syshook}] 1 - ? [list $entity @syshook 0] {wrong # args: should be "get obj prop"} - ? [list $entity eval {set :@syshook 0}] 0 - ? [list $entity @syshook] 1 - - -} - -Test case switch-parts { - - set script { - package req nx - namespace import ::nx::* - Class create Enil { - # The class Enil defines the behaviour for all Enil objects, - # however, it is deprecated and will be removed from the - # provided doc entities in the next iteration ... - # - # @author ssoberni@wu.ac.at - # @deprecated + Test case switch-parts { - # @.property attr1 - # - # This property 1 will be invisibile in the generated doc - # - # @stashed - :property attr1 + set script { + package req nx + namespace import ::nx::* + Class create Enil { + # The class Enil defines the behaviour for all Enil objects, + # however, it is deprecated and will be removed from the + # provided doc entities in the next iteration ... + # + # @author ssoberni@wu.ac.at + # @deprecated + + # @.property attr1 + # + # This property 1 will be invisibile in the generated doc + # + # @stashed + :property attr1 + + # @.method foo + # + # This describes the foo method which is called from within the + # nx-enabled Tcl engine + # + # @syshook + :public method foo {a b} {;} + + :public method baz {} { + # This method entity sets a couple of properties in series ... + # + # @property c-implemented syshook + } + } + } - # @.method foo - # - # This describes the foo method which is called from within the - # nx-enabled Tcl engine - # - # @syshook - :public method foo {a b} {;} + set prj [processor process -sandboxed -type eval $script] + set cl [@class id ::Enil] - :public method baz {} { - # This method entity sets a couple of properties in series ... - # - # @property c-implemented syshook - } + ? [list $cl eval {set :@deprecated}] 1 + ? [list $cl @deprecated] 1 + ? [list $cl eval {set :@c-implemented}] 0 + ? [list $cl eval {set :@stashed}] 0 + ? [list $cl @author] ssoberni@wu.ac.at + + set entity [@property id $cl class attr1] + ? [list $entity eval {set :@deprecated}] 0 + ? [list $entity eval {set :@stashed}] 1 + ? [list $entity @stashed] 1 + ? [list $entity eval {set :@c-implemented}] 0 + + set entity [@method id ::Enil class foo] + ? [list $entity eval {set :@deprecated}] 0 + ? [list $entity eval {set :@stashed}] 0 + ? [list $entity eval {set :@c-implemented}] 0 + ? [list $entity eval {set :@syshook}] 1 + ? [list $entity @syshook] 1 + + set entity [@method id ::Enil class baz] + ? [list $entity eval {set :@deprecated}] 0 + ? [list $entity eval {set :@stashed}] 0 + ? [list $entity eval {set :@c-implemented}] 1 + ? [list $entity @c-implemented] 1 + ? [list $entity eval {set :@syshook}] 1 + ? [list $entity @syshook] 1 + + } - } - - set prj [processor process -sandboxed -type eval $script] - set cl [@class id ::Enil] - - ? [list $cl eval {set :@deprecated}] 1 - ? [list $cl @deprecated] 1 - ? [list $cl eval {set :@c-implemented}] 0 - ? [list $cl eval {set :@stashed}] 0 - ? [list $cl @author] ssoberni@wu.ac.at - - set entity [@property id $cl class attr1] - ? [list $entity eval {set :@deprecated}] 0 - ? [list $entity eval {set :@stashed}] 1 - ? [list $entity @stashed] 1 - ? [list $entity eval {set :@c-implemented}] 0 - - set entity [@method id ::Enil class foo] - ? [list $entity eval {set :@deprecated}] 0 - ? [list $entity eval {set :@stashed}] 0 - ? [list $entity eval {set :@c-implemented}] 0 - ? [list $entity eval {set :@syshook}] 1 - ? [list $entity @syshook] 1 - - set entity [@method id ::Enil class baz] - ? [list $entity eval {set :@deprecated}] 0 - ? [list $entity eval {set :@stashed}] 0 - ? [list $entity eval {set :@c-implemented}] 1 - ? [list $entity @c-implemented] 1 - ? [list $entity eval {set :@syshook}] 1 - ? [list $entity @syshook] 1 - - -} -puts stderr ================================================= + if {0} { + puts stderr ================================================= -# TODO: Figure out where to place nsf.nxd for convenient location ... + # TODO: Figure out where to place nsf.nxd for convenient location ... -puts stderr >>>>>>>NextScriptingFramework<<<<<<<< -set project [::nx::doc::@project new \ - -name NextScriptingFramework \ - -url http://www.next-scripting.org/ \ - -version 1.0.0a \ - -@namespace "::nsf" \ - -sources { - package nsf - }] + puts stderr >>>>>>>NextScriptingFramework<<<<<<<< + set project [::nx::doc::@project new \ + -name NextScriptingFramework \ + -url http://www.next-scripting.org/ \ + -version 1.0.0a \ + -@namespace "::nsf" \ + -sources { + package nsf + }] -set ::nsf::includes { - ::nsf::alias - ::nsf::configure - ::nsf::current - ::nsf::finalize - ::nsf::interp - ::nsf::is - ::nsf::log - ::nsf::my - ::nsf::next - ::nsf::relation - ::nsf::tmpdir - ::nsf::assertion - ::nsf::objectsystem::create - ::nsf::dispatch - ::nsf::var::exists - ::nsf::exithandler - ::nsf::forward - ::nsf::var::import - ::nsf::object::exists - ::nsf::method - ::nsf::method::property - ::nsf::method::provide - ::nsf::object::qualify - ::nsf::method::require - ::nsf::setter - ::nsf::var::set -} + set ::nsf::includes { + ::nsf::alias + ::nsf::configure + ::nsf::current + ::nsf::finalize + ::nsf::interp + ::nsf::is + ::nsf::log + ::nsf::my + ::nsf::next + ::nsf::relation + ::nsf::tmpdir + ::nsf::assertion + ::nsf::objectsystem::create + ::nsf::dispatch + ::nsf::var::exists + ::nsf::exithandler + ::nsf::forward + ::nsf::var::import + ::nsf::object::exists + ::nsf::method + ::nsf::method::property + ::nsf::method::provide + ::nsf::object::qualify + ::nsf::method::require + ::nsf::setter + ::nsf::var::set + } -set project [processor process \ - -sandboxed \ - -validate \ - -include $::nsf::includes $project] + set project [processor process \ + -sandboxed \ + -validate \ + -include $::nsf::includes $project] -::nx::doc::make doc \ - -format html \ - $project \ - -theme yuidoc \ - -layout many-to-many \ - -outdir [::nsf::tmpdir] + ::nx::doc::make doc \ + -format html \ + $project \ + -theme yuidoc \ + -layout many-to-many \ + -outdir [::nsf::tmpdir] -::nx::doc::make doc \ - -format xowiki \ - $project \ - -theme yuidoc \ - -layout many-to-1 \ - -outdir [::nsf::tmpdir] + ::nx::doc::make doc \ + -format xowiki \ + $project \ + -theme yuidoc \ + -layout many-to-1 \ + -outdir [::nsf::tmpdir] -puts stderr >>>>>>>NextScriptingLanguage<<<<<<<< -set ::nx::excludes { - ::nsf::parametersfromslots - ::nx::infoOptions - ::nx::isSlotContainer - ::nx::slotObj -} -# lappend ::nx::excludes {*}::nsf::classes::nx::Object::[join { -# __default_property_call_protection -# __default_method_call_protection -# __resolve_method_path -# cleanup -# defaultmethod -# init -# objectparameter -# residualargs -# uplevel -# upvar -# } " ::nsf::classes::nx::Object::"] + puts stderr >>>>>>>NextScriptingLanguage<<<<<<<< -set project [::nx::doc::@project new \ - -name NextScriptingLanguage \ - -url http://www.next-scripting.org/ \ - -version 1.0.0a \ - -@namespace "::nx" \ - -sources { - package nx - } -depends $project] + set ::nx::excludes { + ::nsf::parametersfromslots + ::nx::infoOptions + ::nx::isSlotContainer + ::nx::slotObj + } -dict set timings process [time { + # lappend ::nx::excludes {*}::nsf::classes::nx::Object::[join { + # __default_property_call_protection + # __default_method_call_protection + # __resolve_method_path + # cleanup + # defaultmethod + # init + # objectparameter + # residualargs + # uplevel + # upvar + # } " ::nsf::classes::nx::Object::"] - # ISSUE: If calling '-namespace "::nx"' instead of '-@namespace - # "::nx"', we get an irritating failure. VERIFY! - processor process \ - -validate \ - -sandboxed \ - -exclude $::nx::excludes \ - $project -} 1] + set project [::nx::doc::@project new \ + -name NextScriptingLanguage \ + -url http://www.next-scripting.org/ \ + -version 1.0.0a \ + -@namespace "::nx" \ + -sources { + package nx + } -depends $project] -dict set timings make.html.yuidoc [time { - ::nx::doc::make doc $project \ - -outdir [::nsf::tmpdir] -} 1] + dict set timings process [time { -dict set timings make.html.asciidoc [time { -::nx::doc::make doc \ - -format html \ - $project \ - -theme asciidoc \ - -layout 1-to-1 \ - -outdir [::nsf::tmpdir] -} 1] + # ISSUE: If calling '-namespace "::nx"' instead of '-@namespace + # "::nx"', we get an irritating failure. VERIFY! + processor process \ + -validate \ + -sandboxed \ + -exclude $::nx::excludes \ + $project + } 1] -dict set timings make.xowiki.yuidoc [time { -::nx::doc::make doc \ - -format xowiki \ - $project \ - -theme yuidoc \ - -layout many-to-1 \ - -outdir [::nsf::tmpdir] -} 1] + dict set timings make.html.yuidoc [time { + ::nx::doc::make doc $project \ + -outdir [::nsf::tmpdir] + } 1] -dict for {probe t} $timings { - puts stderr "\t$probe -> $t" -} + dict set timings make.html.asciidoc [time { + ::nx::doc::make doc \ + -format html \ + $project \ + -theme asciidoc \ + -layout 1-to-1 \ + -outdir [::nsf::tmpdir] + } 1] -set project [::nx::doc::@project new \ - -name XOTcl2 \ - -url http://www.xotcl.org/ \ - -version 2.0.0 \ - -@namespace "::xotcl" \ - -sources { - @package XOTcl-langRef - }] + dict set timings make.xowiki.yuidoc [time { + ::nx::doc::make doc \ + -format xowiki \ + $project \ + -theme yuidoc \ + -layout many-to-1 \ + -outdir [::nsf::tmpdir] + } 1] -processor process \ - -sandboxed \ - $project + dict for {probe t} $timings { + puts stderr "\t$probe -> $t" + } -::nx::doc::make doc \ - -format html \ - $project \ - -theme yuidoc \ - -outdir [::nsf::tmpdir] + set project [::nx::doc::@project new \ + -name XOTcl2 \ + -url http://www.xotcl.org/ \ + -version 2.0.0 \ + -@namespace "::xotcl" \ + -sources { + @package XOTcl-langRef + }] -::nx::doc::make doc \ - -format xowiki \ - $project \ - -theme yuidoc \ - -layout many-to-1 \ - -outdir [::nsf::tmpdir] + processor process \ + -sandboxed \ + $project -# # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # -# # # # # # # # # # # # # # # # # # # # + ::nx::doc::make doc \ + -format html \ + $project \ + -theme yuidoc \ + -outdir [::nsf::tmpdir] -# 1) Test case scoping rules -> in Object->eval() + ::nx::doc::make doc \ + -format xowiki \ + $project \ + -theme yuidoc \ + -layout many-to-1 \ + -outdir [::nsf::tmpdir] -Test case issues? { + } + # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # - # TODO: where to locate the @ comments (in predefined.xotcl, in - # gentclAPI.decls)? how to deal with ::nsf::* vs. ::nx::* - - # TODO: which values are returned from Object->configure() and - # passed to init()? how to document residualargs()? + # 1) Test case scoping rules -> in Object->eval() - # TODO: Object->cleanup() said: "Resets an object or class into an - # initial state, as after construction." If by construction it means - # after create(), then cleanup() is missing a configure() call to - # set defaults, etc! - # ?? cleanup does not set defaults; depending on "softrecreate", it - # deletes instances, childobjects, procs, instprocs, ... + Test case issues? { - # TODO: what is Object->__next() for? + # TODO: where to locate the @ comments (in predefined.xotcl, in + # gentclAPI.decls)? how to deal with ::nsf::* vs. ::nx::* + + # TODO: which values are returned from Object->configure() and + # passed to init()? how to document residualargs()? - # See the following script: - # + # TODO: Object->cleanup() said: "Resets an object or class into an + # initial state, as after construction." If by construction it means + # after create(), then cleanup() is missing a configure() call to + # set defaults, etc! + # ?? cleanup does not set defaults; depending on "softrecreate", it + # deletes instances, childobjects, procs, instprocs, ... -# Object instproc defaultmethod {} {puts "[self proc]"; return [self]} -# Class A -# A instproc defaultmethod {} {puts "[self proc]"; [::xotcl::my info parent] __next} -# Class D -instproc t {} {puts "my stuff"} -# D create d1 -# puts [d1 t] -# ### we create a subobject named t, which shadows effectively D->t -# A create d1::t -# puts === -# # when we call "d1 t", we effectively call "d1::t", which calls "default method". -# # the defaultmethod should do a next on object d1. -# puts [d1 t] -# puts ===EXIT + # TODO: what is Object->__next() for? - # but seems - at least in this usecase broken. Deactivated - # in source for now. + # See the following script: + # - # TODO: why is XOTclOUplevelMethodStub/XOTclOUplevelMethod defined - # with "args" while it logically uses the stipulated parameter - # signature (level ...). is this because of the first pos, optional - # parameter? ... same goes for upvar() ... + # Object instproc defaultmethod {} {puts "[self proc]"; return [self]} + # Class A + # A instproc defaultmethod {} {puts "[self proc]"; [::xotcl::my info parent] __next} + # Class D -instproc t {} {puts "my stuff"} + # D create d1 + # puts [d1 t] + # ### we create a subobject named t, which shadows effectively D->t + # A create d1::t + # puts === + # # when we call "d1 t", we effectively call "d1::t", which calls "default method". + # # the defaultmethod should do a next on object d1. + # puts [d1 t] + # puts ===EXIT - # the logic is a tribute to the argument logic in Tcl, which complex. - # uplevel ?level? arg ?arg ...? - # It is a combination between an optional first argument and - # and an args logic. - # - # Most likely, it could be partly solved with a logic for optional - # first arguments (if the number of actual arguments is - # higher than the minimal number of arguments, one could fill optional - # parameter up..... but this calculation requires as well the interactions - # with nonpos arguments, which might be values for positional arguments - # as well.... not, sure, it is worth to invest much time here. + # but seems - at least in this usecase broken. Deactivated + # in source for now. - # TODO: how is upvar affected by the ":"-prefixing? -> AVOID_RESOLVERS ... + # TODO: why is XOTclOUplevelMethodStub/XOTclOUplevelMethod defined + # with "args" while it logically uses the stipulated parameter + # signature (level ...). is this because of the first pos, optional + # parameter? ... same goes for upvar() ... - # this is a tcl question, maybe version dependent. - + # the logic is a tribute to the argument logic in Tcl, which complex. + # uplevel ?level? arg ?arg ...? + # It is a combination between an optional first argument and + # and an args logic. + # + # Most likely, it could be partly solved with a logic for optional + # first arguments (if the number of actual arguments is + # higher than the minimal number of arguments, one could fill optional + # parameter up..... but this calculation requires as well the interactions + # with nonpos arguments, which might be values for positional arguments + # as well.... not, sure, it is worth to invest much time here. + # TODO: how is upvar affected by the ":"-prefixing? -> AVOID_RESOLVERS ... - # TODO: the objectsystems subcommand of ::nsf::configure does - # not really fit in there because it does not allow for configuring - # anything. it is a mere introspection-only command. relocate (can - # we extend standard [info] somehow, i.e., [info objectsystems] + # this is a tcl question, maybe version dependent. + - # what means "configuring anything"? - # maybe you are refering to "configure objectsystems" which is parked there. - # there would be an option to change the internally called methods via - # configure as well, but i think, one is asking for troubles by allowing - # this. - # extending info is possible via the shadowcommands, but the tct - # does not like it. - # - # ad configure: we could fold as well methodproperty and - # objectproperty into configure since these allow as well setting - # and querying.... - # - # configure method METHODHANDLE public - # configure object OBJECT metaclass - # - # but there, the object property is just for quering. - # Another option is define and "info" - # - # ::nsf::info object OBJECT metaclass - # ::nsf::info objectsystems - # - # but if we would fold these into tcl-info, conflicts with - # tcl will arise. - # ISSUE: Object->info->parameter() still needed to retrieve - # objectparameters? + # TODO: the objectsystems subcommand of ::nsf::configure does + # not really fit in there because it does not allow for configuring + # anything. it is a mere introspection-only command. relocate (can + # we extend standard [info] somehow, i.e., [info objectsystems] - # TODO: decide how to deal with @package and @project names (don't - # need namespace delimiters!) + # what means "configuring anything"? + # maybe you are refering to "configure objectsystems" which is parked there. + # there would be an option to change the internally called methods via + # configure as well, but i think, one is asking for troubles by allowing + # this. + # extending info is possible via the shadowcommands, but the tct + # does not like it. + # + # ad configure: we could fold as well methodproperty and + # objectproperty into configure since these allow as well setting + # and querying.... + # + # configure method METHODHANDLE public + # configure object OBJECT metaclass + # + # but there, the object property is just for quering. + # Another option is define and "info" + # + # ::nsf::info object OBJECT metaclass + # ::nsf::info objectsystems + # + # but if we would fold these into tcl-info, conflicts with + # tcl will arise. -} + # ISSUE: Object->info->parameter() still needed to retrieve + # objectparameters? + + # TODO: decide how to deal with @package and @project names (don't + # need namespace delimiters!) + + }