texlab 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,11 +1,12 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "rake4latex"
4
- gem "plusminus"
5
- gem "easystats"
6
- gem "to_latex"
7
- gem "gnuplot"
8
- gem "latex"
3
+ gem "rake4latex", "0.1.3"
4
+ gem "plusminus", "0.2.0"
5
+ gem "easystats", "0.1.0"
6
+ gem "to_latex", "0.4.0"
7
+ gem "gnuplot", "~> 2.4.1"
8
+ gem "latex", "0.1.3"
9
+ gem "nio-percent_fmt", "0.0.0"
9
10
 
10
11
  group :development do
11
12
  gem "rspec", "~> 2.8.0"
@@ -17,7 +17,9 @@ GEM
17
17
  log4r (1.1.10)
18
18
  nio (0.2.5)
19
19
  flt (>= 1.0.0)
20
- plusminus (0.1.0)
20
+ nio-percent_fmt (0.0.0)
21
+ nio
22
+ plusminus (0.2.0)
21
23
  nio
22
24
  rake (0.9.2.2)
23
25
  rake4latex (0.1.3)
@@ -42,13 +44,14 @@ PLATFORMS
42
44
 
43
45
  DEPENDENCIES
44
46
  bundler (~> 1.0.0)
45
- easystats
46
- gnuplot
47
+ easystats (= 0.1.0)
48
+ gnuplot (~> 2.4.1)
47
49
  jeweler (~> 1.8.3)
48
- latex
49
- plusminus
50
- rake4latex
50
+ latex (= 0.1.3)
51
+ nio-percent_fmt (= 0.0.0)
52
+ plusminus (= 0.2.0)
53
+ rake4latex (= 0.1.3)
51
54
  rcov
52
55
  rdoc (~> 3.12)
53
56
  rspec (~> 2.8.0)
54
- to_latex
57
+ to_latex (= 0.4.0)
data/Rakefile CHANGED
@@ -22,6 +22,7 @@ Jeweler::Tasks.new do |gem|
22
22
  gem.email = "kallo.bernat@gmail.com"
23
23
  gem.authors = ["Bernát Kalló"]
24
24
  gem.executables = ["texlab-compile"]
25
+ gem.files = FileList["lib/**/*.rb", "bin/*", "[A-Z]*", "spec/**/*"].to_a
25
26
  # dependencies defined in Gemfile
26
27
  end
27
28
  Jeweler::RubygemsDotOrgTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
Binary file
@@ -18,11 +18,11 @@ begin
18
18
  infile = ARGV[0] || fail
19
19
  outfile = ARGV[1] || infile.sub(/(\.texlab)?$/, ".tex")
20
20
 
21
- src = nil
21
+ content = nil
22
22
  File.open infile do |f|
23
- src = f.read
23
+ content = f.read
24
24
  end
25
- fail if !src
25
+ fail if !content
26
26
 
27
27
  rescue
28
28
  STDERR.puts File.basename($0) + " <inputfile> <outputfile>"
@@ -32,13 +32,25 @@ EOU
32
32
 
33
33
  else
34
34
 
35
- # load boot code
36
- File.open File.expand_path(__FILE__+"/../../lib/texlab/boot.rb") do |f|
37
- src = "<%\n" << f.read << "\n%>\n" << src
35
+ src = "<% $_binding=binding %>"
36
+
37
+ # load modules
38
+
39
+ %w(hash latex debug figure macro math plot stats table tikz).each do |f|
40
+ f = File.expand_path(__FILE__+"/../../lib/texlab/#{f}.rb")
41
+ File.open f do |file|
42
+ s = file.read
43
+ s.gsub!(/([\\#"])/,"\\\\\\1"); s.gsub!(/\n/, "\\\\n")
44
+ f.gsub!(/([\\#"])/,"\\\\\\1"); f.gsub!(/\n/, "\\\\n")
45
+ src << "<% eval(\"#{s}\",binding,\"#{f}\") %>"
46
+ end
38
47
  end
39
48
 
49
+ src << content
50
+
40
51
  # run erb
41
52
  erb = TEXERB.new(src.untaint, nil, ">", "$_erbout")
53
+ erb.filename = infile
42
54
 
43
55
  File.open outfile, "w" do |f|
44
56
  f.print erb.result(TOPLEVEL_BINDING.taint)
@@ -0,0 +1,7 @@
1
+
2
+ # debug
3
+ def debug *args
4
+ args.each {|a| STDERR.puts a.inspect}
5
+ return *args
6
+ end
7
+
@@ -0,0 +1,32 @@
1
+ # Figure generation
2
+ #
3
+
4
+ def figure *args
5
+ opts = args.extract_options!
6
+ caption = args.shift
7
+ format = opts[:width] ? "width=#{opts[:width]}" : opts[:format]
8
+ label = opts[:label]
9
+ filename = opts[:filename]
10
+ if @_figures
11
+ @_figures << Figure.new(format, filename, caption, label)
12
+ else
13
+ raise "not implemented"
14
+ end
15
+ end
16
+
17
+ def figures *args
18
+ opts = args.extract_options!
19
+ placement = opts.delete(:placement) || "htbp"
20
+ label = opts.delete(:label)
21
+ newPageThreshold = opts.delete(:newPageThreshold) || 29
22
+ caption = args.shift
23
+
24
+ @_figures = []
25
+ yield
26
+
27
+ $_latexfile.figures(caption, @_figures, newPageThreshold, placement, label)
28
+
29
+ @_figures = nil
30
+ end
31
+
32
+
@@ -0,0 +1,52 @@
1
+
2
+ # tweak Array
3
+ class Array
4
+ def extract_options!
5
+ if last.is_a? Hash
6
+ pop
7
+ else
8
+ {}
9
+ end
10
+ end
11
+ end
12
+
13
+ # tweak Hash
14
+ class Hash
15
+ # Object-like behavior
16
+ def method_missing name, *args
17
+ name_string = name.to_s
18
+ case name_string[-1]
19
+ when "="
20
+ self[name_string[0..-2].to_sym] = args[0]
21
+ when "!"
22
+ self[name_string[0..-2].to_sym] = {}
23
+ when "?"
24
+ !! self[name_string[0..-2]]
25
+ else
26
+ self[name]
27
+ end
28
+ end
29
+
30
+ def slice *args
31
+ args.mash{|k| self[k]}
32
+ end
33
+ end
34
+
35
+ module Enumerable
36
+ # map-hash
37
+ def mash
38
+ res = {}
39
+ each do |*x|
40
+ k,v = yield(*x)
41
+ res[k] = v
42
+ end
43
+ res
44
+ end
45
+ end
46
+
47
+ class Hash
48
+ def mash! &block
49
+ replace mash(&block)
50
+ end
51
+ end
52
+
@@ -0,0 +1,22 @@
1
+ # latex generation helper
2
+ require "plusminus"
3
+ require "to_latex"
4
+ require "nio/percent_fmt"
5
+
6
+ require "texlab/texlabfile"
7
+
8
+ $_latexfile = TexlabFile.new $_erbout
9
+
10
+ def documentHeader *args
11
+ $_latexfile.documentHeader *args
12
+ end
13
+
14
+ def env *args
15
+ $_latexfile.env(*args){yield}
16
+ end
17
+
18
+ def puts string
19
+ $_erbout << string.to_latex << "\n"
20
+ end
21
+
22
+
@@ -0,0 +1,101 @@
1
+ # macros
2
+
3
+ $_macros={}
4
+
5
+ # a macro is available in tex (\asdf) and in ruby (:asdf.to_latex or $asdf). It will go to math
6
+ # mode
7
+ def macro hash
8
+ hash.each do |key, value|
9
+ value = value.latex!.to_latex_math
10
+ define_latex_macro key, value
11
+ define_symbol_macro key, value
12
+ define_global_macro key, value
13
+ end
14
+ end
15
+
16
+ # a text macro is available in tex (\asdf) and in ruby (:asdf, $asdf). It will not be
17
+ # forced to math mode
18
+ def text_macro hash
19
+ hash.each do |key, value|
20
+ value = "\\text{#{value}}".latex!
21
+ define_latex_macro key, value
22
+ define_symbol_macro key, value
23
+ define_global_macro key, value
24
+ end
25
+ end
26
+
27
+ def define_symbol_macro key, value
28
+ $_macros[key] = value
29
+ end
30
+
31
+ def define_latex_macro key, value
32
+ $_erbout << "\\def\\#{key}{#{value}}"
33
+ end
34
+
35
+ def define_global_macro key, value
36
+ eval "$#{key} = '#{value.gsub("\\","\\\\").gsub("'", "\\'")}'"
37
+ end
38
+
39
+ class Symbol
40
+ # symbol's to_latex is the macro with the same name
41
+ def to_latex
42
+ $_macros[self] or raise "Undefined macro: #{self}"
43
+ end
44
+
45
+ def + str
46
+ "#{to_latex}#{str}".latex!.to_latex_math
47
+ end
48
+
49
+ def * unit
50
+ "\\unit[\\text{#{to_latex}}]{#{unit}}".latex!.to_latex_math
51
+ end
52
+ end
53
+
54
+
55
+
56
+
57
+ %w(
58
+ alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon phi chi psi omega
59
+ ).each do |a|
60
+ [a, a.capitalize].each do |b|
61
+ key = b.to_sym
62
+ value = "\\#{b}".latex!.to_latex_math
63
+ define_symbol_macro key, value
64
+ define_global_macro key, value
65
+ end
66
+ end
67
+
68
+ ('a'..'z').each do |a|
69
+ [a, a.capitalize].each do |b|
70
+ key = b.to_sym
71
+ value = "#{b}".latex!.to_latex_math
72
+ define_symbol_macro key, value
73
+ define_global_macro key, value
74
+ end
75
+ end
76
+
77
+
78
+ # units
79
+ $_units = {}
80
+
81
+ def unit hash
82
+ # allow array keys to be DRY
83
+ hash.each do |ks,v|
84
+ [*ks].each do |k|
85
+ $_units[k] = v
86
+ end
87
+ end
88
+ end
89
+
90
+ class Symbol
91
+ def with_unit
92
+ raise "No unit defined for #{self}" unless $_units.key? self
93
+ if $_units[self]
94
+ self * "(#{$_units[self]})"
95
+ else
96
+ to_latex
97
+ end
98
+ end
99
+ end
100
+
101
+
@@ -0,0 +1,13 @@
1
+ # include Math
2
+ include Math
3
+
4
+ # degree radian
5
+ def degrees x
6
+ x * 180.0 / Math::PI
7
+ end
8
+
9
+ def radians x
10
+ x / 180.0 * Math::PI
11
+ end
12
+
13
+
@@ -0,0 +1,177 @@
1
+ # plotting
2
+ #
3
+
4
+ require "gnuplot"
5
+ require "open3"
6
+
7
+ # override to have "w+" mode
8
+ def Gnuplot.open( persist=true )
9
+ cmd = Gnuplot.gnuplot( persist ) or raise 'gnuplot not found'
10
+ IO::popen( cmd, "w+") { |io| yield io }
11
+ end
12
+
13
+ def plot *args
14
+ opts = args.extract_options!
15
+ title = args[0]
16
+
17
+ placement = opts.delete(:placement) || (opts[:label] ? "htbp" : "H")
18
+ width = opts.delete(:width) || "17cm"
19
+ height = opts.delete(:height) || "10cm"
20
+ cmd = opts.delete(:cmd) || "plot"
21
+ label = opts.delete(:label)
22
+ debug = opts.delete(:debug)
23
+
24
+ env :figure, "[#{placement}]" do
25
+ env :center do
26
+ @_datasets = []
27
+ yield
28
+ @_datasets
29
+
30
+ gnuplot = Gnuplot.gnuplot(true) or raise "gnuplot not found"
31
+ Open3.popen3(gnuplot) do |gp, out, err, external|
32
+ gp = STDERR if debug
33
+ gp <<<<-GP
34
+ set terminal latex size #{width}, #{height}
35
+ GP
36
+
37
+ Gnuplot::Plot.new(gp, cmd) do |plot|
38
+ opts.each do |key, value|
39
+ case value
40
+ when true
41
+ plot.send key
42
+ when false
43
+ gp << "unset #{key}\n"
44
+ else
45
+ plot.send key, value.to_s.gsub(/([\\])/, "\\\\\\1")
46
+ end
47
+ end
48
+
49
+ @_datasets.each do |ds|
50
+ plot.data << ds
51
+ end
52
+ end
53
+ gp.close
54
+ $_erbout << out.readlines.join("\n")
55
+
56
+ if not external.value.success?
57
+ errlines = err.readlines
58
+ raise "could not plot:\n" + errlines.join("\n")
59
+ end
60
+ end
61
+ end
62
+ $_erbout << "\\caption{#{title}}" if title
63
+ $_erbout << "\\label{#{label}}" if label
64
+ end
65
+ end
66
+
67
+ def splot *args, &block
68
+ opts = args.extract_options!
69
+ opts.cmd = "splot"
70
+ plot *args, opts, &block
71
+ end
72
+
73
+ def dataset *args
74
+ opts = args.extract_options!
75
+
76
+ data = args.shift
77
+ data_is_expr = !!data
78
+ if data
79
+ # simple function
80
+ ds = Gnuplot::DataSet.new data
81
+ else
82
+ # data
83
+ @_datastrings = []
84
+ yield
85
+
86
+ c = @_datastrings.first.count
87
+ data = (0...c).map do |i|
88
+ @_datastrings.map do |t|
89
+ case value = t[i]
90
+ when String
91
+ "\"#{value.to_s.gsub(/([\\"])/, "\\\\\\1")}\""
92
+ else
93
+ value.to_s
94
+ end
95
+ end
96
+ end
97
+
98
+ ds = Gnuplot::DataSet.new data
99
+ end
100
+
101
+ # check args
102
+ raise ArgumentError, "Unnecessary parameters: #{args}" unless args.empty?
103
+
104
+ # tweak args (syntax candy)
105
+ opts[:title] = nil unless data_is_expr or opts.has_key? :title
106
+ if opts.key? :title and not opts[:title]
107
+ opts.delete(:title)
108
+ opts[:notitle] = true
109
+ end
110
+
111
+ # send options
112
+ opts.each do |key, value|
113
+ case value
114
+ when true
115
+ ds.send key
116
+ else
117
+ ds.send :"#{key}=", value
118
+ end
119
+ end
120
+
121
+ @_datasets << ds
122
+
123
+ end
124
+
125
+ def datastring arg
126
+ @_datastrings << arg
127
+ end
128
+
129
+ def data *args
130
+ datastring args
131
+ end
132
+
133
+
134
+ # fitting
135
+ def fit expr, opts={}
136
+ raise "via: is a necessary parameter" if not opts[:via]
137
+ via = opts[:via]
138
+ vars = via.split(",")
139
+
140
+ using = opts[:using]
141
+
142
+ @_datasets = []
143
+
144
+ dataset do
145
+ yield
146
+ end
147
+
148
+ ds = @_datasets.first
149
+
150
+ errlines = []
151
+ result = {}
152
+
153
+ gnuplot = Gnuplot.gnuplot(true) or raise "gnuplot not found"
154
+ Open3.popen3(gnuplot) do |gp, out, err, external|
155
+ vars.each do |var|
156
+ gp << "#{var} = #{rand}\n"
157
+ end
158
+ gp <<<<-GP
159
+ fit #{expr} '-' #{"using " + using if using} via #{via}
160
+ GP
161
+ gp << ds.to_gplot
162
+ gp.close
163
+
164
+ errlines = err.readlines
165
+ errlines.each do |l|
166
+ if l =~ /\A([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*([0-9eE.+-]+)\s*\+\/-\s*([0-9eE.+-]+)/
167
+ result[$1.to_sym] = $2.to_f.pm($3.to_f)
168
+ end
169
+ end
170
+ end
171
+
172
+ vars.map do |v|
173
+ result[v.to_sym] or raise "could not fit:\n" + errlines.join("\n")
174
+ end
175
+ end
176
+
177
+