calco 0.1.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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +34 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +26 -0
  5. data/LICENSE +21 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +360 -0
  8. data/Rakefile +1 -0
  9. data/calco.gemspec +23 -0
  10. data/examples/ages.ods +0 -0
  11. data/examples/compute_cells.rb +61 -0
  12. data/examples/data.csv +8 -0
  13. data/examples/example.rb +97 -0
  14. data/examples/multiplication_tables.ods +0 -0
  15. data/examples/multiplication_tables.rb +73 -0
  16. data/examples/register_function.rb +44 -0
  17. data/examples/using_date_functions.rb +42 -0
  18. data/examples/write_csv.rb +68 -0
  19. data/examples/write_ods.rb +69 -0
  20. data/lib/calco.rb +17 -0
  21. data/lib/calco/core_ext/fixnum.rb +22 -0
  22. data/lib/calco/core_ext/float.rb +22 -0
  23. data/lib/calco/core_ext/range.rb +15 -0
  24. data/lib/calco/core_ext/string.rb +20 -0
  25. data/lib/calco/date_functions.rb +13 -0
  26. data/lib/calco/definition_dsl.rb +127 -0
  27. data/lib/calco/elements/aggregator.rb +17 -0
  28. data/lib/calco/elements/builtin_function.rb +84 -0
  29. data/lib/calco/elements/constant.rb +31 -0
  30. data/lib/calco/elements/current.rb +19 -0
  31. data/lib/calco/elements/element.rb +31 -0
  32. data/lib/calco/elements/empty.rb +9 -0
  33. data/lib/calco/elements/formula.rb +42 -0
  34. data/lib/calco/elements/if.rb +26 -0
  35. data/lib/calco/elements/operation.rb +34 -0
  36. data/lib/calco/elements/operator.rb +17 -0
  37. data/lib/calco/elements/or.rb +26 -0
  38. data/lib/calco/elements/value_extractor.rb +42 -0
  39. data/lib/calco/elements/variable.rb +35 -0
  40. data/lib/calco/engines/calculator_builtin_functions.rb +32 -0
  41. data/lib/calco/engines/csv_engine.rb +80 -0
  42. data/lib/calco/engines/default_engine.rb +140 -0
  43. data/lib/calco/engines/office_engine.rb +263 -0
  44. data/lib/calco/engines/simple_calculator_engine.rb +151 -0
  45. data/lib/calco/math_functions.rb +9 -0
  46. data/lib/calco/sheet.rb +363 -0
  47. data/lib/calco/spreadsheet.rb +172 -0
  48. data/lib/calco/string_functions.rb +9 -0
  49. data/lib/calco/style.rb +15 -0
  50. data/lib/calco/time_functions.rb +12 -0
  51. data/lib/calco/version.rb +3 -0
  52. data/spec/absolute_references_spec.rb +86 -0
  53. data/spec/builtin_functions_spec.rb +161 -0
  54. data/spec/calculator_engine_spec.rb +251 -0
  55. data/spec/conditions_spec.rb +118 -0
  56. data/spec/content_change_spec.rb +190 -0
  57. data/spec/csv_engine_spec.rb +324 -0
  58. data/spec/default_engine_spec.rb +135 -0
  59. data/spec/definitions_spec.rb +65 -0
  60. data/spec/errors_spec.rb +189 -0
  61. data/spec/functions_spec.rb +251 -0
  62. data/spec/header_row_spec.rb +63 -0
  63. data/spec/range_spec.rb +189 -0
  64. data/spec/sheet_selections_spec.rb +49 -0
  65. data/spec/sheet_spec.rb +229 -0
  66. data/spec/smart_types_spec.rb +43 -0
  67. data/spec/spreadsheet_spec.rb +80 -0
  68. data/spec/styles_spec.rb +29 -0
  69. data/spec/variables_spec.rb +41 -0
  70. metadata +158 -0
@@ -0,0 +1,65 @@
1
+ require 'calco'
2
+
3
+ RSpec.configure do |c|
4
+ c.alias_example_to :check
5
+ end
6
+
7
+ describe "definitions" do
8
+
9
+ check "definitions setup" do
10
+
11
+ doc = spreadsheet do
12
+
13
+ definitions do
14
+
15
+ set a: 8
16
+ set b: 'hello'
17
+
18
+ function f1: a
19
+ function f2: b
20
+
21
+ end
22
+
23
+ sheet "A" do
24
+ column value_of(:a)
25
+ column value_of(:b)
26
+ column :f1
27
+ column :f2
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ check "definitions are visible to all sheets" do
35
+
36
+ doc = spreadsheet do
37
+
38
+ definitions do
39
+
40
+ set a: 8
41
+
42
+ function f1: a
43
+
44
+ end
45
+
46
+ sheet "A" do
47
+ column value_of(:a)
48
+ column :f1
49
+ end
50
+
51
+ sheet "B" do
52
+ column value_of(:a)
53
+ column :f1
54
+ end
55
+
56
+ sheet "C" do
57
+ column value_of(:a)
58
+ column :f1
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,189 @@
1
+ require 'calco'
2
+
3
+ RSpec.configure do |c|
4
+ c.alias_example_to :detect
5
+ end
6
+
7
+ describe 'Spreadsheet errors' do
8
+
9
+ detect "variable does not exist" do
10
+
11
+ expect {
12
+
13
+ spreadsheet do
14
+
15
+ sheet do
16
+
17
+ column value_of(:some_var)
18
+
19
+ end
20
+
21
+ end
22
+
23
+ }.to raise_error("Unknown variable some_var")
24
+
25
+ end
26
+
27
+ detect "function using an unknown variable" do
28
+
29
+ expect {
30
+
31
+ doc = spreadsheet do
32
+
33
+ definitions do
34
+
35
+ function some_var + 1
36
+
37
+ end
38
+
39
+ end
40
+
41
+ }.to raise_error("Unknown function or variable 'some_var'")
42
+
43
+ end
44
+
45
+ detect "assiging value to unknown variable" do
46
+
47
+ doc = spreadsheet do
48
+
49
+ sheet do
50
+
51
+ end
52
+
53
+ end
54
+
55
+ expect {
56
+
57
+ doc.save($stdout) do |spreadsheet|
58
+
59
+ sheet = spreadsheet.current
60
+
61
+ sheet[:some_var] = 12
62
+
63
+ end
64
+
65
+ }.to raise_error("Unknown variable 'some_var'")
66
+
67
+ end
68
+
69
+ detect "reference to an unknown function" do
70
+
71
+ expect {
72
+
73
+ spreadsheet do
74
+
75
+ sheet do
76
+
77
+ column :some_function
78
+
79
+ end
80
+
81
+ end
82
+
83
+ }.to raise_error("Unknown function or variable 'some_function'")
84
+
85
+ end
86
+
87
+ detect "using an unknown function" do
88
+
89
+ expect {
90
+
91
+ spreadsheet do
92
+
93
+ definitions do
94
+
95
+ function name: some_function
96
+
97
+ end
98
+
99
+ end
100
+
101
+ }.to raise_error("Unknown function or variable 'some_function'")
102
+
103
+ end
104
+
105
+ detect "declaring a variable twice" do
106
+
107
+ expect {
108
+
109
+ spreadsheet do
110
+
111
+ definitions do
112
+
113
+ set var: 12
114
+ set var: "hello"
115
+
116
+ end
117
+
118
+ end
119
+
120
+ }.to raise_error("Variable 'var' already set")
121
+
122
+ end
123
+
124
+ detect "declaring a function twice" do
125
+
126
+ expect {
127
+
128
+ spreadsheet do
129
+
130
+ definitions do
131
+
132
+ function f: 12
133
+ function f: "hello"
134
+
135
+ end
136
+
137
+ end
138
+
139
+ }.to raise_error("Function 'f' already defined")
140
+
141
+ end
142
+
143
+ detect "unnamed option for column" do
144
+
145
+ expect {
146
+
147
+ spreadsheet do
148
+
149
+ definitions do
150
+
151
+ set price: 11
152
+
153
+ end
154
+
155
+ sheet do
156
+ column :price, 'pp'
157
+ end
158
+
159
+ end
160
+
161
+ }.to raise_error(ArgumentError, "Options should be a Hash")
162
+
163
+ end
164
+
165
+ detect "unknown column id" do
166
+
167
+ expect {
168
+
169
+ doc = spreadsheet do
170
+
171
+ definitions do
172
+
173
+ set a: 'a'
174
+
175
+ end
176
+
177
+ sheet do
178
+ column :a
179
+ end
180
+
181
+ end
182
+
183
+ doc.current.replace_content :no_id, nil
184
+
185
+ }.to raise_error(RuntimeError, "Column id 'no_id' not found")
186
+
187
+ end
188
+
189
+ end
@@ -0,0 +1,251 @@
1
+ require 'calco'
2
+
3
+ RSpec.configure do |c|
4
+ c.alias_example_to :support
5
+ end
6
+
7
+ describe "Functions support" do
8
+
9
+ support "operators" do
10
+
11
+ doc = spreadsheet do
12
+
13
+ definitions do
14
+
15
+ set price: 14.4
16
+ set product: 'USB 8Gb'
17
+ set tax: 13
18
+ set quantity: 30
19
+
20
+ function total: price * quantity * (tax / 100 + 1)
21
+
22
+ end
23
+
24
+ sheet do
25
+
26
+ column value_of(:product)
27
+ column value_of(:price)
28
+ column value_of(:quantity)
29
+ column value_of(:tax)
30
+ column skip
31
+ column :total
32
+
33
+ end
34
+
35
+ end
36
+
37
+ row = doc.row(1)
38
+
39
+ expect(row[0]).to eq('"USB 8Gb"')
40
+ expect(row[1]).to eq('14.4')
41
+ expect(row[2]).to eq('30')
42
+ expect(row[3]).to eq('13')
43
+
44
+ expect(row[5]).to eq('(B1*C1)*((D1/100)+1)')
45
+
46
+ end
47
+
48
+ support "functions using functions" do
49
+
50
+ doc = spreadsheet do
51
+
52
+ definitions do
53
+
54
+ set price: 14.4
55
+ set product: 'USB 8Gb'
56
+ set tax: 13
57
+ set quantity: 30
58
+
59
+ function total: price * quantity
60
+ function total_with_taxes: total * (tax / 100 + 1)
61
+
62
+ end
63
+
64
+ sheet do
65
+
66
+ column value_of(:product)
67
+ column value_of(:price)
68
+ column value_of(:quantity)
69
+ column value_of(:tax)
70
+ column skip
71
+ column :total
72
+ column :total_with_taxes
73
+
74
+ end
75
+
76
+ end
77
+
78
+ row = doc.row(1)
79
+
80
+ expect(row[0]).to eq('"USB 8Gb"')
81
+ expect(row[1]).to eq('14.4')
82
+ expect(row[2]).to eq('30')
83
+ expect(row[3]).to eq('13')
84
+
85
+ expect(row[5]).to eq('B1*C1')
86
+ expect(row[6]).to eq('F1*((D1/100)+1)')
87
+
88
+ end
89
+
90
+ support "conditions with functions" do
91
+
92
+ doc = spreadsheet do
93
+
94
+ definitions do
95
+
96
+ set x: 9
97
+
98
+ function f0: x + 3
99
+ function f1: f0 * f0
100
+ function f2: f1 + f0
101
+ function f3: f2 + 7
102
+
103
+ function cond: _if(f1 > 2, f2, f3)
104
+
105
+ end
106
+
107
+ sheet do
108
+
109
+ column value_of(:x)
110
+ column :f0
111
+ column :f1
112
+ column :f2
113
+ column :f3
114
+
115
+ column :cond
116
+
117
+ end
118
+
119
+ end
120
+
121
+ row = doc.row(1)
122
+
123
+ expect(row[0]).to eq('9')
124
+ expect(row[1]).to eq('A1+3')
125
+ expect(row[2]).to eq('B1*B1')
126
+ expect(row[3]).to eq('C1+B1')
127
+ expect(row[4]).to eq('D1+7')
128
+ expect(row[5]).to eq('IF(C1>2;D1;E1)')
129
+
130
+ end
131
+
132
+ support "containing literals" do
133
+
134
+ some_day = Date.new(1998, 7, 12)
135
+
136
+ doc = spreadsheet do
137
+
138
+ definitions do
139
+
140
+ function a: 'string'
141
+ function b: 12
142
+ function c: 34.9
143
+ function d: some_day
144
+
145
+ end
146
+
147
+ sheet do
148
+
149
+ column :a
150
+ column :b
151
+ column :c
152
+ column :d
153
+
154
+ end
155
+
156
+ end
157
+
158
+ row = doc.current.row(1)
159
+
160
+ expect(row[0]).to eq('"string"')
161
+ expect(row[1]).to eq("12")
162
+ expect(row[2]).to eq("34.9")
163
+ expect(row[3]).to eq(some_day.to_s)
164
+
165
+ end
166
+
167
+ support "starting with an integer" do
168
+
169
+ doc = spreadsheet do
170
+
171
+ definitions do
172
+
173
+ set x: 12
174
+
175
+ function add: 66 + x
176
+
177
+ end
178
+
179
+ sheet do
180
+
181
+ column value_of(:x)
182
+ column :add
183
+
184
+ end
185
+
186
+ end
187
+
188
+ row = doc.row(1)
189
+
190
+ expect(row[0]).to eq('12')
191
+ expect(row[1]).to eq('66+A1')
192
+
193
+ end
194
+
195
+ support "starting with a float" do
196
+
197
+ doc = spreadsheet do
198
+
199
+ definitions do
200
+
201
+ set x: 12.9
202
+
203
+ function add: 34.7 + x
204
+
205
+ end
206
+
207
+ sheet do
208
+
209
+ column value_of(:x)
210
+ column :add
211
+
212
+ end
213
+
214
+ end
215
+
216
+ row = doc.row(1)
217
+
218
+ expect(row[0]).to eq('12.9')
219
+ expect(row[1]).to eq('34.7+A1')
220
+
221
+ end
222
+
223
+ support "starting with a string" do
224
+
225
+ doc = spreadsheet do
226
+
227
+ definitions do
228
+
229
+ set name: "Joe"
230
+
231
+ function greeting: "Hello " + name
232
+
233
+ end
234
+
235
+ sheet do
236
+
237
+ column value_of(:name)
238
+ column :greeting
239
+
240
+ end
241
+
242
+ end
243
+
244
+ row = doc.row(1)
245
+
246
+ expect(row[0]).to eq('"Joe"')
247
+ expect(row[1]).to eq('"Hello "+A1')
248
+
249
+ end
250
+
251
+ end