-module(gliff@internal@inline).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gliff/internal/inline.gleam").
-export([highlight/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-file("src/gliff/internal/inline.gleam", 105).
?DOC(false).
-spec classify_edit(gliff@types:raw_edit(), boolean()) -> {binary(), boolean()}.
classify_edit(Edit, For_delete) ->
case Edit of
{raw_equal, V} ->
{V, false};
{raw_delete, V@1} ->
case For_delete of
true ->
{V@1, true};
false ->
{<<""/utf8>>, false}
end;
{raw_insert, V@2} ->
case For_delete of
true ->
{<<""/utf8>>, false};
false ->
{V@2, true}
end
end.
-file("src/gliff/internal/inline.gleam", 57).
?DOC(false).
-spec collect_spans(
list(gliff@types:raw_edit()),
boolean(),
binary(),
boolean(),
list(gliff@types:span())
) -> list(gliff@types:span()).
collect_spans(Edits, For_delete, Current, Current_is_changed, Acc) ->
case Edits of
[] ->
case Current of
<<""/utf8>> ->
Acc;
_ ->
case Current_is_changed of
true ->
[{changed, Current} | Acc];
false ->
[{unchanged, Current} | Acc]
end
end;
[Edit | Rest] ->
{Char, Is_changed} = classify_edit(Edit, For_delete),
case Char of
<<""/utf8>> ->
collect_spans(
Rest,
For_delete,
Current,
Current_is_changed,
Acc
);
_ ->
case Is_changed =:= Current_is_changed of
true ->
collect_spans(
Rest,
For_delete,
<<Current/binary, Char/binary>>,
Current_is_changed,
Acc
);
false ->
New_acc = case Current of
<<""/utf8>> ->
Acc;
_ ->
case Current_is_changed of
true ->
[{changed, Current} | Acc];
false ->
[{unchanged, Current} | Acc]
end
end,
collect_spans(
Rest,
For_delete,
Char,
Is_changed,
New_acc
)
end
end
end.
-file("src/gliff/internal/inline.gleam", 52).
?DOC(false).
-spec raw_edits_to_spans(list(gliff@types:raw_edit()), boolean()) -> list(gliff@types:span()).
raw_edits_to_spans(Raw_edits, For_delete) ->
_pipe = collect_spans(Raw_edits, For_delete, <<""/utf8>>, false, []),
lists:reverse(_pipe).
-file("src/gliff/internal/inline.gleam", 39).
?DOC(false).
-spec diff_line_pair(list(binary()), list(binary()), boolean()) -> list(gliff@types:span()).
diff_line_pair(Del_lines, Ins_lines, For_delete) ->
Del_text = gleam@string:join(Del_lines, <<"\n"/utf8>>),
Ins_text = gleam@string:join(Ins_lines, <<"\n"/utf8>>),
Del_chars = gleam@string:to_graphemes(Del_text),
Ins_chars = gleam@string:to_graphemes(Ins_text),
Raw_edits = gliff@internal@myers:diff(Del_chars, Ins_chars),
raw_edits_to_spans(Raw_edits, For_delete).
-file("src/gliff/internal/inline.gleam", 15).
?DOC(false).
-spec highlight_loop(list(gliff@types:edit()), list(gliff@types:inline_edit())) -> list(gliff@types:inline_edit()).
highlight_loop(Edits, Acc) ->
case Edits of
[] ->
Acc;
[{equal, Lines} | Rest] ->
highlight_loop(Rest, [{inline_equal, Lines} | Acc]);
[{delete, Del_lines}, {insert, Ins_lines} | Rest@1] ->
Del_spans = diff_line_pair(Del_lines, Ins_lines, true),
Ins_spans = diff_line_pair(Del_lines, Ins_lines, false),
highlight_loop(
Rest@1,
[{inline_insert, Ins_spans}, {inline_delete, Del_spans} | Acc]
);
[{delete, Lines@1} | Rest@2] ->
Spans = gleam@list:map(Lines@1, fun(L) -> {changed, L} end),
highlight_loop(Rest@2, [{inline_delete, Spans} | Acc]);
[{insert, Lines@2} | Rest@3] ->
Spans@1 = gleam@list:map(Lines@2, fun(L@1) -> {changed, L@1} end),
highlight_loop(Rest@3, [{inline_insert, Spans@1} | Acc])
end.
-file("src/gliff/internal/inline.gleam", 10).
?DOC(false).
-spec highlight(list(gliff@types:edit())) -> list(gliff@types:inline_edit()).
highlight(Edits) ->
_pipe = highlight_loop(Edits, []),
lists:reverse(_pipe).