texlab 0.0.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.
@@ -0,0 +1,7 @@
1
+ require "rubygems"
2
+ require "rake4latex"
3
+
4
+ rule ".tex" => ".texlab" do |t|
5
+ sh %("#{File.expand_path(__FILE__+"/../../bin/texlab-compile")}" "#{t.source}" > "#{t.name}")
6
+ end
7
+
@@ -0,0 +1,20 @@
1
+ # To be sourced in VIM at startup
2
+
3
+ # Set up path
4
+ $: << (ENV["TEXLAB"]+"/lib") << (ENV["TEXLAB"]+"/lib/ruby")
5
+ Dir.glob(ENV["TEXLAB"]+"/gems/**/lib").each do |dir|
6
+ $: << dir
7
+ end
8
+
9
+
10
+ require "rubygems"
11
+ #require "irb"
12
+ require "yaml"
13
+ require "rake4latex"
14
+
15
+
16
+ task :compile do
17
+ Rake::Task[VIM::Buffer.current.name.sub(/\.[^.]+\z/, ".pdf")].invoke
18
+ end
19
+
20
+
@@ -0,0 +1,373 @@
1
+ # This is the boot file to be loaded before parsing a .texlab file
2
+ # encoding: ASCII-8bit
3
+ require "easystats"
4
+ require "plusminus"
5
+ require "to_latex"
6
+ require "gnuplot"
7
+ require "open3"
8
+
9
+ # tweak Array
10
+ class Array
11
+ def extract_options!
12
+ if last.is_a? Hash
13
+ pop
14
+ else
15
+ {}
16
+ end
17
+ end
18
+ end
19
+
20
+ # tweak Hash
21
+ class Hash
22
+ # Object-like behavior
23
+ def method_missing name, *args
24
+ name_string = name.to_s
25
+ case name_string[-1]
26
+ when "="
27
+ self[name_string[0..-2].to_sym] = args[0]
28
+ when "!"
29
+ self[name_string[0..-2].to_sym] = {}
30
+ when "?"
31
+ !! self[name_string[0..-2]]
32
+ else
33
+ self[name]
34
+ end
35
+ end
36
+ end
37
+
38
+ module Enumerable
39
+ # map-hash
40
+ def mash
41
+ res = {}
42
+ each do |*x|
43
+ k,v = yield(*x)
44
+ res[k] = v
45
+ end
46
+ res
47
+ end
48
+ end
49
+
50
+ class Hash
51
+ def mash! &block
52
+ replace mash(&block)
53
+ end
54
+ end
55
+
56
+
57
+ # Average method for array with uncertainty calculation
58
+ class Array
59
+ def average
60
+ m = mean
61
+ m.pm(Math.sqrt(m.delta**2 + (standard_deviation*3)**2))
62
+ end
63
+ end
64
+
65
+
66
+ # latex generation helper
67
+ require "texlab/texlabfile"
68
+
69
+ $_latexfile = TexlabFile.new $_erbout
70
+
71
+ def documentHeader *args
72
+ $_latexfile.documentHeader *args
73
+ end
74
+
75
+ def env *args
76
+ $_latexfile.env(*args){yield}
77
+ end
78
+
79
+ def puts string
80
+ $_erbout << string.to_latex << "\n"
81
+ end
82
+
83
+ # table generation
84
+ #
85
+
86
+ def table title, settings={}
87
+ @_table = {}
88
+ yield
89
+ entries = @_table
90
+
91
+ unless @_tables
92
+ $_latexfile.table(entries, title, settings)
93
+ else
94
+ @_tables << [entries, title, settings]
95
+ end
96
+ end
97
+
98
+ def column title
99
+ @_table_columns << (@_table_columns.last[title] || {})
100
+
101
+ result = yield
102
+ subcolumns = @_table_columns.pop
103
+
104
+ unless subcolumns.empty?
105
+ result = subcolumns
106
+ end
107
+
108
+ @_table_columns.last[title] = result
109
+ end
110
+
111
+ def row title
112
+ @_table_columns = [@_table[title] || {}]
113
+ yield
114
+ @_table[title] = @_table_columns.first
115
+ end
116
+
117
+ def tables *args
118
+ opts = args.extract_options!
119
+ caption = args.shift
120
+
121
+ @_tables = []
122
+ yield
123
+
124
+ $_latexfile.tables(@_tables, caption, opts)
125
+
126
+ @_tables = nil
127
+ end
128
+
129
+
130
+ # Figure generation
131
+ #
132
+
133
+ def figure *args
134
+ opts = args.extract_options!
135
+ caption = args.shift
136
+ format = opts[:width] ? "width=#{opts[:width]}" : opts[:format]
137
+ label = opts[:label]
138
+ filename = opts[:filename]
139
+ if @_figures
140
+ @_figures << Figure.new(format, filename, caption, label)
141
+ else
142
+ raise "not implemented"
143
+ end
144
+ end
145
+
146
+ def figures *args
147
+ opts = args.extract_options!
148
+ placement = opts.delete(:placement) || "htbp"
149
+ label = opts.delete(:label)
150
+ newPageThreshold = opts.delete(:newPageThreshold) || 29
151
+ caption = args.shift
152
+
153
+ @_figures = []
154
+ yield
155
+
156
+ $_latexfile.figures(caption, @_figures, newPageThreshold, placement, label)
157
+
158
+ @_figures = nil
159
+ end
160
+
161
+
162
+ # plotting
163
+ #
164
+
165
+ require "gnuplot"
166
+
167
+ # override to have "w+" mode
168
+ def Gnuplot.open( persist=true )
169
+ cmd = Gnuplot.gnuplot( persist ) or raise 'gnuplot not found'
170
+ IO::popen( cmd, "w+") { |io| yield io }
171
+ end
172
+
173
+ def plot *args
174
+ opts = args.extract_options!
175
+ title = args[0]
176
+
177
+ placement = opts.delete(:placement) || "htbp"
178
+ width = opts.delete(:width) || "17cm"
179
+ height = opts.delete(:height) || "10cm"
180
+ cmd = opts.delete(:cmd) || "plot"
181
+
182
+ env :figure, "[#{placement}]" do
183
+ env :center do
184
+ @_datasets = []
185
+ yield
186
+ @_datasets
187
+
188
+ gnuplot = Gnuplot.gnuplot(true) or raise "gnuplot not found"
189
+ Open3.popen3(gnuplot) do |gp, out, err, external|
190
+ gp <<<<-GP
191
+ set terminal latex size #{width}, #{height}
192
+ GP
193
+
194
+ Gnuplot::Plot.new(gp, cmd) do |plot|
195
+ opts.each do |key, value|
196
+ case value
197
+ when true
198
+ plot.send key
199
+ else
200
+ plot.send key, value.gsub(/([\\ ])/, "\\\\\\1")
201
+ end
202
+ end
203
+
204
+ @_datasets.each do |ds|
205
+ plot.data << ds
206
+ end
207
+ end
208
+ gp.close
209
+ $_erbout << out.readlines.join("\n")
210
+
211
+ if not external.value.success?
212
+ errlines = err.readlines
213
+ raise "could not plot:\n" + errlines.join("\n")
214
+ end
215
+ end
216
+ end
217
+ $_erbout << "\\caption{#{title}}" if title
218
+ end
219
+ end
220
+
221
+ def splot *args, &block
222
+ opts = args.extract_options!
223
+ opts.cmd = "splot"
224
+ plot *args, opts, &block
225
+ end
226
+
227
+ def dataset *args
228
+ opts = args.extract_options!
229
+
230
+ data = args.shift
231
+ data_is_expr = !!data
232
+ if data
233
+ # simple function
234
+ ds = Gnuplot::DataSet.new data
235
+ else
236
+ # data
237
+ @_datastrings = []
238
+ yield
239
+
240
+ c = @_datastrings.first.count
241
+ data = (0...c).map do |i|
242
+ @_datastrings.map{|t|t[i]}
243
+ end
244
+
245
+ ds = Gnuplot::DataSet.new data
246
+ end
247
+
248
+ # check args
249
+ raise ArgumentError, "Unnecessary parameters: #{args}" unless args.empty?
250
+
251
+ # tweak args (syntax candy)
252
+ opts[:title] = nil unless data_is_expr or opts.has_key? :title
253
+ if opts.key? :title and not opts[:title]
254
+ opts.delete(:title)
255
+ opts[:notitle] = true
256
+ end
257
+
258
+ # send options
259
+ opts.each do |key, value|
260
+ case value
261
+ when true
262
+ ds.send key
263
+ else
264
+ ds.send :"#{key}=", value
265
+ end
266
+ end
267
+
268
+ @_datasets << ds
269
+
270
+ end
271
+
272
+ def datastring arg
273
+ @_datastrings << arg
274
+ end
275
+
276
+ def data *args
277
+ datastring args
278
+ end
279
+
280
+
281
+ # fitting
282
+ def fit expr, opts={}
283
+ raise "via: is a necessary parameter" if not opts[:via]
284
+ via = opts[:via]
285
+ vars = via.split(",")
286
+
287
+ using = opts[:using]
288
+
289
+ @_datasets = []
290
+
291
+ dataset do
292
+ yield
293
+ end
294
+
295
+ ds = @_datasets.first
296
+
297
+ errlines = []
298
+ result = {}
299
+
300
+ gnuplot = Gnuplot.gnuplot(true) or raise "gnuplot not found"
301
+ Open3.popen3(gnuplot) do |gp, out, err, external|
302
+ vars.each do |var|
303
+ gp << "#{var} = #{rand}\n"
304
+ end
305
+ gp <<<<-GP
306
+ fit #{expr} '-' #{"using " + using if using} via #{via}
307
+ GP
308
+ gp << ds.to_gplot
309
+ gp.close
310
+
311
+ errlines = err.readlines
312
+ errlines.each do |l|
313
+ if l =~ /\A([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*([0-9eE.+-]+)\s*\+\/-\s*([0-9eE.+-]+)/
314
+ result[$1.to_sym] = $2.to_f.pm($3.to_f)
315
+ end
316
+ end
317
+ end
318
+
319
+ vars.map do |v|
320
+ result[v.to_sym] or raise "could not fit:\n" + errlines.join("\n")
321
+ end
322
+ end
323
+
324
+
325
+ # macros
326
+
327
+ $_macros={}
328
+
329
+ # a macro is available in tex (\asdf) and in ruby (:asdf.to_latex or $asdf). It will go to math
330
+ # mode
331
+ def macro hash
332
+ text_macro hash.mash{|key, value| [key, value.latex!.to_latex_math] }
333
+ end
334
+
335
+ # a text macro is available in tex (\asdf) and in ruby (:asdf). It will not be
336
+ # forced to math mode
337
+ def text_macro hash
338
+ hash.each do |key, value|
339
+ $_macros[key] = value
340
+ eval "$#{key} = '#{value.gsub("\\","\\\\").gsub("'", "\\'")}'"
341
+ $_erbout << "\\def\\#{key}{#{value}}"
342
+ end
343
+ end
344
+
345
+ class Symbol
346
+ # symbol's to_latex is the macro with the same name
347
+ def to_latex
348
+ $_macros[self] or raise "Undefined macro: #{self}"
349
+ end
350
+
351
+ def + str
352
+ "#{to_latex}#{str}".latex!.to_latex_math
353
+ end
354
+ end
355
+
356
+
357
+ # debug
358
+ def debug *args
359
+ args.each {|a| STDERR.puts a.inspect}
360
+ return *args
361
+ end
362
+
363
+ # include Math
364
+ include Math
365
+
366
+ # degree radian
367
+ def degrees x
368
+ x * 180.0 / Math::PI
369
+ end
370
+
371
+ def radians x
372
+ x / 180.0 * Math::PI
373
+ end
@@ -0,0 +1,164 @@
1
+ # encoding: ASCII-8bit
2
+ require "latex"
3
+
4
+ class TexlabFile < LatexFile
5
+ # create new instance.
6
+ # @param _erbout the string or file to write to
7
+ def initialize _erbout
8
+ # we don't call super
9
+
10
+ @_erbout = _erbout
11
+
12
+ # replay actions in super
13
+
14
+ @extras = {
15
+ :documentclass => :article,
16
+ :fontsize => "10pt"
17
+ }
18
+
19
+ #use defaults for unused entries:
20
+ @indent = 0 # indent lines in blocks
21
+
22
+ @usePackages = {
23
+ :inputenc=>:latin1,
24
+ :graphics=>:final,
25
+ :graphicx=>:pdftex,
26
+ :color=>:dvips,
27
+ :amsfonts=>true,
28
+ :subfigure=>true,
29
+ :lscape=>true,
30
+ :hyperref=>true,
31
+ :amsmath=>true,
32
+ :units=>true,
33
+ :float=>true,
34
+ :xcolor=>"table"
35
+ #:subfig=>["lofdepth", "lotdepth"]
36
+ }
37
+
38
+ @default_table_align = 'c'
39
+
40
+ @lastWasPrint = false
41
+ end
42
+
43
+ def puts string
44
+ lines = string.split("\n")
45
+ for line in lines
46
+ @indent -= 2 if line[0,5]=='\\end{' && @indent >= 2
47
+ if @lastWasPrint
48
+ @_erbout << line.latex! << "\n"
49
+ @lastWasPrint = false
50
+ else
51
+ @_erbout << (" " * @indent).latex! << line.latex! << "\n"
52
+ end
53
+ @indent += 2 if line[0,7]=='\\begin{'
54
+ end
55
+ end
56
+
57
+ def print string
58
+ @lastWasPrint = true
59
+ @indent -= 2 if string[/\\end/]
60
+ @indent += 2 if string[/\\begin/]
61
+ @_erbout << string.latex! << "\n"
62
+ end
63
+
64
+ def prettyPrintCell x
65
+ x.to_latex
66
+ end
67
+
68
+ def documentHeader extras={}
69
+ @extras.merge! extras
70
+ @usePackages.merge! extras[:usePackages] || {}
71
+
72
+ dcsettings = [@extras[:fontsize]]
73
+ dcsettings << "twocolumn" if @extras[:twocolumn]
74
+
75
+ puts "\\documentclass[#{dcsettings.join(",")}]{#{@extras[:documentclass]}}"
76
+
77
+ @usePackages.each do |package, settings|
78
+ case settings
79
+ when true then puts "\\usepackage{#{package}}"
80
+ when Array then puts "\\usepackage[#{settings.join(",")}]{#{package}}"
81
+ else puts "\\usepackage[#{settings}]{#{package}}"
82
+ end
83
+ end
84
+ puts "\\addtolength{\\oddsidemargin}{-3.5cm}"
85
+ puts "\\addtolength{\\textwidth}{7cm}"
86
+ puts "\\addtolength{\\topmargin}{-3cm}"
87
+ puts "\\addtolength{\\textheight}{5cm}"
88
+ puts "\\newcommand{\\hide}[1]{}"
89
+
90
+ puts "\\special{landscape}" if @extras[:landscape]
91
+
92
+ #puts "\\begin{document}"
93
+ puts "\\DeclareGraphicsExtensions{.jpg,.pdf,.mps,.png}"
94
+ end
95
+
96
+
97
+ def env(name, *args)
98
+ # overridden for compatibility with new Array#to_s
99
+ puts "\\begin{#{name}}#{args.join("")}"
100
+ yield if block_given?
101
+ puts "\\end{#{name}}"
102
+ end
103
+
104
+ def table entries, caption, args={}
105
+
106
+ # override defaults
107
+ args = {
108
+ :sort=> proc{0},
109
+ :header_hlines=>true
110
+ }.merge(args)
111
+
112
+
113
+ args[:rowTitle] = args[:rowTitle].to_latex if args[:rowTitle]
114
+
115
+ entries = convertKeysToLatex(entries)
116
+
117
+ super(entries, caption, args)
118
+ end
119
+
120
+ def plain_table entries, caption, opts={}
121
+ # capture output of table()
122
+ temp_erbout = @_erbout; @_erbout = ""
123
+ table(entries, caption, opts)
124
+ src = @_erbout; @_erbout = temp_erbout
125
+
126
+ src.sub!(/\A.*?\\begin{center}(.*)\\end{center}.*\z/m, '\1') or raise "internal error"
127
+ src.sub!(/\\caption{#{caption}}/, "") or raise "internal error"
128
+
129
+ end
130
+
131
+ def tables data, caption, opts={}
132
+ placement = opts.delete(:placement) || "htbp"
133
+ tableLandscape = opts.delete(:landscape)
134
+ tableFontSize = opts.delete(:fontSize) || @defaultTableFontSize
135
+ tableLabel = opts.delete(:label) || ""
136
+ tableCaption = caption
137
+
138
+ puts "\\begin{landscape}" if tableLandscape
139
+ puts "\n\\begin{table}[#{placement}]\n\\begin{center}"
140
+ puts "\\#{tableFontSize}" if tableFontSize
141
+
142
+ puts data.map { |args|
143
+ entries, caption, opts = *args
144
+ "\\subtable[#{caption}]{#{plain_table(*args)}}"
145
+ }.join("\\qquad")
146
+
147
+ puts "\\caption{#{tableCaption}}\n" if tableCaption
148
+ puts "\\label{tab:#{tableLabel}}" if tableLabel
149
+ puts "\\end{center}\n\\end{table}\n"
150
+ puts "\\end{landscape}" if @tableLandscape
151
+ end
152
+
153
+ private
154
+
155
+ def convertKeysToLatex value
156
+ case value
157
+ when Hash
158
+ value.mash{|k,v| [k.to_latex, convertKeysToLatex(v)] }
159
+ else
160
+ value
161
+ end
162
+ end
163
+
164
+ end