Packages

Tree-sitter bindings (nif) for elixir. Currently small subset of the tree-sitter api is supported, but happy to accept merge requests/patches

Current section

6 Versions

Jump to

Compare versions

4 files changed
+145 additions
-27 deletions
  @@ -2,14 +2,14 @@
2 2 [{<<"issues">>,<<"https://codeberg.org/edwinvanl/treesitter_elixir/issues">>},
3 3 {<<"source">>,<<"https://codeberg.org/edwinvanl/treesitter_elixir">>}]}.
4 4 {<<"name">>,<<"treesitter_elixir">>}.
5 - {<<"version">>,<<"0.1.4">>}.
5 + {<<"version">>,<<"0.1.6">>}.
6 6 {<<"description">>,
7 7 <<"Tree-sitter bindings (nif) for elixir. Currently small subset of the tree-sitter api is supported, but happy to accept merge requests/patches">>}.
8 8 {<<"elixir">>,<<"~> 1.18">>}.
9 9 {<<"app">>,<<"treesitter_elixir">>}.
10 10 {<<"files">>,
11 - [<<"lib">>,<<"lib/treesitter">>,<<"lib/treesitter/node.ex">>,
12 - <<"lib/treesitter/querycursor.ex">>,<<"lib/treesitter.ex">>,
11 + [<<"lib">>,<<"lib/treesitter.ex">>,<<"lib/treesitter">>,
12 + <<"lib/treesitter/querycursor.ex">>,<<"lib/treesitter/node.ex">>,
13 13 <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"src">>,
14 14 <<"src/treesitter_nif.c">>,<<"Makefile">>]}.
15 15 {<<"licenses">>,[<<"MIT">>]}.
  @@ -78,6 +78,14 @@ defmodule TreeSitter.Nif do
78 78 :erlang.nif_error(:nif_not_loaded)
79 79 end
80 80
81 + def node_descendant_for_byte_range(_, _, _) do
82 + :erlang.nif_error(:nif_not_loaded)
83 + end
84 +
85 + def node_descendant_for_point_range(_, _, _) do
86 + :erlang.nif_error(:nif_not_loaded)
87 + end
88 +
81 89 def node_string(_) do
82 90 :erlang.nif_error(:nif_not_loaded)
83 91 end
  @@ -139,6 +147,18 @@ defmodule TreeSitter.Nif do
139 147 def query_cursor_set_byte_range(_, _, _) do
140 148 :erlang.nif_error(:nif_not_loaded)
141 149 end
150 +
151 + def query_cursor_set_containing_point_range(query, from, to)
152 +
153 + def query_cursor_set_containing_point_range(_, _, _) do
154 + :erlang.nif_error(:nif_not_loaded)
155 + end
156 +
157 + def query_cursor_set_containing_byte_range(query, from, to)
158 +
159 + def query_cursor_set_containing_byte_range(_, _, _) do
160 + :erlang.nif_error(:nif_not_loaded)
161 + end
142 162 end
143 163
144 164 defmodule TreeSitter.Application do
  @@ -6,7 +6,7 @@ defmodule Treesitter.MixProject do
6 6 app: :treesitter_elixir,
7 7 description:
8 8 "Tree-sitter bindings (nif) for elixir. Currently small subset of the tree-sitter api is supported, but happy to accept merge requests/patches",
9 - version: "0.1.4",
9 + version: "0.1.6",
10 10 elixir: "~> 1.18",
11 11 compilers: [:elixir_make] ++ Mix.compilers(),
12 12 start_permanent: Mix.env() == :prod,
  @@ -121,6 +121,28 @@ ERL_NIF_TERM to_ok_term(ErlNifEnv *env, ERL_NIF_TERM value) {
121 121 return enif_make_tuple2(env, enif_make_atom(env, "ok"), value);
122 122 }
123 123
124 + TSPoint point_from_map(ErlNifEnv *env, ERL_NIF_TERM map) {
125 + TSPoint pt;
126 + ERL_NIF_TERM row_term, column_term;
127 +
128 + // Get the row and column terms from the map
129 + if (!enif_get_map_value(env, map, enif_make_atom(env, "row"), &row_term) ||
130 + !enif_get_map_value(env, map, enif_make_atom(env, "column"),
131 + &column_term)) {
132 + // TODO: Handle error: keys not found in the map
133 + // You might want to return a default value or raise an error
134 + pt.row = 0;
135 + pt.column = 0;
136 + return pt;
137 + }
138 +
139 + // Get the integer values from the terms
140 + enif_get_uint(env, row_term, &pt.row);
141 + enif_get_uint(env, column_term, &pt.column);
142 +
143 + return pt;
144 + }
145 +
124 146 static ERL_NIF_TERM parser_new(ErlNifEnv *env, int argc,
125 147 const ERL_NIF_TERM argv[]) {
126 148 WRParser *wrap = enif_alloc_resource(parser_resource_type, sizeof(WRParser));
  @@ -252,6 +274,59 @@ static ERL_NIF_TERM node_child(ErlNifEnv *env, int argc,
252 274 }
253 275 }
254 276
277 + /**
278 + * Get the smallest node within this node that spans the given range of bytes
279 + * or (row, column) positions.
280 + */
281 + static ERL_NIF_TERM node_descendant_for_byte_range(ErlNifEnv *env, int argc,
282 + const ERL_NIF_TERM argv[]) {
283 + WRNode *wrap;
284 + if (!enif_get_resource(env, argv[0], node_resource_type, (void **)&wrap)) {
285 + return to_error_string(env, "Unable to unwrap node");
286 + }
287 +
288 + uint32_t start_byte;
289 + uint32_t end_byte;
290 + enif_get_uint(env, argv[1], &start_byte);
291 + enif_get_uint(env, argv[2], &end_byte);
292 +
293 + TSNode node =
294 + ts_node_descendant_for_byte_range(wrap->data, start_byte, end_byte);
295 +
296 + if (ts_node_is_null(node)) {
297 + return to_error_nil(env);
298 + } else {
299 + WRNode *wrapnode = enif_alloc_resource(node_resource_type, sizeof(WRNode));
300 + wrapnode->data = node;
301 + return to_ok_term(env, enif_make_resource(env, wrapnode));
302 + }
303 + }
304 +
305 + /**
306 + * Get the smallest node within this node that spans the given range of bytes
307 + * or (row, column) positions.
308 + */
309 + static ERL_NIF_TERM node_descendant_for_point_range(ErlNifEnv *env, int argc,
310 + const ERL_NIF_TERM argv[]) {
311 + WRNode *wrap;
312 + if (!enif_get_resource(env, argv[0], node_resource_type, (void **)&wrap)) {
313 + return to_error_string(env, "Unable to unwrap node");
314 + }
315 +
316 + TSPoint start_point = point_from_map(env, argv[1]);
317 + TSPoint end_point = point_from_map(env, argv[2]);
318 +
319 + TSNode node =
320 + ts_node_descendant_for_point_range(wrap->data, start_point, end_point);
321 +
322 + if (ts_node_is_null(node)) {
323 + return to_error_nil(env);
324 + } else {
325 + WRNode *wrapnode = enif_alloc_resource(node_resource_type, sizeof(WRNode));
326 + wrapnode->data = node;
327 + return to_ok_term(env, enif_make_resource(env, wrapnode));
328 + }
329 + }
255 330 static ERL_NIF_TERM node_next_sibling(ErlNifEnv *env, int argc,
256 331 const ERL_NIF_TERM argv[]) {
257 332 WRNode *wrap;
  @@ -337,28 +412,6 @@ ERL_NIF_TERM point_to_map(ErlNifEnv *env, TSPoint point) {
337 412 return map;
338 413 }
339 414
340 - TSPoint point_from_map(ErlNifEnv *env, ERL_NIF_TERM map) {
341 - TSPoint pt;
342 - ERL_NIF_TERM row_term, column_term;
343 -
344 - // Get the row and column terms from the map
345 - if (!enif_get_map_value(env, map, enif_make_atom(env, "row"), &row_term) ||
346 - !enif_get_map_value(env, map, enif_make_atom(env, "column"),
347 - &column_term)) {
348 - // TODO: Handle error: keys not found in the map
349 - // You might want to return a default value or raise an error
350 - pt.row = 0;
351 - pt.column = 0;
352 - return pt;
353 - }
354 -
355 - // Get the integer values from the terms
356 - enif_get_uint(env, row_term, &pt.row);
357 - enif_get_uint(env, column_term, &pt.column);
358 -
359 - return pt;
360 - }
361 -
362 415 static ERL_NIF_TERM node_point_range(ErlNifEnv *env, int argc,
363 416 const ERL_NIF_TERM argv[]) {
364 417 WRNode *wrap;
  @@ -557,6 +610,45 @@ static ERL_NIF_TERM query_cursor_set_byte_range(ErlNifEnv *env, int argc,
557 610 }
558 611 }
559 612
613 + static ERL_NIF_TERM
614 + query_cursor_set_containing_point_range(ErlNifEnv *env, int argc,
615 + const ERL_NIF_TERM argv[]) {
616 + WRQueryCursor *querycursor_wrap;
617 + if (!enif_get_resource(env, argv[0], querycursor_resource_type,
618 + (void **)&querycursor_wrap)) {
619 + return to_error_string(env, "Unable to unwrap querycursor");
620 + }
621 + TSPoint start_point = point_from_map(env, argv[1]);
622 + TSPoint end_point = point_from_map(env, argv[2]);
623 + if (ts_query_cursor_set_containing_point_range(querycursor_wrap->data,
624 + start_point, end_point)) {
625 + return enif_make_atom(env, "ok");
626 + } else {
627 + return to_error_string(env, "Invalid range");
628 + }
629 + }
630 +
631 + static ERL_NIF_TERM
632 + query_cursor_set_containing_byte_range(ErlNifEnv *env, int argc,
633 + const ERL_NIF_TERM argv[]) {
634 + WRQueryCursor *querycursor_wrap;
635 + if (!enif_get_resource(env, argv[0], querycursor_resource_type,
636 + (void **)&querycursor_wrap)) {
637 + return to_error_string(env, "Unable to unwrap querycursor");
638 + }
639 +
640 + uint32_t start_byte;
641 + uint32_t end_byte;
642 + enif_get_uint(env, argv[1], &start_byte);
643 + enif_get_uint(env, argv[2], &end_byte);
644 + if (ts_query_cursor_set_containing_byte_range(querycursor_wrap->data,
645 + start_byte, end_byte)) {
646 + return enif_make_atom(env, "ok");
647 + } else {
648 + return to_error_string(env, "Invalid range");
649 + }
650 + }
651 +
560 652 static ErlNifFunc nif_funcs[] = {
561 653 {"parser_new", 0, parser_new, 0},
562 654 {"language", 2, language, 0},
  @@ -567,6 +659,8 @@ static ErlNifFunc nif_funcs[] = {
567 659 {"node_child", 1, node_child, 0},
568 660 {"node_next_sibling", 1, node_next_sibling, 0},
569 661 {"node_prev_sibling", 1, node_prev_sibling, 0},
662 + {"node_descendant_for_byte_range", 3, node_descendant_for_byte_range, 0},
663 + {"node_descendant_for_point_range", 3, node_descendant_for_point_range, 0},
570 664 {"node_string", 1, node_string, 0},
571 665 {"node_type", 1, node_type, 0},
572 666 {"node_byte_range", 1, node_byte_range, 0},
  @@ -577,6 +671,10 @@ static ErlNifFunc nif_funcs[] = {
577 671 {"query_pattern_byte_range", 2, query_pattern_byte_range, 0},
578 672 {"query_capture_name_for_id", 2, query_capture_name_for_id, 0},
579 673 {"query_cursor_set_byte_range", 3, query_cursor_set_byte_range, 0},
580 - {"query_cursor_set_point_range", 3, query_cursor_set_point_range, 0}};
674 + {"query_cursor_set_point_range", 3, query_cursor_set_point_range, 0},
675 + {"query_cursor_set_containing_byte_range", 3,
676 + query_cursor_set_containing_byte_range, 0},
677 + {"query_cursor_set_containing_point_range", 3,
678 + query_cursor_set_containing_point_range, 0}};
581 679
582 680 ERL_NIF_INIT(Elixir.TreeSitter.Nif, nif_funcs, load, NULL, NULL, NULL)