spreadshit 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8458cafa69246fc6038f2ac8a6823569e39de820
4
- data.tar.gz: 2982c754d56740b6234255cf2c90c50b141f78cd
3
+ metadata.gz: 3b8708f78a939f35fc9529dd41df30a084580930
4
+ data.tar.gz: a49ecd2eaa4f5565520cb6da994468532d91b3ab
5
5
  SHA512:
6
- metadata.gz: 0cc85771b717af20087bc7ee1a64da872a26143f6e40d2682acf8afe093eb850193e2737ab2676f5ff1a657b9c3f2523592028583d0516a5c30c2497aab575a7
7
- data.tar.gz: 497cb849983596238a0a49b742517c126ddc4473abe2a730ba4540a03a1faee053a0eb74be2fedb0cdc05a538d875424e32fb84c7e9f8db58fac5919c2ab2a0b
6
+ metadata.gz: 1379f58cb3098c6e12ed2c755651e629da2156a7e4f5de3a35b7e590c693d3ad74ab19978b5260a8b0f62eec86b4cdff1cf9d8cb667d11805238d9bf5defd6cc
7
+ data.tar.gz: 4d9731115926c43cf44a975c6b3dc7dfda4131b756d2ed383d98a7bffaa5d12775fbe4fdbb7d177e7124333693502d99c67940cd9d5482a8d67cde34d83c221a
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  Gemfile.lock
2
+ pkg/
@@ -1,4 +1,5 @@
1
1
  class Spreadshit
2
+ require "spreadshit/cell"
2
3
  require "spreadshit/formula"
3
4
  require "spreadshit/functions"
4
5
 
@@ -64,49 +65,3 @@ class Spreadshit
64
65
  end
65
66
  end
66
67
  end
67
-
68
- class Cell
69
- attr_reader :raw
70
-
71
- def initialize(raw = "", &expression)
72
- @raw = raw
73
- @observers = Set.new
74
- @observed = []
75
- update(&expression) if block_given?
76
- end
77
-
78
- def value
79
- if @@caller
80
- @observers << @@caller
81
- @@caller.observed << self
82
- end
83
- @value
84
- end
85
-
86
- def update(value = raw || "", &expression)
87
- @raw = value
88
- @expression = expression
89
- compute
90
- @value
91
- end
92
-
93
- protected
94
-
95
- attr_reader :observers, :observed
96
-
97
- def compute
98
- @observed.each { |observed| observed.observers.delete(self) }
99
- @observed = []
100
-
101
- @@caller = self
102
- new_value = @expression.call
103
- @@caller = nil
104
-
105
- if new_value != @value
106
- @value = new_value
107
- observers = @observers
108
- @observers = Set.new
109
- observers.each { |observer| observer.compute }
110
- end
111
- end
112
- end
@@ -0,0 +1,45 @@
1
+ class Spreadshit::Cell
2
+ attr_reader :raw
3
+
4
+ def initialize(raw = "", &expression)
5
+ @raw = raw
6
+ @observers = Set.new
7
+ @observed = []
8
+ update(&expression) if block_given?
9
+ end
10
+
11
+ def value
12
+ if @@caller
13
+ @observers << @@caller
14
+ @@caller.observed << self
15
+ end
16
+ @value
17
+ end
18
+
19
+ def update(value = raw || "", &expression)
20
+ @raw = value
21
+ @expression = expression
22
+ compute
23
+ @value
24
+ end
25
+
26
+ protected
27
+
28
+ attr_reader :observers, :observed
29
+
30
+ def compute
31
+ @observed.each { |observed| observed.observers.delete(self) }
32
+ @observed = []
33
+
34
+ @@caller = self
35
+ new_value = @expression.call
36
+ @@caller = nil
37
+
38
+ if new_value != @value
39
+ @value = new_value
40
+ observers = @observers
41
+ @observers = Set.new
42
+ observers.each { |observer| observer.compute }
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  class Spreadshit
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -1,263 +1,265 @@
1
1
  require "curses"
2
2
 
3
- class Spreadshit::Window
4
- class Address < Struct.new(:col, :row)
5
- def to_s
6
- [col, row].join
7
- end
3
+ class Spreadshit
4
+ class Window
5
+ class Address < Struct.new(:col, :row)
6
+ def to_s
7
+ [col, row].join
8
+ end
8
9
 
9
- def to_sym
10
- to_s.to_sym
10
+ def to_sym
11
+ to_s.to_sym
12
+ end
11
13
  end
12
- end
13
14
 
14
- class SpreadsheetDelegate
15
- def initialize
16
- @cell_updated, @cell_value, @cell_content = Proc.new {}
17
- end
15
+ class SpreadsheetDelegate
16
+ def initialize
17
+ @cell_updated, @cell_value, @cell_content = Proc.new {}
18
+ end
18
19
 
19
- def cell_updated(&block)
20
- if block_given?
21
- @cell_updated = block
22
- else
23
- @cell_updated
20
+ def cell_updated(&block)
21
+ if block_given?
22
+ @cell_updated = block
23
+ else
24
+ @cell_updated
25
+ end
24
26
  end
25
- end
26
27
 
27
- def cell_value(&block)
28
- if block_given?
29
- @cell_value = block
30
- else
31
- @cell_value
28
+ def cell_value(&block)
29
+ if block_given?
30
+ @cell_value = block
31
+ else
32
+ @cell_value
33
+ end
32
34
  end
33
- end
34
35
 
35
- def cell_content(&block)
36
- if block_given?
37
- @cell_content = block
38
- else
39
- @cell_content
36
+ def cell_content(&block)
37
+ if block_given?
38
+ @cell_content = block
39
+ else
40
+ @cell_content
41
+ end
40
42
  end
41
43
  end
42
- end
43
44
 
44
- include Curses
45
+ include Curses
45
46
 
46
- def initialize
47
- @mode = :navigation
48
- @x, @y = 0, 0
49
- @sx, @sy = 0, 0
50
- @col_width = 13
51
- @letters = ("A".."ZZZ").to_a
52
- @spreadsheet_delegate = SpreadsheetDelegate.new
53
- yield @spreadsheet_delegate
54
- end
55
-
56
- def start
57
- init_screen
58
- start_color
59
- init_pair(COLOR_WHITE, COLOR_BLACK, COLOR_WHITE)
60
- init_pair(COLOR_BLUE, COLOR_BLACK, COLOR_BLUE)
61
- init_pair(COLOR_GREEN, COLOR_BLACK, COLOR_GREEN)
62
- init_pair(COLOR_RED, COLOR_BLACK, COLOR_MAGENTA)
63
- use_default_colors
64
- redraw
65
-
66
- loop { capture_input }
67
- end
68
-
69
- private
47
+ def initialize
48
+ @mode = :navigation
49
+ @x, @y = 0, 0
50
+ @sx, @sy = 0, 0
51
+ @col_width = 13
52
+ @letters = ("A".."ZZZ").to_a
53
+ @spreadsheet_delegate = SpreadsheetDelegate.new
54
+ yield @spreadsheet_delegate
55
+ end
70
56
 
71
- def max_cols
72
- cols / @col_width
73
- end
57
+ def start
58
+ init_screen
59
+ start_color
60
+ init_pair(COLOR_WHITE, COLOR_BLACK, COLOR_WHITE)
61
+ init_pair(COLOR_BLUE, COLOR_BLACK, COLOR_BLUE)
62
+ init_pair(COLOR_GREEN, COLOR_BLACK, COLOR_GREEN)
63
+ init_pair(COLOR_RED, COLOR_BLACK, COLOR_MAGENTA)
64
+ use_default_colors
65
+ redraw
66
+
67
+ loop { capture_input }
68
+ end
74
69
 
75
- def max_rows
76
- lines - 3
77
- end
70
+ private
78
71
 
79
- def address
80
- Address.new(@letters[@x], @y + 1)
81
- end
72
+ def max_cols
73
+ cols / @col_width
74
+ end
82
75
 
83
- def current_cell_value
84
- cell_value_at(address)
85
- end
76
+ def max_rows
77
+ lines - 3
78
+ end
86
79
 
87
- def cell_value_at(address)
88
- @spreadsheet_delegate.cell_value.call(address)
89
- end
80
+ def address
81
+ Address.new(@letters[@x], @y + 1)
82
+ end
90
83
 
91
- def current_cell_content
92
- @spreadsheet_delegate.cell_content.call(address)
93
- end
84
+ def current_cell_value
85
+ cell_value_at(address)
86
+ end
94
87
 
95
- def current_cell_content=(value)
96
- @spreadsheet_delegate.cell_updated.call(address, value)
97
- end
88
+ def cell_value_at(address)
89
+ @spreadsheet_delegate.cell_value.call(address)
90
+ end
98
91
 
99
- def capture_input
100
- case @mode
101
- when :navigation
102
- navigate
103
- when :edit
104
- read_cell_definition
92
+ def current_cell_content
93
+ @spreadsheet_delegate.cell_content.call(address)
105
94
  end
106
- end
107
95
 
108
- def navigate
109
- cbreak
110
- noecho
111
- stdscr.keypad = true
112
- case getch
113
- when KEY_UP
114
- @y -= 1
115
- @y = 0 if @y < 0
116
- @sy -= 1 if @y < @sy
117
- @sy = 0 if @sy < 0
118
- when KEY_DOWN
119
- @y += 1
120
- @sy += 1 if @y >= max_rows
121
- when KEY_LEFT
122
- @x -= 1
123
- @x = 0 if @x < 0
124
- @sx -= 1 if @x < @sx
125
- @sx = 0 if @sx < 0
126
- when KEY_RIGHT
127
- @x += 1
128
- @sx += 1 if @x >= max_cols
129
- when 10
130
- @mode = :edit
131
- when 27
132
- exit 0
133
- else
134
- return
96
+ def current_cell_content=(value)
97
+ @spreadsheet_delegate.cell_updated.call(address, value)
135
98
  end
136
99
 
137
- redraw
138
- end
100
+ def capture_input
101
+ case @mode
102
+ when :navigation
103
+ navigate
104
+ when :edit
105
+ read_cell_definition
106
+ end
107
+ end
139
108
 
140
- def read_cell_definition
141
- echo
142
- self.current_cell_content = getstr
143
- @mode = :navigation
144
- redraw
145
- end
109
+ def navigate
110
+ cbreak
111
+ noecho
112
+ stdscr.keypad = true
113
+ case getch
114
+ when KEY_UP
115
+ @y -= 1
116
+ @y = 0 if @y < 0
117
+ @sy -= 1 if @y < @sy
118
+ @sy = 0 if @sy < 0
119
+ when KEY_DOWN
120
+ @y += 1
121
+ @sy += 1 if @y >= max_rows
122
+ when KEY_LEFT
123
+ @x -= 1
124
+ @x = 0 if @x < 0
125
+ @sx -= 1 if @x < @sx
126
+ @sx = 0 if @sx < 0
127
+ when KEY_RIGHT
128
+ @x += 1
129
+ @sx += 1 if @x >= max_cols
130
+ when 10
131
+ @mode = :edit
132
+ when 27
133
+ exit 0
134
+ else
135
+ return
136
+ end
146
137
 
147
- def redraw
148
- draw_cells
149
- draw_letters_header
150
- draw_numbers_header
151
- draw_text_field
152
- cursor_to_input_line
153
- refresh
154
- end
138
+ redraw
139
+ end
155
140
 
156
- def draw_text_field
157
- setpos(divider_line, 0)
141
+ def read_cell_definition
142
+ echo
143
+ self.current_cell_content = getstr
144
+ @mode = :navigation
145
+ redraw
146
+ end
158
147
 
159
- case @mode
160
- when :navigation
161
- draw_divider(
162
- color: color_pair(COLOR_RED) | A_NORMAL,
163
- left_text: current_cell_value.to_s,
164
- center_text: "Press ENTER to edit #{address}",
165
- )
166
- cursor_to_input_line
167
- addstr(current_cell_content.to_s)
168
- clrtoeol
169
- when :edit
170
- draw_divider(
171
- color: color_pair(COLOR_GREEN) | A_NORMAL,
172
- left_text: current_cell_content.to_s,
173
- center_text: "Editing #{address}"
174
- )
148
+ def redraw
149
+ draw_cells
150
+ draw_letters_header
151
+ draw_numbers_header
152
+ draw_text_field
175
153
  cursor_to_input_line
176
- clrtoeol
154
+ refresh
177
155
  end
178
- end
179
156
 
180
- def draw_divider(color: color_pair(COLOR_GREEN) | A_NORMAL, left_text: "", right_text: "", center_text: "")
181
- attron color do
157
+ def draw_text_field
182
158
  setpos(divider_line, 0)
183
- addstr(" " * cols)
184
159
 
185
- setpos(divider_line, 2)
186
- addstr(left_text.ljust(cols / 3))
160
+ case @mode
161
+ when :navigation
162
+ draw_divider(
163
+ color: color_pair(COLOR_RED) | A_NORMAL,
164
+ left_text: current_cell_value.to_s,
165
+ center_text: "Press ENTER to edit #{address}",
166
+ )
167
+ cursor_to_input_line
168
+ addstr(current_cell_content.to_s)
169
+ clrtoeol
170
+ when :edit
171
+ draw_divider(
172
+ color: color_pair(COLOR_GREEN) | A_NORMAL,
173
+ left_text: current_cell_content.to_s,
174
+ center_text: "Editing #{address}"
175
+ )
176
+ cursor_to_input_line
177
+ clrtoeol
178
+ end
179
+ end
187
180
 
188
- setpos(divider_line, cols / 3)
189
- addstr(center_text.center(cols / 3))
181
+ def draw_divider(color: color_pair(COLOR_GREEN) | A_NORMAL, left_text: "", right_text: "", center_text: "")
182
+ attron color do
183
+ setpos(divider_line, 0)
184
+ addstr(" " * cols)
190
185
 
191
- setpos(divider_line, cols - right_text.size - 2)
192
- addstr(right_text)
186
+ setpos(divider_line, 2)
187
+ addstr(left_text.ljust(cols / 3))
188
+
189
+ setpos(divider_line, cols / 3)
190
+ addstr(center_text.center(cols / 3))
191
+
192
+ setpos(divider_line, cols - right_text.size - 2)
193
+ addstr(right_text)
194
+ end
193
195
  end
194
- end
195
196
 
196
- def visible_letters
197
- (@sx...max_cols + @sx).map { |col| @letters[col] }
198
- end
197
+ def visible_letters
198
+ (@sx...max_cols + @sx).map { |col| @letters[col] }
199
+ end
199
200
 
200
- def selected?(row, col)
201
- address.col == col && address.row == (@sy + row)
202
- end
201
+ def selected?(row, col)
202
+ address.col == col && address.row == (@sy + row)
203
+ end
203
204
 
204
- def draw_cells(padding: 4)
205
- 1.upto(max_rows).each do |row|
206
- visible_letters.each.with_index do |col, index|
207
- setpos(row, padding + index * @col_width)
205
+ def draw_cells(padding: 4)
206
+ 1.upto(max_rows).each do |row|
207
+ visible_letters.each.with_index do |col, index|
208
+ setpos(row, padding + index * @col_width)
208
209
 
209
- if selected? row, col
210
- attron(color_pair(@mode == :edit ? COLOR_GREEN : COLOR_WHITE) | A_TOP) do
210
+ if selected? row, col
211
+ attron(color_pair(@mode == :edit ? COLOR_GREEN : COLOR_WHITE) | A_TOP) do
212
+ draw_cell @sy + row, col
213
+ end
214
+ else
211
215
  draw_cell @sy + row, col
212
216
  end
213
- else
214
- draw_cell @sy + row, col
215
217
  end
216
218
  end
217
219
  end
218
- end
219
220
 
220
- def draw_letters_header(padding: 4, color: COLOR_BLUE)
221
- visible_letters.each.with_index do |letter, index|
222
- setpos(0, padding + index * @col_width)
221
+ def draw_letters_header(padding: 4, color: COLOR_BLUE)
222
+ visible_letters.each.with_index do |letter, index|
223
+ setpos(0, padding + index * @col_width)
223
224
 
224
- attron(color_pair(color) | A_TOP) do
225
- addstr(letter.center(@col_width))
225
+ attron(color_pair(color) | A_TOP) do
226
+ addstr(letter.center(@col_width))
227
+ end
226
228
  end
227
229
  end
228
- end
229
230
 
230
- def draw_numbers_header(padding: 4, color: COLOR_BLUE)
231
- 1.upto(max_rows).each.with_index do |row, index|
232
- setpos(row, 0)
231
+ def draw_numbers_header(padding: 4, color: COLOR_BLUE)
232
+ 1.upto(max_rows).each.with_index do |row, index|
233
+ setpos(row, 0)
233
234
 
234
- attron(color_pair(COLOR_BLUE) | A_TOP) do
235
- addstr (@sy + row).to_s.rjust(padding)
235
+ attron(color_pair(COLOR_BLUE) | A_TOP) do
236
+ addstr (@sy + row).to_s.rjust(padding)
237
+ end
236
238
  end
237
239
  end
238
- end
239
240
 
240
- def draw_cell(row, col)
241
- value = cell_value_at(Address.new(col, row)).to_s
241
+ def draw_cell(row, col)
242
+ value = cell_value_at(Address.new(col, row)).to_s
242
243
 
243
- if value == Float::NAN.to_s
244
- addstr("#VALUE!".center(@col_width))
245
- elsif value.size >= @col_width
246
- addstr(value.chars.last(@col_width).join)
247
- else
248
- addstr(value.rjust(@col_width))
244
+ if value == Float::NAN.to_s
245
+ addstr("#VALUE!".center(@col_width))
246
+ elsif value.size >= @col_width
247
+ addstr(value.chars.last(@col_width).join)
248
+ else
249
+ addstr(value.rjust(@col_width))
250
+ end
249
251
  end
250
- end
251
252
 
252
- def input_line
253
- lines - 1
254
- end
253
+ def input_line
254
+ lines - 1
255
+ end
255
256
 
256
- def divider_line
257
- lines - 2
258
- end
257
+ def divider_line
258
+ lines - 2
259
+ end
259
260
 
260
- def cursor_to_input_line
261
- setpos(input_line, 2)
261
+ def cursor_to_input_line
262
+ setpos(input_line, 2)
263
+ end
262
264
  end
263
265
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spreadshit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Navarro
@@ -81,6 +81,7 @@ files:
81
81
  - bin/demo
82
82
  - bin/setup
83
83
  - lib/spreadshit.rb
84
+ - lib/spreadshit/cell.rb
84
85
  - lib/spreadshit/formula.rb
85
86
  - lib/spreadshit/formula.treetop
86
87
  - lib/spreadshit/functions.rb