summaryrefslogtreecommitdiff
path: root/scripts/context/ruby/rlxtools.rb
blob: 7962474eb10451d756432bdf382e119279268da7 (plain)
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#!/usr/bin/env ruby

# program   : rlxtools
# copyright : PRAGMA Advanced Document Engineering
# version   : 2004-2005
# author    : Hans Hagen
#
# project   : ConTeXt / eXaMpLe
# concept   : Hans Hagen
# info      : j.hagen@xs4all.nl
# www       : www.pragma-ade.com

banner = ['RlxTools', 'version 1.0.1', '2004/2005', 'PRAGMA ADE/POD']

unless defined? ownpath
    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
    $: << ownpath
end

require 'base/switch'
require 'base/logger'
require 'base/system'
require 'base/kpse'

require 'ftools'
require 'rexml/document'

class Commands

    include CommandBase

    # <?xml version='1.0 standalone='yes'?>
    # <rl:manipulators>
    #    <rl:manipulator name='lowres' suffix='pdf'>
    #         <rl:step>
    #             texmfstart
    #             --verbose
    #             --iftouched=<rl:value name='path'/>/<rl:value name='file'/>,<rl:value name='path'/>/<rl:value name='prefix'/><rl:value name='file'/>
    #             pstopdf
    #             --method=5
    #             --inputpath=<rl:value name='path'/>
    #             --outputpath=<rl:value name='path'/>/<rl:value name='prefix'/>
    #             <rl:value name='file'/>
    #         </rl:step>
    #     </rl:manipulator>
    # </rl:manipulators>
    #
    # <?xml version='1.0' standalone='yes'?>
    # <rl:library>
    #     <rl:usage>
    #         <rl:type>figure</rl:type>
    #         <rl:state>found</rl:state>
    #         <rl:file>cow.pdf</rl:file>
    #         <rl:suffix>pdf</rl:suffix>
    #         <rl:path>.</rl:path>
    #         <rl:conversion>lowres</rl:conversion>
    #         <rl:prefix>lowres/</rl:prefix>
    #         <rl:width>276.03125pt</rl:width>
    #         <rl:height>200.75pt</rl:height>
    #     </rl:usage>
    # </r:library>

    def manipulate

        procname = @commandline.argument('first')  || ''
        filename = @commandline.argument('second') || ''

        procname = Kpse.found(procname)

        if procname.empty? || ! FileTest.file?(procname) then
            report('provide valid manipulator file')
        elsif filename.empty? || ! FileTest.file?(filename) then
            report('provide valid resource log file')
        else
            begin
                data = REXML::Document.new(File.new(filename))
            rescue
                report('provide valid resource log file (xml error)')
                return
            end
            begin
                proc = REXML::Document.new(File.new(procname))
            rescue
                report('provide valid manipulator file (xml error)')
                return
            end
            report("manipulator file: #{procname}")
            report("resourcelog file: #{filename}")
            begin
                nofrecords, nofdone = 0, 0
                REXML::XPath.each(data.root,"/rl:library/rl:usage") do |usage|
                    nofrecords += 1
                    variables = Hash.new
                    usage.elements.each do |e|
                        variables[e.name] = e.text.to_s
                    end
                    report("processing record #{nofrecords} (#{variables['file'] || 'noname'}: #{variables.size} entries)")
                    if conversion = variables['conversion'] then
                        report("testing for conversion #{conversion}")
                        if suffix = variables['suffix'] then
                            if file = variables['file'] then
                                report("conversion #{conversion} for suffix #{suffix} for file #{file}")
                            else
                                report("conversion #{conversion} for suffix #{suffix}")
                            end
                            pattern = "@name='#{conversion}' and @suffix='#{suffix}'"
                            if steps = REXML::XPath.first(proc.root,"/rl:manipulators/rl:manipulator[#{pattern}]") then
                                localsteps = steps.deep_clone
                                ['rl:old','rl:new'].each do |tag|
                                    REXML::XPath.each(localsteps,tag) do |extras|
                                        REXML::XPath.each(extras,"rl:value") do |value|
                                            if name = value.attributes['name'] then
                                                substititute(value,variables[name.to_s])
                                            end
                                        end
                                    end
                                end
                                old = REXML::XPath.first(localsteps,"rl:old")
                                new = REXML::XPath.first(localsteps,"rl:new")
                                if old && new then
                                    old, new = justtext(old.to_s), justtext(new.to_s)
                                    variables['old'], variables['new'] = old, new
                                    begin
                                        [old,new].each do |d|
                                            File.makedirs(File.dirname(d))
                                        end
                                    rescue
                                        report("error during path creation")
                                    end
                                    report("old file #{old}")
                                    report("new file #{new}")
                                    level = if File.needsupdate(old,new) then 2 else 0 end
                                else
                                    level = 1
                                end
                                if level>0 then
                                    REXML::XPath.each(localsteps,"rl:step") do |command|
                                        REXML::XPath.each(command,"rl:old") do |value|
                                            replace(value,old)
                                        end
                                        REXML::XPath.each(command,"rl:new") do |value|
                                            replace(value,new)
                                        end
                                        REXML::XPath.each(command,"rl:value") do |value|
                                            if name = value.attributes['name'] then
                                                substititute(value,variables[name.to_s])
                                            end
                                        end
                                        str = justtext(command.to_s)
                                        # str.gsub!(/(\.\/)+/io, '')
                                        report("command #{str}")
                                        System.run(str) unless @commandline.option('test')
                                        report("synchronizing #{old} and #{new}")
                                        File.syncmtimes(old,new) if level > 1
                                        nofdone += 1
                                    end
                                else
                                    report("no need for a manipulation")
                                end
                            else
                                report("no manipulator found")
                            end
                        else
                            report("no suffix specified")
                        end
                    else
                        report("no conversion needed")
                    end
                end
                if nofdone > 0 then
                    jobname = filename.gsub(/\.(.*?)$/,'') # not 'tuo' here
                    tuoname = jobname + '.tuo'
                    if FileTest.file?(tuoname) && (f = File.open(tuoname,'a')) then
                        f.puts("%\n% number of rlx manipulations: #{nofdone}\n")
                        f.close
                    end
                end
            rescue
                report('error in manipulating files')
            end
            begin
                logname = "#{filename}.log"
                File.delete(logname) if FileTest.file?(logname)
                File.copy(filename,logname)
            rescue
            end
        end

    end

    private

    def justtext(str)
        str = str.to_s
        str.gsub!(/<[^>]*?>/o, '')
        str.gsub!(/\s+/o, ' ')
        str.gsub!(/&lt;/o, '<')
        str.gsub!(/&gt;/o, '>')
        str.gsub!(/&amp;/o, '&')
        str.gsub!(/&quot;/o, '"')
        str.gsub!(/[\/\\]+/o, '/')
        return str.strip
    end

    def substititute(value,str)
        if str then
            begin
                if value.attributes.key?('method') then
                    str = filtered(str.to_s,value.attributes['method'].to_s)
                end
                if str.empty? && value.attributes.key?('default') then
                    str = value.attributes['default'].to_s
                end
                value.insert_after(value,REXML::Text.new(str.to_s))
            rescue Exception
            end
        end
    end

    def replace(value,str)
        if str then
            begin
                value.insert_after(value,REXML::Text.new(str.to_s))
            rescue Exception
            end
        end
    end

    def filtered(str,method)

        str = str.to_s # to be sure
        case method
            when 'name' then # no path, no suffix
                case str
                    when /^.*[\\\/](.+?)\..*?$/o then $1
                    when /^.*[\\\/](.+?)$/o      then $1
                    when /^(.*)\..*?$/o          then $1
                    else                              str
                end
            when 'path'     then if str =~ /^(.+)([\\\/])(.*?)$/o then $1 else ''  end
            when 'suffix'   then if str =~ /^.*\.(.*?)$/o         then $1 else ''  end
            when 'nosuffix' then if str =~ /^(.*)\..*?$/o         then $1 else str end
            when 'nopath'   then if str =~ /^.*[\\\/](.*?)$/o     then $1 else str end
            else                                                               str
        end
    end

end

logger      = Logger.new(banner.shift)
commandline = CommandLine.new

commandline.registeraction('manipulate', ' [--test] manipulatorfile resourselog')

commandline.registeraction('help')
commandline.registeraction('version')

commandline.registerflag('test')

commandline.expand

Commands.new(commandline,logger,banner).send(commandline.action || 'help')