hokusai-zero 0.1.3 → 0.1.4

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/Gemfile.lock +4 -0
  4. data/README.md +2 -0
  5. data/ast/src/core/hml.c +9 -9
  6. data/ast/src/core/text.c +1 -3
  7. data/ast/test/text.c +3 -3
  8. data/docs.sh +29 -0
  9. data/ext/extconf.rb +50 -14
  10. data/grammar/corpus/1_document.txt +24 -0
  11. data/grammar/corpus/6_styles.txt +23 -0
  12. data/grammar/grammar.js +4 -4
  13. data/grammar/src/grammar.json +19 -19
  14. data/grammar/src/parser.c +1904 -1956
  15. data/grammar/test.nml +10 -8
  16. data/hokusai.gemspec +2 -1
  17. data/ui/examples/assets/Delius-Regular.ttf +0 -0
  18. data/ui/examples/assets/DoHyeon.ttf +0 -0
  19. data/ui/examples/assets/Inter-Regular.ttf +0 -0
  20. data/ui/examples/assets/ernest.gif +0 -0
  21. data/ui/examples/assets/icons/audio-x-generic.png +0 -0
  22. data/ui/examples/assets/icons/image-x-generic.png +0 -0
  23. data/ui/examples/assets/icons/media-playback-pause.png +0 -0
  24. data/ui/examples/assets/icons/media-playback-start.png +0 -0
  25. data/ui/examples/assets/icons/media-playback-stop.png +0 -0
  26. data/ui/examples/assets/icons/package-x-generic.png +0 -0
  27. data/ui/examples/assets/icons/text-x-generic.png +0 -0
  28. data/ui/examples/assets/icons/video-x-generic.png +0 -0
  29. data/ui/examples/buddy.rb +16 -14
  30. data/ui/examples/clock.rb +38 -36
  31. data/ui/examples/counter.rb +100 -98
  32. data/ui/examples/dynamic.rb +115 -113
  33. data/ui/examples/foobar.rb +189 -187
  34. data/ui/examples/forum/file.rb +54 -0
  35. data/ui/examples/forum/music.rb +76 -0
  36. data/ui/examples/forum/post.rb +146 -0
  37. data/ui/examples/forum.rb +198 -0
  38. data/ui/examples/spreadsheet/csv.rb +261 -0
  39. data/ui/examples/spreadsheet.rb +138 -0
  40. data/ui/examples/stock.rb +86 -92
  41. data/ui/examples/stock_decider/option.rb +1 -1
  42. data/ui/examples/tic_tac_toe.rb +193 -191
  43. data/ui/lib/lib_hokusai.rb +0 -1
  44. data/ui/src/hokusai/ast.rb +42 -43
  45. data/ui/src/hokusai/backends/raylib/font.rb +1 -2
  46. data/ui/src/hokusai/backends/raylib.rb +16 -7
  47. data/ui/src/hokusai/backends/sdl2/font.rb +13 -9
  48. data/ui/src/hokusai/backends/sdl2.rb +5 -5
  49. data/ui/src/hokusai/block.rb +7 -0
  50. data/ui/src/hokusai/blocks/hblock.rb +2 -2
  51. data/ui/src/hokusai/blocks/image.rb +5 -1
  52. data/ui/src/hokusai/blocks/input.rb +17 -0
  53. data/ui/src/hokusai/blocks/label.rb +5 -2
  54. data/ui/src/hokusai/blocks/text.rb +10 -5
  55. data/ui/src/hokusai/blocks/titlebar/osx.rb +4 -4
  56. data/ui/src/hokusai/blocks/variable.rb +33 -0
  57. data/ui/src/hokusai/blocks/vblock.rb +1 -1
  58. data/ui/src/hokusai/commands/rect.rb +4 -4
  59. data/ui/src/hokusai/commands.rb +33 -31
  60. data/ui/src/hokusai/diff.rb +11 -0
  61. data/ui/src/hokusai/event.rb +19 -5
  62. data/ui/src/hokusai/events/mouse.rb +9 -1
  63. data/ui/src/hokusai/font.rb +60 -0
  64. data/ui/src/hokusai/meta.rb +10 -16
  65. data/ui/src/hokusai/node.rb +1 -1
  66. data/ui/src/hokusai/painter.rb +1 -2
  67. data/ui/src/hokusai/util/clamping_iterator.rb +5 -6
  68. data/ui/src/hokusai.rb +36 -4
  69. metadata +37 -3
data/ui/examples/stock.rb CHANGED
@@ -5,111 +5,105 @@ require_relative "./stock_decider/option"
5
5
 
6
6
  # aim for over 24 percent sort by percentage first
7
7
  # 3 week = 1 option premium * 100 shares / 12
8
- module StockDecider
9
- # Expecting a data prop in the form of
10
- #
11
- class StackedBar < Hokusai::Block
12
- COLORS = {
13
- :week_3 => [157, 221, 117],
14
- :week_4 => [117, 157, 221],
15
- :week_5 => [221, 180, 117]
16
- }
17
-
18
- template <<~EOF
19
- [template]
20
- virtual
21
- EOF
22
-
23
- uses(
24
- vblock: Hokusai::Blocks::Vblock,
25
- label: Hokusai::Blocks::Label
26
- )
27
-
28
- computed! :data
29
-
30
- def symbol
31
- data[0]
32
- end
8
+ module Demos
9
+ module StockDecider
10
+ class StackedBar < Hokusai::Block
11
+ COLORS = {
12
+ :week_3 => [157, 221, 117],
13
+ :week_4 => [117, 157, 221],
14
+ :week_5 => [221, 180, 117]
15
+ }
16
+
17
+ template <<~EOF
18
+ [template]
19
+ virtual
20
+ EOF
21
+
22
+ uses(
23
+ vblock: Hokusai::Blocks::Vblock,
24
+ label: Hokusai::Blocks::Label
25
+ )
26
+
27
+ computed! :data
28
+
29
+ def symbol
30
+ data[0]
31
+ end
33
32
 
34
- def render(canvas)
35
- key, weeks = data
36
- theight = canvas.height - 50
37
- draw do
38
- weeks.reject(&:nil?).sort { |a, b| b <=> a }.each_with_index do |percent, idx|
39
- color = COLORS["week_#{idx + 3}".to_sym]
40
- height = (theight * percent) / 100
41
- y = canvas.y + theight - height
42
-
43
- rect(canvas.x, y , 150, height) do |command|
44
- command.color = Hokusai::Color.convert(color)
45
- command.outline = Hokusai::Outline.convert("4,4, 0, 0")
46
- command.outline_color = Hokusai::Color.convert("0,0,0,110")
33
+ def render(canvas)
34
+ key, weeks = data
35
+ theight = canvas.height - 50
36
+ draw do
37
+ weeks.reject(&:nil?).sort { |a, b| b <=> a }.each_with_index do |percent, idx|
38
+ color = COLORS["week_#{idx + 3}".to_sym]
39
+ height = (theight * percent) / 100
40
+ y = canvas.y + theight - height
41
+
42
+ rect(canvas.x, y , 150, height) do |command|
43
+ command.color = Hokusai::Color.convert(color)
44
+ command.outline = Hokusai::Outline.convert("4,4, 0, 0")
45
+ command.outline_color = Hokusai::Color.convert("0,0,0,110")
46
+ end
47
+
48
+ text("Week #{idx + 3} (#{percent.round(2)})", canvas.x + 2, y + 10) do |command|
49
+ command.size = 12
50
+ end
47
51
  end
48
52
 
49
- text("Week #{idx + 3} (#{percent.round(2)})", canvas.x + 2, y + 10) do |command|
50
- command.size = 12
53
+ text(symbol, canvas.x + 12, theight + 5) do |command|
54
+ command.size = 25
55
+ command.color = Hokusai::Color.new(233,233,233,255)
51
56
  end
52
57
  end
53
58
 
54
- text(symbol, canvas.x + 12, theight + 5) do |command|
55
- command.size = 25
56
- command.color = Hokusai::Color.new(233,233,233,255)
57
- end
59
+ canvas.x -= 100
60
+ yield canvas
58
61
  end
59
-
60
- canvas.x -= 100
61
- yield canvas
62
62
  end
63
- end
64
63
 
65
- class App < Hokusai::Block
66
- template <<~EOF
67
- [template]
68
- vblock { background="84,23,77" padding="0,20,0,20"}
69
- hblock { padding="0,20,0,20"}
70
- [for="data in attractive_options"]
71
- stackedbar { :key="key(index)" :data="data" }
72
- EOF
73
-
74
- uses(
75
- vblock: Hokusai::Blocks::Vblock,
76
- hblock: Hokusai::Blocks::Hblock,
77
- stackedbar: StackedBar
78
- )
79
-
80
- def attractive_options
81
- @options.to_a
82
- end
64
+ class App < Hokusai::Block
65
+ template <<~EOF
66
+ [template]
67
+ vblock { background="84,23,77" padding="0,20,0,20"}
68
+ hblock { padding="0,20,0,20"}
69
+ [for="data in attractive_options"]
70
+ stackedbar { :key="key(index)" :data="data" }
71
+ EOF
72
+
73
+ uses(
74
+ vblock: Hokusai::Blocks::Vblock,
75
+ hblock: Hokusai::Blocks::Hblock,
76
+ stackedbar: StackedBar
77
+ )
78
+
79
+ def attractive_options
80
+ @options.to_a
81
+ end
83
82
 
84
- def key(index)
85
- "Key_#{index}"
86
- end
83
+ def key(index)
84
+ "Key_#{index}"
85
+ end
87
86
 
88
- def on_mounted
89
- puts ["mounted"]
90
- add_ticker("TSLA")
91
- add_ticker("OXY")
92
- add_ticker("DG")
93
- end
87
+ def on_mounted
88
+ puts ["mounted"]
89
+ add_ticker("TSLA")
90
+ add_ticker("OXY")
91
+ add_ticker("DG")
92
+ end
94
93
 
95
- def add_ticker(sym)
96
- ticker_opts = Option.from_ticker(sym)
97
- w3 = ticker_opts.select { |a| a.attractive?(3) }.sort_by { |a| a.percent(3) }.last
98
- w4 = ticker_opts.select { |a| a.attractive?(4) }.sort_by { |a| a.percent(4) }.last
99
- w5 = ticker_opts.select { |a| a.attractive?(5) }.sort_by { |a| a.percent(5) }.last
100
- @options[sym] = [w3&.percent(3), w4&.percent(4), w5&.percent(5)]
101
- puts @options[sym]
102
- end
94
+ def add_ticker(sym)
95
+ ticker_opts = Option.from_ticker(sym)
96
+ w3 = ticker_opts.select { |a| a.attractive?(3) }.sort_by { |a| a.percent(3) }.last
97
+ w4 = ticker_opts.select { |a| a.attractive?(4) }.sort_by { |a| a.percent(4) }.last
98
+ w5 = ticker_opts.select { |a| a.attractive?(5) }.sort_by { |a| a.percent(5) }.last
99
+ @options[sym] = [w3&.percent(3), w4&.percent(4), w5&.percent(5)]
100
+ puts @options[sym]
101
+ end
103
102
 
104
- def initialize(**args)
105
- @options = {}
106
- super
103
+ def initialize(**args)
104
+ @options = {}
105
+ super
106
+ end
107
107
  end
108
108
  end
109
109
  end
110
- # #
111
- # Hokusai::Backends::SDLBackend.run(StockDecider::App) do |config|
112
- # config.width = 500
113
- # config.height = 500
114
- # config.title = "Loop application"
115
- # end
@@ -2,7 +2,7 @@ require 'json'
2
2
  require 'date'
3
3
  require "rest-client"
4
4
 
5
- module StockDecider
5
+ module Demos::StockDecider
6
6
  class Option
7
7
  URL = "https://cdn.cboe.com/api/global/delayed_quotes/options"
8
8
  def self.from_ticker(sym)
@@ -2,238 +2,240 @@ require_relative "../src/hokusai"
2
2
  require_relative "../src/hokusai/backends/raylib"
3
3
  require_relative "../src/hokusai/backends/sdl2"
4
4
 
5
- module TicTacToe
6
- module Player
7
- X = 0
8
- O = 1
9
- None = 2
10
- end
11
-
12
- class Square < Hokusai::Block
13
- style <<-EOF
14
- [style]
15
- squareStyle {
16
- outline: 3.0;
17
- outline_color: rgb(233,233,233);
18
- }
19
- EOF
20
-
21
- template <<-EOF
22
- [template]
23
- vblock {
24
- @click="emit_position"
25
- @hover="set_hover"
26
- @mouseout="set_mouseout"
27
- :background="compute_background"
28
- ...squareStyle
5
+ module Demos
6
+ module TicTacToe
7
+ module Player
8
+ X = 0
9
+ O = 1
10
+ None = 2
11
+ end
12
+
13
+ class Square < Hokusai::Block
14
+ style <<-EOF
15
+ [style]
16
+ squareStyle {
17
+ outline: 3.0;
18
+ outline_color: rgb(233,233,233);
29
19
  }
30
- label { height="13" :content="read_position" }
31
- [if="has_player"]
32
- image { :source="square_image" }
33
- EOF
34
-
35
- computed! :player
36
- computed! :position
37
-
38
- uses(
39
- vblock: Hokusai::Blocks::Vblock,
40
- image: Hokusai::Blocks::Image,
41
- label: Hokusai::Blocks::Label
42
- )
43
-
44
- def compute_background
45
- case player
46
- when Player::X
47
- [52,168,77]
48
- when Player::O
49
- [219,176,57]
50
- when Player::None
51
- @hover ? [55, 110, 155] : [47,98,140]
20
+ EOF
21
+
22
+ template <<-EOF
23
+ [template]
24
+ vblock {
25
+ @click="emit_position"
26
+ @hover="set_hover"
27
+ @mouseout="set_mouseout"
28
+ :background="compute_background"
29
+ ...squareStyle
30
+ }
31
+ label { height="13" :content="read_position" }
32
+ [if="has_player"]
33
+ image { :source="square_image" }
34
+ EOF
35
+
36
+ computed! :player
37
+ computed! :position
38
+
39
+ uses(
40
+ vblock: Hokusai::Blocks::Vblock,
41
+ image: Hokusai::Blocks::Image,
42
+ label: Hokusai::Blocks::Label
43
+ )
44
+
45
+ def compute_background
46
+ case player
47
+ when Player::X
48
+ [52,168,77]
49
+ when Player::O
50
+ [219,176,57]
51
+ when Player::None
52
+ @hover ? [55, 110, 155] : [47,98,140]
53
+ end
52
54
  end
53
- end
54
55
 
55
- def set_hover(event)
56
- @hover = true
57
- end
56
+ def set_hover(event)
57
+ @hover = true
58
+ end
58
59
 
59
- def set_mouseout(event)
60
- @hover = false
61
- end
60
+ def set_mouseout(event)
61
+ @hover = false
62
+ end
62
63
 
63
- def read_position
64
- position.inspect
65
- end
64
+ def read_position
65
+ position.inspect
66
+ end
66
67
 
67
- def emit_position(click)
68
- emit("position", position)
69
- end
68
+ def emit_position(click)
69
+ emit("position", position)
70
+ end
70
71
 
71
- def has_player
72
- player != Player::None
73
- end
72
+ def has_player
73
+ player != Player::None
74
+ end
74
75
 
75
- def square_image
76
- case player
77
- when Player::X
78
- return "#{__dir__}/assets/science-troll.png"
79
- when Player::O
80
- return "#{__dir__}/assets/football-troll.png"
76
+ def square_image
77
+ case player
78
+ when Player::X
79
+ return "#{__dir__}/assets/science-troll.png"
80
+ when Player::O
81
+ return "#{__dir__}/assets/football-troll.png"
82
+ end
81
83
  end
82
84
  end
83
- end
84
85
 
85
- class Row < Hokusai::Block
86
- template <<-EOF
87
- [template]
88
- hblock
89
- [for="player in row"]
90
- square { cursor="pointer" @position="emit_position" :player="player" :key="key(index)" :position="position(index)" }
91
- EOF
86
+ class Row < Hokusai::Block
87
+ template <<-EOF
88
+ [template]
89
+ hblock
90
+ [for="player in row"]
91
+ square { cursor="pointer" @position="emit_position" :player="player" :key="key(index)" :position="position(index)" }
92
+ EOF
92
93
 
93
- uses(
94
- square: Square,
95
- hblock: Hokusai::Blocks::Hblock
96
- )
94
+ uses(
95
+ square: Square,
96
+ hblock: Hokusai::Blocks::Hblock
97
+ )
97
98
 
98
- computed! :row
99
- computed! :row_index
99
+ computed! :row
100
+ computed! :row_index
100
101
 
101
- def emit_position(pos)
102
- emit("position", pos)
103
- end
102
+ def emit_position(pos)
103
+ emit("position", pos)
104
+ end
104
105
 
105
- def key(index)
106
- "player_#{row_index}_#{index}"
107
- end
106
+ def key(index)
107
+ "player_#{row_index}_#{index}"
108
+ end
108
109
 
109
- def position(index)
110
- [row_index, index]
111
- end
110
+ def position(index)
111
+ [row_index, index]
112
+ end
112
113
 
113
- end
114
+ end
114
115
 
115
- class App < Hokusai::Block
116
- template <<-EOF
117
- [template]
118
- vblock
119
- [if="has_winner"]
120
- vblock { background="10,10,10,222" }
121
- img { :source="winner_image"}
116
+ class App < Hokusai::Block
117
+ template <<-EOF
118
+ [template]
119
+ vblock
120
+ [if="has_winner"]
121
+ vblock { background="10,10,10,222" }
122
+ img { :source="winner_image"}
123
+ vblock
124
+ label { :content="winner_text" color="255,255,255", size="30"}
125
+ label { @click="restart" color="222,199,199" size="20" content="restart"}
126
+ [else]
122
127
  vblock
123
- label { :content="winner_text" color="255,255,255", size="30"}
124
- label { @click="restart" color="222,199,199" size="20" content="restart"}
125
- [else]
126
- vblock
127
- [for="row in board"]
128
- row { @position="update_game" :row="row" :key="key(index)" :row_index="index" }
129
- EOF
130
-
131
- uses(
132
- row: Row,
133
- vblock: Hokusai::Blocks::Vblock,
134
- hblock: Hokusai::Blocks::Hblock,
135
- label: Hokusai::Blocks::Label,
136
- empty: Hokusai::Blocks::Empty,
137
- img: Hokusai::Blocks::Image
138
- )
139
-
140
- attr_accessor :current_player, :board, :count
141
-
142
- def initialize(**args)
143
- @current_player = Player::X
144
- @count = 0
145
- super
146
-
147
- restart
148
- end
128
+ [for="row in board"]
129
+ row { @position="update_game" :row="row" :key="key(index)" :row_index="index" }
130
+ EOF
131
+
132
+ uses(
133
+ row: Row,
134
+ vblock: Hokusai::Blocks::Vblock,
135
+ hblock: Hokusai::Blocks::Hblock,
136
+ label: Hokusai::Blocks::Label,
137
+ empty: Hokusai::Blocks::Empty,
138
+ img: Hokusai::Blocks::Image
139
+ )
140
+
141
+ attr_accessor :current_player, :board, :count
142
+
143
+ def initialize(**args)
144
+ @current_player = Player::X
145
+ @count = 0
146
+ super
147
+
148
+ restart
149
+ end
149
150
 
150
- def restart(*args)
151
- @board = [
152
- [Player::None, Player::None, Player::None],
153
- [Player::None, Player::None, Player::None],
154
- [Player::None, Player::None, Player::None]
155
- ]
156
- self.count = 0
157
- end
151
+ def restart(*args)
152
+ @board = [
153
+ [Player::None, Player::None, Player::None],
154
+ [Player::None, Player::None, Player::None],
155
+ [Player::None, Player::None, Player::None]
156
+ ]
157
+ self.count = 0
158
+ end
158
159
 
159
- def key(index)
160
- "row_#{index}"
161
- end
160
+ def key(index)
161
+ "row_#{index}"
162
+ end
162
163
 
163
- def winner_image
164
- case winner
165
- when Player::X
166
- return "#{__dir__}/assets/science-troll.png"
167
- when Player::O
168
- return "#{__dir__}/assets/football-troll.png"
169
- else
170
- return "#{__dir__}/assets/baby_sean.png"
164
+ def winner_image
165
+ case winner
166
+ when Player::X
167
+ return "#{__dir__}/assets/science-troll.png"
168
+ when Player::O
169
+ return "#{__dir__}/assets/football-troll.png"
170
+ else
171
+ return "#{__dir__}/assets/baby_sean.png"
172
+ end
171
173
  end
172
- end
173
174
 
174
- def winner_text
175
- case winner
176
- when Player::X
177
- "Player X won!"
178
- when Player::O
179
- "Player O won!"
180
- else
181
- "No winner"
175
+ def winner_text
176
+ case winner
177
+ when Player::X
178
+ "Player X won!"
179
+ when Player::O
180
+ "Player O won!"
181
+ else
182
+ "No winner"
183
+ end
182
184
  end
183
- end
184
185
 
185
- def has_winner
186
- count >= 9 || !check_win.nil?
187
- end
186
+ def has_winner
187
+ count >= 9 || !check_win.nil?
188
+ end
188
189
 
189
- def winner
190
- check_win
191
- end
190
+ def winner
191
+ check_win
192
+ end
192
193
 
193
- def update_game(position)
194
- row, col = position
194
+ def update_game(position)
195
+ row, col = position
195
196
 
196
- self.count += 1
197
+ self.count += 1
197
198
 
198
- case current_player
199
- when Player::X
200
- board[row][col] = Player::X unless board[row][col] != Player::None
201
- self.current_player = Player::O
202
- when Player::O
203
- board[row][col] = Player::O unless board[row][col] != Player::None
204
- self.current_player = Player::X
199
+ case current_player
200
+ when Player::X
201
+ board[row][col] = Player::X unless board[row][col] != Player::None
202
+ self.current_player = Player::O
203
+ when Player::O
204
+ board[row][col] = Player::O unless board[row][col] != Player::None
205
+ self.current_player = Player::X
206
+ end
205
207
  end
206
- end
207
208
 
208
- def check_win
209
- [Player::X, Player::O].each do |player|
210
- (0...3).step do |i|
211
- if board[i][0] == player && board[i][1] == player && board[i][2] == player
212
- return player
213
- end
209
+ def check_win
210
+ [Player::X, Player::O].each do |player|
211
+ (0...3).step do |i|
212
+ if board[i][0] == player && board[i][1] == player && board[i][2] == player
213
+ return player
214
+ end
214
215
 
215
- if board[0][i] == player && board[1][i] == player && board[2][i] == player
216
- return player
217
- end
216
+ if board[0][i] == player && board[1][i] == player && board[2][i] == player
217
+ return player
218
+ end
218
219
 
219
- diagonal_left = board[0][0] == player && board[1][1] == player && board[2][2] == player
220
- diagonal_right = board[2][0] == player && board[1][1] == player && board[0][2] == player
220
+ diagonal_left = board[0][0] == player && board[1][1] == player && board[2][2] == player
221
+ diagonal_right = board[2][0] == player && board[1][1] == player && board[0][2] == player
221
222
 
222
- if diagonal_left || diagonal_right
223
- return player
223
+ if diagonal_left || diagonal_right
224
+ return player
225
+ end
224
226
  end
225
227
  end
226
- end
227
228
 
228
- nil
229
- end
229
+ nil
230
+ end
230
231
 
231
- def render(canvas)
232
- if Hokusai.can_render(canvas)
232
+ def render(canvas)
233
+ if Hokusai.can_render(canvas)
233
234
 
234
- emit("width", canvas.width)
235
+ emit("width", canvas.width)
235
236
 
236
- yield canvas
237
+ yield canvas
238
+ end
237
239
  end
238
240
  end
239
241
  end
@@ -29,7 +29,6 @@ module LibHokusai
29
29
 
30
30
  def self.parse_style(template)
31
31
  ptr = FFI::MemoryPointer.new :pointer
32
- pp template
33
32
  code = LibHokusai.hoku_style_from_template(ptr, template)
34
33
 
35
34
  raise LibHokusai::Error.new("Couldn't parse style template") unless code.zero?