Current section

Files

Jump to
caffeine_lang src caffeine_lang@position_utils.erl
Raw

src/caffeine_lang@position_utils.erl

-module(caffeine_lang@position_utils).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/position_utils.gleam").
-export([find_name_position/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/caffeine_lang/position_utils.gleam", 54).
-spec is_word_char(binary()) -> boolean().
is_word_char(G) ->
case G of
<<"_"/utf8>> ->
true;
_ ->
case gleam@string:to_utf_codepoints(G) of
[Cp] ->
Code = gleam_stdlib:identity(Cp),
(((Code >= 65) andalso (Code =< 90)) orelse ((Code >= 97)
andalso (Code =< 122)))
orelse ((Code >= 48) andalso (Code =< 57));
_ ->
false
end
end.
-file("src/caffeine_lang/position_utils.gleam", 30).
?DOC(
" Searches for `name` as a whole word within `line`, starting from `offset`.\n"
" Returns Ok(column) as 0-indexed offset on match, Error(Nil) if not found.\n"
).
-spec find_whole_word(binary(), binary(), integer()) -> {ok, integer()} |
{error, nil}.
find_whole_word(Line, Name, Offset) ->
case gleam@string:split_once(Line, Name) of
{error, _} ->
{error, nil};
{ok, {Before, After}} ->
Col = Offset + string:length(Before),
Before_ok = case gleam@string:last(Before) of
{ok, C} ->
not is_word_char(C);
{error, _} ->
true
end,
After_ok = case gleam@string:first(After) of
{ok, C@1} ->
not is_word_char(C@1);
{error, _} ->
true
end,
case Before_ok andalso After_ok of
true ->
{ok, Col};
false ->
Skip = string:length(Before) + string:length(Name),
find_whole_word(
gleam@string:drop_start(Line, Skip),
Name,
Offset + Skip
)
end
end.
-file("src/caffeine_lang/position_utils.gleam", 12).
-spec find_in_lines(list(binary()), binary(), integer()) -> {integer(),
integer()}.
find_in_lines(Lines, Name, Line_num) ->
case Lines of
[] ->
{1, 1};
[First | Rest] ->
case find_whole_word(First, Name, 0) of
{ok, Col} ->
{Line_num, Col + 1};
{error, _} ->
find_in_lines(Rest, Name, Line_num + 1)
end
end.
-file("src/caffeine_lang/position_utils.gleam", 7).
?DOC(
" Finds the 1-indexed line and column of the first whole-word occurrence\n"
" of a name in source. Returns #(1, 1) if not found.\n"
).
-spec find_name_position(binary(), binary()) -> {integer(), integer()}.
find_name_position(Content, Name) ->
Lines = gleam@string:split(Content, <<"\n"/utf8>>),
find_in_lines(Lines, Name, 1).