wortsammler 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +131 -0
- data/README.pdf +0 -0
- data/Rakefile +34 -0
- data/bin/wortsammler +4 -0
- data/lib/wortsammler/class.Traceable.md.rb +104 -0
- data/lib/wortsammler/class.Traceable.rb +387 -0
- data/lib/wortsammler/class.proolib.rb +747 -0
- data/lib/wortsammler/class.treetopHelper.rb +117 -0
- data/lib/wortsammler/exe.wortsammler.rb +428 -0
- data/lib/wortsammler/log_helper.rb +8 -0
- data/lib/wortsammler/mdTraceParser.treetop +55 -0
- data/lib/wortsammler/rake_helper.rb +28 -0
- data/lib/wortsammler/version.rb +3 -0
- data/lib/wortsammler.rb +5 -0
- data/pkg/wortsammler-0.0.1.gem +0 -0
- data/resources/default.latex +225 -0
- data/resources/logo.jpg +0 -0
- data/resources/main.md +268 -0
- data/resources/rakefile.rb +5 -0
- data/resources/requirementsSynopsis.graphml +17 -0
- data/resources/sample_the-sample-document.yaml +51 -0
- data/spec/test.graphml +74 -0
- data/spec/traceable_spec.rb +299 -0
- data/spec/wortsammler_spec.rb +168 -0
- data/testresults/wortsammler_testresults.html +408 -0
- data/testresults/wortsammler_testresults.log +59 -0
- data/wortsammler.gemspec +53 -0
- metadata +282 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# this mixin provides a convenient interface
|
4
|
+
# for the syntaxtree
|
5
|
+
#
|
6
|
+
|
7
|
+
class Treetop::Runtime::SyntaxNode
|
8
|
+
|
9
|
+
# this delivers a child node of the AST
|
10
|
+
def child
|
11
|
+
elements.select{|e| e.is_ast?} if ! elements.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
# returns an array of all descendants of the current node
|
15
|
+
# in the AST in document order
|
16
|
+
def descendant
|
17
|
+
child.map{|e| [e, e.descendant]}.flatten.compact if not child.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
# returns this and all descendant in document order
|
21
|
+
def thisdescendant
|
22
|
+
[self, descendant].flatten
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns all nodes to up to the AST root
|
26
|
+
def ancestor
|
27
|
+
if ! parent.nil?
|
28
|
+
[parent, parent.ancestor].flatten
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# indicates if the current treetop node is important enough
|
33
|
+
# to be in the intended AST
|
34
|
+
def is_ast?
|
35
|
+
true # nonterminal? # parent.nil? or extension_modules.include?(Xmine)
|
36
|
+
end
|
37
|
+
|
38
|
+
# indicates if a meaningful name for the node in the AST
|
39
|
+
# is available
|
40
|
+
def has_rule_name?
|
41
|
+
not (extension_modules.nil? or extension_modules.empty?)
|
42
|
+
end
|
43
|
+
|
44
|
+
# returns a meaning name for the node in the AST
|
45
|
+
def rule_name
|
46
|
+
if has_rule_name? then
|
47
|
+
extension_modules.first.name.split("::").last.gsub(/[0-9]/,"")
|
48
|
+
else
|
49
|
+
"###"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# another quick info for a node
|
54
|
+
def to_info
|
55
|
+
rule_name + ": "+ text_value
|
56
|
+
end
|
57
|
+
|
58
|
+
# exposes a node in the AST as xml
|
59
|
+
def to_xml
|
60
|
+
if child.nil? or child.empty?
|
61
|
+
"#>" +interval.to_s + ":"+ text_value + "<#"
|
62
|
+
else
|
63
|
+
[ xml_start_tag,
|
64
|
+
(child.nil? ? [] : child).map{|x| x.to_xml},
|
65
|
+
xml_end_tag
|
66
|
+
].join
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# get the XML start tag
|
71
|
+
def xml_start_tag
|
72
|
+
if has_rule_name? then
|
73
|
+
"<" + rule_name + ">"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# get the XML end tag
|
78
|
+
def xml_end_tag
|
79
|
+
if has_rule_name? then
|
80
|
+
"</" + rule_name + ">"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# clean the tree by removing garbage nodes
|
85
|
+
# which are not part of the intended AST
|
86
|
+
def clean_tree(root_node)
|
87
|
+
return if(root_node.elements.nil?)
|
88
|
+
root_node.elements.delete_if{|node| not node.is_ast? }
|
89
|
+
root_node.elements.each{|e| e.clean_tree(e)}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
class Treetop::Runtime::SyntaxNode
|
95
|
+
def as_xml
|
96
|
+
[(["<", getLabel, ">" ].join if getLabel),
|
97
|
+
(if elements
|
98
|
+
elements.map { |e| e.as_xml }.join
|
99
|
+
else
|
100
|
+
text_value
|
101
|
+
end),
|
102
|
+
(["</", getLabel, ">" ].join if getLabel)
|
103
|
+
].join
|
104
|
+
end
|
105
|
+
|
106
|
+
def wrap(tag,body)
|
107
|
+
"<#{tag}>#{body}</#{tag}>"
|
108
|
+
end
|
109
|
+
|
110
|
+
def getLabel
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
@@ -0,0 +1,428 @@
|
|
1
|
+
require "optparse" # for option parser
|
2
|
+
require 'wortsammler/log_helper'
|
3
|
+
require 'wortsammler/class.proolib.rb'
|
4
|
+
require 'wortsammler/class.Traceable.rb'
|
5
|
+
require 'wortsammler/class.Traceable.md.rb'
|
6
|
+
require 'wortsammler/version.rb'
|
7
|
+
|
8
|
+
|
9
|
+
options = {}
|
10
|
+
config = nil
|
11
|
+
|
12
|
+
optparse = OptionParser.new do|opts|
|
13
|
+
# Set a banner, displayed at the top
|
14
|
+
# of the help screen.
|
15
|
+
opts.banner = ["This is Wortsammler #{Wortsammler::VERSION}",
|
16
|
+
"",
|
17
|
+
"Usage: Wortsammler [options]",
|
18
|
+
"",
|
19
|
+
"examples:",
|
20
|
+
"",
|
21
|
+
" wortsammler -cbpm mymanifest.yaml",
|
22
|
+
" -- beautify collect process files from mymanifest.yaml",
|
23
|
+
"",
|
24
|
+
" wortsammler -cbpi .",
|
25
|
+
" -- beautify collect process files in current folder"
|
26
|
+
].join("\n")
|
27
|
+
|
28
|
+
##
|
29
|
+
# Define the options, and what they do
|
30
|
+
|
31
|
+
opts.separator nil
|
32
|
+
opts.separator "options:"
|
33
|
+
opts.separator nil
|
34
|
+
|
35
|
+
# This displays the help screen, all programs are
|
36
|
+
# assumed to have this option.
|
37
|
+
opts.on( '-h', '--help', 'display this screen' ) do
|
38
|
+
puts opts
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
options[:version] = false
|
44
|
+
opts.on( "-v", '--version', 'print Version info, then turn on verbose mode' ) do
|
45
|
+
options[:version] = true
|
46
|
+
options[:verbose] = true
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.separator nil
|
50
|
+
|
51
|
+
options[:init] = false
|
52
|
+
opts.on( "-n", '--init DIR', 'create a project folder in DIR' ) do|file|
|
53
|
+
options[:init] = file
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
opts.separator nil
|
58
|
+
|
59
|
+
options[:input_path] = false
|
60
|
+
opts.on( '-i', '--input PATH', 'set input file/project folder for processing') do|path|
|
61
|
+
options[:input_path] = path
|
62
|
+
end
|
63
|
+
|
64
|
+
options[:manifest] = false
|
65
|
+
opts.on( '-m', '--manifest PATH', 'set mainfest file for processing' ) do|file|
|
66
|
+
options[:manifest] = file
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.separator nil
|
70
|
+
|
71
|
+
options[:outputformats] = ['pdf']
|
72
|
+
opts.on( '-f', '--format formatList', 'set the outputformat to formatList' ) do|formatlist|
|
73
|
+
options[:outputformats] = formatlist.split(":")
|
74
|
+
end
|
75
|
+
|
76
|
+
options[:outputfolder] = false
|
77
|
+
opts.on( '-o', '--output PATH', 'set the output to PATH' ) do|path|
|
78
|
+
options[:outputfolder] = path
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
opts.separator nil
|
83
|
+
|
84
|
+
options[:collect] = false
|
85
|
+
opts.on( '-c', '--collect', 'collect traceables by manifest' ) do
|
86
|
+
options[:collect] = true
|
87
|
+
end
|
88
|
+
|
89
|
+
options[:process] = false
|
90
|
+
opts.on( '-p', '--process', 'process documents by manifest' ) do
|
91
|
+
options[:process] = true
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
options[:beautify] = false
|
96
|
+
opts.on( "-b", '--beautify', 'bautify markdownfiles' ) do
|
97
|
+
options[:beautify] = true
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# now parse the commandline
|
104
|
+
#
|
105
|
+
begin
|
106
|
+
optparse.parse!
|
107
|
+
rescue OptionParser::ParseError => option
|
108
|
+
$log.error "Invalid option #{option}"
|
109
|
+
exit false
|
110
|
+
|
111
|
+
rescue RegexpError => error
|
112
|
+
$log.error "#{error}"
|
113
|
+
exit
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
module Wortsammler
|
118
|
+
def self.wortsammler_execute(options)
|
119
|
+
##
|
120
|
+
#
|
121
|
+
# print version info
|
122
|
+
#
|
123
|
+
if options[:version] then
|
124
|
+
puts "Wortsammler #{Wortsammler::VERSION}"
|
125
|
+
|
126
|
+
pandoc=`pandocx -v`.split("\n")[0] rescue pandoc="error running pandoc"
|
127
|
+
xetex=`xelatex -v`.split("\n")[0] rescue pandoc="error running xelatex"
|
128
|
+
|
129
|
+
puts "found #{pandoc}"
|
130
|
+
puts "found #{xetex}"
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# initialize a project
|
136
|
+
#
|
137
|
+
if project_folder=options[:init] then
|
138
|
+
if File.exists?(project_folder)
|
139
|
+
$log.error "directory already exists: '#{project_folder}'"
|
140
|
+
exit(false)
|
141
|
+
end
|
142
|
+
Wortsammler::init_folders(project_folder)
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
##
|
147
|
+
#
|
148
|
+
# load the manifest
|
149
|
+
#
|
150
|
+
config=nil
|
151
|
+
if config_file=options[:manifest] then
|
152
|
+
config = ProoConfig.new(config_file)
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# process input path
|
157
|
+
#
|
158
|
+
#
|
159
|
+
input_files=nil
|
160
|
+
if input_path = options[:input_path]
|
161
|
+
unless File.exists? input_path then
|
162
|
+
$log.error "path does not exist path '#{input_path}'"
|
163
|
+
exit(false)
|
164
|
+
end
|
165
|
+
if File.file?(input_path) #(RS_Mdc)
|
166
|
+
input_files=[input_path]
|
167
|
+
elsif File.exists?(input_path)
|
168
|
+
input_files=Dir["#{input_path}/**/*.md", "#{input_path}/**/*.markdown"]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
##
|
173
|
+
#
|
174
|
+
# beautify markdown files
|
175
|
+
#
|
176
|
+
#
|
177
|
+
cleaner = PandocBeautifier.new($log)
|
178
|
+
|
179
|
+
if options[:beautify]
|
180
|
+
|
181
|
+
|
182
|
+
# process path
|
183
|
+
|
184
|
+
if input_files then
|
185
|
+
input_files.each{|f| cleaner.beautify(f)}
|
186
|
+
end
|
187
|
+
|
188
|
+
# process manifest
|
189
|
+
|
190
|
+
if config then
|
191
|
+
config.input.each{|f| cleaner.beautify(f)}
|
192
|
+
end
|
193
|
+
|
194
|
+
unless input_files or config
|
195
|
+
$log.error "no input specified. Please use -m or -i to specify input"
|
196
|
+
exit false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# process collect in markdown files
|
202
|
+
#
|
203
|
+
|
204
|
+
if options[:collect]
|
205
|
+
|
206
|
+
# collect by path
|
207
|
+
|
208
|
+
if input_files then
|
209
|
+
$log.warn "collect from path not yet implemented"
|
210
|
+
end
|
211
|
+
|
212
|
+
# collect by manifest
|
213
|
+
|
214
|
+
if config then
|
215
|
+
Wortsammler.collect_traces(config)
|
216
|
+
end
|
217
|
+
|
218
|
+
unless input_files or config
|
219
|
+
$log.error "no input specified. Please use -m or -i to specify input"
|
220
|
+
exit false
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
|
226
|
+
##
|
227
|
+
# process files
|
228
|
+
#
|
229
|
+
if options[:process]
|
230
|
+
|
231
|
+
if input_files then
|
232
|
+
|
233
|
+
if options[:outputformats] then
|
234
|
+
outputformats = options[:outputformats]
|
235
|
+
end
|
236
|
+
|
237
|
+
if options[:outputfolder] then
|
238
|
+
outputfolder = options[:outputfolder]
|
239
|
+
else
|
240
|
+
$log.error "no output folder specified"
|
241
|
+
exit false
|
242
|
+
end
|
243
|
+
|
244
|
+
unless File.exists?(outputfolder) then
|
245
|
+
$log.info "creating folder '#{outputfolder}'"
|
246
|
+
FileUtils.mkdir_p(outputfolder)
|
247
|
+
end
|
248
|
+
|
249
|
+
input_files.each{|f| cleaner.render_single_document(f, outputfolder, outputformats)}
|
250
|
+
end
|
251
|
+
|
252
|
+
# collect by manifest
|
253
|
+
|
254
|
+
if config then
|
255
|
+
cleaner.generateDocument(config.input,
|
256
|
+
config.outdir,
|
257
|
+
config.outname,
|
258
|
+
config.format,
|
259
|
+
config.vars,
|
260
|
+
config.editions,
|
261
|
+
config.snippets,
|
262
|
+
config)
|
263
|
+
end
|
264
|
+
|
265
|
+
unless input_files or config
|
266
|
+
$log.error "no input specified. Please use -m or -i to specify input"
|
267
|
+
exit false
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
end #execute
|
272
|
+
|
273
|
+
|
274
|
+
#
|
275
|
+
# This method can verify wortsammler options delivered by option parser
|
276
|
+
# @param options [Hash] Option hash delivered by option parser
|
277
|
+
#
|
278
|
+
# @return [Boolean] true if successful. otherwise exits the program
|
279
|
+
def self.verify_options(options)
|
280
|
+
if options[:input_path] or options[:manifest] then
|
281
|
+
unless options[:process] or options[:beautify] or options[:collect] then
|
282
|
+
$log.error "no procesing option (p, b, c) specified"
|
283
|
+
exit false
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
if options[:input_path] and options[:process] then
|
288
|
+
unless options[:outputfolder] then
|
289
|
+
$log.error "no output folder specified for input path"
|
290
|
+
exit false
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
true
|
295
|
+
end #verify_options
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
#
|
300
|
+
# Initialize a project directory. It creates a bunch of
|
301
|
+
# folders, a root document, a manifest and an intial rakefile
|
302
|
+
#
|
303
|
+
# @param root [String] [The path to the root folder of the sample project]
|
304
|
+
#
|
305
|
+
# @return [Boolean] [always true]
|
306
|
+
def self.init_folders(root)
|
307
|
+
|
308
|
+
folders=["ZSUPP_Manifests",
|
309
|
+
"ZGEN_Documents",
|
310
|
+
"ZSUPP_Tools",
|
311
|
+
"ZSUPP_Styles",
|
312
|
+
"ZGEN_RequirementsTracing",
|
313
|
+
"001_Main"
|
314
|
+
]
|
315
|
+
|
316
|
+
folders.each{|folder|
|
317
|
+
FileUtils.mkdir_p("#{root}/#{folder}")
|
318
|
+
}
|
319
|
+
|
320
|
+
resourcedir=File.dirname(__FILE__)+"/../../resources"
|
321
|
+
Dir["#{resourcedir}/*.yaml"].each{|f|
|
322
|
+
FileUtils.cp(f, "#{root}/ZSUPP_Manifests")
|
323
|
+
}
|
324
|
+
FileUtils.cp("#{resourcedir}/main.md", "#{root}/001_Main")
|
325
|
+
FileUtils.cp("#{resourcedir}/rakefile.rb", "#{root}/ZSUPP_Tools")
|
326
|
+
FileUtils.cp("#{resourcedir}/default.latex", "#{root}/ZSUPP_Styles")
|
327
|
+
FileUtils.cp("#{resourcedir}/logo.jpg", "#{root}/ZSUPP_Styles")
|
328
|
+
|
329
|
+
true
|
330
|
+
end
|
331
|
+
|
332
|
+
|
333
|
+
#
|
334
|
+
# This collects the traces in a doucment specified by a manifest
|
335
|
+
# @param config [ProolibConfig] the manifest model
|
336
|
+
#
|
337
|
+
# @return [type] no specific return
|
338
|
+
def self.collect_traces(config)
|
339
|
+
|
340
|
+
files = config.input # get the input files
|
341
|
+
rootdir = config.rootdir # get the root directory
|
342
|
+
|
343
|
+
downstream_tracefile = config.downstream_tracefile # String to save downstram filenames
|
344
|
+
reqtracefile_base = config.reqtracefile_base # string to determine the requirements tracing results
|
345
|
+
upstream_tracefiles = config.upstream_tracefiles # String to read upstream tracefiles
|
346
|
+
|
347
|
+
traceable_set = TraceableSet.new
|
348
|
+
|
349
|
+
# collect all traceables in input
|
350
|
+
files.each{|f|
|
351
|
+
x=TraceableSet.processTracesInMdFile(f)
|
352
|
+
traceable_set.merge(x)
|
353
|
+
}
|
354
|
+
|
355
|
+
# collect all upstream traceables
|
356
|
+
#
|
357
|
+
upstream_traceable_set=TraceableSet.new
|
358
|
+
unless upstream_tracefiles.nil?
|
359
|
+
upstream_tracefiles.each{|f|
|
360
|
+
x=TraceableSet.processTracesInMdFile(f)
|
361
|
+
upstream_traceable_set.merge(x)
|
362
|
+
}
|
363
|
+
end
|
364
|
+
|
365
|
+
# check undefined traces
|
366
|
+
all_traceable_set=TraceableSet.new
|
367
|
+
all_traceable_set.merge(traceable_set)
|
368
|
+
all_traceable_set.merge(upstream_traceable_set)
|
369
|
+
undefineds=all_traceable_set.undefined_ids
|
370
|
+
$log.warn "undefined traces: #{undefineds.join(' ')}" unless undefineds.empty?
|
371
|
+
|
372
|
+
|
373
|
+
# check duplicates
|
374
|
+
duplicates=all_traceable_set.duplicate_traces
|
375
|
+
if duplicates.count > 0
|
376
|
+
$logger.warn "duplicated trace ids found:"
|
377
|
+
duplicates.each{|d| d.each{|t| $log.warn "#{t.id} in #{t.info}"}}
|
378
|
+
end
|
379
|
+
|
380
|
+
# write traceables to the intermediate Tracing file
|
381
|
+
outname="#{rootdir}/#{reqtracefile_base}.md"
|
382
|
+
|
383
|
+
# poke ths sort order for the traceables
|
384
|
+
all_traceable_set.sort_order=config.traceSortOrder if config.traceSortOrder
|
385
|
+
traceable_set.sort_order=config.traceSortOrder if config.traceSortOrder
|
386
|
+
# generate synopsis of traceableruby 1.8.7 garbage at end of file
|
387
|
+
|
388
|
+
|
389
|
+
tracelist=""
|
390
|
+
File.open(outname, "w"){|fx|
|
391
|
+
fx.puts ""
|
392
|
+
fx.puts "\\clearpage"
|
393
|
+
fx.puts ""
|
394
|
+
fx.puts "# Requirements Tracing"
|
395
|
+
fx.puts ""
|
396
|
+
tracelist=all_traceable_set.reqtraceSynopsis(:SPECIFICATION_ITEM)
|
397
|
+
fx.puts tracelist
|
398
|
+
}
|
399
|
+
|
400
|
+
# output the graphxml
|
401
|
+
# write traceables to the intermediate Tracing file
|
402
|
+
outname="#{rootdir}/#{reqtracefile_base}.graphml"
|
403
|
+
File.open(outname, "w") {|fx| fx.puts all_traceable_set.to_graphml}
|
404
|
+
|
405
|
+
outname="#{rootdir}/#{reqtracefile_base}Compare.txt"
|
406
|
+
File.open(outname, "w") {|fx| fx.puts traceable_set.to_compareEntries}
|
407
|
+
|
408
|
+
# write the downstream_trace file - to be included in downstream - speciifcations
|
409
|
+
outname="#{rootdir}/#{downstream_tracefile}"
|
410
|
+
File.open(outname, "w") {|fx|
|
411
|
+
fx.puts ""
|
412
|
+
fx.puts "\\clearpage"
|
413
|
+
fx.puts ""
|
414
|
+
fx.puts "# Upstream Requirements"
|
415
|
+
fx.puts ""
|
416
|
+
fx.puts traceable_set.to_downstream_tracefile(:SPECIFICATION_ITEM)
|
417
|
+
} unless downstream_tracefile.nil?
|
418
|
+
|
419
|
+
|
420
|
+
# now add the upstream traces to input
|
421
|
+
files.concat( upstream_tracefiles) unless upstream_tracefiles.nil?
|
422
|
+
|
423
|
+
nil
|
424
|
+
end
|
425
|
+
end # module
|
426
|
+
|
427
|
+
Wortsammler.verify_options(options)
|
428
|
+
Wortsammler.wortsammler_execute(options)
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# setup the logger
|
2
|
+
require 'Logger'
|
3
|
+
$log = Logger.new(STDOUT)
|
4
|
+
$log.level = Logger::INFO
|
5
|
+
$log.datetime_format= "%Y-%m-%d %H:%M:%S"
|
6
|
+
$log.formatter = proc do |severity, datetime, progname, msg|
|
7
|
+
"[#{severity}] #{progname}: #{datetime.strftime($log.datetime_format)}: #{msg}\n"
|
8
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
grammar TraceInMarkdown
|
3
|
+
|
4
|
+
rule top
|
5
|
+
(document '' )
|
6
|
+
{def getLabel ; "top" ; end}
|
7
|
+
end
|
8
|
+
|
9
|
+
rule document
|
10
|
+
( (noMarkupText / trace / markupAbort)* '')
|
11
|
+
{def getLabel ; "document" ; end}
|
12
|
+
end
|
13
|
+
|
14
|
+
rule noMarkupText
|
15
|
+
[^\[]+ { def as_xml; wrap('noMarkupText',super); end }
|
16
|
+
end
|
17
|
+
|
18
|
+
rule markupAbort
|
19
|
+
"["
|
20
|
+
end
|
21
|
+
|
22
|
+
rule trace
|
23
|
+
traceId s? traceHead s? traceBody uptraces:traceUpLink
|
24
|
+
{def getLabel ; "trace" ; end}
|
25
|
+
end
|
26
|
+
|
27
|
+
rule traceId
|
28
|
+
"[" payload:label "]"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
rule label
|
33
|
+
[a-zA-Z]+ "_" [a-zA-Z]+ "_" [0-9]+
|
34
|
+
end
|
35
|
+
|
36
|
+
rule traceHead
|
37
|
+
'**' payload:(!'*' . / '\*')+ '**'
|
38
|
+
end
|
39
|
+
|
40
|
+
rule traceBody
|
41
|
+
"{" payload:(nestedBody / [^{}])+ "}"
|
42
|
+
end
|
43
|
+
|
44
|
+
rule nestedBody
|
45
|
+
"{" (nestedBody / [^{}])+ "}"
|
46
|
+
end
|
47
|
+
|
48
|
+
rule traceUpLink
|
49
|
+
"(" payload:(","? s? label)* ")"
|
50
|
+
end
|
51
|
+
|
52
|
+
rule s
|
53
|
+
[\s]+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
##
|
3
|
+
#
|
4
|
+
# (c) 2013 Bernhard Weichel
|
5
|
+
#
|
6
|
+
#
|
7
|
+
|
8
|
+
|
9
|
+
##
|
10
|
+
# generate a task for each manifest file
|
11
|
+
#
|
12
|
+
Dir["../ZSUPP_Manifests/*.yaml"].each{|file|
|
13
|
+
taskdesc=File.basename(file, ".yaml")
|
14
|
+
taskname=taskdesc.split("_")[0]
|
15
|
+
desc "generate #{taskdesc}"
|
16
|
+
task taskname do
|
17
|
+
cmd="wortsammler -cbpm #{file}"
|
18
|
+
sh cmd
|
19
|
+
end
|
20
|
+
}
|
21
|
+
|
22
|
+
##
|
23
|
+
# the default task
|
24
|
+
|
25
|
+
desc "print this help"
|
26
|
+
task :default do
|
27
|
+
system "rake -T"
|
28
|
+
end
|
data/lib/wortsammler.rb
ADDED
Binary file
|