latex 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,9 @@
1
+ 0.1.2
2
+ 2004-10-12 Christian Bang <cbang@cbang@web.de>
3
+
4
+ * Non-centered table columns are now supported.
5
+ See doc for table and new example.
6
+ * Bug with LatexFile optional arguments (extras) fixed.
7
+
8
+
9
+
data/README CHANGED
@@ -45,7 +45,7 @@ Usage
45
45
  -----
46
46
 
47
47
  In order to get an overview of the features you can generate
48
- the RDoc documentation and hava a look at the examples/ directory.
48
+ the RDoc documentation and have a look at the examples/ directory.
49
49
 
50
50
 
51
51
  License
data/examples/latex.rb ADDED
@@ -0,0 +1,558 @@
1
+ # Copyright (c) 2004 Christian Bang <cbang AT web.de> and Frank Hutter
2
+ #
3
+ # Version 0.1.2
4
+ #
5
+ # All rights reserved. You can redistribute and/or modify it under the same terms as Ruby.
6
+ #
7
+ # This file provides a LatexFile class for Ruby.
8
+
9
+ class String
10
+ #Escapes underscores. Use this if you have a string that contains
11
+ #such but you don't mean the latex semantic of underscore.
12
+ def escape_
13
+ gsub(/_/,"\\_")
14
+ end
15
+ end
16
+
17
+ #examples: Figure.new("9cm", "image.eps", "Test image")
18
+ # Figure.new("angle=-90,width=9.5cm", "rotatedimage.eps", "Rotated image", "link01")
19
+ Figure = Struct.new(:format, :filename, :title, :label)
20
+
21
+ class FormatError < StandardError
22
+ end
23
+
24
+ # +LatexFile+ is a +File+ with special functions for easy generation of
25
+ # LaTeX code.
26
+ # Current mayor features are +table+ and +figures+ generation.
27
+ #
28
+ # You may want to quote underscores ('_') in some Latex code you create. For this use String.escape_ which
29
+ # is available with this file.
30
+ class LatexFile < File
31
+ Header = Struct.new(:name, :align, :children)
32
+
33
+ # the default table font size, default is nil which means the Latex default. See #table for possible values
34
+ attr_accessor :defaultTableFontSize
35
+
36
+ @@defaultUsePackages = %w([latin1]{inputenc} [final]{graphics} [pdftex]{graphicx} [dvips]{color}
37
+ {amsfonts} {subfigure} {lscape} {hyperref})
38
+ @@default_extras = {:fontsize => "10pt" }
39
+ attr_reader :extras
40
+
41
+ @default_table_align = 'c'
42
+ # The default table alignment is <tt>'c'</tt> but can be changed.
43
+ attr_accessor :default_table_align
44
+
45
+ # Open a new latex-file for writing.
46
+ # +extras+ is an optional hash that may contain the following flags
47
+ # <tt>:landscape</tt>:: turns all pages 90�
48
+ # <tt>:twocolumn</tt>:: the whole document has two columns
49
+ # <tt>extras[:fontsize]</tt>:: string containing the font size like "10pt"
50
+ # === Example:
51
+ # f = LatexFile.new("test.tex", :twocolumn => true, :fontsize => "11pt")
52
+ def initialize(filename, extras = nil)
53
+ super(filename,"w") # open a file for write access
54
+ @extras = extras || Hash.new
55
+ #use defaults for unused entries:
56
+ @@default_extras.each_key{|key| @extras[key] ||= @@default_extras[key] }
57
+ @indent = 0 # indent lines in blocks
58
+
59
+ @usePackages = @extras[:usePackages] || @@defaultUsePackages
60
+
61
+ writeDocumentHeader
62
+ @lastWasPrint = false
63
+ end
64
+
65
+ def writeDocumentHeader
66
+ twocolumn = @extras[:twocolumn] ? ",twocolumn" : ""
67
+ landscape = @extras[:landscape] ? "\\special{landscape}" : ""
68
+ puts "\\documentclass[#{@extras[:fontsize]}#{twocolumn}]{article}"
69
+ @usePackages.each{|package| puts "\\usepackage#{package}"}
70
+ puts "\\addtolength{\\oddsidemargin}{-3.5cm}"
71
+ puts "\\addtolength{\\textwidth}{7cm}"
72
+ puts "\\addtolength{\\topmargin}{-3cm}"
73
+ puts "\\addtolength{\\textheight}{5cm}"
74
+ puts "\\newcommand{\\hide}[1]{}"
75
+ puts "#{landscape}"
76
+ puts "\\begin{document}"
77
+ puts "\\DeclareGraphicsExtensions{.jpg,.pdf,.mps,.png}"
78
+ end
79
+
80
+ #Write the latex-file footer and closes the file.
81
+ def close
82
+ puts "\\end{document}"
83
+ super
84
+ end
85
+
86
+ #Prints a string to the latex file and indents each line with respect to the
87
+ #current indentation level that depends on nested blocks.
88
+ def puts(string)
89
+ lines = string.split("\n")
90
+ for line in lines
91
+ @indent -= 2 if line[0,5]=='\\end{' && @indent >= 2
92
+ if @lastWasPrint
93
+ super(line)
94
+ @lastWasPrint = false
95
+ else
96
+ super(" " * @indent + line)
97
+ end
98
+ @indent += 2 if line[0,7]=='\\begin{'
99
+ end
100
+ end
101
+
102
+ #Insert spaces up to the current indentation level
103
+ def indent
104
+ print " "*@indent
105
+ end
106
+
107
+ #Other than puts, print does NOT indent the text. If you want to do so
108
+ #call +indent+ before.
109
+ def print(string)
110
+ @lastWasPrint = true
111
+ @indent -= 2 if string[/\\end/]
112
+ @indent += 2 if string[/\\begin/]
113
+ super(string)
114
+ end
115
+
116
+ # Easy creation of environments.
117
+ # +name+:: the name of the environment.
118
+ # +args+:: an optional list of arguments that will be added after the environment definition.
119
+ # === Example:
120
+ # tex.env("table","[ht]") do
121
+ # tex.puts "<table body>"
122
+ # end
123
+ def env(name, *args)
124
+ puts "\\begin{#{name}}#{args}"
125
+ yield if block_given?
126
+ puts "\\end{#{name}}"
127
+ end
128
+
129
+ ########### Figure generation #################################################
130
+
131
+ #Inserts one (ore more) figure block(s) with given figures as subfigures.
132
+ #+figures+::
133
+ # is an array consisting of +Figure+ instances.
134
+ # <tt>Figure = Struct.new(:format, :filename, :title)</tt>
135
+ # If +format+ begins with a number, it is assumed to be the width of the image.
136
+ # But you can also set e.g. <tt>"height=10.5cm,angle=-90"</tt>.
137
+ # For more info see the documentation to <tt>\includegraphics </tt> in the
138
+ # +graphicx+ package of _LaTeX_.
139
+ #+caption+:: is placed on each figure block that is created.
140
+ #+newPageThreshold+::
141
+ # is maximum the number of figures in a block.
142
+ # If more figures are given then a new block is created with the same
143
+ # caption.
144
+ #+placement+:: an optional placement for the figure blocks.
145
+ #+label+:: an optional label of the figures block ('fig:' is added)
146
+ # You can also use label="\\hypertarget{...}" if you like.
147
+ # Otherwise a \label{fig:...} is generated.
148
+ #=== Example:
149
+ # Experiment = Struct.new(:caption, :figures)
150
+ # thisExperiment = Experiment.new
151
+ # thisExperiment.caption = "Instance: #{instance}_1.dat".escape_
152
+ # thisExperiment.figures = [
153
+ # Figure.new("6.5cm", epsDirectory, "#{instance}-a.eps"),
154
+ # Figure.new("6.5cm", epsDirectory, "#{instance}-b.eps"),
155
+ # Figure.new("14cm", epsDirectory, "#{instance}-c.eps", "Title for image c)")
156
+ # ]
157
+ # tex.figures(thisExperiment.caption, thisExperiment.figures, 3)
158
+ def figures(caption, figures, newPageThreshold, placement = "htbp", label = nil)
159
+ lastimagepath = ""
160
+ figures.each_with_index do |figure,i|
161
+ figure.title = "[{#{figure.title}}]" unless figure.title == "" or figure.title == nil
162
+ if i % newPageThreshold == 0
163
+ puts "\\begin{figure}[#{placement}]"
164
+ puts "\\caption{#{caption}}"
165
+ if label
166
+ if label[0,1]=='\\' #you can use \hypertarget here
167
+ puts label
168
+ else
169
+ puts "\\label{fig:#{label}}"
170
+ end
171
+ end
172
+ puts "\\centering"
173
+ end
174
+ imagepath = File.dirname(figure.filename)
175
+ puts "\\graphicspath{{#{imagepath}}}" if imagepath != "" and imagepath != "." and lastimagepath != imagepath
176
+ lastimagepath = imagepath
177
+ figure.format = "width="+figure.format if figure.format =~ /^[0-9\.]/
178
+ if figure.label
179
+ if figure.label[0,1]=='\\'
180
+ puts figure.label
181
+ else
182
+ puts "\\label{#{figure.label}}"
183
+ end
184
+ end
185
+ puts "\\subfigure#{figure.title}{\\includegraphics[#{figure.format}]{#{File.basename(figure.filename)}}}"
186
+ if i % newPageThreshold == newPageThreshold-1 or figure == figures[-1]
187
+ puts "\\end{figure}"
188
+ puts "\\clearpage"
189
+ end
190
+ end
191
+ end
192
+
193
+ ########### Table Generation functions #################################################
194
+
195
+ #This is a helper function for table generation.
196
+ #It computes the number of columns that are leaves of the tree with root +header_node+.
197
+ #You can also say, it computes the number of leaves of the given tree.
198
+ #+header+:: is of type +Header+: (name, children)
199
+ def getNumColsOfHeader(header)
200
+ header.children.inject(0) do |numChildren, child|
201
+ numChildren + (child.children ? getNumColsOfHeader(child) : 1)
202
+ end
203
+ end
204
+ private :getNumColsOfHeader
205
+
206
+ #+list+:: must contain hashes as values for all keys.
207
+ #These child hashes will be joined/merged to one big hash.
208
+ #The actual leafes will be ignored so that only the header remain.
209
+ def getHeaderMergedHash(list)
210
+ merged = {}
211
+ toMerge = Hash.new {|h,k| h[k] = [] }
212
+ nothingToMerge = true
213
+ for entry in list
214
+ if entry.class == Hash
215
+ entry.each_pair do |key,value|
216
+ toMerge[key] << value
217
+ end
218
+ nothingToMerge = false
219
+ end
220
+ end
221
+ #return list if nothingToMerge
222
+ return nil if nothingToMerge #return only header tree without any data
223
+ toMerge.each_pair do |key,value|
224
+ if key.class == Symbol
225
+ merged[key] = value unless merged[key]
226
+ else
227
+ merged[key] = getHeaderMergedHash(value)
228
+ end
229
+ end
230
+ return merged
231
+ end
232
+ private :getHeaderMergedHash
233
+
234
+ @@default_sort = Proc.new { |x,y| x <=> y }
235
+
236
+ #Given a list of hashes, initially a hash-list of each row it
237
+ #returns a sorted tree representation - a headerList.
238
+ #+sort_block+:: a block that compares header names
239
+ #side effects::
240
+ # deletes :align entries from the +hash+ and transforms
241
+ # hash[:value] = value hashes to normal entries
242
+ def hash2HeaderList(hash, sort_block = @@default_sort)
243
+ headerList = []
244
+ entries = hash.to_a
245
+ entries.sort! do |x,y| sort_block.call(x[0],y[0])
246
+ end
247
+ for key,value in entries
248
+ if value.class == Hash
249
+ align = value.delete(:align) || @default_table_align
250
+ align = align[0] if align.class == Array
251
+ if value[:value] #transform hashes with :value keys to normal entries
252
+ hash[key] = value = value[:value]
253
+ headerList << Header.new(key,align,nil)
254
+ else
255
+ subtree = hash2HeaderList(value, sort_block)
256
+ headerList << Header.new(key,align,subtree)
257
+ end
258
+ else
259
+ headerList << Header.new(key,@default_table_align,nil)
260
+ end
261
+ end
262
+ return headerList
263
+ end
264
+ private :hash2HeaderList
265
+
266
+ #Performes a breath first traversal of the given tree
267
+ #+headerList+:: a list of header nodes of class +Header+.
268
+ #Returns a list of headers (together with the number of columns they use) for each header line needed.
269
+ #example: <tt>[['B',['C',['F','G']], ['D',['H','I']],['E']]]</tt> =>
270
+ #<tt>[['B'], ['C','D','E'], ['F','G','H','I']]</tt> and with their column width information
271
+ #if the (sub)header covers more than one column =>
272
+ #<tt>[[['B',5]], [['C',2],['D',2],'E'], ['F','G','H','I']]</tt>
273
+ #The length of the returned list is the number of rows needed for the headers.
274
+ def getHeaderLines(headerList) #:nodoc:
275
+ line = []
276
+ nextLevel = [] # collects the children nodes of all nodes processed (BFS)
277
+ hasChildrenInNextLevel = false
278
+ for header in headerList
279
+ if header.is_a?(Array) and header[0] == "~"
280
+ line << header
281
+ nextLevel << header # insert this for lines below this
282
+ elsif header.children == nil # leaf node ?
283
+ line << [header.name, header.align]
284
+ nextLevel << ["~",header.align] # insert this for lines below this
285
+ else
286
+ line << [header.name, header.align, getNumColsOfHeader(header)]
287
+ nextLevel += header.children
288
+ hasChildrenInNextLevel = true
289
+ end
290
+ end
291
+ return hasChildrenInNextLevel ? [line] + getHeaderLines(nextLevel) : [line]
292
+ end
293
+ private :getHeaderLines
294
+
295
+ #Returns a list of paths to all leaf nodes of the given header-tree list. The Leaf nodes are the final
296
+ #columns. In order to compute the table value at (row,col) we want to access only the leaf cols and not
297
+ #the header columns.
298
+ #Example: let <tt>[['B',['C',['F','G']], ['D',['H','I']],['E']]]</tt> be our
299
+ #header tree. The real columns are F,G,H,I,E. In order to access e.g. 'I' we need to know the path [B,D,I].
300
+ #<tt> => [["B", "C", "F"], ["B", "C", "G"], ["B", "D", "H"], ["B", "D", "I"], ["B", "E"]]</tt>
301
+ def getLeafColumns(headerList, path_prefix = nil) #:nodoc:
302
+ paths = []
303
+ path_prefix = path_prefix || []
304
+ for header in headerList
305
+ if header.children
306
+ paths += getLeafColumns(header.children, path_prefix + [header.name])
307
+ else #header is not of class Header but a leaf header (string)
308
+ paths << path_prefix + [header.name]
309
+ end
310
+ end
311
+ return paths
312
+ end
313
+ private :getLeafColumns
314
+
315
+ #Pretty print output of table entries. If an entry is an array then
316
+ #+prettyPrintCell+ will be called for every table item. You can override this
317
+ #function if you like a special behaviour.
318
+ def prettyPrintCell(x)
319
+ if x.kind_of?(Integer)
320
+ x = "%d" % x
321
+ elsif x.kind_of?(Float)
322
+ x = "%.2f" % x
323
+ else
324
+ x = x.to_s
325
+ end
326
+ raise(FormatError, "Invalid format: #{x.inspect} contains % that is not sufficiently quoted for latex.", caller) if x =~ /[^\\]%|^%/
327
+ x.gsub(/1.#J|Infinity|1.#INF0/, "$\\infty$")
328
+ end
329
+
330
+
331
+ # Generates a table with the specified entries.
332
+ # +entries+::
333
+ # the row-hash where the keys are the row names which are printed in the first column.
334
+ # The <tt>entries[row]</tt> is a column-hash. Its keys are the column names.
335
+ # A column-hash value can be either
336
+ # - an object (with a <tt>to_s</tt> method) that are printed
337
+ # - an array containing objects. In this case a new row is added for each array entry
338
+ # - a hash in which case the keys of this hash are subheaders.
339
+ # +caption+:: the caption of the table.
340
+ # +args+::
341
+ # is either a hash or further arguments
342
+ # Case 1::
343
+ # The hash is indexed by one of the argument symbols below, the values correspond to the
344
+ # argument values you want to set to the corresponding argument.
345
+ # Instead of symbols you can also use strings, e.g. <tt>:label</tt> or <tt>"label"<</tt>
346
+ # Case 2::
347
+ # args are some more arguments. Then they will be interpreted as the following arguments
348
+ # in the same order. You need not use all of them.
349
+ # <tt>:rowTitle</tt>:: the title of the first column that contains the row names.
350
+ # <tt>:label</tt>:: the label of the table. The "tab:" prefix is added automatically .
351
+ # <tt>:newTableThreshold</tt>::
352
+ # maximum number of lines per table. If reached then a new table will be created.
353
+ # Zero means no restriction. An empty row (entries[name] == nil) also toggles a new table.
354
+ # <tt>:placement</tt>:: the LaTeX placement for the table. See the LaTeX documentation for details.
355
+ # <tt>:empty</tt>:: a string that will be put in those fields that have no value.
356
+ # <tt>:sort</tt>::
357
+ # is used to sort the rows and columns. Default is alphabetical ordering.
358
+ # See the example below to get an idea on how to implement customized ordering.
359
+ # <tt>:landscape</tt>:: if true, it will turn the page by 90 degree.
360
+ # <tt>:fontSize</tt>::
361
+ # A latex fontsize modifier like tiny, scriptsize, footnotesize, small,
362
+ # normalsize (default), large, Large, LARGE, huge, Huge.
363
+ # <tt>:header_hlines</tt>::
364
+ # If +true+, then horizontal lines between headers of different depths are drawn.
365
+ # Default is +false+ (no horizontal header lines).
366
+ # <tt>:rowAlign</tt>::
367
+ # Alignment of the column containing the row names. Values are 'r','c','l'.
368
+ # See also the attribute +default_table_align+.
369
+ #
370
+ # === Example:
371
+ # require 'latex'
372
+ # tex = LatexFile.new("table.tex")
373
+ # rows["row1"] = {'Main Header'=>
374
+ # {'A'=> '5',
375
+ # 'B'=> {'D'=>'1','E'=>'2'},
376
+ # 'C'=> {'F'=>'3','G'=>'4'}},
377
+ # 'X'=> [1,3,55.55]}
378
+ # tex.table(rows,"table with hierarchical headers",:rowTitle=>"Instance")
379
+ # tableSort = Proc.new do |x,y|
380
+ # order = %w{A X B C D E}
381
+ # (order.index(x) && order.index(y)) ? order.index(x) <=> order.index(y) : x <=> y
382
+ # end
383
+ # tex.table(rows,"special ordering", :rowTitle=>"Instance", :sort => tableSort)
384
+ #
385
+ # === Column alignment:
386
+ # By default alignment is centered. You can change this for all columns using the attribute
387
+ # +default_table_align+.
388
+ # The alignment can also be changed for each column separately:
389
+ # Headers can be aligned as demonstrated in the following examples:
390
+ # rows['1'] = {'Main Header' => {:align => 'l', 'A' => '5','B' => '6'}}
391
+ # This affects only the header and not the columns, because this is no final column header.
392
+ # Subheader and so the final columns themselves are aligned as follows:
393
+ # rows['1'] = {'Main Header' => {'A' => {:value => '5', :align => 'l'} ,'B' => '6'}}
394
+ # rows['2'] = {'Main Header' => {'A' => '77','B' => '8'}}
395
+ # As you can see it is only needed to define the alignment of a column once. It can be done
396
+ # as often as you like but only one alignment definition is used.
397
+ def table(entries, caption, *args)
398
+ tableValidArgs = [:rowTitle, :label, :newTableThreshold, :placement, :empty, :sort, :landscape, :fontSize, :grouping, :header_hlines, :rowAlign]
399
+ # raise(ArgumentError,"Too many arguments Latex.table", caller) unless args.length <= 1
400
+ hash = {}
401
+ args = if args[0].kind_of?(Hash)
402
+ args[0].each_pair{|key,value| hash[key.to_sym]= value}; hash # allow string keys also
403
+ else
404
+ args.each_with_index{|arg,i| hash[tableValidArgs[i].to_sym] = arg}; hash
405
+ end
406
+ args.each_key{|key| raise(ArgumentError,"Invalid argument: #{key} for Latex.table", caller) unless tableValidArgs.include?(key)}
407
+ @tableCaption = caption
408
+ rowTitle = args[:rowTitle] || ""
409
+ @tableLabel = args[:label] || ""
410
+ newTableThreshold = args[:newTableThreshold] || (args[:landscape] ? 38 : 60)
411
+ placement = args[:placement] || "htbp"
412
+ empty = args[:empty] ||"-"
413
+ sort_block = args[:sort] ||@@default_sort
414
+ grouping = args[:grouping] || [entries.keys]
415
+ @tableLandscape = args[:landscape]
416
+ @tableFontSize = args[:fontSize] || @defaultTableFontSize
417
+ @header_hlines = args[:header_hlines]
418
+ @rowAlign = args[:rowAlign] || @default_table_align
419
+
420
+ #access an element in the table which is located in row _rowName_ and in a column
421
+ #that is defined by a _path_ through the headers that can be obtained with
422
+ #the function +getLeafColumns+.
423
+ def accessElement(entries, rowName, path) #:nodoc:
424
+ entry = entries[rowName]
425
+ for key in path
426
+ entry = entry[key]
427
+ return [] unless entry
428
+ end
429
+ entry = entry[:value] if entry.is_a?(Hash)
430
+ return entry.is_a?(Array) ? entry : [entry]
431
+ end
432
+
433
+ def printTableHeader(placement, headerLines, leafColumns, rowTitle) #:nodoc:
434
+ puts "\\begin{landscape}" if @tableLandscape
435
+ puts "\n\\begin{table}[#{placement}]\n\\begin{center}"
436
+ puts "\\#{@tableFontSize}" if @tableFontSize
437
+ print " "*@indent + "\\begin{tabular}{|"
438
+ # print the alignment {c,r,l} for each leaf column
439
+ print "#{@rowAlign}|" # the first column with the row names
440
+ headerLines[-1].each {|headerName, colAlign| print "#{colAlign}|" }
441
+ puts "}"
442
+ currentHeaderRowNumber = 0
443
+ puts "\\hline"
444
+ for headerLine in headerLines
445
+ print " "*@indent
446
+ if headerLine == headerLines[-1]
447
+ print "#{rowTitle} & " # row name title comes in the last header line
448
+ else
449
+ print "~ & "
450
+ end
451
+ currentColumn = 2
452
+ cline = ""
453
+ print headerLine.map {|headerName, align, columns|
454
+ raise(FormatError, "Invalid format: #{headerName.inspect} contains % that is not sufficiently quoted for latex.", caller) if headerName =~ /[^\\]%|^%/
455
+ if columns
456
+ cline += "\\cline{#{currentColumn}-#{(currentColumn+=columns)-1}}" if @header_hlines
457
+ "\\multicolumn{#{columns}}{#{align}|}{#{headerName}}"
458
+ else
459
+ currentColumn += 1
460
+ if currentHeaderRowNumber == headerLines.length-1 || headerName == "~"
461
+ headerName
462
+ else
463
+ delta = "%.1f" % ((headerLines.length-currentHeaderRowNumber-1).to_f)
464
+ "\\raisebox{-#{delta}\\totalheight}[1ex][1ex]{#{headerName}}"
465
+ end
466
+ end
467
+ }.join(" & ")
468
+ puts "\\\\"+cline
469
+ currentHeaderRowNumber += 1
470
+ end
471
+ puts "\\hline\\hline"
472
+ end
473
+
474
+ def printTableFooter #:nodoc:
475
+ puts "\\end{tabular}"
476
+ puts "\\caption{#{@tableCaption}}\n\\label{tab:#@tableLabel}"
477
+ puts "\\end{center}\n\\end{table}\n"
478
+ puts "\\end{landscape}" if @tableLandscape
479
+ end
480
+
481
+ #====== Generate header
482
+ headerList = hash2HeaderList(getHeaderMergedHash(entries.values), sort_block)
483
+ headerLines = getHeaderLines(headerList)
484
+ leafColumns = getLeafColumns(headerList)
485
+ printTableHeader(placement, headerLines, leafColumns, rowTitle)
486
+
487
+ currentRow = 0
488
+ for row_names in grouping
489
+ #======= Compute table break for multiple groupings.
490
+ new_lines = 0
491
+ for row_name in row_names
492
+ max_lines_per_entry = 1
493
+ for col_header in leafColumns
494
+ max_lines_per_entry = [max_lines_per_entry, accessElement(entries,row_name,col_header).length].max
495
+ end
496
+ new_lines += max_lines_per_entry
497
+ end
498
+
499
+ if (currentRow > 0 and currentRow + new_lines >= newTableThreshold)
500
+ currentRow = 0
501
+ printTableFooter # close last table
502
+ printTableHeader(placement, headerLines, leafColumns, rowTitle) # open new table
503
+ else
504
+ unless currentRow == 0
505
+ puts "\\hline" unless row_names == []
506
+ currentRow += 0.5
507
+ end
508
+ end
509
+
510
+ row_names.sort! &sort_block
511
+ #====== Generate entries.
512
+ for row_name in row_names
513
+ if (newTableThreshold > 0 and currentRow >= newTableThreshold)
514
+ currentRow = 0
515
+ printTableFooter # close last table
516
+ printTableHeader(placement, headerLines, leafColumns, rowTitle) # open new table
517
+ end
518
+ max_lines_per_entry = 1
519
+ for col_header in leafColumns
520
+ max_lines_per_entry = [max_lines_per_entry, accessElement(entries,row_name,col_header).length].max
521
+ end
522
+
523
+ for i in 0...max_lines_per_entry
524
+ #print row-name
525
+ print " "*@indent
526
+ output = (i==0 ? row_name.to_s.gsub(/_/,"\\_") : "~")
527
+ delta = "%.1f" % ((max_lines_per_entry-1).to_f)
528
+ output = "\\raisebox{-#{delta}\\totalheight}[1ex][1ex]{#{output}}" if max_lines_per_entry > 1
529
+ print output
530
+
531
+ #print the other columns
532
+ for col_header in leafColumns
533
+ entry = accessElement(entries,row_name,col_header)
534
+ if entry[i]
535
+ output = prettyPrintCell(entry[i])
536
+ delta = "%.1f" % (max_lines_per_entry-entry.length).to_f
537
+ else
538
+ output = (i==0 ? empty : "~")
539
+ delta = max_lines_per_entry
540
+ end
541
+ #Center the entries vertically in the cell. Out-comment this if you don't like that.
542
+ if entry.length != max_lines_per_entry# && entry.length > 0
543
+ output = "\\raisebox{-#{delta}\\totalheight}[1ex][1ex]{#{output}}" unless output == "~"
544
+ end
545
+ print " & " + output
546
+ end
547
+ puts "\\\\"
548
+ end
549
+ puts "\\hline"
550
+ currentRow += max_lines_per_entry
551
+ end
552
+ end
553
+ #====== Generate footer.
554
+ printTableFooter
555
+ end
556
+ end
557
+
558
+
@@ -0,0 +1,19 @@
1
+ \relax
2
+ \ifx\hyper@anchor\@undefined
3
+ \global \let \oldcontentsline\contentsline
4
+ \gdef \contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
5
+ \global \let \oldnewlabel\newlabel
6
+ \gdef \newlabel#1#2{\newlabelxx{#1}#2}
7
+ \gdef \newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
8
+ \AtEndDocument{\let \contentsline\oldcontentsline
9
+ \let \newlabel\oldnewlabel}
10
+ \else
11
+ \global \let \hyper@last\relax
12
+ \fi
13
+
14
+ \@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces common table}}{1}{table.1}}
15
+ \newlabel{tab:}{{1}{1}{\relax }{table.1}{}}
16
+ \@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces hierarchical headers}}{1}{table.2}}
17
+ \newlabel{tab:}{{2}{1}{\relax }{table.2}{}}
18
+ \@writefile{lot}{\contentsline {table}{\numberline {3}{\ignorespaces both tables}}{2}{table.3}}
19
+ \newlabel{tab:}{{3}{2}{\relax }{table.3}{}}
Binary file
@@ -0,0 +1,197 @@
1
+ This is TeXk, Version 3.14159 (Web2C 7.4.5) (format=latex 2003.11.5) 12 OCT 2004 15:46
2
+ Source specials enabled.
3
+ **\nonstopmode\input{latextest.tex}
4
+ (./latextest.tex (/usr/share/texmf/tex/latex/base/article.cls
5
+ Document Class: article 2001/04/21 v1.4e Standard LaTeX document class
6
+ (/usr/share/texmf/tex/latex/base/size10.clo
7
+ File: size10.clo 2001/04/21 v1.4e Standard LaTeX file (size option)
8
+ )
9
+ \c@part=\count79
10
+ \c@section=\count80
11
+ \c@subsection=\count81
12
+ \c@subsubsection=\count82
13
+ \c@paragraph=\count83
14
+ \c@subparagraph=\count84
15
+ \c@figure=\count85
16
+ \c@table=\count86
17
+ \abovecaptionskip=\skip41
18
+ \belowcaptionskip=\skip42
19
+ \bibindent=\dimen102
20
+ )
21
+ (/usr/share/texmf/tex/latex/base/inputenc.sty
22
+ Package: inputenc 2001/07/10 v0.99a Input encoding file
23
+
24
+ (/usr/share/texmf/tex/latex/base/latin1.def
25
+ File: latin1.def 2001/07/10 v0.99a Input encoding file
26
+ ))
27
+ (/usr/share/texmf/tex/latex/graphics/graphics.sty
28
+ Package: graphics 2001/07/07 v1.0n Standard LaTeX Graphics (DPC,SPQR)
29
+
30
+ (/usr/share/texmf/tex/latex/graphics/trig.sty
31
+ Package: trig 1999/03/16 v1.09 sin cos tan (DPC)
32
+ )
33
+ (/usr/share/texmf/tex/latex/config/graphics.cfg
34
+ File: graphics.cfg 2001/08/31 v1.1 graphics configuration of teTeX/TeXLive
35
+ )
36
+ Package graphics Info: Driver file: dvips.def on input line 80.
37
+
38
+ (/usr/share/texmf/tex/latex/graphics/dvips.def
39
+ File: dvips.def 1999/02/16 v3.0i Driver-dependant file (DPC,SPQR)
40
+ ))
41
+ (/usr/share/texmf/tex/latex/graphics/graphicx.sty
42
+ Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR)
43
+
44
+ (/usr/share/texmf/tex/latex/graphics/keyval.sty
45
+ Package: keyval 1999/03/16 v1.13 key=value parser (DPC)
46
+ \KV@toks@=\toks14
47
+ )
48
+ \Gin@req@height=\dimen103
49
+ \Gin@req@width=\dimen104
50
+ )
51
+ (/usr/share/texmf/tex/latex/graphics/color.sty
52
+ Package: color 1999/02/16 v1.0i Standard LaTeX Color (DPC)
53
+
54
+ (/usr/share/texmf/tex/latex/config/color.cfg
55
+ File: color.cfg 2001/08/31 v1.1 color configuration of teTeX/TeXLive
56
+ )
57
+ Package color Info: Driver file: dvips.def on input line 125.
58
+
59
+ (/usr/share/texmf/tex/latex/graphics/dvipsnam.def
60
+ File: dvipsnam.def 1999/02/16 v3.0i Driver-dependant file (DPC,SPQR)
61
+ ))
62
+ (/usr/share/texmf/tex/latex/amsfonts/amsfonts.sty
63
+ Package: amsfonts 2001/10/25 v2.2f
64
+ \@emptytoks=\toks15
65
+ \symAMSa=\mathgroup4
66
+ \symAMSb=\mathgroup5
67
+ LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold'
68
+ (Font) U/euf/m/n --> U/euf/b/n on input line 132.
69
+ )
70
+ (/usr/share/texmf/tex/latex/misc/subfigure.sty
71
+ Package: subfigure 2002/07/30 v2.1.4 subfigure package
72
+ \subfigtopskip=\skip43
73
+ \subfigcapskip=\skip44
74
+ \subfigcaptopadj=\dimen105
75
+ \subfigbottomskip=\skip45
76
+ \subfigcapmargin=\dimen106
77
+ \subfiglabelskip=\skip46
78
+ \c@subfigure=\count87
79
+ \c@lofdepth=\count88
80
+ \c@subtable=\count89
81
+ \c@lotdepth=\count90
82
+ \subfig@top=\skip47
83
+ \subfig@bottom=\skip48
84
+ )
85
+ (/usr/share/texmf/tex/latex/graphics/lscape.sty
86
+ Package: lscape 2000/10/22 v3.01 Landscape Pages (DPC)
87
+ )
88
+ (/usr/share/texmf/tex/latex/hyperref/hyperref.sty
89
+ Package: hyperref 2003/01/22 v6.73n Hypertext links for LaTeX
90
+ \@linkdim=\dimen107
91
+ \Hy@linkcounter=\count91
92
+ \Hy@pagecounter=\count92
93
+
94
+ (/usr/share/texmf/tex/latex/hyperref/pd1enc.def
95
+ File: pd1enc.def 2003/01/22 v6.73n Hyperref: PDFDocEncoding definition (HO)
96
+ )
97
+ (/usr/share/texmf/tex/latex/config/hyperref.cfg
98
+ File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive and teTeX
99
+ )
100
+ Package hyperref Info: Hyper figures OFF on input line 1792.
101
+ Package hyperref Info: Link nesting OFF on input line 1797.
102
+ Package hyperref Info: Hyper index ON on input line 1800.
103
+ Package hyperref Info: Plain pages ON on input line 1805.
104
+ Package hyperref Info: Backreferencing OFF on input line 1812.
105
+
106
+ Implicit mode ON; LaTeX internals redefined
107
+ Package hyperref Info: Bookmarks ON on input line 1916.
108
+ (/usr/share/texmf/tex/latex/html/url.sty
109
+ Package: url 1999/03/02 ver 1.4 Verb mode for urls, email addresses, and file
110
+ names
111
+ )
112
+ LaTeX Info: Redefining \url on input line 2055.
113
+ \Fld@menulength=\count93
114
+ \Field@Width=\dimen108
115
+ \Fld@charsize=\dimen109
116
+ \Choice@toks=\toks16
117
+ \Field@toks=\toks17
118
+ Package hyperref Info: Hyper figures OFF on input line 2513.
119
+ Package hyperref Info: Link nesting OFF on input line 2518.
120
+ Package hyperref Info: Hyper index ON on input line 2521.
121
+ Package hyperref Info: backreferencing OFF on input line 2528.
122
+ Package hyperref Info: Link coloring OFF on input line 2533.
123
+ \c@Item=\count94
124
+ \c@Hfootnote=\count95
125
+ )
126
+ *hyperref using default driver hdvips*
127
+ (/usr/share/texmf/tex/latex/hyperref/hdvips.def
128
+ File: hdvips.def 2003/01/22 v6.73n Hyperref driver for dvips
129
+
130
+ (/usr/share/texmf/tex/latex/hyperref/pdfmark.def
131
+ File: pdfmark.def 2003/01/22 v6.73n Hyperref definitions for pdfmark specials
132
+ \pdf@docset=\toks18
133
+ \pdf@box=\box26
134
+ \pdf@toks=\toks19
135
+ \pdf@defaulttoks=\toks20
136
+ \Fld@listcount=\count96
137
+ \@outlinefile=\write3
138
+ )) (./latextest.aux
139
+
140
+ LaTeX Warning: Label `tab:' multiply defined.
141
+
142
+
143
+ LaTeX Warning: Label `tab:' multiply defined.
144
+
145
+ )
146
+ \openout1 = `latextest.aux'.
147
+
148
+ LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 15.
149
+ LaTeX Font Info: ... okay on input line 15.
150
+ LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 15.
151
+ LaTeX Font Info: ... okay on input line 15.
152
+ LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 15.
153
+ LaTeX Font Info: ... okay on input line 15.
154
+ LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 15.
155
+ LaTeX Font Info: ... okay on input line 15.
156
+ LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 15.
157
+ LaTeX Font Info: ... okay on input line 15.
158
+ LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 15.
159
+ LaTeX Font Info: ... okay on input line 15.
160
+ LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 15.
161
+ LaTeX Font Info: ... okay on input line 15.
162
+ Package hyperref Info: Link coloring OFF on input line 15.
163
+ (/usr/share/texmf/tex/latex/hyperref/nameref.sty
164
+ Package: nameref 2001/01/27 v2.19 Cross-referencing by name of section
165
+ \c@section@level=\count97
166
+ )
167
+ LaTeX Info: Redefining \ref on input line 15.
168
+ LaTeX Info: Redefining \pageref on input line 15.
169
+ (./latextest.out)
170
+ (./latextest.out)
171
+ \openout3 = `latextest.out'.
172
+
173
+ LaTeX Font Info: Try loading font information for U+msa on input line 20.
174
+ (/usr/share/texmf/tex/latex/amsfonts/umsa.fd
175
+ File: umsa.fd 2002/01/19 v2.2g AMS font definitions
176
+ )
177
+ LaTeX Font Info: Try loading font information for U+msb on input line 20.
178
+
179
+ (/usr/share/texmf/tex/latex/amsfonts/umsb.fd
180
+ File: umsb.fd 2002/01/19 v2.2g AMS font definitions
181
+ ) [1
182
+
183
+ ] [2] (./latextest.aux)
184
+
185
+ LaTeX Warning: There were multiply-defined labels.
186
+
187
+ )
188
+ Here is how much of TeX's memory you used:
189
+ 2561 strings out of 95847
190
+ 35076 string characters out of 1195962
191
+ 105293 words of memory out of 1000001
192
+ 5494 multiletter control sequences out of 10000+50000
193
+ 5339 words of font info for 22 fonts, out of 500000 for 1000
194
+ 14 hyphenation exceptions out of 1000
195
+ 26i,9n,24p,689b,344s stack positions out of 1500i,500n,5000p,200000b,5000s
196
+
197
+ Output written on latextest.dvi (2 pages, 13996 bytes).
File without changes
@@ -0,0 +1,91 @@
1
+ \documentclass[10pt]{article}
2
+ \usepackage[latin1]{inputenc}
3
+ \usepackage[final]{graphics}
4
+ \usepackage[pdftex]{graphicx}
5
+ \usepackage[dvips]{color}
6
+ \usepackage{amsfonts}
7
+ \usepackage{subfigure}
8
+ \usepackage{lscape}
9
+ \usepackage{hyperref}
10
+ \addtolength{\oddsidemargin}{-3.5cm}
11
+ \addtolength{\textwidth}{7cm}
12
+ \addtolength{\topmargin}{-3cm}
13
+ \addtolength{\textheight}{5cm}
14
+ \newcommand{\hide}[1]{}
15
+ \begin{document}
16
+ \DeclareGraphicsExtensions{.jpg,.pdf,.mps,.png}
17
+
18
+ \begin{table}[htbp]
19
+ \begin{center}
20
+ \begin{tabular}{|c|c|c|c|c|}
21
+ \hline
22
+ & Col3 & col1 & col2 & col3\\
23
+ \hline\hline
24
+ \raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
25
+ \raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & 3\\
26
+ \hline
27
+ \raisebox{-2.0\totalheight}[1ex][1ex]{row2} & r2c3 & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
28
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & 1.4 & ~ & ~ & ~\\
29
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & 2 & ~ & ~ & ~\\
30
+ \hline
31
+ \end{tabular}
32
+ \caption{common table}
33
+ \label{tab:}
34
+ \end{center}
35
+ \end{table}
36
+
37
+ \begin{table}[htbp]
38
+ \begin{center}
39
+ \begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|}
40
+ \hline
41
+ ~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{X}\\
42
+ ~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~\\
43
+ ~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~\\
44
+ Rows & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~\\
45
+ \hline\hline
46
+ \raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{11} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1\\
47
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
48
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55\\
49
+ \hline
50
+ \raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55000} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
51
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~\\
52
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~\\
53
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~\\
54
+ \hline
55
+ \end{tabular}
56
+ \caption{hierarchical headers}
57
+ \label{tab:}
58
+ \end{center}
59
+ \end{table}
60
+
61
+ \begin{table}[htbp]
62
+ \begin{center}
63
+ \begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|c|c|c|c|}
64
+ \hline
65
+ ~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{Col3} & \raisebox{-3.0\totalheight}[1ex][1ex]{X} & \raisebox{-3.0\totalheight}[1ex][1ex]{col1} & \raisebox{-3.0\totalheight}[1ex][1ex]{col2} & \raisebox{-3.0\totalheight}[1ex][1ex]{col3}\\
66
+ ~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~ & ~ & ~ & ~ & ~\\
67
+ ~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
68
+ Instance & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
69
+ \hline\hline
70
+ \raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{11} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
71
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3 & ~ & ~ & ~\\
72
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55 & ~ & ~ & ~\\
73
+ \hline
74
+ \raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55000} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
75
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~ & ~ & ~ & ~ & ~\\
76
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~ & ~ & ~ & ~ & ~\\
77
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~ & ~ & ~ & ~ & ~\\
78
+ \hline
79
+ \raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
80
+ \raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
81
+ \hline
82
+ \raisebox{-2.0\totalheight}[1ex][1ex]{row2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & r2c3 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
83
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1.4 & ~ & ~ & ~ & ~\\
84
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 2 & ~ & ~ & ~ & ~\\
85
+ \hline
86
+ \end{tabular}
87
+ \caption{both tables}
88
+ \label{tab:}
89
+ \end{center}
90
+ \end{table}
91
+ \end{document}
@@ -0,0 +1,91 @@
1
+ \documentclass[]{article}
2
+ \usepackage[latin1]{inputenc}
3
+ \usepackage[final]{graphics}
4
+ \usepackage[pdftex]{graphicx}
5
+ \usepackage[dvips]{color}
6
+ \usepackage{amsfonts}
7
+ \usepackage{subfigure}
8
+ \usepackage{lscape}
9
+ \usepackage{hyperref}
10
+ \addtolength{\oddsidemargin}{-3.5cm}
11
+ \addtolength{\textwidth}{7cm}
12
+ \addtolength{\topmargin}{-3cm}
13
+ \addtolength{\textheight}{5cm}
14
+ \newcommand{\hide}[1]{}
15
+ \begin{document}
16
+ \DeclareGraphicsExtensions{.jpg,.pdf,.mps,.png}
17
+
18
+ \begin{table}[htbp]
19
+ \begin{center}
20
+ \begin{tabular}{|c|c|c|c|c|}
21
+ \hline
22
+ & Col3 & col1 & col2 & col3\\
23
+ \hline\hline
24
+ \raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
25
+ \raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & 3\\
26
+ \hline
27
+ \raisebox{-2.0\totalheight}[1ex][1ex]{row2} & r2c3 & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
28
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & 1.4 & ~ & ~ & ~\\
29
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & 2 & ~ & ~ & ~\\
30
+ \hline
31
+ \end{tabular}
32
+ \caption{common table}
33
+ \label{tab:}
34
+ \end{center}
35
+ \end{table}
36
+
37
+ \begin{table}[htbp]
38
+ \begin{center}
39
+ \begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|}
40
+ \hline
41
+ ~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{X}\\
42
+ ~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~\\
43
+ ~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~\\
44
+ Rows & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~\\
45
+ \hline\hline
46
+ \raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1\\
47
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
48
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55\\
49
+ \hline
50
+ \raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
51
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~\\
52
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~\\
53
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~\\
54
+ \hline
55
+ \end{tabular}
56
+ \caption{hierarchical headers}
57
+ \label{tab:}
58
+ \end{center}
59
+ \end{table}
60
+
61
+ \begin{table}[htbp]
62
+ \begin{center}
63
+ \begin{tabular}{|c|c|c|c|c|c|c|c|c|r|c|c|c|c|c|c|}
64
+ \hline
65
+ ~ & \multicolumn{10}{l|}{B} & \raisebox{-3.0\totalheight}[1ex][1ex]{Col3} & \raisebox{-3.0\totalheight}[1ex][1ex]{X} & \raisebox{-3.0\totalheight}[1ex][1ex]{col1} & \raisebox{-3.0\totalheight}[1ex][1ex]{col2} & \raisebox{-3.0\totalheight}[1ex][1ex]{col3}\\
66
+ ~ & \raisebox{-2.0\totalheight}[1ex][1ex]{A} & \multicolumn{3}{c|}{C} & \multicolumn{4}{c|}{D} & \raisebox{-2.0\totalheight}[1ex][1ex]{E} & \raisebox{-2.0\totalheight}[1ex][1ex]{X} & ~ & ~ & ~ & ~ & ~\\
67
+ ~ & ~ & \raisebox{-1.0\totalheight}[1ex][1ex]{F} & \raisebox{-1.0\totalheight}[1ex][1ex]{G} & \raisebox{-1.0\totalheight}[1ex][1ex]{G2} & \raisebox{-1.0\totalheight}[1ex][1ex]{H} & \raisebox{-1.0\totalheight}[1ex][1ex]{I} & \multicolumn{2}{c|}{I2} & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
68
+ Instance & ~ & ~ & ~ & ~ & ~ & ~ & a & b & ~ & ~ & ~ & ~ & ~ & ~ & ~\\
69
+ \hline\hline
70
+ \raisebox{-2.0\totalheight}[1ex][1ex]{A1} & \raisebox{-1.0\totalheight}[1ex][1ex]{5} & \raisebox{-2.0\totalheight}[1ex][1ex]{1} & \raisebox{-2.0\totalheight}[1ex][1ex]{2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{3} & \raisebox{-2.0\totalheight}[1ex][1ex]{4} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & 1 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
71
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & \raisebox{-1.0\totalheight}[1ex][1ex]{6} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3 & ~ & ~ & ~\\
72
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 55.55 & ~ & ~ & ~\\
73
+ \hline
74
+ \raisebox{-3.0\totalheight}[1ex][1ex]{A2} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{11} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{22} & \raisebox{-3.0\totalheight}[1ex][1ex]{33} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-3.0\totalheight}[1ex][1ex]{44} & \raisebox{-3.0\totalheight}[1ex][1ex]{66} & \raisebox{-3.0\totalheight}[1ex][1ex]{55} & 2.30 & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-} & \raisebox{-4\totalheight}[1ex][1ex]{-}\\
75
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 5.11 & ~ & ~ & ~ & ~ & ~\\
76
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1 & ~ & ~ & ~ & ~ & ~\\
77
+ \raisebox{-3.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 4 & ~ & ~ & ~ & ~ & ~\\
78
+ \hline
79
+ \raisebox{-1.0\totalheight}[1ex][1ex]{row1} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-2\totalheight}[1ex][1ex]{-} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c1} & \raisebox{-1.0\totalheight}[1ex][1ex]{r1c2} & r1c3\\
80
+ \raisebox{-1.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 3\\
81
+ \hline
82
+ \raisebox{-2.0\totalheight}[1ex][1ex]{row2} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-3\totalheight}[1ex][1ex]{-} & r2c3 & \raisebox{-3\totalheight}[1ex][1ex]{-} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c1} & \raisebox{-2.0\totalheight}[1ex][1ex]{r2c2} & \raisebox{-3\totalheight}[1ex][1ex]{-}\\
83
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 1.4 & ~ & ~ & ~ & ~\\
84
+ \raisebox{-2.0\totalheight}[1ex][1ex]{~} & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & ~ & 2 & ~ & ~ & ~ & ~\\
85
+ \hline
86
+ \end{tabular}
87
+ \caption{both tables}
88
+ \label{tab:}
89
+ \end{center}
90
+ \end{table}
91
+ \end{document}
@@ -0,0 +1 @@
1
+ {" row1{" col1" r1c1" col2" r1c2" col3[" r1c3"3" row2{" col1" r2c1" col2" r2c2" Col3[" r2c3"1.4"2
@@ -14,20 +14,24 @@ rows = {}
14
14
  rows["A1"] = {'B'=>
15
15
  {'A'=> ['5',6],
16
16
  'C'=> {'F'=>'1','G'=>'2'},
17
- 'D'=> {'H'=>'3','I'=>'4'}
17
+ 'D'=> {'H'=>'3','I'=>'4'},
18
+ 'E'=> 11
18
19
  },
19
20
  'X'=>[1,3,55.55]}
20
- rows["A2"] = {'B'=>
21
- {'C'=> {'F'=>'11','G2'=>'22'},
21
+ rows["A2"] = {'B'=>
22
+ {:align => "l", # define special alignment for the 'B' header, doesn't affect the final columns.
23
+ 'C'=> {'F'=>'11','G2'=>'22'},
22
24
  'D'=> {'H'=>'33','I2'=>{'a'=>'44','b'=>'66'}},
23
- 'E'=> '55'},
24
- 'X'=>[2.3,5.111,1,4]}
25
+ 'E'=> {:value => '55000', :align => 'r'}, # define alignment for the 'E' column and all data.
26
+ 'X'=>[2.3,5.111,1,4]}}
27
+
25
28
  tex.table(rows,"hierarchical headers", "Rows")
26
29
 
27
30
  File.open("saved_table.dat","r") do |f|
28
31
  old_rows = Marshal::load(f)
29
32
  rows.merge!(old_rows)
30
33
  end
34
+
31
35
  tex.table(rows,"both tables",:rowTitle=>"Instance") do |x,y|
32
36
  order = %w{X B C D E G F H col1 col2 col3 Col3}
33
37
  if order.index(x) && order.index(y)
@@ -0,0 +1,40 @@
1
+ require 'latex'
2
+
3
+ tex=LatexFile.new("latextest.tex")
4
+ rows = {}
5
+ rows["row1"] = {"col1" => "r1c1", "col2"=>"r1c2", "col3"=>["r1c3","3"]}
6
+ rows["row2"] = {"col1" => "r2c1", "col2"=>"r2c2", "Col3"=>["r2c3","1.4","2"]}
7
+ tex.table(rows,"common table")
8
+
9
+ File.open("saved_table.dat","w") do |f|
10
+ Marshal::dump(rows, f)
11
+ end
12
+
13
+ rows = {}
14
+ rows["A1"] = {'B'=>
15
+ {'A'=> ['5',6],
16
+ 'C'=> {'F'=>'1','G'=>'2'},
17
+ 'D'=> {'H'=>'3','I'=>'4'}
18
+ },
19
+ 'X'=>[1,3,55.55]}
20
+ rows["A2"] = {'B'=>
21
+ {'C'=> {'F'=>'11','G2'=>'22'},
22
+ 'D'=> {'H'=>'33','I2'=>{'a'=>'44','b'=>'66'}},
23
+ 'E'=> '55'},
24
+ 'X'=>[2.3,5.111,1,4]}
25
+ tex.table(rows,"hierarchical headers", "Rows")
26
+
27
+ File.open("saved_table.dat","r") do |f|
28
+ old_rows = Marshal::load(f)
29
+ rows.merge!(old_rows)
30
+ end
31
+ tex.table(rows,"both tables",:rowTitle=>"Instance") do |x,y|
32
+ order = %w{X B C D E G F H col1 col2 col3 Col3}
33
+ if order.index(x) && order.index(y)
34
+ order.index(x) <=> order.index(y)
35
+ else
36
+ x <=> y
37
+ end
38
+ end
39
+ tex.close
40
+
data/lib/latex.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # Copyright (c) 2004 Christian Bang <cbang AT web.de> and Frank Hutter
2
2
  #
3
- # Version 0.1.1
3
+ # Version 0.1.2
4
4
  #
5
5
  # All rights reserved. You can redistribute and/or modify it under the same terms as Ruby.
6
6
  #
@@ -28,7 +28,7 @@ end
28
28
  # You may want to quote underscores ('_') in some Latex code you create. For this use String.escape_ which
29
29
  # is available with this file.
30
30
  class LatexFile < File
31
- Header = Struct.new(:name, :children)
31
+ Header = Struct.new(:name, :align, :children)
32
32
 
33
33
  # the default table font size, default is nil which means the Latex default. See #table for possible values
34
34
  attr_accessor :defaultTableFontSize
@@ -38,18 +38,22 @@ class LatexFile < File
38
38
  @@default_extras = {:fontsize => "10pt" }
39
39
  attr_reader :extras
40
40
 
41
+ @default_table_align = 'c'
42
+ # The default table alignment is <tt>'c'</tt> but can be changed.
43
+ attr_accessor :default_table_align
44
+
41
45
  # Open a new latex-file for writing.
42
46
  # +extras+ is an optional hash that may contain the following flags
43
47
  # <tt>:landscape</tt>:: turns all pages 90�
44
48
  # <tt>:twocolumn</tt>:: the whole document has two columns
45
49
  # <tt>extras[:fontsize]</tt>:: string containing the font size like "10pt"
46
50
  # === Example:
47
- # f = LatexFile.new("test.tex", {:twocolumn => true, :fontsize => "11pt"})
51
+ # f = LatexFile.new("test.tex", :twocolumn => true, :fontsize => "11pt")
48
52
  def initialize(filename, extras = nil)
49
53
  super(filename,"w") # open a file for write access
50
54
  @extras = extras || Hash.new
51
55
  #use defaults for unused entries:
52
- @extras.each_key{|key| @extras[key] |= @@default_extras[key] }
56
+ @@default_extras.each_key{|key| @extras[key] ||= @@default_extras[key] }
53
57
  @indent = 0 # indent lines in blocks
54
58
 
55
59
  @usePackages = @extras[:usePackages] || @@defaultUsePackages
@@ -194,12 +198,12 @@ class LatexFile < File
194
198
  #+header+:: is of type +Header+: (name, children)
195
199
  def getNumColsOfHeader(header)
196
200
  header.children.inject(0) do |numChildren, child|
197
- numChildren + ((child.class == Header) ? getNumColsOfHeader(child) : 1)
201
+ numChildren + (child.children ? getNumColsOfHeader(child) : 1)
198
202
  end
199
203
  end
200
204
  private :getNumColsOfHeader
201
205
 
202
- #+hash+:: must contain hashes as values for all keys.
206
+ #+list+:: must contain hashes as values for all keys.
203
207
  #These child hashes will be joined/merged to one big hash.
204
208
  #The actual leafes will be ignored so that only the header remain.
205
209
  def getHeaderMergedHash(list)
@@ -217,7 +221,11 @@ class LatexFile < File
217
221
  #return list if nothingToMerge
218
222
  return nil if nothingToMerge #return only header tree without any data
219
223
  toMerge.each_pair do |key,value|
220
- merged[key] = getHeaderMergedHash(value)
224
+ if key.class == Symbol
225
+ merged[key] = value unless merged[key]
226
+ else
227
+ merged[key] = getHeaderMergedHash(value)
228
+ end
221
229
  end
222
230
  return merged
223
231
  end
@@ -228,16 +236,27 @@ class LatexFile < File
228
236
  #Given a list of hashes, initially a hash-list of each row it
229
237
  #returns a sorted tree representation - a headerList.
230
238
  #+sort_block+:: a block that compares header names
239
+ #side effects::
240
+ # deletes :align entries from the +hash+ and transforms
241
+ # hash[:value] = value hashes to normal entries
231
242
  def hash2HeaderList(hash, sort_block = @@default_sort)
232
243
  headerList = []
233
244
  entries = hash.to_a
234
- entries.sort! {|x,y| sort_block.call(x[0],y[0])}
245
+ entries.sort! do |x,y| sort_block.call(x[0],y[0])
246
+ end
235
247
  for key,value in entries
236
248
  if value.class == Hash
237
- subtree = hash2HeaderList(value, sort_block)
238
- headerList << Header.new(key,subtree)
249
+ align = value.delete(:align) || @default_table_align
250
+ align = align[0] if align.class == Array
251
+ if value[:value] #transform hashes with :value keys to normal entries
252
+ hash[key] = value = value[:value]
253
+ headerList << Header.new(key,align,nil)
254
+ else
255
+ subtree = hash2HeaderList(value, sort_block)
256
+ headerList << Header.new(key,align,subtree)
257
+ end
239
258
  else
240
- headerList << key
259
+ headerList << Header.new(key,@default_table_align,nil)
241
260
  end
242
261
  end
243
262
  return headerList
@@ -257,11 +276,14 @@ class LatexFile < File
257
276
  nextLevel = [] # collects the children nodes of all nodes processed (BFS)
258
277
  hasChildrenInNextLevel = false
259
278
  for header in headerList
260
- if header.class != Header
261
- line << header #leaf node will not be put in an array with column width info
262
- nextLevel += ["~"] # insert this for lines below this
279
+ if header.is_a?(Array) and header[0] == "~"
280
+ line << header
281
+ nextLevel << header # insert this for lines below this
282
+ elsif header.children == nil # leaf node ?
283
+ line << [header.name, header.align]
284
+ nextLevel << ["~",header.align] # insert this for lines below this
263
285
  else
264
- line << [header.name, getNumColsOfHeader(header)]
286
+ line << [header.name, header.align, getNumColsOfHeader(header)]
265
287
  nextLevel += header.children
266
288
  hasChildrenInNextLevel = true
267
289
  end
@@ -280,10 +302,10 @@ class LatexFile < File
280
302
  paths = []
281
303
  path_prefix = path_prefix || []
282
304
  for header in headerList
283
- if header.class == Header
305
+ if header.children
284
306
  paths += getLeafColumns(header.children, path_prefix + [header.name])
285
307
  else #header is not of class Header but a leaf header (string)
286
- paths << path_prefix + [header]
308
+ paths << path_prefix + [header.name]
287
309
  end
288
310
  end
289
311
  return paths
@@ -341,6 +363,9 @@ class LatexFile < File
341
363
  # <tt>:header_hlines</tt>::
342
364
  # If +true+, then horizontal lines between headers of different depths are drawn.
343
365
  # Default is +false+ (no horizontal header lines).
366
+ # <tt>:rowAlign</tt>::
367
+ # Alignment of the column containing the row names. Values are 'r','c','l'.
368
+ # See also the attribute +default_table_align+.
344
369
  #
345
370
  # === Example:
346
371
  # require 'latex'
@@ -355,9 +380,22 @@ class LatexFile < File
355
380
  # order = %w{A X B C D E}
356
381
  # (order.index(x) && order.index(y)) ? order.index(x) <=> order.index(y) : x <=> y
357
382
  # end
358
- # tex.table(rows,"special ordering", :rowTitle=>"Instance", :sort => tableSort)
383
+ # tex.table(rows,"special ordering", :rowTitle=>"Instance", :sort => tableSort)
384
+ #
385
+ # === Column alignment:
386
+ # By default alignment is centered. You can change this for all columns using the attribute
387
+ # +default_table_align+.
388
+ # The alignment can also be changed for each column separately:
389
+ # Headers can be aligned as demonstrated in the following examples:
390
+ # rows['1'] = {'Main Header' => {:align => 'l', 'A' => '5','B' => '6'}}
391
+ # This affects only the header and not the columns, because this is no final column header.
392
+ # Subheader and so the final columns themselves are aligned as follows:
393
+ # rows['1'] = {'Main Header' => {'A' => {:value => '5', :align => 'l'} ,'B' => '6'}}
394
+ # rows['2'] = {'Main Header' => {'A' => '77','B' => '8'}}
395
+ # As you can see it is only needed to define the alignment of a column once. It can be done
396
+ # as often as you like but only one alignment definition is used.
359
397
  def table(entries, caption, *args)
360
- tableValidArgs = [:rowTitle, :label, :newTableThreshold, :placement, :empty, :sort, :landscape, :fontSize, :grouping, :header_hlines]
398
+ tableValidArgs = [:rowTitle, :label, :newTableThreshold, :placement, :empty, :sort, :landscape, :fontSize, :grouping, :header_hlines, :rowAlign]
361
399
  # raise(ArgumentError,"Too many arguments Latex.table", caller) unless args.length <= 1
362
400
  hash = {}
363
401
  args = if args[0].kind_of?(Hash)
@@ -377,6 +415,7 @@ class LatexFile < File
377
415
  @tableLandscape = args[:landscape]
378
416
  @tableFontSize = args[:fontSize] || @defaultTableFontSize
379
417
  @header_hlines = args[:header_hlines]
418
+ @rowAlign = args[:rowAlign] || @default_table_align
380
419
 
381
420
  #access an element in the table which is located in row _rowName_ and in a column
382
421
  #that is defined by a _path_ through the headers that can be obtained with
@@ -387,6 +426,7 @@ class LatexFile < File
387
426
  entry = entry[key]
388
427
  return [] unless entry
389
428
  end
429
+ entry = entry[:value] if entry.is_a?(Hash)
390
430
  return entry.is_a?(Array) ? entry : [entry]
391
431
  end
392
432
 
@@ -395,7 +435,9 @@ class LatexFile < File
395
435
  puts "\n\\begin{table}[#{placement}]\n\\begin{center}"
396
436
  puts "\\#{@tableFontSize}" if @tableFontSize
397
437
  print " "*@indent + "\\begin{tabular}{|"
398
- print "c|" * (leafColumns.length+1)
438
+ # print the alignment {c,r,l} for each leaf column
439
+ print "#{@rowAlign}|" # the first column with the row names
440
+ headerLines[-1].each {|headerName, colAlign| print "#{colAlign}|" }
399
441
  puts "}"
400
442
  currentHeaderRowNumber = 0
401
443
  puts "\\hline"
@@ -408,11 +450,11 @@ class LatexFile < File
408
450
  end
409
451
  currentColumn = 2
410
452
  cline = ""
411
- print headerLine.map {|headerName, columns|
453
+ print headerLine.map {|headerName, align, columns|
412
454
  raise(FormatError, "Invalid format: #{headerName.inspect} contains % that is not sufficiently quoted for latex.", caller) if headerName =~ /[^\\]%|^%/
413
455
  if columns
414
456
  cline += "\\cline{#{currentColumn}-#{(currentColumn+=columns)-1}}" if @header_hlines
415
- "\\multicolumn{#{columns}}{c|}{#{headerName}}"
457
+ "\\multicolumn{#{columns}}{#{align}|}{#{headerName}}"
416
458
  else
417
459
  currentColumn += 1
418
460
  if currentHeaderRowNumber == headerLines.length-1 || headerName == "~"
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.1
3
3
  specification_version: 1
4
4
  name: latex
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.1
7
- date: 2004-09-30
6
+ version: 0.1.2
7
+ date: 2004-10-19
8
8
  summary: Latex is a LaTeX text generation library for Ruby.
9
9
  require_paths:
10
10
  - lib
@@ -13,7 +13,7 @@ email: cbang AT web.de
13
13
  homepage: http://latex.rubyforge.org
14
14
  rubyforge_project: latex
15
15
  description:
16
- autorequire: latex/latex
16
+ autorequire: latex
17
17
  default_executable:
18
18
  bindir: bin
19
19
  has_rdoc: true
@@ -29,7 +29,17 @@ files:
29
29
  - lib/latex.rb
30
30
  - README
31
31
  - LICENSE.txt
32
+ - ChangeLog
33
+ - examples/saved_table.dat
34
+ - examples/test-latex.rb.~1.3.~
32
35
  - examples/test-latex.rb
36
+ - examples/latextest.aux
37
+ - examples/latextest.dvi
38
+ - examples/latextest.log
39
+ - examples/latextest.out
40
+ - examples/latextest.tex
41
+ - examples/latextest.tex~
42
+ - examples/latex.rb
33
43
  test_files: []
34
44
  rdoc_options: []
35
45
  extra_rdoc_files: []