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,14 @@
1
+ #include "greatest.h"
2
+ #include "parser.c"
3
+ #include "text.c"
4
+
5
+ GREATEST_MAIN_DEFS();
6
+
7
+ int main(int argc, char** argv) {
8
+ GREATEST_MAIN_BEGIN();
9
+
10
+ RUN_SUITE(hoku_parser_suite);
11
+ RUN_SUITE(hoku_text_suite);
12
+
13
+ GREATEST_MAIN_END();
14
+ }
data/ast/test/parser.c ADDED
@@ -0,0 +1,234 @@
1
+ #include "../src/core/ast.c"
2
+ #include "../src/core/style.c"
3
+ #include "../src/core/hml.c"
4
+
5
+ void walk_tree(TSNode node, char* template, int level)
6
+ {
7
+ TSNode child;
8
+ uint32_t child_count = ts_node_child_count(node);
9
+ for (uint32_t i = 0; i < child_count; i++)
10
+ {
11
+ child = ts_node_child(node, i);
12
+ walk_tree(child, template, level + 1);
13
+ }
14
+ }
15
+
16
+ hoku_ast* parse_string(char* template)
17
+ {
18
+ hoku_ast* comp;
19
+ hoku_ast_from_template(&comp, "root", template);
20
+ return comp;
21
+ }
22
+
23
+ hoku_style* parse_style(char* template)
24
+ {
25
+ hoku_style* style;
26
+ int ret = hoku_style_from_template(&style, template);
27
+ if (ret != 0)
28
+ {
29
+ printf("FAILED STYLE PARSE");
30
+ return NULL;
31
+ }
32
+ }
33
+
34
+ TEST test_hoku_parse_macros()
35
+ {
36
+ char* template =
37
+ "[template]\n"
38
+ " [for=\"post in posts\"]\n"
39
+ " two\n"
40
+ " [if=\"truth\"]\n"
41
+ " three\n"
42
+ " [else]\n"
43
+ " four\n";
44
+
45
+ hoku_ast* root = parse_string(template);
46
+ ASSERT_STR_EQ("root", root->type);
47
+ hoku_ast* child1 = root->relations->next_child;
48
+ ASSERT_NEQ(NULL, child1->loop);
49
+ hoku_ast* child2 = child1->relations->next_child;
50
+ ASSERT_NEQ(NULL, child2->cond);
51
+ ASSERT_NEQ(NULL, child2->else_relations);
52
+
53
+ PASS();
54
+ }
55
+
56
+ TEST test_hoku_simple_if()
57
+ {
58
+ char* template =
59
+ "[template]\n"
60
+ " vblock\n"
61
+ " [if=\"state\"]\n"
62
+ " conda\n"
63
+ " [else]\n"
64
+ " condb\n"
65
+ " control\n";
66
+
67
+ hoku_ast* root = parse_string(template);
68
+
69
+ PASS();
70
+ }
71
+
72
+ TEST test_hoku_parse_style()
73
+ {
74
+ char* template =
75
+ "[style]\n"
76
+ "additionStyles {\n"
77
+ " background: color(67,99,168)\n"
78
+ " rounding: 0.0;\n"
79
+ "}\n";
80
+
81
+ hoku_style* root = parse_style(template);
82
+
83
+ PASS();
84
+ }
85
+
86
+
87
+ TEST test_hoku_parse_loop()
88
+ {
89
+ char* template =
90
+ "[template]\n"
91
+ " panel\n"
92
+ " [for=\"content in messages\"]\n"
93
+ " ptext\n"
94
+ " textfield";
95
+
96
+ hoku_ast* root = parse_string(template);
97
+ ASSERT_STR_EQ("root", root->type);
98
+ hoku_ast* child1 = root->relations->next_child;
99
+ ASSERT_STR_EQ("panel", child1->type);
100
+
101
+ hoku_ast* textfield = child1->relations->next_sibling;
102
+ ASSERT_NEQ(NULL, textfield);
103
+ ASSERT_STR_EQ("textfield", textfield->type);
104
+
105
+ hoku_ast* child2 = child1->relations->next_child;
106
+ ASSERT_NEQ(NULL, child2);
107
+ ASSERT_STR_EQ("ptext", child2->type);
108
+
109
+ PASS();
110
+ }
111
+
112
+ TEST test_hoku_parse_loop_if()
113
+ {
114
+ char* template =
115
+ "[template]\n"
116
+ " panel\n"
117
+ " [for=\"content in messages\"]\n"
118
+ " [if=\"is(item)\"]\n"
119
+ " ptext\n"
120
+ " [else]\n"
121
+ " textfield";
122
+
123
+ hoku_ast* root = parse_string(template);
124
+ hoku_dump(root, 0);
125
+
126
+ ASSERT_STR_EQ("root", root->type);
127
+ hoku_ast* child1 = root->relations->next_child;
128
+ ASSERT_STR_EQ("panel", child1->type);
129
+
130
+ hoku_ast* for_if = child1->relations->next_child;
131
+ ASSERT_NEQ(NULL, for_if);
132
+ ASSERT_STR_EQ("ptext", for_if->type);
133
+ ASSERT_NEQ(NULL, for_if->loop);
134
+ ASSERT_NEQ(NULL, for_if->cond);
135
+
136
+ PASS();
137
+ }
138
+
139
+ TEST test_hoku_parse_sibling_macros()
140
+ {
141
+ char* template =
142
+ "[template]\n"
143
+ " [for=\"post in posts\"]\n"
144
+ " two\n"
145
+ " [if=\"truth\"]\n"
146
+ " three\n"
147
+ " [else]\n"
148
+ " four\n";
149
+
150
+ hoku_ast* root = parse_string(template);
151
+ ASSERT_STR_EQ("root", root->type);
152
+ hoku_ast* child1 = root->relations->next_child;
153
+ ASSERT_STR_EQ("two", child1->type);
154
+ ASSERT_NEQ(NULL, child1->loop);
155
+ hoku_ast* child2 = child1->relations->next_child;
156
+ ASSERT_NEQ(NULL, child2->cond);
157
+ ASSERT_NEQ(NULL, child2->else_relations);
158
+ PASS();
159
+ }
160
+
161
+ TEST test_hoku_parse_basic()
162
+ {
163
+ char* template =
164
+ "[template]\n"
165
+ "child1#it.foo.bar { @click=\"handleClick(arg1, arg2)\", @hover=\"handleHover(one)\"}\n"
166
+ " grandchild1\n"
167
+ " grandchild2\n"
168
+ " great-grandchild1 {:prop=\"value\"}";
169
+
170
+ hoku_ast* root = parse_string(template);
171
+
172
+ ASSERT_STR_EQ("root", root->type);
173
+ hoku_ast* child1 = root->relations->next_child;
174
+ ASSERT_STR_EQ("child1", child1->type);
175
+ ASSERT_NEQ(NULL, child1->id);
176
+ ASSERT_EQ(NULL, child1->error);
177
+ ASSERT_STR_EQ("it", child1->id);
178
+ ASSERT_EQ(true, hoku_ast_class_list_includes(child1, "foo"));
179
+ ASSERT_EQ(true, hoku_ast_class_list_includes(child1, "bar"));
180
+ ASSERT_EQ(false, hoku_ast_class_list_includes(child1, "baz"));
181
+ ASSERT_EQ_FMT(2, child1->child_len, "%d");
182
+ ASSERT_EQ_FMT(2, hoku_ast_events_count(child1), "%d");
183
+ ASSERT_EQ_FMT(0, hoku_ast_props_count(child1), "%d");
184
+ ASSERT_EQ(NULL, child1->relations->next_sibling);
185
+
186
+ hoku_ast_event* click = hoku_ast_get_event(child1, &(hoku_ast_event){.name="click"});
187
+ ASSERT_NEQ(NULL, click);
188
+ ASSERT_EQ_FMT(2, click->call->args_len, "%d");
189
+ ASSERT_STR_EQ("handleClick", click->call->function);
190
+ ASSERT_STR_EQ("arg1", click->call->strargs[0]);
191
+ ASSERT_STR_EQ("arg2", click->call->strargs[1]);
192
+
193
+ hoku_ast_event* hover = hoku_ast_get_event(child1, &(hoku_ast_event){.name="hover"});
194
+ ASSERT_NEQ(NULL, hover);
195
+ ASSERT_STR_EQ("handleHover", hover->call->function);
196
+ ASSERT_EQ_FMT(1, hover->call->args_len, "%d");
197
+ ASSERT_STR_EQ("one" , hover->call->strargs[0]);
198
+
199
+ hoku_ast* gchild1 = child1->relations->next_child;
200
+ ASSERT_STR_EQ("grandchild1", gchild1->type);
201
+ ASSERT_EQ_FMT(0, hoku_ast_events_count(gchild1), "%d");
202
+ ASSERT_EQ_FMT(0, hoku_ast_props_count(gchild1), "%d");
203
+ ASSERT_EQ_FMT(0, gchild1->child_len, "%d");
204
+
205
+ hoku_ast* gchild2 = gchild1->relations->next_sibling;
206
+ ASSERT_NEQ(NULL, gchild2);
207
+ ASSERT_STR_EQ("grandchild2", gchild2->type);
208
+ ASSERT_EQ_FMT(1, gchild2->child_len, "%d");
209
+ ASSERT_EQ(NULL, gchild2->relations->next_sibling);
210
+
211
+ hoku_ast* ggchild1 = gchild2->relations->next_child;
212
+ ASSERT_STR_EQ("great-grandchild1", ggchild1->type);
213
+ ASSERT_EQ(NULL, ggchild1->relations->next_child);
214
+ ASSERT_EQ(NULL, ggchild1->relations->next_sibling);
215
+ ASSERT_EQ_FMT(1, hoku_ast_props_count(ggchild1), "%d");
216
+ hoku_ast_prop* prop = hoku_ast_get_prop(ggchild1, &(hoku_ast_prop){.name="prop"});
217
+ ASSERT_NEQ(NULL, prop);
218
+ ASSERT_EQ_FMT(true, prop->computed, "%d");
219
+ ASSERT_STR_EQ("prop", prop->name);
220
+ ASSERT_EQ_FMT(0, prop->call->args_len, "%d");
221
+ ASSERT_STR_EQ("value", prop->call->function);
222
+
223
+ PASS();
224
+ }
225
+
226
+ SUITE(hoku_parser_suite)
227
+ {
228
+ RUN_TEST(test_hoku_parse_basic);
229
+ RUN_TEST(test_hoku_parse_macros);
230
+ RUN_TEST(test_hoku_parse_loop);
231
+ RUN_TEST(test_hoku_parse_loop_if);
232
+ RUN_TEST(test_hoku_parse_style);
233
+ // RUN_TEST(test_hoku_simple_if);
234
+ }
data/ast/test/text.c ADDED
@@ -0,0 +1,116 @@
1
+ #include "../src/core/text.c"
2
+
3
+ int test_char_width_cb(char letter, void* payload)
4
+ {
5
+ return 2;
6
+ }
7
+
8
+ TEST test_hoku_clamp_basic()
9
+ {
10
+ hoku_clamping* clamp;
11
+ int ret = hoku_text_clamp(&clamp, "aabbcc", 4, 0.0, NULL, test_char_width_cb);
12
+ ASSERT_EQ_FMT(0, ret, "%d");
13
+
14
+ hoku_text_clamp_debug(clamp);
15
+
16
+ hoku_segment* seg = clamp->segments;
17
+ hoku_char* chr;
18
+
19
+ int i;
20
+ for (i = 0; i < 2; i++)
21
+ {
22
+ ASSERT_NEQ(NULL, seg);
23
+ ASSERT_EQ_FMT(i * 2, seg->offset, "%d");
24
+ ASSERT_EQ_FMT(2, seg->size, "%d");
25
+
26
+ chr = seg->chars;
27
+
28
+ // validate chars
29
+ int d;
30
+ for (d = 0; d < 2; d++)
31
+ {
32
+
33
+ printf("[seg: %d] %d\n", i, d);
34
+ ASSERT_NEQ(NULL, chr);
35
+ ASSERT_EQ_FMT(i * 2 + d, chr->offset, "%d");
36
+ ASSERT_EQ_FMT(2, seg->size, "%d");
37
+
38
+ chr = chr->next_char;
39
+ }
40
+
41
+ seg = seg->next_segment;
42
+ }
43
+
44
+ PASS();
45
+ }
46
+
47
+ TEST test_hoku_clamp_newline()
48
+ {
49
+ hoku_clamping* clamp;
50
+ int ret = hoku_text_clamp(&clamp, "aab\nbcc", 4, 0.0, NULL, test_char_width_cb);
51
+ ASSERT_EQ_FMT(0, ret, "%d");
52
+
53
+ hoku_text_clamp_debug(clamp);
54
+ PASS();
55
+ }
56
+
57
+ TEST test_hoku_clamp_wrap()
58
+ {
59
+ hoku_clamping* clamp;
60
+ int ret = hoku_text_clamp(&clamp, "the quick brown fox jumped over the yellow dog", 4, 0.0, NULL, test_char_width_cb);
61
+ ASSERT_EQ_FMT(0, ret, "%d");
62
+
63
+ hoku_text_clamp_debug(clamp);
64
+ PASS();
65
+ }
66
+
67
+ TEST test_hoku_clamp_file()
68
+ {
69
+ char *buffer;
70
+ FILE *fh = fopen("ui/examples/foobar.rb", "rb");
71
+ if ( fh != NULL )
72
+ {
73
+ fseek(fh, 0L, SEEK_END);
74
+ long s = ftell(fh);
75
+ rewind(fh);
76
+ buffer = malloc(s);
77
+ if ( buffer != NULL )
78
+ {
79
+ fread(buffer, s, 1, fh);
80
+ // we can now close the file
81
+ fclose(fh); fh = NULL;
82
+
83
+ printf("%s\n", buffer);
84
+
85
+ hoku_clamping* clamp;
86
+ int ret = hoku_text_clamp(&clamp, buffer, 400, 0.0, NULL, test_char_width_cb);
87
+ ASSERT_EQ_FMT(0, ret, "%d");
88
+
89
+ // hoku_text_clamp_debug(clamp);
90
+ }
91
+ else
92
+ {
93
+ perror("Bad");
94
+ }
95
+ }
96
+
97
+ PASS();
98
+ }
99
+
100
+ TEST test_hoku_clamp_markdown()
101
+ {
102
+ hoku_clamping* clamp;
103
+ int ret = hoku_text_md_clamp(&clamp, "hello _world_\nMy my **my**", 20, 0.0, NULL, test_char_width_cb);
104
+ ASSERT_EQ_FMT(0, ret, "%d");
105
+ printf("clamp text: %s\n", clamp->text);
106
+ PASS();
107
+
108
+ }
109
+
110
+ SUITE(hoku_text_suite)
111
+ {
112
+ RUN_TEST(test_hoku_clamp_basic);
113
+ RUN_TEST(test_hoku_clamp_markdown);
114
+ // RUN_TEST(test_hoku_clamp_newline);
115
+ // RUN_TEST(test_hoku_clamp_file);
116
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "mkmf"
2
+
3
+ File.open("Makefile", "w") do |io|
4
+ io << <<~EOF
5
+ all: clean hokusai
6
+
7
+ install:
8
+ #{"\t"}echo "done"
9
+
10
+ vendor/lib/libtree-sitter.a:
11
+ #{"\t"}xmake q -y tree-sitter
12
+
13
+ vendor/lib/libmd4c.a:
14
+ #{"\t"}xmake q -y md4c
15
+
16
+ hokusai: vendor/lib/libmd4c.a vendor/lib/libtree-sitter.a
17
+ #{"\t"}xmake b -y hokusai
18
+
19
+ clean:
20
+ #{"\t"}xmake clean
21
+ #{"\t"}xmake q -y --uninstall tree-sitter
22
+ #{"\t"}xmake q -y --uninstall md4c
23
+ #{"\t"}rm -f vendor/lib/libhokusai.*
24
+ #{"\t"}rm -f vendor/lib/libmd4c.*
25
+ #{"\t"}rm -f vendor/lib/libtree-sitter.*
26
+ EOF
27
+ end
@@ -0,0 +1,80 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 3
4
+
5
+ [[package]]
6
+ name = "aho-corasick"
7
+ version = "1.1.2"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
10
+ dependencies = [
11
+ "memchr",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "cc"
16
+ version = "1.0.83"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
19
+ dependencies = [
20
+ "libc",
21
+ ]
22
+
23
+ [[package]]
24
+ name = "libc"
25
+ version = "0.2.153"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
28
+
29
+ [[package]]
30
+ name = "memchr"
31
+ version = "2.7.1"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
34
+
35
+ [[package]]
36
+ name = "regex"
37
+ version = "1.10.3"
38
+ source = "registry+https://github.com/rust-lang/crates.io-index"
39
+ checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
40
+ dependencies = [
41
+ "aho-corasick",
42
+ "memchr",
43
+ "regex-automata",
44
+ "regex-syntax",
45
+ ]
46
+
47
+ [[package]]
48
+ name = "regex-automata"
49
+ version = "0.4.5"
50
+ source = "registry+https://github.com/rust-lang/crates.io-index"
51
+ checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
52
+ dependencies = [
53
+ "aho-corasick",
54
+ "memchr",
55
+ "regex-syntax",
56
+ ]
57
+
58
+ [[package]]
59
+ name = "regex-syntax"
60
+ version = "0.8.2"
61
+ source = "registry+https://github.com/rust-lang/crates.io-index"
62
+ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
63
+
64
+ [[package]]
65
+ name = "tree-sitter"
66
+ version = "0.20.10"
67
+ source = "registry+https://github.com/rust-lang/crates.io-index"
68
+ checksum = "e747b1f9b7b931ed39a548c1fae149101497de3c1fc8d9e18c62c1a66c683d3d"
69
+ dependencies = [
70
+ "cc",
71
+ "regex",
72
+ ]
73
+
74
+ [[package]]
75
+ name = "tree-sitter-HML"
76
+ version = "0.0.1"
77
+ dependencies = [
78
+ "cc",
79
+ "tree-sitter",
80
+ ]
@@ -0,0 +1,26 @@
1
+ [package]
2
+ name = "tree-sitter-HML"
3
+ description = "HML grammar for the tree-sitter parsing library"
4
+ version = "0.0.1"
5
+ keywords = ["incremental", "parsing", "HML"]
6
+ categories = ["parsing", "text-editors"]
7
+ repository = "https://github.com/tree-sitter/tree-sitter-HML"
8
+ edition = "2018"
9
+ license = "MIT"
10
+
11
+ build = "bindings/rust/build.rs"
12
+ include = [
13
+ "bindings/rust/*",
14
+ "grammar.js",
15
+ "queries/*",
16
+ "src/*",
17
+ ]
18
+
19
+ [lib]
20
+ path = "bindings/rust/lib.rs"
21
+
22
+ [dependencies]
23
+ tree-sitter = "~0.20.10"
24
+
25
+ [build-dependencies]
26
+ cc = "1.0"
@@ -0,0 +1,20 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "tree_sitter_HML_binding",
5
+ "include_dirs": [
6
+ "<!(node -e \"require('nan')\")",
7
+ "src"
8
+ ],
9
+ "sources": [
10
+ "bindings/node/binding.cc",
11
+ "src/parser.c",
12
+ "src/scanner.c"
13
+ # If your language uses an external scanner, add it here.
14
+ ],
15
+ "cflags_c": [
16
+ "-std=c99",
17
+ ]
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,28 @@
1
+ #include "tree_sitter/parser.h"
2
+ #include <node.h>
3
+ #include "nan.h"
4
+
5
+ using namespace v8;
6
+
7
+ extern "C" TSLanguage * tree_sitter_HML();
8
+
9
+ namespace {
10
+
11
+ NAN_METHOD(New) {}
12
+
13
+ void Init(Local<Object> exports, Local<Object> module) {
14
+ Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
15
+ tpl->SetClassName(Nan::New("Language").ToLocalChecked());
16
+ tpl->InstanceTemplate()->SetInternalFieldCount(1);
17
+
18
+ Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
19
+ Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
20
+ Nan::SetInternalFieldPointer(instance, 0, tree_sitter_HML());
21
+
22
+ Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("HML").ToLocalChecked());
23
+ Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
24
+ }
25
+
26
+ NODE_MODULE(tree_sitter_HML_binding, Init)
27
+
28
+ } // namespace
@@ -0,0 +1,19 @@
1
+ try {
2
+ module.exports = require("../../build/Release/tree_sitter_HML_binding");
3
+ } catch (error1) {
4
+ if (error1.code !== 'MODULE_NOT_FOUND') {
5
+ throw error1;
6
+ }
7
+ try {
8
+ module.exports = require("../../build/Debug/tree_sitter_HML_binding");
9
+ } catch (error2) {
10
+ if (error2.code !== 'MODULE_NOT_FOUND') {
11
+ throw error2;
12
+ }
13
+ throw error1
14
+ }
15
+ }
16
+
17
+ try {
18
+ module.exports.nodeTypeInfo = require("../../src/node-types.json");
19
+ } catch (_) {}
@@ -0,0 +1,40 @@
1
+ fn main() {
2
+ let src_dir = std::path::Path::new("src");
3
+
4
+ let mut c_config = cc::Build::new();
5
+ c_config.include(&src_dir);
6
+ c_config
7
+ .flag_if_supported("-Wno-unused-parameter")
8
+ .flag_if_supported("-Wno-unused-but-set-variable")
9
+ .flag_if_supported("-Wno-trigraphs");
10
+ let parser_path = src_dir.join("parser.c");
11
+ c_config.file(&parser_path);
12
+
13
+ // If your language uses an external scanner written in C,
14
+ // then include this block of code:
15
+
16
+ /*
17
+ let scanner_path = src_dir.join("scanner.c");
18
+ c_config.file(&scanner_path);
19
+ println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
20
+ */
21
+
22
+ c_config.compile("parser");
23
+ println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
24
+
25
+ // If your language uses an external scanner written in C++,
26
+ // then include this block of code:
27
+
28
+ /*
29
+ let mut cpp_config = cc::Build::new();
30
+ cpp_config.cpp(true);
31
+ cpp_config.include(&src_dir);
32
+ cpp_config
33
+ .flag_if_supported("-Wno-unused-parameter")
34
+ .flag_if_supported("-Wno-unused-but-set-variable");
35
+ let scanner_path = src_dir.join("scanner.cc");
36
+ cpp_config.file(&scanner_path);
37
+ cpp_config.compile("scanner");
38
+ println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
39
+ */
40
+ }
@@ -0,0 +1,52 @@
1
+ //! This crate provides HML language support for the [tree-sitter][] parsing library.
2
+ //!
3
+ //! Typically, you will use the [language][language func] function to add this language to a
4
+ //! tree-sitter [Parser][], and then use the parser to parse some code:
5
+ //!
6
+ //! ```
7
+ //! let code = "";
8
+ //! let mut parser = tree_sitter::Parser::new();
9
+ //! parser.set_language(tree_sitter_HML::language()).expect("Error loading HML grammar");
10
+ //! let tree = parser.parse(code, None).unwrap();
11
+ //! ```
12
+ //!
13
+ //! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
14
+ //! [language func]: fn.language.html
15
+ //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
16
+ //! [tree-sitter]: https://tree-sitter.github.io/
17
+
18
+ use tree_sitter::Language;
19
+
20
+ extern "C" {
21
+ fn tree_sitter_HML() -> Language;
22
+ }
23
+
24
+ /// Get the tree-sitter [Language][] for this grammar.
25
+ ///
26
+ /// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
27
+ pub fn language() -> Language {
28
+ unsafe { tree_sitter_HML() }
29
+ }
30
+
31
+ /// The content of the [`node-types.json`][] file for this grammar.
32
+ ///
33
+ /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
34
+ pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
35
+
36
+ // Uncomment these to include any queries that this grammar contains
37
+
38
+ // pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
39
+ // pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
40
+ // pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
41
+ // pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
42
+
43
+ #[cfg(test)]
44
+ mod tests {
45
+ #[test]
46
+ fn test_can_load_grammar() {
47
+ let mut parser = tree_sitter::Parser::new();
48
+ parser
49
+ .set_language(super::language())
50
+ .expect("Error loading HML language");
51
+ }
52
+ }