Current section
19 Versions
Jump to
Current section
19 Versions
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 |