1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
# import.tcl --
#
# Importing indices into other formats.
#
# Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.
# ### ### ### ######### ######### #########
## Requisites
package require Tcl 8.4
package require struct::map
package require doctools::idx::structure
package require fileutil::paths
package require pluginmgr
package require snit
# ### ### ### ######### ######### #########
## API
snit::type ::doctools::idx::import {
# ### ### ### ######### ######### #########
## Options :: None
# ### ### ### ######### ######### #########
## Creation, destruction.
constructor {} {
install myconfig using ::struct::map ${selfns}::config
install myinclude using ::fileutil::paths ${selfns}::include
return
}
destructor {
$myconfig destroy
$myinclude destroy
# Clear the cache of loaded import plugins.
foreach k [array names myplugin] {
$myplugin($k) destroy
}
return
}
# ### ### ### ######### ######### #########
## Convert from other formats to the Tcl index serialization
method {import object text} {obj text {format {}}} {
$obj deserialize [$self import text $text $format]
return
}
method {import object file} {obj path {format {}}} {
$obj deserialize [$self import file $path $format]
return
}
# ### ### ### ######### ######### #########
method {import text} {text {format {}}} {
set plugin [$self GetPlugin $format]
set configuration [$myconfig get]
lappend configuration user $::tcl_platform(user)
lappend configuration format [$plugin plugin]
return [$plugin do import $text $configuration]
}
method {import file} {path {format {}}} {
# The plugin is not trusted to handle the file to convert.
return [$self import text [fileutil::cat $path] $format]
}
# ### ### ### ######### ######### #########
## Internal methods
method GetPlugin {format} {
if {$format eq {}} { set format docidx }
if {![info exists myplugin($format)]} {
set plugin [pluginmgr ${selfns}::fmt-$format \
-pattern doctools::idx::import::* \
-api { import } \
-setup [mymethod PluginSetup]]
::pluginmgr::paths $plugin doctools::idx::import
$plugin load $format
set myplugin($format) $plugin
} else {
set plugin $myplugin($format)
}
return $plugin
}
method PluginSetup {mgr ip} {
# Inject a pseudo package into the plugin interpreter the
# import plugins can use to check that they were loaded into a
# proper environment.
$ip eval {package provide doctools::idx::import::plugin 1}
# The import plugins may use msgcat, which requires access to
# tcl_platform during its initialization, and won't have it by
# default. We trust them enough to hand out the information.
# TODO :: remove user/wordSize, etc. We need only 'os'.
$ip eval [list array set ::tcl_platform [array get ::tcl_platform]]
# Provide an alias-command a plugin can use to ask for any
# file, so that it can handle the processing of include files,
# should its format have that concept. Like docidx. The alias
# will be directed to a method of ours and use the configured
# include paths to find the file, analogous to the GetFile
# procedure of doctools::idx::parse.
#8.5+: ::interp alias $ip include {} {*}[mymethod IncludeFile]
eval [linsert [mymethod IncludeFile] 0 ::interp alias $ip include {}]
return
}
method IncludeFile {currentfile path} {
# result = ok text fullpath error-code error-message
# Find the file, or not.
set fullpath [$self Locate $path]
if {$fullpath eq {}} {
return [list 0 {} $path notfound {}]
}
# Read contents, or not.
if {[catch {
set data [fileutil::cat $fullpath]
} msg]} {
set error notread
set emessage $msg
return [list 0 {} $fullpath notread $msg]
}
return [list 1 $data $fullpath {} {}]
}
method Locate {path} {
upvar 1 currentfile currentfile
if {$currentfile ne {}} {
set pathstosearch \
[linsert [$myinclude paths] 0 \
[file dirname [file normalize $currentfile]]]
} else {
set pathstosearch [$myinclude paths]
}
foreach base $pathstosearch {
set try [file join $base $path]
if {![file exists $try]} continue
return $try
}
# Nothing found
return {}
}
# ### ### ### ######### ######### #########
## State
# Array serving as a cache for the various plugin managers holding
# a specific import plugin.
variable myplugin -array {}
# A component managing the configuration given to the import
# plugins when they are invoked.
component myconfig -public config
component myinclude -public include
##
# ### ### ### ######### ######### #########
}
# ### ### ### ######### ######### #########
## Ready
package provide doctools::idx::import 0.2.1
return
|