Class: BaseDoc

Inherits:
Object
  • Object
show all
Defined in:
lib/libisi/doc/base.rb

Overview

Copyright © 2007-2010 Logintas AG Switzerland

This file is part of Libisi.

Libisi is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Libisi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Libisi. If not, see <www.gnu.org/licenses/>.

Direct Known Subclasses

HtmlDoc, TextDoc, WikiDoc

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ BaseDoc

Returns a new instance of BaseDoc.



20
21
22
23
# File 'lib/libisi/doc/base.rb', line 20

def initialize(options = {})
  @writer = options[:writer] if options[:writer]
  @init = options[:doc_started] if options[:doc_started]
end

Instance Method Details

#bare_table(options = {}, &block) ⇒ Object



126
127
128
# File 'lib/libisi/doc/base.rb', line 126

def bare_table(options = {}, &block)
  generate_bare_table(options, &block)
end

#call_total_function(function_name, options = {}) ⇒ Object



205
206
207
208
209
210
# File 'lib/libisi/doc/base.rb', line 205

def call_total_function(function_name, options = {})
  level = options[:group_keys].length - 1
  function = options[(function_name.to_s + level.to_s).to_sym]
  return unless function
  function.call(options_for_functions(options))
end

#closeObject



381
382
383
384
# File 'lib/libisi/doc/base.rb', line 381

def close
  to_stdout(@writer)
  @writer.close if @writer and @writer.respond_to?(:close)
end

#end_docObject



379
# File 'lib/libisi/doc/base.rb', line 379

def end_doc; end

#flatten_columns(columns, options) ⇒ Object



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
# File 'lib/libisi/doc/base.rb', line 39

def flatten_columns(columns, options)
  # we will use this for grouping
  options[:columns] ||= []

  case columns
  when Array
    options[:columns] << columns
  when Hash
    options[:group_bys] ||= []      
    columns.each {|key,columns|
	unless key.nil?
 options[:group_bys] << Proc.new {|element| 
   case element
   when Hash
     element[key]
   else
     element.send(key)
   end
 }
	end
	flatten_columns(columns, options)
    }
  else 
    raise "Unexpected columns type #{columns.class.name}"
  end
  options
end

#generate_bare_table(options = {}, &block) ⇒ Object



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
# File 'lib/libisi/doc/base.rb', line 68

def generate_bare_table(options = {},&block) 
  return yield if options[:columns].nil? and options[:items].nil?

  options = flatten_columns(options.delete(:columns),options) if options[:columns].class == Hash
  
  if options[:group_bys]      
    raise "No items given" unless options[:items]
    # group the items
    benchmark("Table group bys") {
	options[:items] = options[:items].group_bys(*options[:group_bys])
    }
    options[:grouped] = true
  end
  
  if options[:items] and options[:columns] and not options[:no_header]
    # create header
    tr(options) { options[:columns].flatten.each_with_index{|c,i| th(options) {
   if f = options[:header_function]
     case f
     when Proc
if f.arity == 1
  f.call(c)
else
  f.call(c,i)
end
     when Symbol, String
c.send(f)
     else
	raise "Unexpected header function #{f.inspect}"
     end
   else
     c
   end
 }}}
  end

  if options[:items]
    options[:header_function].call(options_for_functions(options) ) if options[:header_function]
    table_items(options[:items],options,&block)
    options[:footer_function].call(options_for_functions(options) ) if options[:footer_function]
  else
    options[:columns].flatten.each_with_index {|column, column_index|
	tr(options) {
 th(options) {column}
 #	  td(options) {
 # problem with tee here
 td {options[:columns].inspect}
 case block.arity
 when 2
   yield(column,column_index)
 else
   yield(column)
 end
	}
	#	}
    }
  end
end

#generate_table(options = {}, &block) ⇒ Object



67
# File 'lib/libisi/doc/base.rb', line 67

def generate_table(options = {}, &block); generate_bare_table(options, &block) end

#options_for_functions(options) ⇒ Object



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
# File 'lib/libisi/doc/base.rb', line 134

def options_for_functions(options)
  options[:item_tree] = options[:items].to_hash(true) unless options[:item_tree]
  o = options.dup
  if o[:group_bys]
    benchmark("Doc.options_for_functions") {
	total_groupings = o[:group_bys].length
	if o[:group_column_index]
 # we are at item output
 depth = o[:group_column_index]
	else
 # we are at grouping
 depth = (o[:group_keys] or []).length - 1
	end
	
	# correct group_keys because we are maybe already
	# in a gouping
	o[:group_keys] = (o[:group_keys] or []).dup[0..depth]

	o[:group_tree] = options[:item_tree]

	o[:group_keys].each {|k|
 o[:group_tree] = o[:group_tree][k]
	}
	
	o[:group_items] = o[:group_tree]
	o[:group_items] = o[:group_items].values.flatten if o[:group_items].class == Hash
	#      while !o[:group_items].nil? and o[:group_items][0].class == Hash
	(total_groupings - depth - 2).times {
 o[:group_items] = o[:group_items].map {|h| h.values}.flatten
	}
	#      end
    }
  end
  o
end

#options_for_functions_orig(options) ⇒ Object



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
# File 'lib/libisi/doc/base.rb', line 171

def options_for_functions_orig(options)
  o = options.dup
  if o[:group_bys]
    benchmark("Doc.options_for_functions") {
	total_groupings = o[:group_bys].length
	if o[:group_column_index]
 # we are at item output
 depth = o[:group_column_index]
	else
 # we are at grouping
 depth = o[:group_keys].length - 1
	end
	
	# correct group_keys because we are maybe already
	# in a gourping
	o[:group_keys] = o[:group_keys].dup[0..depth]

	o[:group_tree] = options[:items].to_hash(true)
	o[:group_keys].each {|k|
 o[:group_tree] = o[:group_tree][k]
	}
	
	o[:group_items] = o[:group_tree]
	o[:group_items] = o[:group_items].values.flatten if o[:group_items].class == Hash
	#      while !o[:group_items].nil? and o[:group_items][0].class == Hash
	(total_groupings - depth - 2).times {
 o[:group_items] = o[:group_items].map {|h| h.values}.flatten
	}
	#      end
    }
  end
  o
end

#p(options = {}, &block) ⇒ Object



28
29
30
# File 'lib/libisi/doc/base.rb', line 28

def p(options = {}, &block)
  writer(options, &block) << yield + "\n\n"
end


25
26
27
# File 'lib/libisi/doc/base.rb', line 25

def print(options = {}, &block)
  writer(options, &block) << yield
end

#start_docObject



378
# File 'lib/libisi/doc/base.rb', line 378

def start_doc; end

#table(options = {}, &block) ⇒ Object



129
130
131
132
# File 'lib/libisi/doc/base.rb', line 129

def table(options = {}, &block)
#    options[:writer] = writer(options, &block) unless options[:writer]
  generate_table(options,&block)
end

#table_item(item, item_index, options = {}, &block) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/libisi/doc/base.rb', line 257

def table_item(item, item_index, options = {}, &block)    
  redo_item = false
  options[:item_index] += 1 if options[:item_index]
  if (cols = options[:columns])
    # yield one per column
    column_index = -1

    # cols in format 
    #  [ [groupcol,groupcol,groupcol], # columns for group element 1
    #    [groupcol,groupcol,groupcol], # columns for group element 2
    #    col,col,col ] 
    cols.each_with_index {|subcolumns, group_column_index|
	options[:group_column_index] = group_column_index

	if subcolumns.class == Array
 # ok these are subcolumns of a group
	else
 subcolumns = [subcolumns]
	end
	
	subcolumns.each_with_index {|column,subcol_index|
 # column_index counts trough each column (including group cols)
 column_index += 1

 el = item

 group_column = (options[:group_elements] and 
     options[:group_elements].length > group_column_index)
 if group_column
   # This is a group column
   
   if options[:group_elements][group_column_index] == NilClass 
     # we already yielded this group element
     td(options) {} 
     next
   else
     el = options[:group_elements][group_column_index]
     # mark group element as visited if all group columns
     # for that group element have been yielded
     if (subcolumns.length - 1) == subcol_index
options[:group_elements][group_column_index] = NilClass 
if options[:span_grouping]
  redo_item = true 
  
  # TODO: this is not right, but works for group items with one column
  total_columns = options[:columns].flatten.length
  grouped_columns = (options[:group_elements].length - 1)
  
  options = { :colspan => total_columns - grouped_columns}.merge(options)		    
  #		    td({:colspan => grouped_columns}.merge(options)) {} unless grouped_columns == 0
  #		    th({:colspan => total_columns - grouped_columns}.merge(options)) {yield(key}
end
									
     end

     if block_given? and block.arity == 1		
td(options) {
  if options[:span_grouping]
    # we already printed grouping
    ""
  else
    el.to_s
  end
} 
next
     end	  
   end
 end

 next td(options){el.to_s} unless block_given?
 case block.arity
 when 2
   td(options) {yield(el,column)}
 when 3
   td(options) {yield(el,column,item_index)}
 when 4
   td(options) {yield(el,column,item_index,column_index)}
 when 5
   o = options_for_functions(options)	    
   td(options) {yield(el,column,item_index,column_index,o)}
 else
   yield(el)
   # class is handling columns themself
   break
 end
 if redo_item
   options.delete(:group_column_index)
   return true 
 end
	}
	options.delete(:group_column_index)
    }
    false
  else
    if options[:group_elements]
	options[:group_elements].each_with_index {|group_element, group_element_index|	  
 if group_element
   td(options) { group_element} 
 else
   td(options) {} 
 end
 options[:group_elements][group_element_index] = nil
	}
    end

    return td(options) {item.to_s} unless block_given?

    case block.arity
    when 2
	yield(item,item_index)
    else
	return yield(item)
    end
  end
end

#table_items(items, options = {}, &block) ⇒ Object



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
# File 'lib/libisi/doc/base.rb', line 212

def table_items(items, options = {}, &block)
  redo_item = false
  if options[:grouped]
    options[:group_elements] ||= []
    options[:group_keys] ||= []
    options[:item_index] ||= 0

    if items[0].class == Array and 
 items[0].length == 2
	# this is still a group
	items.each_with_index {|val, group_index|
 key, group = val
 options[:group_elements] << key
 options[:group_keys] << key
 call_total_function(:before_group_function, options)
 table_items(group, options, &block)
 call_total_function(:after_group_function, options)
 options[:group_elements].pop
 options[:group_keys].pop
	}
    else
	# finished grouping, do output
	if options[:return_group_at_once]
 tr(options) {	    
   redo_item = table_item(items, options[:item_index], options, &block)
 }	  
	else
 items.each_with_index {|item, item_index|
   tr(options) {
     redo_item = table_item(item, options[:item_index], options, &block)
   }
   redo if redo_item
 }
	end
    end
  else
    options[:items].each_with_index {|item, item_index|
	tr(options) {
 redo_item = table_item(item, item_index, options, &block)
	}
	redo if redo_item
    }      
  end
end

#title(text, options = {}, &block) ⇒ Object



32
33
34
35
36
37
# File 'lib/libisi/doc/base.rb', line 32

def title(text, options = {}, &block)
  @title_depth ||= 0
  @title_depth += 1
  generate_title(text, options, &block)
  @title_depth -= 1
end

#tn(options = {}, &block) ⇒ Object



373
374
375
376
# File 'lib/libisi/doc/base.rb', line 373

def tn(options = {}, &block); 
  options[:text_align] ||= "right"
  td(options, &block)
end