spreadshit 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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