2
votes

I'm a beginner on tcl/tk. I'm trying to create a package using namespace ensemble.

My idea is to create a set of file to keep it simple managing the project, something like <name_package>-<name_procedure>.tcl

May you explain me how to split a namespace ensemble into several files within a package?

I'm trying to do create one file containing

package provide <name> 0.1

namespace eval <namespace> {

namespace export proc1 proc2 proc3 ...
namespace ensemble create

}

and the files containing the procedures

package provide <name> 0.1

proc ::<namespace>::proc { ... } {

...

}

It doesn't work.

I'd appreciate any suggestion.

Many thanks

2

2 Answers

6
votes

I would use the pkgIndex file to source all the constituent files for your package. That will load everything up. Then declare the ensemble once the interpreter has everything loaded.

package ifneeded Mypackage 1.2.3 \
   "source \[file join [list $dir] pkg-part1.tcl\] ; \
    source \[file join [list $dir] pkg-part2.tcl\] ; \
    namespace ensemble create {...} ; \
    package provide Mypackage 1.2.3"

Don't 'provide' in each sub-component. Its better to provide the package once everything was successfully loaded into the interpreter so I'd do that at the end of the file, or in this case and the end loading the full set. If you really want to treat each part as a subpackage, there is no reason not to declare them as subpackages, with a master package that requires each subpackage. eg:

<main package>
  package require Package::part1
  package require Package::part2
  package provide Package 1.0

<subpackage files>
  namespace eval Package {
     ... stuff ...
  }
  ... more stuff ...
  package provide Package::partN 1.0

<pkgIndex.tcl>
  package ifneeded Package::part1 1.0 [list source [file join $dir part1.tcl]]
  package ifneeded Package::part2 1.0 [list source [file join $dir part2.tcl]]
  package ifneeded Package 1.0 [list source [file join $dir package.tcl]]

This model can be useful if the sub-components might be helpful on their own or if it might be handy to only load certain parts into an interp. The tcllib SASL package does this to avoid having some mechanisms loaded by default (eg NTLM).

0
votes

I solved. The second solution of patthoyts is perfect.

I modified it a bit adding

<subpackage files>
  namespace eval Package {
     namespace export <proc_name>
  }
  ... more stuff ...
  package provide Package::partN 1.0

and in the

<pkgIndex.tcl>
  package ifneeded Package::part1 1.0 [list source [file join $dir part1.tcl]]
  package ifneeded Package::part2 1.0 [list source [file join $dir part2.tcl]]
  package ifneeded Package 1.0 "[list source [file join $dir package.tcl]];\
                               namespace eval <package> {namespace ensemble create};\ 
                               package provide <package> 0.1"

Many many thanks