libisi 0.3.0
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/LICENSE +677 -0
- data/Manifest +89 -0
- data/Rakefile +34 -0
- data/lib/inifile.rb +119 -0
- data/lib/libisi.rb +948 -0
- data/lib/libisi/attribute.rb +32 -0
- data/lib/libisi/attribute/activerecord.rb +34 -0
- data/lib/libisi/attribute/base.rb +33 -0
- data/lib/libisi/base.rb +109 -0
- data/lib/libisi/bridge.rb +21 -0
- data/lib/libisi/bridge/base.rb +23 -0
- data/lib/libisi/bridge/java.rb +71 -0
- data/lib/libisi/bridge/python.rb +37 -0
- data/lib/libisi/cache.rb +21 -0
- data/lib/libisi/cache/base.rb +67 -0
- data/lib/libisi/cache/file_cache.rb +24 -0
- data/lib/libisi/chart.rb +21 -0
- data/lib/libisi/chart/base.rb +320 -0
- data/lib/libisi/chart/jfreechart.rb +682 -0
- data/lib/libisi/chart/jfreechart_generator.rb +206 -0
- data/lib/libisi/color.rb +21 -0
- data/lib/libisi/color/base.rb +66 -0
- data/lib/libisi/color/colortools.rb +92 -0
- data/lib/libisi/color/java.rb +44 -0
- data/lib/libisi/concept.rb +33 -0
- data/lib/libisi/concept/activerecord.rb +39 -0
- data/lib/libisi/concept/base.rb +58 -0
- data/lib/libisi/doc.rb +35 -0
- data/lib/libisi/doc/base.rb +414 -0
- data/lib/libisi/doc/html.rb +85 -0
- data/lib/libisi/doc/text.rb +98 -0
- data/lib/libisi/doc/wiki.rb +55 -0
- data/lib/libisi/environment.rb +21 -0
- data/lib/libisi/environment/base.rb +36 -0
- data/lib/libisi/environment/http.rb +105 -0
- data/lib/libisi/environment/rails.rb +27 -0
- data/lib/libisi/environment/root.rb +23 -0
- data/lib/libisi/fake_logger/logger.rb +61 -0
- data/lib/libisi/function/base.rb +30 -0
- data/lib/libisi/hal.rb +558 -0
- data/lib/libisi/instance.rb +27 -0
- data/lib/libisi/instance/activerecord.rb +21 -0
- data/lib/libisi/instance/base.rb +42 -0
- data/lib/libisi/log.rb +237 -0
- data/lib/libisi/mail/base.rb +32 -0
- data/lib/libisi/mail/tmail.rb +120 -0
- data/lib/libisi/parameter/base.rb +41 -0
- data/lib/libisi/property.rb +27 -0
- data/lib/libisi/property/base.rb +28 -0
- data/lib/libisi/reciever/base.rb +31 -0
- data/lib/libisi/reciever/socket.rb +31 -0
- data/lib/libisi/relation.rb +23 -0
- data/lib/libisi/request.rb +22 -0
- data/lib/libisi/request/base.rb +29 -0
- data/lib/libisi/request/http.rb +129 -0
- data/lib/libisi/response/base.rb +27 -0
- data/lib/libisi/task/base.rb +27 -0
- data/lib/libisi/task/http.rb +90 -0
- data/lib/libisi/tee.rb +296 -0
- data/lib/libisi/ui/base.rb +116 -0
- data/lib/libisi/ui/console.rb +238 -0
- data/lib/libisi/ui/kde.rb +94 -0
- data/lib/libisi/ui/nobody.rb +29 -0
- data/lib/libisi/ui/rails.rb +150 -0
- data/lib/libisi/ui/x11.rb +55 -0
- data/lib/libisi/uri.rb +42 -0
- data/lib/libisi/uri/activerecord.rb +152 -0
- data/lib/libisi/uri/base.rb +115 -0
- data/lib/libisi/uri/file.rb +43 -0
- data/lib/libisi/uri/ldap.rb +72 -0
- data/lib/libisi/uri/mysql.rb +98 -0
- data/lib/libisi/value.rb +31 -0
- data/lib/libisi/value/attribute_value.rb +19 -0
- data/lib/libisi/value/base.rb +55 -0
- data/lib/libisi/value/property_value.rb +19 -0
- data/lib/libisi/value/relation_value.rb +19 -0
- data/lib/ordered_hash.rb +228 -0
- data/libisi.gemspec +31 -0
- data/test/bridge_test.rb +77 -0
- data/test/cache_test.rb +65 -0
- data/test/chart_test.rb +179 -0
- data/test/color_test.rb +64 -0
- data/test/concept_test.rb +56 -0
- data/test/doc_test.rb +172 -0
- data/test/fixtures/test.db +0 -0
- data/test/ordered_hash_test.rb +39 -0
- data/test/profile_test.rb +36 -0
- data/test/request_test.rb +121 -0
- data/test/test +0 -0
- data/test/ui_test.rb +62 -0
- metadata +244 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Copyright (C) 2007-2010 Logintas AG Switzerland
|
|
2
|
+
#
|
|
3
|
+
# This file is part of Libisi.
|
|
4
|
+
#
|
|
5
|
+
# Libisi is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# Libisi is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Libisi. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "libisi/attribute"
|
|
19
|
+
require "libisi/property"
|
|
20
|
+
require "libisi/relation"
|
|
21
|
+
class ActiverecordConcept < BaseConcept
|
|
22
|
+
|
|
23
|
+
def attribute_names
|
|
24
|
+
base_class.column_names
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def attributes
|
|
28
|
+
base_class.columns.map {|c| Attribute.create(self, c)}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def relation_names
|
|
32
|
+
base_class.reflections.keys.map {|r| r.to_s}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def relations
|
|
36
|
+
base_class.reflections.map {|r| Relation.create(self, r)}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright (C) 2007-2010 Logintas AG Switzerland
|
|
2
|
+
#
|
|
3
|
+
# This file is part of Libisi.
|
|
4
|
+
#
|
|
5
|
+
# Libisi is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# Libisi is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Libisi. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
class BaseConcept
|
|
19
|
+
|
|
20
|
+
VALUE_TYPES = [:attributes, :properties, :relations]
|
|
21
|
+
|
|
22
|
+
attr_reader :base_class
|
|
23
|
+
|
|
24
|
+
def initialize(base_class, options = {})
|
|
25
|
+
@base_class = base_class
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# There are by default no attributes
|
|
29
|
+
def attribute_names; []; end
|
|
30
|
+
def attributes; []; end
|
|
31
|
+
|
|
32
|
+
def property_names
|
|
33
|
+
ans = attribute_names
|
|
34
|
+
rns = relation_names
|
|
35
|
+
base_class.instance_methods.reject {|mn|
|
|
36
|
+
base_class.instance_method(mn).arity != 0 or
|
|
37
|
+
mn =~ /^to_/ or
|
|
38
|
+
mn =~/^get_/ or
|
|
39
|
+
mn =~/^set_/ or
|
|
40
|
+
mn =~ /=$/ or
|
|
41
|
+
mn =~ /_type$/ or
|
|
42
|
+
mn =~ /_unit$/ or
|
|
43
|
+
ans.include?(mn) or
|
|
44
|
+
rns.include?(mn)
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def properties
|
|
49
|
+
property_names.map {|p|
|
|
50
|
+
Property.create(base_class, p)
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def value_accessors
|
|
55
|
+
VALUE_TYPES.map {|vt| self.send(vt)}.flatten
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
data/lib/libisi/doc.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Copyright (C) 2007-2010 Logintas AG Switzerland
|
|
2
|
+
#
|
|
3
|
+
# This file is part of Libisi.
|
|
4
|
+
#
|
|
5
|
+
# Libisi is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# Libisi is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Libisi. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "libisi/base.rb"
|
|
19
|
+
class Doc < Base
|
|
20
|
+
|
|
21
|
+
def self.output_types
|
|
22
|
+
{"text" => ["txt","text"],
|
|
23
|
+
"html" => ["html","htm"]}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.create(doc, options = {})
|
|
27
|
+
doc = doc.to_s
|
|
28
|
+
raise "Hacking attack!!" unless doc.class == String
|
|
29
|
+
raise "Unexpected Doc name #{doc}." unless doc =~ /^[a-zA-Z][a-zA-Z0-9]*$/
|
|
30
|
+
require "libisi/doc/#{doc}.rb"
|
|
31
|
+
klass = eval("#{doc.capitalize}Doc")
|
|
32
|
+
klass.new(options)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
# Copyright (C) 2007-2010 Logintas AG Switzerland
|
|
2
|
+
#
|
|
3
|
+
# This file is part of Libisi.
|
|
4
|
+
#
|
|
5
|
+
# Libisi is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# Libisi is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Libisi. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
class BaseDoc
|
|
19
|
+
|
|
20
|
+
def initialize(options = {})
|
|
21
|
+
@writer = options[:writer] if options[:writer]
|
|
22
|
+
@init = options[:doc_started] if options[:doc_started]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def print(options = {}, &block)
|
|
26
|
+
writer(options, &block) << yield
|
|
27
|
+
end
|
|
28
|
+
def p(options = {}, &block)
|
|
29
|
+
writer(options, &block) << yield + "\n\n"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def title(text, options = {}, &block)
|
|
33
|
+
@title_depth ||= 0
|
|
34
|
+
@title_depth += 1
|
|
35
|
+
generate_title(text, options, &block)
|
|
36
|
+
@title_depth -= 1
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def flatten_columns(columns, options)
|
|
40
|
+
# we will use this for grouping
|
|
41
|
+
options[:columns] ||= []
|
|
42
|
+
|
|
43
|
+
case columns
|
|
44
|
+
when Array
|
|
45
|
+
options[:columns] << columns
|
|
46
|
+
when Hash
|
|
47
|
+
options[:group_bys] ||= []
|
|
48
|
+
columns.each {|key,columns|
|
|
49
|
+
unless key.nil?
|
|
50
|
+
options[:group_bys] << Proc.new {|element|
|
|
51
|
+
case element
|
|
52
|
+
when Hash
|
|
53
|
+
element[key]
|
|
54
|
+
else
|
|
55
|
+
element.send(key)
|
|
56
|
+
end
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
flatten_columns(columns, options)
|
|
60
|
+
}
|
|
61
|
+
else
|
|
62
|
+
raise "Unexpected columns type #{columns.class.name}"
|
|
63
|
+
end
|
|
64
|
+
options
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def generate_table(options = {}, &block); generate_bare_table(options, &block) end
|
|
68
|
+
def generate_bare_table(options = {},&block)
|
|
69
|
+
return yield if options[:columns].nil? and options[:items].nil?
|
|
70
|
+
|
|
71
|
+
options = flatten_columns(options.delete(:columns),options) if options[:columns].class == Hash
|
|
72
|
+
|
|
73
|
+
if options[:group_bys]
|
|
74
|
+
raise "No items given" unless options[:items]
|
|
75
|
+
# group the items
|
|
76
|
+
benchmark("Table group bys") {
|
|
77
|
+
options[:items] = options[:items].group_bys(*options[:group_bys])
|
|
78
|
+
}
|
|
79
|
+
options[:grouped] = true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
if options[:items] and options[:columns] and not options[:no_header]
|
|
83
|
+
# create header
|
|
84
|
+
tr(options) { options[:columns].flatten.each_with_index{|c,i| th(options) {
|
|
85
|
+
if f = options[:header_function]
|
|
86
|
+
case f
|
|
87
|
+
when Proc
|
|
88
|
+
if f.arity == 1
|
|
89
|
+
f.call(c)
|
|
90
|
+
else
|
|
91
|
+
f.call(c,i)
|
|
92
|
+
end
|
|
93
|
+
when Symbol, String
|
|
94
|
+
c.send(f)
|
|
95
|
+
else
|
|
96
|
+
raise "Unexpected header function #{f.inspect}"
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
c
|
|
100
|
+
end
|
|
101
|
+
}}}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if options[:items]
|
|
105
|
+
options[:header_function].call(options_for_functions(options) ) if options[:header_function]
|
|
106
|
+
table_items(options[:items],options,&block)
|
|
107
|
+
options[:footer_function].call(options_for_functions(options) ) if options[:footer_function]
|
|
108
|
+
else
|
|
109
|
+
options[:columns].flatten.each_with_index {|column, column_index|
|
|
110
|
+
tr(options) {
|
|
111
|
+
th(options) {column}
|
|
112
|
+
# td(options) {
|
|
113
|
+
# problem with tee here
|
|
114
|
+
td {options[:columns].inspect}
|
|
115
|
+
case block.arity
|
|
116
|
+
when 2
|
|
117
|
+
yield(column,column_index)
|
|
118
|
+
else
|
|
119
|
+
yield(column)
|
|
120
|
+
end
|
|
121
|
+
}
|
|
122
|
+
# }
|
|
123
|
+
}
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
def bare_table(options = {}, &block)
|
|
127
|
+
generate_bare_table(options, &block)
|
|
128
|
+
end
|
|
129
|
+
def table(options = {}, &block)
|
|
130
|
+
# options[:writer] = writer(options, &block) unless options[:writer]
|
|
131
|
+
generate_table(options,&block)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def options_for_functions(options)
|
|
135
|
+
options[:item_tree] = options[:items].to_hash(true) unless options[:item_tree]
|
|
136
|
+
o = options.dup
|
|
137
|
+
if o[:group_bys]
|
|
138
|
+
benchmark("Doc.options_for_functions") {
|
|
139
|
+
total_groupings = o[:group_bys].length
|
|
140
|
+
if o[:group_column_index]
|
|
141
|
+
# we are at item output
|
|
142
|
+
depth = o[:group_column_index]
|
|
143
|
+
else
|
|
144
|
+
# we are at grouping
|
|
145
|
+
depth = (o[:group_keys] or []).length - 1
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# correct group_keys because we are maybe already
|
|
149
|
+
# in a gouping
|
|
150
|
+
o[:group_keys] = (o[:group_keys] or []).dup[0..depth]
|
|
151
|
+
|
|
152
|
+
o[:group_tree] = options[:item_tree]
|
|
153
|
+
|
|
154
|
+
o[:group_keys].each {|k|
|
|
155
|
+
o[:group_tree] = o[:group_tree][k]
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
o[:group_items] = o[:group_tree]
|
|
159
|
+
o[:group_items] = o[:group_items].values.flatten if o[:group_items].class == Hash
|
|
160
|
+
# while !o[:group_items].nil? and o[:group_items][0].class == Hash
|
|
161
|
+
(total_groupings - depth - 2).times {
|
|
162
|
+
o[:group_items] = o[:group_items].map {|h| h.values}.flatten
|
|
163
|
+
}
|
|
164
|
+
# end
|
|
165
|
+
}
|
|
166
|
+
end
|
|
167
|
+
o
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def options_for_functions_orig(options)
|
|
172
|
+
o = options.dup
|
|
173
|
+
if o[:group_bys]
|
|
174
|
+
benchmark("Doc.options_for_functions") {
|
|
175
|
+
total_groupings = o[:group_bys].length
|
|
176
|
+
if o[:group_column_index]
|
|
177
|
+
# we are at item output
|
|
178
|
+
depth = o[:group_column_index]
|
|
179
|
+
else
|
|
180
|
+
# we are at grouping
|
|
181
|
+
depth = o[:group_keys].length - 1
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# correct group_keys because we are maybe already
|
|
185
|
+
# in a gourping
|
|
186
|
+
o[:group_keys] = o[:group_keys].dup[0..depth]
|
|
187
|
+
|
|
188
|
+
o[:group_tree] = options[:items].to_hash(true)
|
|
189
|
+
o[:group_keys].each {|k|
|
|
190
|
+
o[:group_tree] = o[:group_tree][k]
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
o[:group_items] = o[:group_tree]
|
|
194
|
+
o[:group_items] = o[:group_items].values.flatten if o[:group_items].class == Hash
|
|
195
|
+
# while !o[:group_items].nil? and o[:group_items][0].class == Hash
|
|
196
|
+
(total_groupings - depth - 2).times {
|
|
197
|
+
o[:group_items] = o[:group_items].map {|h| h.values}.flatten
|
|
198
|
+
}
|
|
199
|
+
# end
|
|
200
|
+
}
|
|
201
|
+
end
|
|
202
|
+
o
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def call_total_function(function_name, options = {})
|
|
206
|
+
level = options[:group_keys].length - 1
|
|
207
|
+
function = options[(function_name.to_s + level.to_s).to_sym]
|
|
208
|
+
return unless function
|
|
209
|
+
function.call(options_for_functions(options))
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def table_items(items, options = {}, &block)
|
|
213
|
+
redo_item = false
|
|
214
|
+
if options[:grouped]
|
|
215
|
+
options[:group_elements] ||= []
|
|
216
|
+
options[:group_keys] ||= []
|
|
217
|
+
options[:item_index] ||= 0
|
|
218
|
+
|
|
219
|
+
if items[0].class == Array and
|
|
220
|
+
items[0].length == 2
|
|
221
|
+
# this is still a group
|
|
222
|
+
items.each_with_index {|val, group_index|
|
|
223
|
+
key, group = val
|
|
224
|
+
options[:group_elements] << key
|
|
225
|
+
options[:group_keys] << key
|
|
226
|
+
call_total_function(:before_group_function, options)
|
|
227
|
+
table_items(group, options, &block)
|
|
228
|
+
call_total_function(:after_group_function, options)
|
|
229
|
+
options[:group_elements].pop
|
|
230
|
+
options[:group_keys].pop
|
|
231
|
+
}
|
|
232
|
+
else
|
|
233
|
+
# finished grouping, do output
|
|
234
|
+
if options[:return_group_at_once]
|
|
235
|
+
tr(options) {
|
|
236
|
+
redo_item = table_item(items, options[:item_index], options, &block)
|
|
237
|
+
}
|
|
238
|
+
else
|
|
239
|
+
items.each_with_index {|item, item_index|
|
|
240
|
+
tr(options) {
|
|
241
|
+
redo_item = table_item(item, options[:item_index], options, &block)
|
|
242
|
+
}
|
|
243
|
+
redo if redo_item
|
|
244
|
+
}
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
else
|
|
248
|
+
options[:items].each_with_index {|item, item_index|
|
|
249
|
+
tr(options) {
|
|
250
|
+
redo_item = table_item(item, item_index, options, &block)
|
|
251
|
+
}
|
|
252
|
+
redo if redo_item
|
|
253
|
+
}
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def table_item(item, item_index, options = {}, &block)
|
|
258
|
+
redo_item = false
|
|
259
|
+
options[:item_index] += 1 if options[:item_index]
|
|
260
|
+
if (cols = options[:columns])
|
|
261
|
+
# yield one per column
|
|
262
|
+
column_index = -1
|
|
263
|
+
|
|
264
|
+
# cols in format
|
|
265
|
+
# [ [groupcol,groupcol,groupcol], # columns for group element 1
|
|
266
|
+
# [groupcol,groupcol,groupcol], # columns for group element 2
|
|
267
|
+
# col,col,col ]
|
|
268
|
+
cols.each_with_index {|subcolumns, group_column_index|
|
|
269
|
+
options[:group_column_index] = group_column_index
|
|
270
|
+
|
|
271
|
+
if subcolumns.class == Array
|
|
272
|
+
# ok these are subcolumns of a group
|
|
273
|
+
else
|
|
274
|
+
subcolumns = [subcolumns]
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
subcolumns.each_with_index {|column,subcol_index|
|
|
278
|
+
# column_index counts trough each column (including group cols)
|
|
279
|
+
column_index += 1
|
|
280
|
+
|
|
281
|
+
el = item
|
|
282
|
+
|
|
283
|
+
group_column = (options[:group_elements] and
|
|
284
|
+
options[:group_elements].length > group_column_index)
|
|
285
|
+
if group_column
|
|
286
|
+
# This is a group column
|
|
287
|
+
|
|
288
|
+
if options[:group_elements][group_column_index] == NilClass
|
|
289
|
+
# we already yielded this group element
|
|
290
|
+
td(options) {}
|
|
291
|
+
next
|
|
292
|
+
else
|
|
293
|
+
el = options[:group_elements][group_column_index]
|
|
294
|
+
# mark group element as visited if all group columns
|
|
295
|
+
# for that group element have been yielded
|
|
296
|
+
if (subcolumns.length - 1) == subcol_index
|
|
297
|
+
options[:group_elements][group_column_index] = NilClass
|
|
298
|
+
if options[:span_grouping]
|
|
299
|
+
redo_item = true
|
|
300
|
+
|
|
301
|
+
# TODO: this is not right, but works for group items with one column
|
|
302
|
+
total_columns = options[:columns].flatten.length
|
|
303
|
+
grouped_columns = (options[:group_elements].length - 1)
|
|
304
|
+
|
|
305
|
+
options = { :colspan => total_columns - grouped_columns}.merge(options)
|
|
306
|
+
# td({:colspan => grouped_columns}.merge(options)) {} unless grouped_columns == 0
|
|
307
|
+
# th({:colspan => total_columns - grouped_columns}.merge(options)) {yield(key}
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
if block_given? and block.arity == 1
|
|
313
|
+
td(options) {
|
|
314
|
+
if options[:span_grouping]
|
|
315
|
+
# we already printed grouping
|
|
316
|
+
""
|
|
317
|
+
else
|
|
318
|
+
el.to_s
|
|
319
|
+
end
|
|
320
|
+
}
|
|
321
|
+
next
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
next td(options){el.to_s} unless block_given?
|
|
327
|
+
case block.arity
|
|
328
|
+
when 2
|
|
329
|
+
td(options) {yield(el,column)}
|
|
330
|
+
when 3
|
|
331
|
+
td(options) {yield(el,column,item_index)}
|
|
332
|
+
when 4
|
|
333
|
+
td(options) {yield(el,column,item_index,column_index)}
|
|
334
|
+
when 5
|
|
335
|
+
o = options_for_functions(options)
|
|
336
|
+
td(options) {yield(el,column,item_index,column_index,o)}
|
|
337
|
+
else
|
|
338
|
+
yield(el)
|
|
339
|
+
# class is handling columns themself
|
|
340
|
+
break
|
|
341
|
+
end
|
|
342
|
+
if redo_item
|
|
343
|
+
options.delete(:group_column_index)
|
|
344
|
+
return true
|
|
345
|
+
end
|
|
346
|
+
}
|
|
347
|
+
options.delete(:group_column_index)
|
|
348
|
+
}
|
|
349
|
+
false
|
|
350
|
+
else
|
|
351
|
+
if options[:group_elements]
|
|
352
|
+
options[:group_elements].each_with_index {|group_element, group_element_index|
|
|
353
|
+
if group_element
|
|
354
|
+
td(options) { group_element}
|
|
355
|
+
else
|
|
356
|
+
td(options) {}
|
|
357
|
+
end
|
|
358
|
+
options[:group_elements][group_element_index] = nil
|
|
359
|
+
}
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
return td(options) {item.to_s} unless block_given?
|
|
363
|
+
|
|
364
|
+
case block.arity
|
|
365
|
+
when 2
|
|
366
|
+
yield(item,item_index)
|
|
367
|
+
else
|
|
368
|
+
return yield(item)
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def tn(options = {}, &block);
|
|
374
|
+
options[:text_align] ||= "right"
|
|
375
|
+
td(options, &block)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def start_doc; end
|
|
379
|
+
def end_doc; end
|
|
380
|
+
|
|
381
|
+
def close
|
|
382
|
+
to_stdout(@writer)
|
|
383
|
+
@writer.close if @writer and @writer.respond_to?(:close)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
private
|
|
387
|
+
def to_stdout(text)
|
|
388
|
+
STDOUT << ("#{text.inspect}\n")
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def writer(options = {}, &block)
|
|
392
|
+
@writer = options[:writer] if options[:writer]
|
|
393
|
+
if @writer and @writer.respond_to?(:call)
|
|
394
|
+
@writer = @writer.call(block)
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
unless @init
|
|
398
|
+
@init = true
|
|
399
|
+
self.start_doc
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
return @writer if @writer
|
|
403
|
+
return STDOUT
|
|
404
|
+
# klass = eval("self.class",block.binding)
|
|
405
|
+
# case klass
|
|
406
|
+
# when BaseDoc
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def generate_title(text, options, &block)
|
|
410
|
+
print(options) { text.to_s.upcase + "\n"}
|
|
411
|
+
yield
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
end
|