hokusai-zero 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.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/Dockerfile +26 -0
  3. data/Gemfile +15 -0
  4. data/Gemfile.lock +91 -0
  5. data/LICENSE +21 -0
  6. data/README.md +28 -0
  7. data/ast/genheader +3 -0
  8. data/ast/include/hashmap.c +1151 -0
  9. data/ast/include/hashmap.c.license +20 -0
  10. data/ast/include/hashmap.h +54 -0
  11. data/ast/src/core/ast.c +448 -0
  12. data/ast/src/core/ast.h +259 -0
  13. data/ast/src/core/common.h +24 -0
  14. data/ast/src/core/component.c +85 -0
  15. data/ast/src/core/component.h +35 -0
  16. data/ast/src/core/hml.c +665 -0
  17. data/ast/src/core/hml.h +11 -0
  18. data/ast/src/core/input.c +458 -0
  19. data/ast/src/core/input.h +118 -0
  20. data/ast/src/core/style.c +101 -0
  21. data/ast/src/core/style.h +41 -0
  22. data/ast/src/core/text.c +784 -0
  23. data/ast/src/core/text.h +93 -0
  24. data/ast/src/core/util.c +140 -0
  25. data/ast/src/core/util.h +48 -0
  26. data/ast/src/hokusai.c +6 -0
  27. data/ast/src/hokusai.h +6 -0
  28. data/ast/test/fixtures/test.ui +13 -0
  29. data/ast/test/greatest.h +1266 -0
  30. data/ast/test/hokusai.c +14 -0
  31. data/ast/test/parser.c +234 -0
  32. data/ast/test/text.c +116 -0
  33. data/ext/extconf.rb +27 -0
  34. data/grammar/Cargo.lock +80 -0
  35. data/grammar/Cargo.toml +26 -0
  36. data/grammar/binding.gyp +20 -0
  37. data/grammar/bindings/node/binding.cc +28 -0
  38. data/grammar/bindings/node/index.js +19 -0
  39. data/grammar/bindings/rust/build.rs +40 -0
  40. data/grammar/bindings/rust/lib.rs +52 -0
  41. data/grammar/corpus/1_document.txt +131 -0
  42. data/grammar/corpus/2_selectors.txt +58 -0
  43. data/grammar/corpus/3_spaces.txt +69 -0
  44. data/grammar/corpus/4_errors.txt +10 -0
  45. data/grammar/corpus/5_macros.txt +175 -0
  46. data/grammar/corpus/6_styles.txt +81 -0
  47. data/grammar/grammar.js +275 -0
  48. data/grammar/package-lock.json +34 -0
  49. data/grammar/package.json +33 -0
  50. data/grammar/src/grammar.json +1269 -0
  51. data/grammar/src/node-types.json +474 -0
  52. data/grammar/src/parser.c +5772 -0
  53. data/grammar/src/scanner.c +258 -0
  54. data/grammar/src/tree_sitter/parser.h +230 -0
  55. data/grammar/src/tree_sitter/scanner.h +12 -0
  56. data/grammar/test.nml +10 -0
  57. data/hokusai.gemspec +19 -0
  58. data/ui/examples/assets/DigitalDisplay.ttf +0 -0
  59. data/ui/examples/assets/OpenSans-Regular.ttf +0 -0
  60. data/ui/examples/assets/addy.png +0 -0
  61. data/ui/examples/assets/baby_sean.png +0 -0
  62. data/ui/examples/assets/football-troll.png +0 -0
  63. data/ui/examples/assets/gear.png +0 -0
  64. data/ui/examples/assets/icecold.ttf +0 -0
  65. data/ui/examples/assets/science-troll.png +0 -0
  66. data/ui/examples/buddy.rb +31 -0
  67. data/ui/examples/clock.rb +58 -0
  68. data/ui/examples/counter.rb +123 -0
  69. data/ui/examples/dynamic.rb +147 -0
  70. data/ui/examples/foobar.rb +236 -0
  71. data/ui/examples/stock.rb +115 -0
  72. data/ui/examples/stock_decider/option.rb +74 -0
  73. data/ui/examples/tic_tac_toe.rb +246 -0
  74. data/ui/lib/lib_hokusai.rb +425 -0
  75. data/ui/spec/hokusai/ast_spec.rb +88 -0
  76. data/ui/spec/hokusai/automation/keys_transcoder_spec.rb +50 -0
  77. data/ui/spec/hokusai/automation/selector_spec.rb +68 -0
  78. data/ui/spec/hokusai/block_spec.rb +126 -0
  79. data/ui/spec/hokusai/directives_spec.rb +327 -0
  80. data/ui/spec/hokusai/e2e/client_spec.rb +58 -0
  81. data/ui/spec/hokusai/e2e/meta_spec.rb +42 -0
  82. data/ui/spec/hokusai/publisher_spec.rb +38 -0
  83. data/ui/spec/hokusai/slots_spec.rb +150 -0
  84. data/ui/spec/hokusai/util/piece_table_spec.rb +90 -0
  85. data/ui/spec/hokusai_spec.rb +0 -0
  86. data/ui/spec/spec_helper.rb +30 -0
  87. data/ui/src/hokusai/ast.rb +446 -0
  88. data/ui/src/hokusai/automation/client.rb +167 -0
  89. data/ui/src/hokusai/automation/constants.rb +98 -0
  90. data/ui/src/hokusai/automation/converters/selector_converter.rb +61 -0
  91. data/ui/src/hokusai/automation/driver.rb +54 -0
  92. data/ui/src/hokusai/automation/driver_command_queue.rb +50 -0
  93. data/ui/src/hokusai/automation/driver_commands/base.rb +79 -0
  94. data/ui/src/hokusai/automation/driver_commands/get_attribute.rb +41 -0
  95. data/ui/src/hokusai/automation/driver_commands/invoke.rb +33 -0
  96. data/ui/src/hokusai/automation/driver_commands/locate.rb +48 -0
  97. data/ui/src/hokusai/automation/driver_commands/trigger_keyboard.rb +94 -0
  98. data/ui/src/hokusai/automation/driver_commands/trigger_mouse.rb +213 -0
  99. data/ui/src/hokusai/automation/keys_transcoder.rb +128 -0
  100. data/ui/src/hokusai/automation/selector.rb +39 -0
  101. data/ui/src/hokusai/automation/server.rb +114 -0
  102. data/ui/src/hokusai/automation.rb +3 -0
  103. data/ui/src/hokusai/backends/raylib/config.rb +47 -0
  104. data/ui/src/hokusai/backends/raylib/font.rb +113 -0
  105. data/ui/src/hokusai/backends/raylib/keys.rb +124 -0
  106. data/ui/src/hokusai/backends/raylib.rb +449 -0
  107. data/ui/src/hokusai/backends/sdl2/Monaco.ttf +0 -0
  108. data/ui/src/hokusai/backends/sdl2/color.rb +12 -0
  109. data/ui/src/hokusai/backends/sdl2/config.rb +31 -0
  110. data/ui/src/hokusai/backends/sdl2/font.rb +127 -0
  111. data/ui/src/hokusai/backends/sdl2/keys.rb +119 -0
  112. data/ui/src/hokusai/backends/sdl2.rb +529 -0
  113. data/ui/src/hokusai/block.rb +237 -0
  114. data/ui/src/hokusai/blocks/button.rb +100 -0
  115. data/ui/src/hokusai/blocks/checkbox.rb +51 -0
  116. data/ui/src/hokusai/blocks/circle.rb +28 -0
  117. data/ui/src/hokusai/blocks/clipped.rb +23 -0
  118. data/ui/src/hokusai/blocks/cursor.rb +49 -0
  119. data/ui/src/hokusai/blocks/dynamic.rb +37 -0
  120. data/ui/src/hokusai/blocks/empty.rb +10 -0
  121. data/ui/src/hokusai/blocks/hblock.rb +35 -0
  122. data/ui/src/hokusai/blocks/image.rb +18 -0
  123. data/ui/src/hokusai/blocks/input.rb +200 -0
  124. data/ui/src/hokusai/blocks/label.rb +39 -0
  125. data/ui/src/hokusai/blocks/panel.rb +126 -0
  126. data/ui/src/hokusai/blocks/rect.rb +24 -0
  127. data/ui/src/hokusai/blocks/scissor_begin.rb +18 -0
  128. data/ui/src/hokusai/blocks/scissor_end.rb +12 -0
  129. data/ui/src/hokusai/blocks/scrollbar.rb +103 -0
  130. data/ui/src/hokusai/blocks/selectable.rb +77 -0
  131. data/ui/src/hokusai/blocks/svg.rb +20 -0
  132. data/ui/src/hokusai/blocks/text.rb +214 -0
  133. data/ui/src/hokusai/blocks/titlebar/osx.rb +145 -0
  134. data/ui/src/hokusai/blocks/toggle.rb +55 -0
  135. data/ui/src/hokusai/blocks/vblock.rb +35 -0
  136. data/ui/src/hokusai/commands/base.rb +22 -0
  137. data/ui/src/hokusai/commands/circle.rb +47 -0
  138. data/ui/src/hokusai/commands/image.rb +45 -0
  139. data/ui/src/hokusai/commands/rect.rb +158 -0
  140. data/ui/src/hokusai/commands/scissor.rb +22 -0
  141. data/ui/src/hokusai/commands/text.rb +92 -0
  142. data/ui/src/hokusai/commands.rb +87 -0
  143. data/ui/src/hokusai/diff.rb +124 -0
  144. data/ui/src/hokusai/error.rb +3 -0
  145. data/ui/src/hokusai/event.rb +54 -0
  146. data/ui/src/hokusai/events/keyboard.rb +84 -0
  147. data/ui/src/hokusai/events/mouse.rb +172 -0
  148. data/ui/src/hokusai/font.rb +280 -0
  149. data/ui/src/hokusai/meta.rb +152 -0
  150. data/ui/src/hokusai/mounting/loop_entry.rb +230 -0
  151. data/ui/src/hokusai/mounting/mount_entry.rb +74 -0
  152. data/ui/src/hokusai/mounting/update_entry.rb +101 -0
  153. data/ui/src/hokusai/node.rb +98 -0
  154. data/ui/src/hokusai/node_mounter.rb +102 -0
  155. data/ui/src/hokusai/painter.rb +214 -0
  156. data/ui/src/hokusai/publisher.rb +32 -0
  157. data/ui/src/hokusai/style.rb +72 -0
  158. data/ui/src/hokusai/types.rb +266 -0
  159. data/ui/src/hokusai/util/clamping_iterator.rb +202 -0
  160. data/ui/src/hokusai/util/piece_table.rb +111 -0
  161. data/ui/src/hokusai/util/selection.rb +145 -0
  162. data/ui/src/hokusai.rb +120 -0
  163. data/ui/vendor/.gitkeep +0 -0
  164. data/vendor/.gitkeep +0 -0
  165. data/xmake.lua +192 -0
  166. metadata +222 -0
@@ -0,0 +1,42 @@
1
+ describe Hokusai::Meta do
2
+ let(:app) do
3
+ Class.new(Hokusai::Block) do
4
+ template <<~EOF
5
+ [template]
6
+ hblock#focus
7
+ empty#first
8
+ empty#second
9
+ hblock#unfocus
10
+ empty#third
11
+ empty#fourth
12
+ EOF
13
+
14
+ uses(
15
+ hblock: Hokusai::Blocks::Hblock,
16
+ empty: Hokusai::Blocks::Empty
17
+ )
18
+ end
19
+ end
20
+
21
+ describe "focusing" do
22
+ it "#focus focuses this block and all of it's children" do
23
+ with_app(app) do |client, app|
24
+ child_to_focus = app.children.first
25
+ child_to_focus.node.meta.focus
26
+
27
+ expect(child_to_focus.node.meta.focused).to be(true)
28
+
29
+ child_to_focus.children.each do |child|
30
+ expect(child.node.meta.focused).to be(true)
31
+ end
32
+
33
+ child_unfocused = app.children.last
34
+ expect(child_unfocused.node.meta.focused).to be(false)
35
+
36
+ child_unfocused.children.each do |child|
37
+ expect(child.node.meta.focused).to be(false)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "../spec_helper"
2
+
3
+ describe Hokusai::Publisher do
4
+ let!(:mock) do
5
+ ->(&block) do
6
+ klass = Class.new do
7
+ attr_reader :state, :publisher
8
+ def initialize
9
+ @state = []
10
+ @publisher = Hokusai::Publisher.new
11
+ end
12
+
13
+ def target(name)
14
+ @state << name
15
+ end
16
+ end
17
+
18
+ block.call klass.new
19
+ end
20
+ end
21
+
22
+ it "publishes events from a child node to it's parent" do
23
+ mock.call do |parent|
24
+ mock.call do |child|
25
+ child.publisher.add(parent)
26
+ child.publisher.notify(:target, "one")
27
+ child.publisher.notify(:target, "two")
28
+ end
29
+
30
+ mock.call do |child|
31
+ child.publisher.add(parent)
32
+ child.publisher.notify(:target, "three")
33
+ end
34
+
35
+ expect(parent.state).to eq(["one", "two", "three"])
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,150 @@
1
+ require_relative "../spec_helper"
2
+
3
+ describe "Slots" do
4
+
5
+ let(:virtual) do
6
+ klass = Class.new(Hokusai::Block) do
7
+ template <<~EOF
8
+ [template]
9
+ virtual
10
+ EOF
11
+ end
12
+
13
+ klass
14
+ end
15
+
16
+ describe "Basic" do
17
+
18
+ let(:slotted) do
19
+ virtual_klass = virtual
20
+
21
+ klass = Class.new(Hokusai::Block) do
22
+ template <<~EOF
23
+ [template]
24
+ sibling1
25
+ slot
26
+ sibling2
27
+ EOF
28
+
29
+ uses(sibling1: virtual_klass, sibling2: virtual_klass)
30
+ end
31
+
32
+ klass
33
+ end
34
+
35
+ let(:root_klass) do
36
+ slotted_klass = slotted
37
+ virtual_klass = virtual
38
+ klass = Class.new(Hokusai::Block) do
39
+ template <<~EOF
40
+ [template]
41
+ slotted
42
+ between { :prop="id" @event="root_event" }
43
+ EOF
44
+
45
+ uses(slotted: slotted_klass, between: virtual_klass)
46
+
47
+ attr_accessor :id
48
+
49
+ def root_event(value)
50
+ self.id += value
51
+ end
52
+
53
+ def initialize(**args)
54
+ @id = 3
55
+
56
+ super
57
+ end
58
+ end
59
+
60
+ klass
61
+ end
62
+
63
+ it "mounts portaled children inside slot" do
64
+ root = root_klass.mount
65
+ expect(root.children.size).to eq(1)
66
+
67
+ child = root.children.first
68
+ expect(child.node.type).to eq('slotted')
69
+
70
+ sibling_types = child.children.map {|c| c.node.type }
71
+
72
+ expect(sibling_types).to eq(["sibling1", "between", "sibling2"])
73
+ end
74
+
75
+ it "slotted blocks have access to their parent data and events" do
76
+ root = root_klass.mount
77
+ between = root.children.first.children[1]
78
+ expect(between.node.meta.props[:prop]).to eq(3)
79
+ between.emit("event", 2)
80
+ expect(root.id).to eq(5)
81
+ end
82
+ end
83
+
84
+ describe "Nested" do
85
+ let(:slot) do
86
+ klass = Class.new(Hokusai::Block) do
87
+ template <<~EOF
88
+ [template]
89
+ slot
90
+ EOF
91
+ end
92
+
93
+ klass
94
+ end
95
+
96
+ let(:nested) do
97
+ slot_klass = slot
98
+ virtual_klass = virtual
99
+ klass = Class.new(Hokusai::Block) do
100
+ template <<~EOF
101
+ [template]
102
+ empty
103
+ slot
104
+ virtual
105
+ EOF
106
+
107
+ uses(empty: slot_klass, virtual: virtual_klass)
108
+ end
109
+
110
+ klass
111
+ end
112
+
113
+ let(:root_klass) do
114
+ nested_klass = nested
115
+ virtual_klass = virtual
116
+ klass = Class.new(Hokusai::Block) do
117
+ template <<~EOF
118
+ [template]
119
+ first { prop="first"}
120
+ nested
121
+ second { prop="second" }
122
+ third { prop="third" }
123
+ EOF
124
+
125
+ uses(first: virtual_klass, nested: nested_klass, second: virtual_klass, third: virtual_klass)
126
+ end
127
+
128
+ klass
129
+ end
130
+
131
+ it "slots can be nested" do
132
+ root = root_klass.mount
133
+
134
+ expect(root.children.size).to eq(3)
135
+ empty = root.children[1].children.first
136
+
137
+ expect(empty.node.type).to eq("empty")
138
+
139
+ second = empty.children.first
140
+ expect(second.node.type).to eq("second")
141
+
142
+ expect(second.node.meta.props[:prop]).to eq("second")
143
+
144
+ children = root.children
145
+ expect(children.first.node.meta.props[:prop]).to eq("first")
146
+
147
+ expect(children.last.node.meta.props[:prop]).to eq("third")
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,90 @@
1
+ describe Hokusai::Util::PieceTable do
2
+ def with_piece_table(initial = "")
3
+ table = Hokusai::Util::PieceTable.new(initial)
4
+
5
+ yield table
6
+ end
7
+
8
+ describe "with no initial buffer" do
9
+ it "inserts correctly" do
10
+ with_piece_table do |table|
11
+ table.insert("hello", 0)
12
+ table.insert(" ", 5)
13
+ table.insert("world", 6)
14
+ expect(table.to_s).to eq("hello world")
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "with buffer" do
20
+ it "#insert at the start of a string" do
21
+ with_piece_table("hello world") do |table|
22
+ table.insert("ok ", 0)
23
+ expect(table.to_s).to eq("ok hello world")
24
+ end
25
+ end
26
+
27
+ it "#insert in the middle of a string" do
28
+ with_piece_table("hello world") do |table|
29
+ table.insert("big ", 6)
30
+ expect(table.to_s).to eq("hello big world")
31
+ end
32
+ end
33
+
34
+ it "#insert at the end of a string" do
35
+ with_piece_table("hello world") do |table|
36
+ table.insert(" ok?", 11)
37
+ expect(table.to_s).to eq("hello world ok?")
38
+ end
39
+ end
40
+
41
+ it "double insert" do
42
+ with_piece_table("hello world") do |table|
43
+ table.insert(" big", 5)
44
+ table.insert(" again", 5)
45
+ expect(table.to_s).to eq("hello again big world")
46
+ end
47
+ end
48
+
49
+ it "delete at the start of a string" do
50
+ with_piece_table("hello world") do |table|
51
+ table.delete(0, 6)
52
+ expect(table.to_s).to eq("world")
53
+ end
54
+ end
55
+
56
+ it "delete at the end of a string" do
57
+ with_piece_table("hello world") do |table|
58
+ table.delete(5, 6)
59
+ expect(table.to_s).to eq("hello")
60
+ end
61
+ end
62
+
63
+ it "delete in the middle of a string" do
64
+ with_piece_table("hello world") do |table|
65
+ table.delete(5, 1)
66
+ expect(table.to_s).to eq("helloworld")
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "error cases" do
72
+ it "#insert wrong initial offset" do
73
+ with_piece_table("hello world") do |table|
74
+ expect { table.insert("boo", 20) }.to raise_error(Hokusai::Error)
75
+ end
76
+ end
77
+
78
+ it "#delete wrong offset" do
79
+ with_piece_table("hello world") do |table|
80
+ expect { table.delete(20, 1) }.to raise_error(Hokusai::Error)
81
+ end
82
+ end
83
+
84
+ it "#delete wrong size" do
85
+ with_piece_table("hello world") do |table|
86
+ expect { table.delete(5, 20) }.to raise_error(Hokusai::Error)
87
+ end
88
+ end
89
+ end
90
+ end
File without changes
@@ -0,0 +1,30 @@
1
+ require_relative "../src/hokusai"
2
+ require_relative "../src/hokusai/backends/raylib"
3
+ require_relative "../src/hokusai/automation"
4
+ require "thread"
5
+
6
+ def with_app(app, &block)
7
+ driver = Hokusai::Automation::Driver.new
8
+
9
+ backend = Hokusai::Backends::RaylibBackend.new do |config|
10
+ config.automate("localhost", 3000)
11
+ config.automation_driver = driver
12
+
13
+ config.width = 500
14
+ config.height = 500
15
+ config.title = "Test application"
16
+ end
17
+
18
+ block = app.mount
19
+
20
+ Hokusai::ThreadPool.post do
21
+ backend.run(block)
22
+ end
23
+
24
+ client = Hokusai::Automation::Client.start
25
+ yield client, block
26
+
27
+ backend.class.stop!
28
+
29
+ client.wait_until_stopped
30
+ end