diff --git a/.credo.exs b/.credo.exs new file mode 100644 index 0000000..f68970a --- /dev/null +++ b/.credo.exs @@ -0,0 +1,167 @@ +# This file contains the configuration for Credo and you are probably reading +# this after creating it with `mix credo.gen.config`. +# +# If you find anything wrong or unclear in this file, please report an +# issue on GitHub: https://github.com/rrrene/credo/issues +# +%{ + # + # You can have as many configs as you like in the `configs:` field. + configs: [ + %{ + # + # Run any exec using `mix credo -C `. If no exec name is given + # "default" is used. + # + name: "default", + # + # These are the files included in the analysis: + files: %{ + # + # You can give explicit globs or simply directories. + # In the latter case `**/*.{ex,exs}` will be used. + # + included: ["lib/", "src/", "test/", "web/", "apps/"], + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + }, + # + # If you create your own checks, you must specify the source files for + # them here, so they can be loaded by Credo before running the analysis. + # + requires: [], + # + # If you want to enforce a style guide and need a more traditional linting + # experience, you can change `strict` to `true` below: + # + strict: true, + # + # If you want to use uncolored output by default, you can change `color` + # to `false` below: + # + color: true, + # + # You can customize the parameters of any check by adding a second element + # to the tuple. + # + # To disable a check put `false` as second element: + # + # {Credo.Check.Design.DuplicatedCode, false} + # + checks: [ + # + ## Consistency Checks + # + {Credo.Check.Consistency.ExceptionNames, []}, + {Credo.Check.Consistency.LineEndings, []}, + {Credo.Check.Consistency.ParameterPatternMatching, []}, + {Credo.Check.Consistency.SpaceAroundOperators, []}, + {Credo.Check.Consistency.SpaceInParentheses, []}, + {Credo.Check.Consistency.TabsOrSpaces, []}, + + # + ## Design Checks + # + # You can customize the priority of any check + # Priority values are: `low, normal, high, higher` + # + {Credo.Check.Design.AliasUsage, + [ + priority: :low, + if_nested_deeper_than: 2, + if_called_more_often_than: 0 + ]}, + # For some checks, you can also set other parameters + # + # If you don't want the `setup` and `test` macro calls in ExUnit tests + # or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just + # set the `excluded_macros` parameter to `[:schema, :setup, :test]`. + # + {Credo.Check.Design.DuplicatedCode, [excluded_macros: []]}, + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + # + {Credo.Check.Design.TagTODO, [exit_status: 0]}, + {Credo.Check.Design.TagFIXME, []}, + + # + ## Readability Checks + # + {Credo.Check.Readability.AliasOrder, []}, + {Credo.Check.Readability.FunctionNames, []}, + {Credo.Check.Readability.LargeNumbers, []}, + {Credo.Check.Readability.MaxLineLength, + [priority: :low, max_length: 80]}, + {Credo.Check.Readability.ModuleAttributeNames, []}, + {Credo.Check.Readability.ModuleDoc, []}, + {Credo.Check.Readability.ModuleNames, []}, + {Credo.Check.Readability.ParenthesesInCondition, []}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, + {Credo.Check.Readability.PredicateFunctionNames, []}, + {Credo.Check.Readability.PreferImplicitTry, []}, + {Credo.Check.Readability.RedundantBlankLines, []}, + {Credo.Check.Readability.Semicolons, []}, + {Credo.Check.Readability.SpaceAfterCommas, []}, + {Credo.Check.Readability.StringSigils, []}, + {Credo.Check.Readability.TrailingBlankLine, []}, + {Credo.Check.Readability.TrailingWhiteSpace, []}, + {Credo.Check.Readability.VariableNames, []}, + + # + ## Refactoring Opportunities + # + {Credo.Check.Refactor.CondStatements, []}, + {Credo.Check.Refactor.CyclomaticComplexity, []}, + {Credo.Check.Refactor.FunctionArity, []}, + {Credo.Check.Refactor.LongQuoteBlocks, []}, + {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.NegatedConditionsInUnless, []}, + {Credo.Check.Refactor.NegatedConditionsWithElse, []}, + {Credo.Check.Refactor.Nesting, []}, + {Credo.Check.Refactor.PipeChainStart, + [ + excluded_argument_types: [:atom, :binary, :fn, :keyword], + excluded_functions: [] + ]}, + {Credo.Check.Refactor.UnlessWithElse, []}, + + # + ## Warnings + # + {Credo.Check.Warning.BoolOperationOnSameValues, []}, + {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, + {Credo.Check.Warning.IExPry, []}, + {Credo.Check.Warning.IoInspect, []}, + {Credo.Check.Warning.OperationOnSameValues, []}, + {Credo.Check.Warning.OperationWithConstantResult, []}, + {Credo.Check.Warning.RaiseInsideRescue, []}, + {Credo.Check.Warning.UnusedEnumOperation, []}, + {Credo.Check.Warning.UnusedFileOperation, []}, + {Credo.Check.Warning.UnusedKeywordOperation, []}, + {Credo.Check.Warning.UnusedListOperation, []}, + {Credo.Check.Warning.UnusedPathOperation, []}, + {Credo.Check.Warning.UnusedRegexOperation, []}, + {Credo.Check.Warning.UnusedStringOperation, []}, + {Credo.Check.Warning.UnusedTupleOperation, []}, + + # + # Controversial and experimental checks (opt-in, just remove `, false`) + # + {Credo.Check.Consistency.MultiAliasImportRequireUse, false}, + {Credo.Check.Readability.Specs, false}, + {Credo.Check.Refactor.ABCSize, false}, + {Credo.Check.Refactor.AppendSingleItem, false}, + {Credo.Check.Refactor.DoubleBooleanNegation, false}, + {Credo.Check.Refactor.MapInto, false}, + {Credo.Check.Refactor.VariableRebinding, false}, + {Credo.Check.Warning.LazyLogging, false}, + {Credo.Check.Warning.MapGetUnsafePass, false}, + {Credo.Check.Warning.UnsafeToAtom, false} + + # + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } + ] +} diff --git a/.dialyzer_ignore b/.dialyzer_ignore new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.dialyzer_ignore @@ -0,0 +1 @@ + diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..865b01e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: http://EditorConfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +max_line_length = 80 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{md,sh}] +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..6d28500 --- /dev/null +++ b/.envrc @@ -0,0 +1,84 @@ +#################################### +# Environment setup for Nix shells # +#################################### + +# From https://github.com/direnv/direnv/wiki/Nix#persistent-cached-shell +# +# Usage: use_nix [...] +# +# Load environment variables from `nix-shell`. +# If you have a `default.nix` or `shell.nix` one of these will be used and +# the derived environment will be stored at ./.direnv/env- +# and symlink to it will be created at ./.direnv/default. +# Dependencies are added to the GC roots, such that the environment remains persistent. +# +# Packages can also be specified directly via e.g `use nix -p ocaml`, +# however those will not be added to the GC roots. +# +# The resulting environment is cached for better performance. +# +# To trigger switch to a different environment: +# `rm -f .direnv/default` +# +# To derive a new environment: +# `rm -rf .direnv/env-$(md5sum {shell,default}.nix 2> /dev/null | cut -c -32)` +# +# To remove cache: +# `rm -f .direnv/dump-*` +# +# To remove all environments: +# `rm -rf .direnv/env-*` +# +# To remove only old environments: +# `find .direnv -name 'env-*' -and -not -name `readlink .direnv/default` -exec rm -rf {} +` +# +use_nix() { + set -e + + local shell="shell.nix" + if [[ ! -f "${shell}" ]]; then + shell="default.nix" + fi + + if [[ ! -f "${shell}" ]]; then + fail "use nix: shell.nix or default.nix not found in the folder" + fi + + local dir="${PWD}"/.direnv + local default="${dir}/default" + if [[ ! -L "${default}" ]] || [[ ! -d `readlink "${default}"` ]]; then + local wd="${dir}/env-`md5sum "${shell}" | cut -c -32`" # TODO: Hash also the nixpkgs version? + mkdir -p "${wd}" + + local drv="${wd}/env.drv" + if [[ ! -f "${drv}" ]]; then + log_status "use nix: deriving new environment" + IN_NIX_SHELL=1 nix-instantiate --add-root "${drv}" --indirect "${shell}" > /dev/null + nix-store -r `nix-store --query --references "${drv}"` --add-root "${wd}/dep" --indirect > /dev/null + fi + + rm -f "${default}" + ln -s `basename "${wd}"` "${default}" + fi + + local drv=`readlink -f "${default}/env.drv"` + local dump="${dir}/dump-`md5sum ".envrc" | cut -c -32`-`md5sum ${drv} | cut -c -32`" + + if [[ ! -f "${dump}" ]] || [[ "${XDG_CONFIG_DIR}/direnv/direnvrc" -nt "${dump}" ]]; then + log_status "use nix: updating cache" + + old=`find "${dir}" -name 'dump-*'` + nix-shell "${drv}" --show-trace "$@" --run 'direnv dump' > "${dump}" + rm -f ${old} + fi + + direnv_load cat "${dump}" + + watch_file "${default}" + watch_file shell.nix + if [[ ${shell} == "default.nix" ]]; then + watch_file default.nix + fi +} + +use nix diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..58ff344 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,7 @@ +[ + inputs: [ + "{mix,.iex,.formatter,.credo}.exs", + "{config,lib,rel,test}/**/*.{ex,exs}" + ], + line_length: 80 +] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f2723d --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +## +## Application artifacts +## + +# direnv cache for Nix shells +/.direnv/ + +# Elixir build directory +/_build/ + +# Elixir dependencies +/deps/ +/.fetch + +# Elixir binary files +*.beam +*.ez +/typed_struct_lens-*.tar +/typed_struct_lens + +# Test coverage and documentation +/cover/ +/doc/ + +## +## Editor artifacts +## + +/.elixir_ls/ +/.history/ + +## +## Crash dumps +## + +# Erang VM +erl_crash.dump diff --git a/.gitsetup b/.gitsetup new file mode 100755 index 0000000..d4e5b16 --- /dev/null +++ b/.gitsetup @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e +set -x + +# Setup git-flow +git flow init -d +git config gitflow.prefix.versiontag "v" +git config gitflow.feature.finish.no-ff true +git config gitflow.release.finish.sign true +git config gitflow.hotfix.finish.sign true diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f23143b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +language: elixir +elixir: + - 1.6 + - 1.7 + - 1.8 +otp_release: + - 19.3 + - 20.3 + - 21.2 +matrix: + exclude: + - elixir: 1.8 + otp_release: 19.3 +env: + - PLT_DIR=$HOME/.plt +before_script: + - mkdir -p $PLT_DIR + - mix deps.compile + - MIX_ENV=test mix deps.compile + - travis_wait mix dialyzer --plt +script: + - mix compile --force --verbose --warnings-as-errors + - mix test --trace + - mix dialyzer --no-compile --no-check --halt-exit-status + - mix credo + - if [[ "$TRAVIS_ELIXIR_VERSION" == "1.8.1" ]]; then mix format --check-formatted; fi +cache: + directories: +- $PLT_DIR diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c9ac075 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.1.0-dev + +* Initial version diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b98d358 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,160 @@ +# Contributing to TypedStructLens + +TypedStructLens is written in [Elixir](https://elixir-lang.org). + +For branching management, this project uses +[git-flow](https://github.com/petervanderdoes/gitflow-avh). The `master` branch +is reserved for releases: the development process occurs on `develop` and +feature branches. **Please never commit to master.** + +You can easily set up a development environment featuring all the dependencies, +including Elixir and `git-flow`, by using [Nix](https://nixos.org/nix/). This is +detailed below. + +## Setup + +### Local repository + +1. Fork the repository + +2. Clone your fork to a local repository: + + $ git clone https://github.com/you/typed_struct_lens.git + $ cd typed_struct_lens + +3. Add the main repository as a remote: + + $ git remote add upstream https://github.com/ejpcmac/typed_struct_lens.git + +4. Checkout to `develop`: + + $ git checkout develop + +### Development environment (without Nix) + +Install an Elixir environment, and optionally install `git-flow`. + +### Development environment (with Nix) + +1. Install Nix by running the script and following the instructions: + + $ curl https://nixos.org/nix/install | sh + +2. Optionally install [direnv](https://github.com/direnv/direnv) to + automatically setup the environment when you enter the project directory: + + $ nix-env -i direnv + + In this case, you also need to add to your `~/.rc`: + + ```sh + eval "$(direnv hook )" + ``` + + *Make sure to replace `` by your shell, namely `bash`, `zsh`, …* + +3. In the project directory, if you **did not** install direnv, start a Nix + shell: + + $ cd typed_struct_lens + $ nix-shell + + If you opted to use direnv, please allow the `.envrc` instead of running a + Nix shell manually: + + $ cd typed_struct_lens + $ direnv allow + + In this case, direnv will automatically update your environment to behave + like a Nix shell whenever you enter the project directory. + +### Git-flow + +If you want to use `git-flow` and use the standard project configuration, please +run: + + $ ./.gitsetup + +### Building the project + +1. Fetch the project dependencies and build the project: + + $ cd typed_struct_lens + $ mix do deps.get, compile + +2. Launch the tests: + + $ mix test + +All the tests should pass. + +## Workflow + +To make a change, please use this workflow: + +1. Checkout to `develop` and apply the last upstream changes (use rebase, not + merge!): + + $ git checkout develop + $ git fetch --all --prune + $ git rebase upstream/develop + +2. For a tiny patch, create a new branch with an explicit name: + + $ git checkout -b + + Alternatively, if you are working on a feature which would need more work, + you can create a feature branch with `git-flow`: + + $ git flow feature start + + *Note: always open an issue and ask before starting a big feature, to avoid + it not beeing merged and your time lost.* + +3. Work on your feature (don’t forget to write typespecs and tests; you can + check your coverage with `mix coveralls.html` and open + `cover/excoveralls.html`): + + # Some work + $ git commit -am "My first change" + # Some work + $ git commit -am "My second change" + ... + +4. When your feature is ready, feel free to use + [interactive rebase](https://help.github.com/articles/about-git-rebase/) so + your history looks clean and is easy to follow. Then, apply the last + upstream changes on `develop` to prepare integration: + + $ git checkout develop + $ git fetch --all --prune + $ git rebase upstream/develop + +5. If there were commits on `develop` since the beginning of your feature + branch, integrate them by **rebasing** if your branch has few commits, or + merging if you had a long-lived branch: + + $ git checkout + $ git rebase develop + + *Note: the only case you should merge is when you are working on a big + feature. If it is the case, we should have discussed this before as stated + above.* + +6. Run the tests and static analyzers to ensure there is no regression and all + works as expected: + + $ mix test + $ mix dialyzer + $ mix credo + +7. If it’s all good, open a pull request to merge your branch into the `develop` + branch on the main repository. + +## Coding style + +Please format your code with `mix format` or your editor and follow +[this style guide](https://github.com/christopheradams/elixir_style_guide). + +All contributed code must be documented and functions must have typespecs. In +general, take your inspiration from the existing code. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..eccccec --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Jean-Philippe Cugnet + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2af4728 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# TypedStructLens + +[![Build Status](https://travis-ci.com/ejpcmac/typed_struct_lens.svg?branch=develop)](https://travis-ci.com/ejpcmac/typed_struct_lens) +[![hex.pm version](http://img.shields.io/hexpm/v/typed_struct_lens.svg?style=flat)](https://hex.pm/packages/typed_struct_lens) + +TypedStructLens is a [TypedStruct](https://github.com/ejpcmac/typed_struct) +plugin for defining a [Lens](https://github.com/obrok/lens) on each field +without writing boilerplate code. + +*This is a work in progress, please look at the `develop` branch for ongoing +development.* + +## [Contributing](CONTRIBUTING.md) + +Before contributing to this project, please read the +[CONTRIBUTING.md](CONTRIBUTING.md). + +## License + +Copyright © 2019 Jean-Philippe Cugnet + +This project is licensed under the [MIT license](LICENSE). diff --git a/config/config.exs b/config/config.exs new file mode 100644 index 0000000..f468b2a --- /dev/null +++ b/config/config.exs @@ -0,0 +1,18 @@ +use Mix.Config + +# This configuration is loaded before any dependency and is restricted to this +# project. If another project depends on this project, this file won’t be loaded +# nor affect the parent project. For this reason, if you want to provide default +# values for your application for 3rd-party users, it should be done in your +# "mix.exs" file. + +if Mix.env() == :test do + # Clear the console before each test run + config :mix_test_watch, clear: true +end + +# # Import environment specific config. This must remain at the bottom of this +# # file so it overrides the configuration defined above. +# unless Mix.env() == :docs do +# import_config "#{Mix.env()}.exs" +# end diff --git a/lib/typed_struct_lens.ex b/lib/typed_struct_lens.ex new file mode 100644 index 0000000..d01b833 --- /dev/null +++ b/lib/typed_struct_lens.ex @@ -0,0 +1,19 @@ +defmodule TypedStructLens do + @moduledoc """ + Documentation for TypedStructLens. + """ + + @doc """ + Hello world. + + ## Examples + + iex> TypedStructLens.hello() + :world + + """ + @spec hello :: :world + def hello do + :world + end +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..d4a2420 --- /dev/null +++ b/mix.exs @@ -0,0 +1,118 @@ +defmodule TypedStructLens.MixProject do + use Mix.Project + + @version "0.1.0" + @repo_url "https://github.com/ejpcmac/typed_struct_lens" + + def project do + [ + app: :typed_struct_lens, + version: @version <> dev(), + elixir: "~> 1.6", + elixirc_paths: elixirc_paths(Mix.env()), + start_permanent: Mix.env() == :prod, + deps: deps(), + + # Tools + dialyzer: dialyzer(), + test_coverage: [tool: ExCoveralls], + preferred_cli_env: cli_env(), + + # Docs + docs: [ + main: "TypedStructLens", + source_url: @repo_url, + source_ref: "v#{@version}" + ], + + # Package + package: package(), + description: "Description for TypedStructLens." + ] + end + + def application do + [ + extra_applications: [:logger] + ] + end + + # Specifies which paths to compile per environment. + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_), do: ["lib"] + + defp deps do + [ + # Development dependencies + {:credo, "~> 1.0", only: :dev, runtime: false}, + {:dialyxir, "~> 1.0-rc", only: :dev, runtime: false}, + {:excoveralls, ">= 0.0.0", only: :test, runtime: false}, + {:mix_test_watch, ">= 0.0.0", only: :test, runtime: false}, + {:ex_unit_notifier, ">= 0.0.0", only: :test, runtime: false}, + {:stream_data, "~> 0.4.0", only: :test}, + + # Project dependencies + + # Documentation dependencies + {:ex_doc, "~> 0.19", only: :docs, runtime: false} + ] + end + + # Dialyzer configuration + defp dialyzer do + [ + # Use a custom PLT directory for continuous integration caching. + plt_core_path: System.get_env("PLT_DIR"), + plt_file: plt_file(), + plt_add_deps: :transitive, + flags: [ + :unmatched_returns, + :error_handling, + :race_conditions + ], + ignore_warnings: ".dialyzer_ignore" + ] + end + + defp plt_file do + case System.get_env("PLT_DIR") do + nil -> nil + plt_dir -> {:no_warn, Path.join(plt_dir, "typed_struct_lens.plt")} + end + end + + defp cli_env do + [ + # Run mix test.watch in `:test` env. + "test.watch": :test, + + # Always run Coveralls Mix tasks in `:test` env. + coveralls: :test, + "coveralls.detail": :test, + "coveralls.html": :test, + + # Use a custom env for docs. + docs: :docs + ] + end + + defp package do + [ + licenses: ["MIT"], + links: %{"GitHub" => @repo_url} + ] + end + + # Helper to add a development revision to the version. Do NOT make a call to + # Git this way in a production release!! + def dev do + with {rev, 0} <- + System.cmd("git", ["rev-parse", "--short", "HEAD"], + stderr_to_stdout: true + ) do + "-dev+" <> String.trim(rev) + else + _ -> "-dev" + end + end +end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..e1e711b --- /dev/null +++ b/mix.lock @@ -0,0 +1,25 @@ +%{ + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, + "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, + "credo": {:hex, :credo, "1.0.5", "fdea745579f8845315fe6a3b43e2f9f8866839cfbc8562bb72778e9fdaa94214", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "dialyxir": {:hex, :dialyxir, "1.0.0-rc.6", "78e97d9c0ff1b5521dd68041193891aebebce52fc3b93463c0a6806874557d7d", [:mix], [{:erlex, "~> 0.2.1", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm"}, + "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, + "erlex": {:hex, :erlex, "0.2.1", "cee02918660807cbba9a7229cae9b42d1c6143b768c781fa6cee1eaf03ad860b", [:mix], [], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_unit_notifier": {:hex, :ex_unit_notifier, "0.1.4", "36a2dcab829f506e01bf17816590680dd1474407926d43e64c1263e627c364b8", [:mix], [], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.10.6", "e2b9718c9d8e3ef90bc22278c3f76c850a9f9116faf4ebe9678063310742edc2", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "file_system": {:hex, :file_system, "0.2.6", "fd4dc3af89b9ab1dc8ccbcc214a0e60c41f34be251d9307920748a14bf41f1d3", [:mix], [], "hexpm"}, + "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, + "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, + "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"}, + "mix_test_watch": {:hex, :mix_test_watch, "0.9.0", "c72132a6071261893518fa08e121e911c9358713f62794a90c95db59042af375", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, + "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"}, + "stream_data": {:hex, :stream_data, "0.4.3", "62aafd870caff0849a5057a7ec270fad0eb86889f4d433b937d996de99e3db25", [:mix], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..4b72ed0 --- /dev/null +++ b/shell.nix @@ -0,0 +1,22 @@ +{ pkgs ? import {} }: + +with pkgs; + +let + inherit (lib) optional optionals; + + elixir = beam.packages.erlangR21.elixir_1_8; + gitflow = gitAndTools.gitflow; +in + +mkShell { + buildInputs = [ elixir git gitflow ] + ++ optional stdenv.isLinux libnotify # For ExUnit Notifier on Linux. + ++ optional stdenv.isLinux inotify-tools # For file_system on Linux. + ++ optional stdenv.isDarwin terminal-notifier # For ExUnit Notifier on macOS. + ++ optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [ + # For file_system on macOS. + CoreFoundation + CoreServices + ]); +} diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..f761b96 --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.configure(formatters: [ExUnit.CLIFormatter, ExUnitNotifier]) +ExUnit.start() diff --git a/test/typed_struct_lens_test.exs b/test/typed_struct_lens_test.exs new file mode 100644 index 0000000..84f2491 --- /dev/null +++ b/test/typed_struct_lens_test.exs @@ -0,0 +1,8 @@ +defmodule TypedStructLensTest do + use ExUnit.Case + doctest TypedStructLens + + test "greets the world" do + assert TypedStructLens.hello() == :world + end +end