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.
- checksums.yaml +7 -0
- data/Dockerfile +26 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +91 -0
- data/LICENSE +21 -0
- data/README.md +28 -0
- data/ast/genheader +3 -0
- data/ast/include/hashmap.c +1151 -0
- data/ast/include/hashmap.c.license +20 -0
- data/ast/include/hashmap.h +54 -0
- data/ast/src/core/ast.c +448 -0
- data/ast/src/core/ast.h +259 -0
- data/ast/src/core/common.h +24 -0
- data/ast/src/core/component.c +85 -0
- data/ast/src/core/component.h +35 -0
- data/ast/src/core/hml.c +665 -0
- data/ast/src/core/hml.h +11 -0
- data/ast/src/core/input.c +458 -0
- data/ast/src/core/input.h +118 -0
- data/ast/src/core/style.c +101 -0
- data/ast/src/core/style.h +41 -0
- data/ast/src/core/text.c +784 -0
- data/ast/src/core/text.h +93 -0
- data/ast/src/core/util.c +140 -0
- data/ast/src/core/util.h +48 -0
- data/ast/src/hokusai.c +6 -0
- data/ast/src/hokusai.h +6 -0
- data/ast/test/fixtures/test.ui +13 -0
- data/ast/test/greatest.h +1266 -0
- data/ast/test/hokusai.c +14 -0
- data/ast/test/parser.c +234 -0
- data/ast/test/text.c +116 -0
- data/ext/extconf.rb +27 -0
- data/grammar/Cargo.lock +80 -0
- data/grammar/Cargo.toml +26 -0
- data/grammar/binding.gyp +20 -0
- data/grammar/bindings/node/binding.cc +28 -0
- data/grammar/bindings/node/index.js +19 -0
- data/grammar/bindings/rust/build.rs +40 -0
- data/grammar/bindings/rust/lib.rs +52 -0
- data/grammar/corpus/1_document.txt +131 -0
- data/grammar/corpus/2_selectors.txt +58 -0
- data/grammar/corpus/3_spaces.txt +69 -0
- data/grammar/corpus/4_errors.txt +10 -0
- data/grammar/corpus/5_macros.txt +175 -0
- data/grammar/corpus/6_styles.txt +81 -0
- data/grammar/grammar.js +275 -0
- data/grammar/package-lock.json +34 -0
- data/grammar/package.json +33 -0
- data/grammar/src/grammar.json +1269 -0
- data/grammar/src/node-types.json +474 -0
- data/grammar/src/parser.c +5772 -0
- data/grammar/src/scanner.c +258 -0
- data/grammar/src/tree_sitter/parser.h +230 -0
- data/grammar/src/tree_sitter/scanner.h +12 -0
- data/grammar/test.nml +10 -0
- data/hokusai.gemspec +19 -0
- data/ui/examples/assets/DigitalDisplay.ttf +0 -0
- data/ui/examples/assets/OpenSans-Regular.ttf +0 -0
- data/ui/examples/assets/addy.png +0 -0
- data/ui/examples/assets/baby_sean.png +0 -0
- data/ui/examples/assets/football-troll.png +0 -0
- data/ui/examples/assets/gear.png +0 -0
- data/ui/examples/assets/icecold.ttf +0 -0
- data/ui/examples/assets/science-troll.png +0 -0
- data/ui/examples/buddy.rb +31 -0
- data/ui/examples/clock.rb +58 -0
- data/ui/examples/counter.rb +123 -0
- data/ui/examples/dynamic.rb +147 -0
- data/ui/examples/foobar.rb +236 -0
- data/ui/examples/stock.rb +115 -0
- data/ui/examples/stock_decider/option.rb +74 -0
- data/ui/examples/tic_tac_toe.rb +246 -0
- data/ui/lib/lib_hokusai.rb +425 -0
- data/ui/spec/hokusai/ast_spec.rb +88 -0
- data/ui/spec/hokusai/automation/keys_transcoder_spec.rb +50 -0
- data/ui/spec/hokusai/automation/selector_spec.rb +68 -0
- data/ui/spec/hokusai/block_spec.rb +126 -0
- data/ui/spec/hokusai/directives_spec.rb +327 -0
- data/ui/spec/hokusai/e2e/client_spec.rb +58 -0
- data/ui/spec/hokusai/e2e/meta_spec.rb +42 -0
- data/ui/spec/hokusai/publisher_spec.rb +38 -0
- data/ui/spec/hokusai/slots_spec.rb +150 -0
- data/ui/spec/hokusai/util/piece_table_spec.rb +90 -0
- data/ui/spec/hokusai_spec.rb +0 -0
- data/ui/spec/spec_helper.rb +30 -0
- data/ui/src/hokusai/ast.rb +446 -0
- data/ui/src/hokusai/automation/client.rb +167 -0
- data/ui/src/hokusai/automation/constants.rb +98 -0
- data/ui/src/hokusai/automation/converters/selector_converter.rb +61 -0
- data/ui/src/hokusai/automation/driver.rb +54 -0
- data/ui/src/hokusai/automation/driver_command_queue.rb +50 -0
- data/ui/src/hokusai/automation/driver_commands/base.rb +79 -0
- data/ui/src/hokusai/automation/driver_commands/get_attribute.rb +41 -0
- data/ui/src/hokusai/automation/driver_commands/invoke.rb +33 -0
- data/ui/src/hokusai/automation/driver_commands/locate.rb +48 -0
- data/ui/src/hokusai/automation/driver_commands/trigger_keyboard.rb +94 -0
- data/ui/src/hokusai/automation/driver_commands/trigger_mouse.rb +213 -0
- data/ui/src/hokusai/automation/keys_transcoder.rb +128 -0
- data/ui/src/hokusai/automation/selector.rb +39 -0
- data/ui/src/hokusai/automation/server.rb +114 -0
- data/ui/src/hokusai/automation.rb +3 -0
- data/ui/src/hokusai/backends/raylib/config.rb +47 -0
- data/ui/src/hokusai/backends/raylib/font.rb +113 -0
- data/ui/src/hokusai/backends/raylib/keys.rb +124 -0
- data/ui/src/hokusai/backends/raylib.rb +449 -0
- data/ui/src/hokusai/backends/sdl2/Monaco.ttf +0 -0
- data/ui/src/hokusai/backends/sdl2/color.rb +12 -0
- data/ui/src/hokusai/backends/sdl2/config.rb +31 -0
- data/ui/src/hokusai/backends/sdl2/font.rb +127 -0
- data/ui/src/hokusai/backends/sdl2/keys.rb +119 -0
- data/ui/src/hokusai/backends/sdl2.rb +529 -0
- data/ui/src/hokusai/block.rb +237 -0
- data/ui/src/hokusai/blocks/button.rb +100 -0
- data/ui/src/hokusai/blocks/checkbox.rb +51 -0
- data/ui/src/hokusai/blocks/circle.rb +28 -0
- data/ui/src/hokusai/blocks/clipped.rb +23 -0
- data/ui/src/hokusai/blocks/cursor.rb +49 -0
- data/ui/src/hokusai/blocks/dynamic.rb +37 -0
- data/ui/src/hokusai/blocks/empty.rb +10 -0
- data/ui/src/hokusai/blocks/hblock.rb +35 -0
- data/ui/src/hokusai/blocks/image.rb +18 -0
- data/ui/src/hokusai/blocks/input.rb +200 -0
- data/ui/src/hokusai/blocks/label.rb +39 -0
- data/ui/src/hokusai/blocks/panel.rb +126 -0
- data/ui/src/hokusai/blocks/rect.rb +24 -0
- data/ui/src/hokusai/blocks/scissor_begin.rb +18 -0
- data/ui/src/hokusai/blocks/scissor_end.rb +12 -0
- data/ui/src/hokusai/blocks/scrollbar.rb +103 -0
- data/ui/src/hokusai/blocks/selectable.rb +77 -0
- data/ui/src/hokusai/blocks/svg.rb +20 -0
- data/ui/src/hokusai/blocks/text.rb +214 -0
- data/ui/src/hokusai/blocks/titlebar/osx.rb +145 -0
- data/ui/src/hokusai/blocks/toggle.rb +55 -0
- data/ui/src/hokusai/blocks/vblock.rb +35 -0
- data/ui/src/hokusai/commands/base.rb +22 -0
- data/ui/src/hokusai/commands/circle.rb +47 -0
- data/ui/src/hokusai/commands/image.rb +45 -0
- data/ui/src/hokusai/commands/rect.rb +158 -0
- data/ui/src/hokusai/commands/scissor.rb +22 -0
- data/ui/src/hokusai/commands/text.rb +92 -0
- data/ui/src/hokusai/commands.rb +87 -0
- data/ui/src/hokusai/diff.rb +124 -0
- data/ui/src/hokusai/error.rb +3 -0
- data/ui/src/hokusai/event.rb +54 -0
- data/ui/src/hokusai/events/keyboard.rb +84 -0
- data/ui/src/hokusai/events/mouse.rb +172 -0
- data/ui/src/hokusai/font.rb +280 -0
- data/ui/src/hokusai/meta.rb +152 -0
- data/ui/src/hokusai/mounting/loop_entry.rb +230 -0
- data/ui/src/hokusai/mounting/mount_entry.rb +74 -0
- data/ui/src/hokusai/mounting/update_entry.rb +101 -0
- data/ui/src/hokusai/node.rb +98 -0
- data/ui/src/hokusai/node_mounter.rb +102 -0
- data/ui/src/hokusai/painter.rb +214 -0
- data/ui/src/hokusai/publisher.rb +32 -0
- data/ui/src/hokusai/style.rb +72 -0
- data/ui/src/hokusai/types.rb +266 -0
- data/ui/src/hokusai/util/clamping_iterator.rb +202 -0
- data/ui/src/hokusai/util/piece_table.rb +111 -0
- data/ui/src/hokusai/util/selection.rb +145 -0
- data/ui/src/hokusai.rb +120 -0
- data/ui/vendor/.gitkeep +0 -0
- data/vendor/.gitkeep +0 -0
- data/xmake.lua +192 -0
- metadata +222 -0
data/ast/test/hokusai.c
ADDED
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
|
data/grammar/Cargo.lock
ADDED
@@ -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
|
+
]
|
data/grammar/Cargo.toml
ADDED
@@ -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"
|
data/grammar/binding.gyp
ADDED
@@ -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
|
+
}
|