Current section

19 Versions

Jump to

Compare versions

5 files changed
+82 additions
-224 deletions
  @@ -1,201 +1,21 @@
1 - Apache License
2 - Version 2.0, January 2004
3 - http://www.apache.org/licenses/
1 + MIT License
4 2
5 - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
3 + Copyright (c) 2018 Anastasiya Dyachenko
6 4
7 - 1. Definitions.
5 + Permission is hereby granted, free of charge, to any person obtaining a copy
6 + of this software and associated documentation files (the "Software"), to deal
7 + in the Software without restriction, including without limitation the rights
8 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 + copies of the Software, and to permit persons to whom the Software is
10 + furnished to do so, subject to the following conditions:
8 11
9 - "License" shall mean the terms and conditions for use, reproduction,
10 - and distribution as defined by Sections 1 through 9 of this document.
12 + The above copyright notice and this permission notice shall be included in all
13 + copies or substantial portions of the Software.
11 14
12 - "Licensor" shall mean the copyright owner or entity authorized by
13 - the copyright owner that is granting the License.
14 -
15 - "Legal Entity" shall mean the union of the acting entity and all
16 - other entities that control, are controlled by, or are under common
17 - control with that entity. For the purposes of this definition,
18 - "control" means (i) the power, direct or indirect, to cause the
19 - direction or management of such entity, whether by contract or
20 - otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 - outstanding shares, or (iii) beneficial ownership of such entity.
22 -
23 - "You" (or "Your") shall mean an individual or Legal Entity
24 - exercising permissions granted by this License.
25 -
26 - "Source" form shall mean the preferred form for making modifications,
27 - including but not limited to software source code, documentation
28 - source, and configuration files.
29 -
30 - "Object" form shall mean any form resulting from mechanical
31 - transformation or translation of a Source form, including but
32 - not limited to compiled object code, generated documentation,
33 - and conversions to other media types.
34 -
35 - "Work" shall mean the work of authorship, whether in Source or
36 - Object form, made available under the License, as indicated by a
37 - copyright notice that is included in or attached to the work
38 - (an example is provided in the Appendix below).
39 -
40 - "Derivative Works" shall mean any work, whether in Source or Object
41 - form, that is based on (or derived from) the Work and for which the
42 - editorial revisions, annotations, elaborations, or other modifications
43 - represent, as a whole, an original work of authorship. For the purposes
44 - of this License, Derivative Works shall not include works that remain
45 - separable from, or merely link (or bind by name) to the interfaces of,
46 - the Work and Derivative Works thereof.
47 -
48 - "Contribution" shall mean any work of authorship, including
49 - the original version of the Work and any modifications or additions
50 - to that Work or Derivative Works thereof, that is intentionally
51 - submitted to Licensor for inclusion in the Work by the copyright owner
52 - or by an individual or Legal Entity authorized to submit on behalf of
53 - the copyright owner. For the purposes of this definition, "submitted"
54 - means any form of electronic, verbal, or written communication sent
55 - to the Licensor or its representatives, including but not limited to
56 - communication on electronic mailing lists, source code control systems,
57 - and issue tracking systems that are managed by, or on behalf of, the
58 - Licensor for the purpose of discussing and improving the Work, but
59 - excluding communication that is conspicuously marked or otherwise
60 - designated in writing by the copyright owner as "Not a Contribution."
61 -
62 - "Contributor" shall mean Licensor and any individual or Legal Entity
63 - on behalf of whom a Contribution has been received by Licensor and
64 - subsequently incorporated within the Work.
65 -
66 - 2. Grant of Copyright License. Subject to the terms and conditions of
67 - this License, each Contributor hereby grants to You a perpetual,
68 - worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 - copyright license to reproduce, prepare Derivative Works of,
70 - publicly display, publicly perform, sublicense, and distribute the
71 - Work and such Derivative Works in Source or Object form.
72 -
73 - 3. Grant of Patent License. Subject to the terms and conditions of
74 - this License, each Contributor hereby grants to You a perpetual,
75 - worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 - (except as stated in this section) patent license to make, have made,
77 - use, offer to sell, sell, import, and otherwise transfer the Work,
78 - where such license applies only to those patent claims licensable
79 - by such Contributor that are necessarily infringed by their
80 - Contribution(s) alone or by combination of their Contribution(s)
81 - with the Work to which such Contribution(s) was submitted. If You
82 - institute patent litigation against any entity (including a
83 - cross-claim or counterclaim in a lawsuit) alleging that the Work
84 - or a Contribution incorporated within the Work constitutes direct
85 - or contributory patent infringement, then any patent licenses
86 - granted to You under this License for that Work shall terminate
87 - as of the date such litigation is filed.
88 -
89 - 4. Redistribution. You may reproduce and distribute copies of the
90 - Work or Derivative Works thereof in any medium, with or without
91 - modifications, and in Source or Object form, provided that You
92 - meet the following conditions:
93 -
94 - (a) You must give any other recipients of the Work or
95 - Derivative Works a copy of this License; and
96 -
97 - (b) You must cause any modified files to carry prominent notices
98 - stating that You changed the files; and
99 -
100 - (c) You must retain, in the Source form of any Derivative Works
101 - that You distribute, all copyright, patent, trademark, and
102 - attribution notices from the Source form of the Work,
103 - excluding those notices that do not pertain to any part of
104 - the Derivative Works; and
105 -
106 - (d) If the Work includes a "NOTICE" text file as part of its
107 - distribution, then any Derivative Works that You distribute must
108 - include a readable copy of the attribution notices contained
109 - within such NOTICE file, excluding those notices that do not
110 - pertain to any part of the Derivative Works, in at least one
111 - of the following places: within a NOTICE text file distributed
112 - as part of the Derivative Works; within the Source form or
113 - documentation, if provided along with the Derivative Works; or,
114 - within a display generated by the Derivative Works, if and
115 - wherever such third-party notices normally appear. The contents
116 - of the NOTICE file are for informational purposes only and
117 - do not modify the License. You may add Your own attribution
118 - notices within Derivative Works that You distribute, alongside
119 - or as an addendum to the NOTICE text from the Work, provided
120 - that such additional attribution notices cannot be construed
121 - as modifying the License.
122 -
123 - You may add Your own copyright statement to Your modifications and
124 - may provide additional or different license terms and conditions
125 - for use, reproduction, or distribution of Your modifications, or
126 - for any such Derivative Works as a whole, provided Your use,
127 - reproduction, and distribution of the Work otherwise complies with
128 - the conditions stated in this License.
129 -
130 - 5. Submission of Contributions. Unless You explicitly state otherwise,
131 - any Contribution intentionally submitted for inclusion in the Work
132 - by You to the Licensor shall be under the terms and conditions of
133 - this License, without any additional terms or conditions.
134 - Notwithstanding the above, nothing herein shall supersede or modify
135 - the terms of any separate license agreement you may have executed
136 - with Licensor regarding such Contributions.
137 -
138 - 6. Trademarks. This License does not grant permission to use the trade
139 - names, trademarks, service marks, or product names of the Licensor,
140 - except as required for reasonable and customary use in describing the
141 - origin of the Work and reproducing the content of the NOTICE file.
142 -
143 - 7. Disclaimer of Warranty. Unless required by applicable law or
144 - agreed to in writing, Licensor provides the Work (and each
145 - Contributor provides its Contributions) on an "AS IS" BASIS,
146 - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 - implied, including, without limitation, any warranties or conditions
148 - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 - PARTICULAR PURPOSE. You are solely responsible for determining the
150 - appropriateness of using or redistributing the Work and assume any
151 - risks associated with Your exercise of permissions under this License.
152 -
153 - 8. Limitation of Liability. In no event and under no legal theory,
154 - whether in tort (including negligence), contract, or otherwise,
155 - unless required by applicable law (such as deliberate and grossly
156 - negligent acts) or agreed to in writing, shall any Contributor be
157 - liable to You for damages, including any direct, indirect, special,
158 - incidental, or consequential damages of any character arising as a
159 - result of this License or out of the use or inability to use the
160 - Work (including but not limited to damages for loss of goodwill,
161 - work stoppage, computer failure or malfunction, or any and all
162 - other commercial damages or losses), even if such Contributor
163 - has been advised of the possibility of such damages.
164 -
165 - 9. Accepting Warranty or Additional Liability. While redistributing
166 - the Work or Derivative Works thereof, You may choose to offer,
167 - and charge a fee for, acceptance of support, warranty, indemnity,
168 - or other liability obligations and/or rights consistent with this
169 - License. However, in accepting such obligations, You may act only
170 - on Your own behalf and on Your sole responsibility, not on behalf
171 - of any other Contributor, and only if You agree to indemnify,
172 - defend, and hold each Contributor harmless for any liability
173 - incurred by, or claims asserted against, such Contributor by reason
174 - of your accepting any such warranty or additional liability.
175 -
176 - END OF TERMS AND CONDITIONS
177 -
178 - APPENDIX: How to apply the Apache License to your work.
179 -
180 - To apply the Apache License to your work, attach the following
181 - boilerplate notice, with the fields enclosed by brackets "[]"
182 - replaced with your own identifying information. (Don't include
183 - the brackets!) The text should be enclosed in the appropriate
184 - comment syntax for the file format. We also recommend that a
185 - file or class name and description of purpose be included on the
186 - same "printed page" as the copyright notice for easier
187 - identification within third-party archives.
188 -
189 - Copyright [yyyy] [name of copyright owner]
190 -
191 - Licensed under the Apache License, Version 2.0 (the "License");
192 - you may not use this file except in compliance with the License.
193 - You may obtain a copy of the License at
194 -
195 - http://www.apache.org/licenses/LICENSE-2.0
196 -
197 - Unless required by applicable law or agreed to in writing, software
198 - distributed under the License is distributed on an "AS IS" BASIS,
199 - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 - See the License for the specific language governing permissions and
201 - limitations under the License.
15 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 + SOFTWARE.
  @@ -4,15 +4,18 @@ Module for matching
4 4
5 5 ### What difference between `Kernel.match?/2` and `RecursiveMatch.match_r/3`?
6 6 When you use `Kernel.match?/2`
7 - * can't invoke functions in pattern
7 + * can't use functions as pattern
8 8 * can't match not strict equality (only `===`, no `==`)
9 9
10 - `RecursiveMatch.match_r/3` allows you invoke functions in patterns, match not strictly (with option `strict: false`)
10 + `RecursiveMatch.match_r/3` allows you:
11 + * use functions as patterns
12 + * match not strictly (with option `strict: false`)
13 + * ignore order of lists item (with option `ignore_order: true`)
11 14
12 15 ### What is for `assert_match/3` and `refute_match/3`?
13 16 Is is same as `assert RecursiveMatch.match_r`, but with detailed fail message. ExUnit has no special message for `match_r/3` and even special message for `match?/2` is not detailed enough, it has no diff in fail message.
14 17
15 - `assert_match/3` provide diff in test fail message
18 + `assert_match/3` provides diff in test fail message
16 19
17 20
18 21 <img src="/images/screenshot.png?raw=true" width="500" height="155">
  @@ -22,6 +25,8 @@ Is is same as `assert RecursiveMatch.match_r`, but with detailed fail message. E
22 25 If [available in Hex](https://hex.pm/docs/publish), the package can be installed
23 26 by adding `test_match` to your list of dependencies in `mix.exs`:
24 27
28 + **Requires `elixir ~> 1.5`**
29 +
25 30 ```elixir
26 31 def deps do
27 32 [
  @@ -35,11 +40,16 @@ end
35 40 defmodule YourModule do
36 41 import RecursiveMatch
37 42
38 - def some_function do
43 + def function1 do
44 + ...
45 + end
46 +
47 + def function2 do
39 48 ...
40 49 match_r 1, 2
41 50 match_r a, b
42 51 match_r :_, b
52 + match_r function1(), 1
43 53 ...
44 54 end
45 55 end
  @@ -58,6 +68,7 @@ defmodule YourModuleTest do
58 68 assert_match :_, b
59 69 assert_match a, b
60 70 refute_match a, c
71 + assert_match YourModule.function1(), 1
61 72 ...
62 73 end
63 74 end
  @@ -1,7 +1,7 @@
1 1 {<<"app">>,<<"test_match">>}.
2 2 {<<"build_tools">>,[<<"mix">>]}.
3 3 {<<"description">>,<<"Recursive matching">>}.
4 - {<<"elixir">>,<<"~> 1.0">>}.
4 + {<<"elixir">>,<<"~> 1.5">>}.
5 5 {<<"files">>,
6 6 [<<"lib">>,<<"lib/recursive_match.ex">>,<<"mix.exs">>,<<"README.md">>,
7 7 <<"LICENSE">>]}.
  @@ -11,4 +11,4 @@
11 11 {<<"maintainers">>,[<<"Anastasiya Dyachenko">>]}.
12 12 {<<"name">>,<<"test_match">>}.
13 13 {<<"requirements">>,[]}.
14 - {<<"version">>,<<"1.1.1">>}.
14 + {<<"version">>,<<"1.2.0">>}.
  @@ -14,8 +14,11 @@ defmodule RecursiveMatch do
14 14
15 15 - tested: Tested value
16 16
17 - - opts:
18 - * strict, when `true` compare using `===`, when `false` compare using `==`, default `true`
17 + - options: Options
18 +
19 + * `strict`, when `true` compare using `===`, when `false` compare using `==`, default `true`
20 +
21 + * `ignore_order`, when `true` - ignore order of items in lists, default `false`
19 22
20 23 ## Example
21 24
  @@ -26,7 +29,7 @@ defmodule RecursiveMatch do
26 29 iex> match_r %{a: 1, b: 2}, %{a: 1}
27 30 false
28 31 """
29 - @spec match_r(any(), any(), list() | nil) :: boolean()
32 + @spec match_r(term, term, list | nil) :: boolean
30 33 def match_r(pattern, tested, options \\ [strict: true])
31 34
32 35 def match_r(pattern, %{__struct__: _} = tested, options) do
  @@ -43,6 +46,21 @@ defmodule RecursiveMatch do
43 46
44 47 def match_r(pattern, tested, options) when is_list(tested) and is_list(pattern) do
45 48 if Enum.count(pattern) == Enum.count(tested) do
49 +
50 + pattern =
51 + if options[:ignore_order] == true do
52 + Enum.sort(pattern)
53 + else
54 + pattern
55 + end
56 +
57 + tested =
58 + if options[:ignore_order] == true do
59 + Enum.sort(tested)
60 + else
61 + tested
62 + end
63 +
46 64 pattern
47 65 |> Enum.zip(tested)
48 66 |> Enum.all?(fn {pattern_item, tested_item} ->
  @@ -70,8 +88,8 @@ defmodule RecursiveMatch do
70 88 end
71 89
72 90 def match_r(a, a, _), do: true
73 - def match_r(a, b, opts) do
74 - case opts[:strict] do
91 + def match_r(a, b, options) do
92 + case options[:strict] do
75 93 true -> a === b
76 94 nil -> a === b
77 95 false -> a == b
  @@ -89,9 +107,12 @@ defmodule RecursiveMatch do
89 107
90 108 - tested: Tested value
91 109
92 - - opts:
110 + - options: Options
111 +
93 112 * strict: when `true` compare using `===`, when `false` compare using `==`, default `true`
94 113
114 + * `ignore_order`, when `true` - ignore order of items in lists, default `false`
115 +
95 116 * message: Custom message on fail
96 117
97 118 ## Example
  @@ -111,11 +132,10 @@ defmodule RecursiveMatch do
111 132 right: %{a: 1}
112 133 """
113 134
114 - @spec assert_match(any(), any(), list() | nil) :: boolean()
115 -
116 - defmacro assert_match(left, right, opts \\ [strict: true]) do
117 - match_r = {:match_r, [], [left, right, opts]}
118 - message = opts[:message] || "match (assert_match) failed"
135 + @spec assert_match(term, term, list | nil) :: boolean
136 + defmacro assert_match(left, right, options \\ [strict: true]) do
137 + match_r = {:match_r, [], [left, right, options]}
138 + message = options[:message] || "match (assert_match) failed"
119 139 quote do
120 140 right = unquote(right)
121 141 left = unquote(left)
  @@ -139,9 +159,12 @@ defmodule RecursiveMatch do
139 159
140 160 - tested: Tested value
141 161
142 - - opts:
162 + - options: Options
163 +
143 164 * strict: when `true` compare using `===`, when `false` compare using `==`, default `true`
144 165
166 + * `ignore_order`, when `true` - ignore order of items in lists, default `false`
167 +
145 168 * message: Custom message on fail
146 169
147 170
  @@ -159,11 +182,10 @@ defmodule RecursiveMatch do
159 182
160 183 match (refute_match) succeeded, but should have failed
161 184 """
162 - @spec refute_match(any(), any(), list() | nil) :: boolean()
163 -
164 - defmacro refute_match(left, right, opts \\ [strict: true]) do
165 - match_r = {:match_r, [], [left, right, opts]}
166 - message = opts[:message] || "match (refute_match) succeeded, but should have failed"
185 + @spec refute_match(term, term, list | nil) :: boolean
186 + defmacro refute_match(left, right, options \\ [strict: true]) do
187 + match_r = {:match_r, [], [left, right, options]}
188 + message = options[:message] || "match (refute_match) succeeded, but should have failed"
167 189 quote do
168 190 right = unquote(right)
169 191 left = unquote(left)
  @@ -4,13 +4,16 @@ defmodule TestMatch.MixProject do
4 4 def project do
5 5 [
6 6 app: :test_match,
7 - version: "1.1.1",
8 - elixir: "~> 1.0",
7 + version: "1.2.0",
8 + elixir: "~> 1.5",
9 9 build_embedded: Mix.env() == :prod,
10 10 start_permanent: Mix.env() == :prod,
11 11 description: description(),
12 12 package: package(),
13 - deps: deps()
13 + deps: deps(),
14 + test_coverage: [tool: ExCoveralls],
15 + preferred_cli_env: ["coveralls": :test, "coveralls.detail": :test, "coveralls.post": :test,
16 + "coveralls.html": :test, "coveralls.travis": :test]
14 17 ]
15 18 end
16 19
  @@ -20,7 +23,9 @@ defmodule TestMatch.MixProject do
20 23
21 24 defp deps do
22 25 [
23 - {:ex_doc, "~> 0.14", only: :dev}
26 + {:ex_doc, "~> 0.14", only: :dev},
27 + {:excoveralls, github: "parroty/excoveralls", only: :test},
28 + {:inch_ex, only: :docs}
24 29 ]
25 30 end