Index: library/lib/doc-assets/@class.html.yuidoc =================================================================== diff -u -rd9b47262886ea198bd62861a30a212ab0e31b3bb -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/lib/doc-assets/@class.html.yuidoc (.../@class.html.yuidoc) (revision d9b47262886ea198bd62861a30a212ab0e31b3bb) +++ library/lib/doc-assets/@class.html.yuidoc (.../@class.html.yuidoc) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -246,3 +246,36 @@ }] + +[:!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/doc-assets/@package.html.yuidoc =================================================================== diff -u -r77c371a2e4a1bd85367d11869de6e2dc9fac4771 -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/lib/doc-assets/@package.html.yuidoc (.../@package.html.yuidoc) (revision 77c371a2e4a1bd85367d11869de6e2dc9fac4771) +++ library/lib/doc-assets/@package.html.yuidoc (.../@package.html.yuidoc) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -1,75 +1,12 @@ -

Package: ${:name} - -

+

Package: ${:name}

[:as_text]
- - [:?var :@require {
Package requires: ${:@require}
-} ] - -
-
- - [:?var :@class { -

This package contains [llength ${:@class}] classes:

- -
- -
- } ] - - [:?var :@object { -

This package contains [llength ${:@object}] objects:

- -
- -
- } ] - - - [:?var :@command { -

This package contains [llength ${:@command}] commands:

- -
- -
- - } ] -
-
- -
-
+}] +[:include overview] Index: library/lib/doc-assets/body-chunked.html.yuidoc =================================================================== diff -u -r440400dcb01fed8b18c4a2d98e4eca5dbaf309e4 -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/lib/doc-assets/body-chunked.html.yuidoc (.../body-chunked.html.yuidoc) (revision 440400dcb01fed8b18c4a2d98e4eca5dbaf309e4) +++ library/lib/doc-assets/body-chunked.html.yuidoc (.../body-chunked.html.yuidoc) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -13,8 +13,10 @@
This is the API documentation for the [:name] project. -

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

+

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

+ [:!let parts $project_entities] + [:include overview] } - { [:include] Index: library/lib/doc-assets/glossary.html.yuidoc =================================================================== diff -u -r984a062f8f5693e249ef6fd36c863db2af6693a9 -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/lib/doc-assets/glossary.html.yuidoc (.../glossary.html.yuidoc) (revision 984a062f8f5693e249ef6fd36c863db2af6693a9) +++ library/lib/doc-assets/glossary.html.yuidoc (.../glossary.html.yuidoc) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -33,7 +33,7 @@ [:for src [dict keys $refs] { - [$src make_link [current]] + [$src make_link [current]]  ([dict get $refs $src]) Index: library/lib/doc-assets/hookmethod.html.yuidoc =================================================================== diff -u --- library/lib/doc-assets/hookmethod.html.yuidoc (revision 0) +++ library/lib/doc-assets/hookmethod.html.yuidoc (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -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/doc-assets/leftbar.html.yuidoc =================================================================== diff -u -r440400dcb01fed8b18c4a2d98e4eca5dbaf309e4 -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/lib/doc-assets/leftbar.html.yuidoc (.../leftbar.html.yuidoc) (revision 440400dcb01fed8b18c4a2d98e4eca5dbaf309e4) +++ library/lib/doc-assets/leftbar.html.yuidoc (.../leftbar.html.yuidoc) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -1,4 +1,4 @@ -[:!let self_owned_parts [[:origin] owned_parts -class ::nx::doc::StructuredEntity]] +[:!let self_owned_parts [:navigatable_parts]] [:!let owned_parts [dict merge $project_entities $self_owned_parts]] Index: library/lib/doc-assets/overview.html.yuidoc =================================================================== diff -u --- library/lib/doc-assets/overview.html.yuidoc (revision 0) +++ library/lib/doc-assets/overview.html.yuidoc (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -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/doc-tools.tcl =================================================================== diff -u -r65f8883a4596ea98365b7de1652700e3ac7394cc -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/lib/doc-tools.tcl (.../doc-tools.tcl) (revision 65f8883a4596ea98365b7de1652700e3ac7394cc) +++ library/lib/doc-tools.tcl (.../doc-tools.tcl) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -715,9 +715,10 @@ } :public method owned_parts { - -class:object + {-class:object "::nx::Object"} + -where } { - set r [dict create] + set __owned_parts [dict create] foreach {s cls} [:part_attributes] { # # Note: For the time being, we skip over the bottom-most level of @@ -728,15 +729,27 @@ [[$s part_class] info superclass -closure $class] eq ""} continue; set accessor [$s name] if {[info exists :$accessor]} { - dict set r $s [sorted [:$accessor] name] + 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 $r + return $__owned_parts } - + :public method validate {} { next - dict for {s entities} [:owned_parts] { + dict for {s entities} [:owned_parts -where "!\${:@stashed}"] { foreach e $entities { # TODO: for now, it is sufficient to escape @use chains # here. review later ... @@ -1085,6 +1098,14 @@ :public forward @method %self @class-method :public forward @class-object-method %self @object-method + + :public forward @hook %self @class-hook + :attribute @class-hook -class ::nx::doc::PartAttribute { + :pretty_name "Hook method" + :pretty_plural "Hook methods" + set :part_class ::nx::doc::@method + } + :attribute @class-method -class ::nx::doc::PartAttribute { :pretty_name "Provided method" :pretty_plural "Provided methods" @@ -1412,23 +1433,26 @@ Class create TemplateData { - #:attribute current_template_name - :class-object attribute renderer :public forward renderer [current] %method - #:class-object attribute current_theme - #:public forward current_theme [current] %method + :public forward rendered [current] %method + :class-object 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}] + } - # - # TODO: For now, this acts as the counterweight to "origin", - # when @use aliasing is used, processed_entity can be used to - # refer to the actual entity at the upper end of the aliasing - # chain. Verify, whether this is an acceptable approach ... - # - :class-object attribute rendered_entity:object,type=::nx::doc::Entity - :public forward rendered_entity [current] %method + :class-object method "rendered pop" {} { + set :__rendered_entity [lassign ${:__rendered_entity} e] + return $e + } + :class-object method "rendered top" {} { + return [lindex ${:__rendered_entity} 0] + } + :public method render_start {} {;} :public method render_end {} {;} @@ -1440,7 +1464,7 @@ -theme {name:substdefault "[namespace tail [:info class]]"} } { - :rendered_entity [current] + :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 \ @@ -1456,6 +1480,7 @@ $tmplscript }]] :render_end + :rendered pop return [string trim $content \n] } @@ -1483,20 +1508,26 @@ set r [uplevel 1 [list $origin eval [list ::set :$varname] ]] } + set where_clause "!\${:@stashed}" if {[info exists where]} { - set l [list] - foreach item $r { - if {[$item eval [list expr $where]]} { + append where_clause "&& $where" + } + set l [list] + foreach item $r { + if {![::nsf::isobject $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 - } + } + set r $l if {[info exists with]} { set l [list] foreach item $r { - lappend l [$item eval [list set :$with]] $item + lappend l [[$item origin] eval [list set :$with]] $item } set r $l } @@ -1547,7 +1578,7 @@ } return [uplevel 1 [list subst $next_then]] } - return [:$next {*}$args] + return [uplevel 1 [list [current] $next {*}$args]] } } @@ -1949,12 +1980,14 @@ return "\[[join $js_array ,\n]\]" } - :method navigatable_parts {} { + :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 -class ::nx::doc::StructuredEntity] + return [[:origin] owned_parts \ + -where "!\${:@stashed}" \ + -class ::nx::doc::StructuredEntity] } :method listing {{-inline true} script} { @@ -2000,7 +2033,7 @@ set path [dict create {*}$path] set entities [dict keys $path] set id [lindex $entities end] - return [$id render_link $tag [:rendered_entity] $path] + return [$id render_link $tag [:rendered top] $path] } } @@ -2094,7 +2127,7 @@ dict for {feature instances} $top_level_entities { if {[$feature name] eq "@package"} { foreach pkg $instances { - dict for {pkg_feature pkg_feature_instances} [$pkg owned_parts] { + dict for {pkg_feature pkg_feature_instances} [$pkg navigatable_parts] { dict lappend top_level_entities $pkg_feature \ {*}$pkg_feature_instances } @@ -2369,19 +2402,29 @@ # 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 [lindex ${:current_packages} end] + set cpackage [:cpackage top] if {$cpackage in ${:permissive_pkgs}} { lappend :source $cpackage $filepath } } - :public method at_register_package {pkg_name} { - lappend :current_packages [string tolower $pkg_name] + :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] - } +# :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] \ @@ -2394,7 +2437,8 @@ ] { # peek the currently processed package (if any) set storable_vars [info vars >*] - set cpackage [lindex ${:current_packages} end] + # 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 { @@ -2404,7 +2448,7 @@ } :public method at_deregister_command [list name:fqn,slot=[current]] { - set cpackage [lindex ${:current_packages} end] + set cpackage [:cpackage top] if {$cpackage in ${:permissive_pkgs}} { dict unset :registered_commands $name } @@ -2613,8 +2657,9 @@ switch -glob -- $subcmd { ifneeded { lassign $args pkg_name version script - append wrapped_script "::nx::doc::__at_register_package $pkg_name;\n" $script "\n::nx::doc::__at_deregister_package;" + 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 @@ -2637,9 +2682,9 @@ #::interp hide "" auto_import ::proc ::auto_import {pattern} { set ns [uplevel [list namespace current]] - ::nx::doc::__at_register_package TCL_LIBRARY; + ::nx::doc::__cpackage push TCL_LIBRARY; interp invokehidden "" -namespace $ns auto_import $pattern - ::nx::doc::__at_deregister_package; + ::nx::doc::__cpackage pop; } } proc __init {} { @@ -2965,10 +3010,10 @@ "" [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_deregister_package \ - "" [current] at_deregister_package ::interp alias ${:interp} ::nx::doc::__at_source \ "" [current] at_source next @@ -3284,6 +3329,19 @@ } } + 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 @@ -3293,12 +3351,9 @@ set prj [:current_project] if {$prj ne ""} { set box [$prj sandbox] - #puts stderr "--- ::nsf::dispatch $obj ::nsf::methods::${scope}::info::method handle $method_name" - set script "array set \"\" \[$obj eval {:__resolve_method_path \"$method_name\"}\]; ::nsf::dispatch \$(object) ::nsf::methods::${scope}::info::method handle \$(methodName)" + set script "if {\[::nsf::isobject $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]]} { - #puts stderr "--- SETTING PDATA for [current] -> $cmdname" - #puts stderr "[$box eval [concat dict get \${:registered_commands} $cmdname]]" :pdata [$box eval [concat dict get \${:registered_commands} $cmdname]] } } @@ -3400,6 +3455,11 @@ 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 @@ -3421,8 +3481,6 @@ } # 2. generated entities (doc[no]->program[yes]) - # => all registered_commands without doc entity - #puts stderr "== TO GENERATE == [join [dict keys $generated_commands] \n]" dict for {cmd info} $generated_commands { dict with info { if {$cmdtype ni [list @command @object @class @method]} continue; @@ -3569,9 +3627,9 @@ # 1-pass. # append 2pass \ - "::nx::doc::__at_register_package $pkg;\n" \ + "::nx::doc::__cpackage push $pkg;\n" \ "source $src;\n" \ - "::nx::doc::__at_deregister_package;\n" + "::nx::doc::__cpackage pop;\n" } $box do "::nx::doc::__init; $2pass" } Index: library/nx/nx.nxd =================================================================== diff -u -r8cfd5973ca93d4c014d0a0500bc4151972e1d80a -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/nx/nx.nxd (.../nx.nxd) (revision 8cfd5973ca93d4c014d0a0500bc4151972e1d80a) +++ library/nx/nx.nxd (.../nx.nxd) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -187,7 +187,7 @@ # Methods of ::nx::Class ######################################################################## -# @class.method {Class alloc} +# @class.hook {Class alloc} # # Creates an uninitialized object. The method '''alloc''' is used by # <<@class.method "::nx::Class create">> to allocate an object and to @@ -196,7 +196,6 @@ # situations, an application developer may consider bypassing the # overall '''create''' mechanism to create uninitialized objects. # -# @property syshook # @parameter objectName The designated object identifier assigned to the # object storage to be allocated. # @return The name of the allocated, uninitialized object @@ -253,9 +252,8 @@ # @parameter args arguments to be passed down to the object creation # procedure used to initialize the object. # @return The name of the created, fully initialized object. -# @syshook -# @class.method {Class dealloc} +# @class.hook {Class dealloc} # # Marks objects for physical deletion in memory. Beware the fact # that calling '''dealloc''' does not necessarily cause the object @@ -267,10 +265,9 @@ # '''::nx::Class''', you may consider refining it in a subclass or # <<@gls mixincls>> for customizing the destruction process. # -# @syshook # @parameter object The name of the object to be scheduled for deletion. -# @class.method {Class recreate} +# @class.hook {Class recreate} # # This method is called upon recreating an object. Recreation is the # scheme for resolving object naming conflicts in the dynamic and @@ -304,15 +301,14 @@ # @parameter args Arbitrary vector of arguments # @return The name of the recreated object -# @class.method {Object residualargs} +# @class.hook {Object residualargs} # # The implementation of the abstracted '''residualargs''' hook called # from within the '''interp''' when executing <<@class.method {Object # configure}>>. It allows for selectively processing the remainder of # the object argument vector, to be forwarded to the constructor # <<@class.method {Object init}>>. # -# @syshook # @parameter args # @class.method {Object cleanup} @@ -326,7 +322,7 @@ # # @syshook -# @class.method {Class unknown} +# @class.hook {Object unknown} # # A hook implementation of the abstracted '''unknown''' hook, called # from within the '''interp''' when the method argument could not @@ -336,8 +332,6 @@ # @parameter args Contains the remainder of the original # argument vector of the indirected method # invocation -# -# @syshook # @command next # @@ -347,7 +341,7 @@ # # @use ::nsf::current -# @class.method {Object configure} +# @class.hook {Object configure} # # This method participates in the object creation process. It is # automatically invoked after having produced a new object by @@ -361,11 +355,10 @@ # "::nx::Object objectparameter">>). The method '''configure''' # can be called at arbitrary times to "re-set" an object. # -# @syshook # @parameter args The variable argument vector stores the object # parameters and their values -# @class.method {Object defaultmethod} +# @class.hook {Object defaultmethod} # # An abstracted hook method which is invoked upon calls to an object # without providing a method name to identify the receiver. In <<@gls @@ -378,10 +371,8 @@ # ''' # This hook is a versatile extension mechanism to alter the standalone # use of Tcl commands representing objects. -# -# @syshook -# @class.method {Object init} +# @class.hook {Object init} # # An abstracted hook method which participates in the object creation # process controlled by <<@class.method {Class create}>>. It is @@ -396,7 +387,6 @@ # {Class new}>> or <<@class.method {Class # create}>>. See also <<@class.method {Object # residualargs}>> -# @syshook # @class.method {Object destroy} # @@ -429,10 +419,7 @@ # Note, however, that '''destroy''' is protected against # application-level redefinition. You must refine it in a subclass # or a <<@gls mixin_class>>. -# -# @syshook - # @class.method {Object uplevel} # # This helper allows you to evaluate a script in the context of @@ -610,9 +597,7 @@ # representing an object. # # @parameter newName The name of the target object -# @syshook - # @class.method {Class forward} # # @use class.method {Object forward} @@ -629,6 +614,16 @@ # @parameter name # @syshook +# @class.hook {Class __unknown} +# +# This method is an abstracted hook method which is invoked from +# within the language runtime upon resolving unknown classes. A class +# is considered "unknown" when no so-named Tcl command is registered +# with the current '''interp'''. The method can be replaced by +# application-level implementations to realise application-specific +# class name resolution and class acquisition schemes. +# +# @parameter name # @class.method {Object info} # @@ -813,7 +808,7 @@ # If set to '''true''', the accessor methods are registered with the # domain object scope only. It defaults to '''false'''. -# @class.method {Object objectparameter} +# @class.hook {Object objectparameter} # # An abstracted hook method which is primarily used from within the # object creation process, that is, the object configuration step @@ -825,7 +820,6 @@ # way. By providing custom hook implementations (by overloading), # developers can define their own object parametrisation scheme. # -# @syshook # @parameter lastparameter Denotes the object parameter to be appended # to the overall object parameter # specification (i.e., at the last Index: library/nx/nx.tcl =================================================================== diff -u -r4536c2540977c43aaf422800dab048e5d9063b3f -rbbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1 --- library/nx/nx.tcl (.../nx.tcl) (revision 4536c2540977c43aaf422800dab048e5d9063b3f) +++ library/nx/nx.tcl (.../nx.tcl) (revision bbf48b80f31cfe50ba2114cf0ec6f1465b60c2e1) @@ -17,6 +17,7 @@ -class.dealloc dealloc -class.recreate recreate -class.requireobject __unknown + -object.cleanup cleanup -object.configure configure -object.defaultmethod defaultmethod -object.destroy destroy