From d9547fd6ff09482e459174483063cecd9c6ee918 Mon Sep 17 00:00:00 2001 From: Anatolii Kosorukov Date: Tue, 31 May 2022 23:35:12 +0300 Subject: [PATCH 1/2] General improvements - rebar.config - Update test profile - Add rebar3_proper plugin for ability to launch Property-Based Tests by rebar3 command. - Update version of proper library. - Add edoc_private profile - Add project_plugins section. - Add rebar3_hex, rebar3_ex_doc - Add settings for publishing hex.pm style documentation. - Makefile - Add option for documentation generation. - Add option to run Property-Based Tests. - Test - Fix typo in the test `pretty_html_test`. - Source code - Tune modules tag semantics for removing Apache Licence description form generated documentation. - Add -spec attribute to public API. --- .gitignore | 7 +++ Makefile | 10 +++- README.md | 18 +++++- doc/img/logo.png | Bin 0 -> 9843 bytes doc/overview.edoc | 9 +++ doc/style.css | 71 ++++++++++++++++++++++ rebar.config | 37 ++++++++++-- src/diffy.erl | 120 ++++++++++++++++++++++++++++++------- src/diffy_simple_patch.erl | 14 ++++- src/diffy_term.erl | 2 +- test/diffy_tests.erl | 2 +- 11 files changed, 257 insertions(+), 33 deletions(-) create mode 100644 doc/img/logo.png create mode 100644 doc/overview.edoc create mode 100644 doc/style.css diff --git a/.gitignore b/.gitignore index 39d5cba..2e0b6a4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,10 @@ deps *.plt erl_crash.dump tags +doc/* +!doc/style.css +!doc/overview.edoc +!doc/img +!doc/img/* +!doc/img/logo.png +exdoc \ No newline at end of file diff --git a/Makefile b/Makefile index 82eaca1..a529105 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ test: eunit eunit: $(REBAR) $(REBAR) as test eunit - + xref: $(REBAR) $(REBAR) as test xref @@ -35,7 +35,15 @@ distclean: rm -rf _build rm $(REBAR) +doc: $(REBAR) + $(REBAR) edoc + +doc_private: $(REBAR) + $(REBAR) as doc_private edoc +exdoc: $(REBAR) + $(REBAR) ex_doc --output exdoc --formatter html + # dializer build-plt: diff --git a/README.md b/README.md index 1854e3d..2225d66 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# Diffy - +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg?logo=apache&logoColor=red)](https://www.apache.org/licenses/LICENSE-2.0) ![Test](https://github.com/zotonic/diffy/workflows/Test/badge.svg) +# Diffy + Diff, Match and Patch implementation for Erlang. ## Introduction @@ -30,3 +31,16 @@ Example Much good info about diff, match and patch can found at link: http://neil.fraser.name/writing/diff/ +## Documentation generation + +## EDoc + +### Generate public API +`make docs` or `rebar3 edoc` + +## Generate private API +`make doc_private` or `rebar3 as doc_private edoc` + +#ExDoc + +`make exdoc` or `rebar3 ex_doc --output exdoc --formatter html` \ No newline at end of file diff --git a/doc/img/logo.png b/doc/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..94ea9de05137b897f08fbc6d773ccaeeb0ae042b GIT binary patch literal 9843 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 TY{%yjg-H9T-tXy0tgrnqF_4I{ literal 0 HcmV?d00001 diff --git a/doc/overview.edoc b/doc/overview.edoc new file mode 100644 index 0000000..6778534 --- /dev/null +++ b/doc/overview.edoc @@ -0,0 +1,9 @@ +@author Maas-Maarten Zeeman +@author Marc Worrell + [https://whatwebwhat.com/] +@author Zotonic Team + [http://zotonic.com] +@title diffy +@doc Diff, match patch implementation +@copyright Apache-2.0 +@since 2014 \ No newline at end of file diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 0000000..cfdb6ba --- /dev/null +++ b/doc/style.css @@ -0,0 +1,71 @@ +/* standard EDoc style sheet */ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + margin-left: .25in; + margin-right: .2in; + margin-top: 0.2in; + margin-bottom: 0.2in; + color: #000000; + background-color: #ffffff; +} +h1,h2 { + margin-left: -0.2in; +} +div.navbar { + background-color: #add8e6; + padding: 0.2em; +} +h2.indextitle { + padding: 0.4em; + background-color: #add8e6; +} +h3.function,h3.typedecl { + background-color: #add8e6; + padding-left: 1em; +} +div.spec { + margin-left: 2em; + + background-color: #eeeeee; +} +a.module { + text-decoration:none +} +a.module:hover { + background-color: #eeeeee; +} +ul.definitions { + list-style-type: none; +} +ul.index { + list-style-type: none; + background-color: #eeeeee; +} + +/* + * Minor style tweaks + */ +ul { + list-style-type: square; +} +table { + border-collapse: collapse; +} +td { + padding: 3px; + vertical-align: middle; +} + +/* +Tune styles +*/ + +table[summary="navigation bar"] { + background-image: url('http://zotonic.com/lib/images/logo.png'); + background-repeat: no-repeat; + background-position: center; +} + +code, p>tt, a>tt { + font-size: 1.2em; +} diff --git a/rebar.config b/rebar.config index adb9366..fa33d64 100644 --- a/rebar.config +++ b/rebar.config @@ -3,11 +3,13 @@ {zotonic_stdlib, "1.2.3"} ]}. - {profiles, [ {test, [ - {deps, [ - {proper, "1.2.0"} + {plugins, [ + rebar3_proper + ]}, + {deps, [ + {proper, "1.4.0"} ]}, {xref_checks, [ @@ -24,5 +26,32 @@ no_return ]} ]} - ]} + ]}, + {doc_private, [ + {edoc_opts, [ + {private, true} + ]} + ]} +]}. + +{project_plugins, [rebar3_hex, rebar3_ex_doc]}. + +{edoc_opts, [ + {preprocess, true}, {stylesheet, "style.css"} ]}. + +{hex, [ + {doc, #{provider => ex_doc}} +]}. + +{ex_doc, [ + {extras, [ + {"README.md", #{title => "Overview"}}, + {"LICENSE", #{title => "License"}} + ]}, + {main, "README.md"}, + {source_url, "https://github.com/zotonic/diffy"}, + {assets, "assets"}, + {api_reference, true} +]}. + diff --git a/src/diffy.erl b/src/diffy.erl index fc75a87..9c5f869 100644 --- a/src/diffy.erl +++ b/src/diffy.erl @@ -2,7 +2,7 @@ %% @copyright 2014-2019 Maas-Maarten Zeeman %% %% @doc Diffy, an erlang diff match and patch implementation -%% +%% @end %% Copyright 2014-2019 Maas-Maarten Zeeman %% %% Licensed under the Apache License, Version 2.0 (the "License"); @@ -79,9 +79,20 @@ length2 = 0 }). +-type patch() :: #patch{ + diffs :: diffs(), + start1 :: non_neg_integer(), + start2 :: non_neg_integer(), + length1 :: non_neg_integer(), + length2 :: non_neg_integer() + }. + % @doc Compute the difference between two binary texts % --spec diff(unicode:unicode_binary(), unicode:unicode_binary()) -> diffs(). +-spec diff(Text1, Text2) -> Result when + Text1 :: unicode:unicode_binary(), + Text2 :: unicode:unicode_binary(), + Result :: diffs(). diff(Text1, Text2) -> diff(Text1, Text2, true). @@ -278,7 +289,11 @@ compute_diff1(Text1, Text2, false) -> diff_bisect(Text1, Text2). -%% Compute diff in linemode +%% @doc Compute diff in linemode +-spec diff_linemode(Text1, Text2) -> Result when + Text1 :: unicode:unicode_binary(), + Text2 :: unicode:unicode_binary(), + Result :: diffs(). diff_linemode(Text1, Text2) -> {CharText1, CharText2, Lines} = lines_to_chars(Text1, Text2), Diffs = diff(CharText1, CharText2, false), @@ -363,10 +378,10 @@ chars_to_lines([{Op, Data}|Rest], LineArray, Acc) -> chars_to_lines(Rest, LineArray, [{Op, Data1}|Acc]). -% Find the 'middle snake' of a diff, split the problem in two +%% @doc Find the 'middle snake' of a diff, split the problem in two %% and return the recursively constructed diff. %% See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. -%% +%%``` %% Args: %% text1: Old string to be diffed. %% text2: New string to be diffed. @@ -374,7 +389,15 @@ chars_to_lines([{Op, Data}|Rest], LineArray, Acc) -> %% %% Returns: %% Array of diff tuples. -%% """ +%%''' +%% @throws {overlap, A1, B1, X, Y} + +-spec diff_bisect(A, B) -> Result when + A :: unicode:unicode_binary(), + B :: unicode:unicode_binary(), + Result :: [DiffTuple], + DiffTuple :: {diff_op(), DiffTupleItem}, + DiffTupleItem :: unicode:unicode_binary(). diff_bisect(A, B) when is_binary(A) andalso is_binary(B) -> ArrA = array_from_binary(A), ArrB = array_from_binary(B), @@ -521,7 +544,10 @@ diff_bisect_split(A, B, X, Y) -> Diffs ++ DiffsB. % @doc Convert the diffs into a pretty html report --spec pretty_html(diffs()) -> iolist(). + +-spec pretty_html(Diffs) -> Result when + Diffs :: diffs(), + Result :: iolist(). pretty_html(Diffs) -> pretty_html(Diffs, []). @@ -540,6 +566,10 @@ pretty_html([{Op, Data}|T], Acc) -> pretty_html(T, [HTML|Acc]). % @doc Compute the source text from a list of diffs. + +-spec source_text(Diffs) -> Result when + Diffs :: diffs(), + Result :: unicode:unicode_binary(). source_text(Diffs) -> source_text(Diffs, <<>>). @@ -552,7 +582,10 @@ source_text([{_Op, Data}|T], Acc) -> % @doc Compute the destination text from a list of diffs. -destination_text(Diffs) -> +-spec destination_text(Diffs) -> Result when + Diffs :: diffs(), + Result :: unicode:unicode_binary(). +destination_text(Diffs) -> destination_text(Diffs, <<>>). destination_text([], Acc) -> @@ -562,7 +595,11 @@ destination_text([{delete, _Data}|T], Acc) -> destination_text([{_Op, Data}|T], Acc) -> destination_text(T, <>). -% @doc Compute the Levenshtein distance, the number of inserted, deleted or substituted characters. +%% @doc Compute the Levenshtein distance, the number of inserted, deleted or substituted characters. + +-spec levenshtein(Diffs) -> Result when + Diffs :: diffs(), + Result :: non_neg_integer(). levenshtein(Diffs) -> levenshtein(Diffs, 0, 0, 0). @@ -579,7 +616,9 @@ levenshtein([{equal, _Data}|T], Insertions, Deletions, Levenshtein) -> %@ @doc Cleanup diffs. % Remove empty operations, merge equal opearations, edits before equal operation and common prefix operations. % --spec cleanup_merge(diffs()) -> diffs(). +-spec cleanup_merge(Diffs) -> Result when + Diffs :: diffs(), + Result :: diffs(). cleanup_merge(Diffs) -> cleanup_merge(Diffs, []). @@ -620,9 +659,11 @@ cleanup_merge([{equal, E1}=H|T], [{Op, I}, {equal, E2}|AccTail]=Acc) when Op =:= cleanup_merge([H|T], Acc) -> cleanup_merge(T, [H|Acc]). -% @doc Do semantic cleanup of diffs -% --spec cleanup_semantic(diffs()) -> diffs(). +%% @doc Do semantic cleanup of diffs + +-spec cleanup_semantic(Diffs) -> Result when + Diffs :: diffs(), + Result :: diffs(). cleanup_semantic(Diffs) -> cleanup_semantic(Diffs, []). @@ -631,12 +672,18 @@ cleanup_semantic([], Acc) -> cleanup_semantic([H|T], Acc) -> cleanup_semantic(T, [H|Acc]). -% @doc Do efficiency cleanup of diffs. -% --spec cleanup_efficiency(diffs()) -> diffs(). +%% @doc Do efficiency cleanup of diffs. + +-spec cleanup_efficiency(Diffs) -> Result when + Diffs :: diffs(), + Result :: diffs(). cleanup_efficiency(Diffs) -> cleanup_efficiency(Diffs, 4). +-spec cleanup_efficiency(Diffs, EditCost) -> Result when + Diffs :: diffs(), + EditCost :: non_neg_integer(), + Result :: diffs(). cleanup_efficiency(Diffs, EditCost) -> cleanup_efficiency(Diffs, false, EditCost, []). @@ -693,18 +740,29 @@ text_smaller_than(<<_C, Rest/binary>>, Size) when Size > 0 -> text_smaller_than(Rest, Size-1). % @doc create a patch from a list of diffs + +-spec make_patch(Diffs) -> Result when + Diffs :: diffs(), + Result :: [patch()]. make_patch(Diffs) when is_list(Diffs) -> %% Reconstruct the source-text from the diffs. make_patch(Diffs, source_text(Diffs)). % @doc create a patch from the source and destination texts + +-spec make_patch(SourceText, DestinationText) -> Result when + SourceText :: unicode:unicode_binary(), + DestinationText :: unicode:unicode_binary(), + Result :: [patch()]. make_patch(SourceText, DestinationText) when is_binary(SourceText) andalso is_binary(DestinationText) -> Diffs = diff(SourceText, DestinationText), Diffs1 = cleanup_semantic(Diffs), Diffs2 = cleanup_efficiency(Diffs1), make_patch(Diffs2, SourceText); -% @doc Creata a patch from a list of diffs and the source text. +%% @doc Creata a patch from a list of diffs and the source text. +%% @throws throw(not_yet) + make_patch(Diffs, SourceText) when is_list(Diffs) andalso is_binary(SourceText) -> make_patch(Diffs, SourceText, SourceText, 0, 0, [#patch{}]). @@ -767,7 +825,13 @@ make_patch([{equal, Data}|T], PrePatchText, PostPatchText, Count1, Count2, [Patc make_patch(T, PrePatchText, PostPatchText, Count1+Size, Count2+Size, [P|Rest]). -% @doc Returns true iff Pattern is a unique match inside Text. +%% @doc Returns `true' if `Pattern' is a unique match inside `Text'. + +-spec unique_match(Pattern, Text) -> Result when + Pattern :: Found | nomatch, + Text :: unicode:unicode_binary(), + Result :: boolean(), + Found :: binary:part(). unique_match(Pattern, Text) -> TextSize = size(Text), case binary:match(Text, Pattern) of @@ -843,6 +907,14 @@ for(From, To, Step, Fun, State) -> S1 end. +-spec split_pre_and_suffix(Text1, Text2) -> Result when + Text1 :: unicode:unicode_binary(), + Text2 :: unicode:unicode_binary(), + Result :: {Prefix, MiddleText1, MiddleText2, Suffix}, + Prefix :: unicode:unicode_binary(), + MiddleText1 :: unicode:unicode_binary(), + MiddleText2 :: unicode:unicode_binary(), + Suffix :: unicode:unicode_binary(). split_pre_and_suffix(Text1, Text2) -> Prefix = common_prefix(Text1, Text2), PrefixLen = size(Prefix), @@ -859,7 +931,7 @@ split_pre_and_suffix(Text1, Text2) -> {Prefix, MiddleText1, MiddleText2, Suffix}. -% @doc Return the common prefix of Text1 and Text2. (utf8 aware) +%% @doc Return the common prefix of Text1 and Text2. (utf8 aware) common_prefix(Text1, Text2) -> Length = binary:longest_common_prefix([Text1, Text2]), Prefix = binary:part(Text1, 0, Length), @@ -868,7 +940,7 @@ common_prefix(Text1, Text2) -> {Prefix1, _} = repair_tail(Prefix), Prefix1. -% @doc Return the common prefix of Text1 and Text2 (utf8 aware) +%% @doc Return the common prefix of Text1 and Text2 (utf8 aware) common_suffix(Text1, Text2) -> Length = binary:longest_common_suffix([Text1, Text2]), Suffix = binary:part(Text1, size(Text1), -Length), @@ -878,7 +950,12 @@ common_suffix(Text1, Text2) -> Suffix1. -% @doc Count the number of characters in a utf8 binary. +%% @doc Count the number of characters in a utf8 binary. +%% @throws error(badarg) + +-spec text_size(Text) -> Result when + Text :: unicode:unicode_binary(), + Result :: non_neg_integer(). text_size(Text) when is_binary(Text) -> text_size(Text, 0). @@ -894,6 +971,7 @@ text_size(_, _) -> %% % @doc Create an array from a utf8 binary. + array_from_binary(Bin) when is_binary(Bin) -> array_from_binary(Bin, 0, array:new()). diff --git a/src/diffy_simple_patch.erl b/src/diffy_simple_patch.erl index 66a6ae8..b470e24 100644 --- a/src/diffy_simple_patch.erl +++ b/src/diffy_simple_patch.erl @@ -2,7 +2,7 @@ %% @copyright 2014 Maas-Maarten Zeeman %% %% @doc Diffy, an erlang diff match and patch implementation -%% +%% @end %% Copyright 2014 Maas-Maarten Zeeman %% %% Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,8 +23,11 @@ -export([make_patch/1, apply_patch/2]). -%% Make a simple patch with edit operations. -%% +%% @doc Make a simple patch with edit operations. + +-spec make_patch(Diffs) -> Result when + Diffs :: diffy_term:diffs(), + Result :: diffy_term:diffs(). make_patch(Diffs) -> make_patch(Diffs, []). @@ -43,6 +46,11 @@ patch_op(delete) -> skip; patch_op(equal) -> copy. % @doc Use the SourceText to reconstruct the destination text. + +-spec apply_patch(SourceText, Diffs) -> Result when + SourceText :: unicode:unicode_binary(), + Diffs :: diffy_term:diffs(), + Result :: binary(). apply_patch(SourceText, Diffs) -> apply_patch(SourceText, 0, Diffs, []). diff --git a/src/diffy_term.erl b/src/diffy_term.erl index ed25387..9d7df6e 100644 --- a/src/diffy_term.erl +++ b/src/diffy_term.erl @@ -3,7 +3,7 @@ %% %% @doc Diffy, an erlang diff match and patch implementation %% Adapted from diffy.erl for simple diff on a list of Erlang terms -%% +%% @end %% Copyright 2014-2015 Maas-Maarten Zeeman, Marc Worrell %% %% Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/test/diffy_tests.erl b/test/diffy_tests.erl index 42065a4..6908cb8 100644 --- a/test/diffy_tests.erl +++ b/test/diffy_tests.erl @@ -335,4 +335,4 @@ cleanup_semantic(Diffs) -> diffy:cleanup_semantic(Diffs). cleanup_merge(Diffs) -> - diffy:cleanup_merge(Diffs). + diffy:cleanup_merge(Diffs). \ No newline at end of file From aebce6b96877a7951a86593ec27367d9d033a40b Mon Sep 17 00:00:00 2001 From: Anatolii Kosorukov Date: Fri, 3 Jun 2022 10:25:01 +0300 Subject: [PATCH 2/2] Update Makefile Add clean_doc target --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a529105..59ef73d 100644 --- a/Makefile +++ b/Makefile @@ -28,9 +28,14 @@ xref: $(REBAR) dialyzer: $(REBAR) $(REBAR) as test dialyzer -clean: $(REBAR) +clean: $(REBAR) clean_doc $(REBAR) clean +clean_doc: + @rm -f doc/*.html + @rm -f doc/erlang.png + @rm -f doc/edoc-info + distclean: rm -rf _build rm $(REBAR)